Added example-vfs project written on Kotlin.

This commit is contained in:
Evgeny Gerashchenko
2012-01-27 18:30:18 +04:00
parent 2dfacc24f1
commit ca1abed3a9
9 changed files with 736 additions and 0 deletions
+1
View File
@@ -7,6 +7,7 @@
<module fileurl="file://$PROJECT_DIR$/build-tools/build-tools.iml" filepath="$PROJECT_DIR$/build-tools/build-tools.iml" />
<module fileurl="file://$PROJECT_DIR$/compiler/cli/cli.iml" filepath="$PROJECT_DIR$/compiler/cli/cli.iml" />
<module fileurl="file://$PROJECT_DIR$/compiler/tests/compiler-tests.iml" filepath="$PROJECT_DIR$/compiler/tests/compiler-tests.iml" />
<module fileurl="file://$PROJECT_DIR$/examples/example-vfs/example-vfs.iml" filepath="$PROJECT_DIR$/examples/example-vfs/example-vfs.iml" />
<module fileurl="file://$PROJECT_DIR$/examples/examples.iml" filepath="$PROJECT_DIR$/examples/examples.iml" />
<module fileurl="file://$PROJECT_DIR$/compiler/frontend/frontend.iml" filepath="$PROJECT_DIR$/compiler/frontend/frontend.iml" />
<module fileurl="file://$PROJECT_DIR$/compiler/frontend.java/frontend.java.iml" filepath="$PROJECT_DIR$/compiler/frontend.java/frontend.java.iml" />
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="jdk" jdkName="1.6" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="stdlib" />
</component>
</module>
+170
View File
@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AntConfiguration">
<defaultAnt bundledAnt="true" />
</component>
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="?*.properties" />
<entry name="?*.xml" />
<entry name="?*.gif" />
<entry name="?*.png" />
<entry name="?*.jpeg" />
<entry name="?*.jpg" />
<entry name="?*.html" />
<entry name="?*.dtd" />
<entry name="?*.tld" />
<entry name="?*.ftl" />
</wildcardResourcePatterns>
<annotationProcessing enabled="false" useClasspath="true" />
</component>
<component name="CopyrightManager" default="">
<module2copyright />
</component>
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/example-vfs.iml" filepath="$PROJECT_DIR$/example-vfs.iml" />
<module fileurl="file://$PROJECT_DIR$/../../stdlib/stdlib.iml" filepath="$PROJECT_DIR$/../../stdlib/stdlib.iml" />
</modules>
</component>
<component name="ProjectResources">
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>
+130
View File
@@ -0,0 +1,130 @@
package org.jetbrains.jet.samples.vfs;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.jetbrains.jet.samples.vfs.utils.*;
import java.util.concurrent.locks.Lock
import java.io.File
import java.util.List
import java.util.ArrayList
import java.util.HashMap
import java.util.Arrays
import java.util.Map
import std.util.*
/**
* File system singleton. To work with virtual file system, read/write locks should be
* acquired: use read() and write() higher-order functions.
*/
public object FileSystem {
private val lock = ReentrantReadWriteLock()
internal val watchedDirectories = ArrayList<VirtualFile>
// FIXME VirtualFiles should be used as hashmap keys themselves,
// but overriden hashCode() method fails in runtime with ClassCastException (KT-1134)
/**
* Mapping from virtual files to metainformation
*/
internal val fileToInfo = HashMap<String, VirtualFileInfo>()
private val listeners = ArrayList<VirtualFileListener>()
/**
* Returns corresponding virtual file for java.io.File.
*
* @param ioFile file
*/
public fun getFileByIoFile(ioFile : File) : VirtualFile {
FileSystem.assertCanRead()
return PhysicalVirtualFile(ioFile.getAbsolutePath().sure().toSystemIndependentPath())
}
/**
* Returns virtual file for path to it.
*
* @param path path to file
*/
public fun getFileByPath(path : String) : VirtualFile {
return getFileByIoFile(File(path))
}
/**
* Runs function with read lock.
*/
public inline fun read<T>(task : () -> T) : T {
return locked(lock.readLock().sure(), task)
}
/**
* Runs function with write lock.
*/
public inline fun write<T>(task : () -> T) : T {
return locked(lock.writeLock().sure(), task)
}
/**
* Adds directory to list of watched directories. Watched directories are
* periodically refreshed and corresponding events are sent to file system listeners.
*
* @param dir directory which should be watched
*/
public fun addWatchedDirectory(dir : VirtualFile) {
assertCanRead()
if (dir.isDirectory()) {
watchedDirectories.add(dir)
scanAndAddRecursivelyNoEvents(dir)
RefreshQueue.scheduleRefresh()
}
}
/* Scans file recursively and adds info about it to fileToInfo map */
private fun scanAndAddRecursivelyNoEvents(file : VirtualFile) {
assert(FileSystem.fileToInfo[file.path] == null)
val fileInfo = VirtualFileInfo(file)
FileSystem.fileToInfo[file.path] = fileInfo
fileInfo.children.foreach{ scanAndAddRecursivelyNoEvents(it) }
}
internal inline fun assertCanRead() {
assert(lock.getReadHoldCount() != 0 || lock.isWriteLockedByCurrentThread())
}
internal inline fun assertCanWrite() {
assert(lock.isWriteLockedByCurrentThread())
}
/**
* Adds file system listener which should be notified about changing of file system.
*/
public fun addVirtualFileListener(listener : VirtualFileListener) {
listeners.add(listener)
}
/**
* Removes file system listener.
*/
public fun removeVirtualFileListener(listener : VirtualFileListener) {
listeners.remove(listener)
}
/* Notifies all listeners */
internal fun notifyEventHappened(event : VirtualFileEvent) {
for (listener in listeners) {
listener.eventHappened(event)
}
}
}
private class VirtualFileInfo(file : VirtualFile) {
/* Last modification time */
var lastModified : Long = 0
/* List of known children */
val children : List<VirtualFile> = ArrayList<VirtualFile>;
{
children.addAll(file.children())
lastModified = file.modificationTime()
}
}
+36
View File
@@ -0,0 +1,36 @@
package org.jetbrains.jet.samples.vfs.sandbox;
import org.jetbrains.jet.samples.vfs.*;
import java.io.InputStreamReader
import java.util.Scanner
/**
* Receives list of directories which should be watched, adds them to virtual file system,
* adds virtual file system listener and waits for 1 minutes, printing out all received event.
*/
fun main(args : Array<String>) {
if (args.size == 0) {
println("Provide list of watched directories as command line arguments")
return
}
// add watched directory
FileSystem.write {
for (val arg in args) {
FileSystem.addWatchedDirectory(FileSystem.getFileByPath(arg))
}
}
// add listener which prints out everything
FileSystem.addVirtualFileListener(object : VirtualFileListener {
override fun eventHappened(event: VirtualFileEvent) {
println(event)
if (event is VirtualFileChangedEvent) {
println("new file size is ${event.file.size()}")
}
}
})
// wait for 1 minute
Thread.sleep(60000)
}
+138
View File
@@ -0,0 +1,138 @@
package org.jetbrains.jet.samples.vfs;
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.List
import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.LinkedBlockingQueue
import java.util.ArrayList
import std.util.*
import java.util.Timer
import java.util.TimerTask
import org.jetbrains.jet.samples.vfs.utils.*
/**
* Singleton which creates thread for periodically checking if there are changes in
* file system and notifying file system listeners.
*/
internal object RefreshQueue : Runnable {
private val taskQueue = LinkedBlockingQueue<List<VirtualFile>>()
private val workerThread: Thread = Thread(this)
private val fullRefreshScheduler = Timer(true);
{
workerThread.setDaemon(true)
workerThread.start()
fullRefreshScheduler.scheduleAtFixedRate(createTimerTask {
scheduleRefresh(FileSystem.watchedDirectories)
}, 0, 5000)
}
private fun takeAndRefreshFiles() {
refreshFiles(taskQueue.take())
}
/* Acquires write lock and refreshes file system */
private fun refreshFiles(files : List<VirtualFile>) {
FileSystem.write {
files.foreach{ refreshFile(it) }
}
}
/* Checks for changes in virtual file recursively, notifying listeners. */
private fun refreshFile(file : VirtualFile) {
FileSystem.assertCanWrite()
if (file.isDirectory()) {
val fileToInfo = FileSystem.fileToInfo
val fileInfo = fileToInfo[file.path]
val oldChildren = fileInfo.children
val newChildren = file.children()
val addedChildren = listDifference(newChildren, oldChildren)
val deletedChildren = listDifference(oldChildren, newChildren)
val commonChildren = listIntersection(oldChildren, newChildren)
addedChildren.foreach{ addRecursively(it) }
deletedChildren.foreach{ deleteRecursively(it) }
fileInfo.children.clear()
fileInfo.children.addAll(newChildren)
commonChildren.foreach{ refreshFile(it) }
} else {
val fileInfo = FileSystem.fileToInfo[file.path]
assert(fileInfo != null)
val newModificationTime = file.modificationTime()
if (fileInfo.lastModified != newModificationTime) {
fileInfo.lastModified = newModificationTime
FileSystem.notifyEventHappened(VirtualFileChangedEvent(file))
}
}
}
/* Adds file to file system recursively, notifying listeners */
private fun addRecursively(file : VirtualFile) {
assert(FileSystem.fileToInfo[file] == null)
val fileInfo = VirtualFileInfo(file)
FileSystem.fileToInfo[file.path] = fileInfo
FileSystem.notifyEventHappened(VirtualFileCreateEvent(file))
fileInfo.children.foreach{ addRecursively(it) }
}
/* Deletes file from file system recursively, notifying listeners */
private fun deleteRecursively(file : VirtualFile) {
val fileInfoMaybe : VirtualFileInfo? = FileSystem.fileToInfo[file.path]
val fileInfo = fileInfoMaybe.sure()
fileInfo.children.foreach{ deleteRecursively(it) }
FileSystem.notifyEventHappened(VirtualFileDeletedEvent(file))
FileSystem.fileToInfo.remove(file)
}
/**
* Schedules refresh for given list of files.
*/
public fun scheduleRefresh(files : List<VirtualFile>) {
taskQueue.put(files)
}
/**
* Schedules refresh for given list of files.
*/
public fun scheduleRefresh(vararg files : VirtualFile) {
// FIXME This could be written more concise, using map() & toList() (KT-1164 & KT-1172)
val filesList = ArrayList<VirtualFile>()
files.foreach{ filesList.add(it) }
taskQueue.put(filesList)
// taskQueue.put(ArrayList<VirtualFile>(files.map{ it }))
// taskQueue.put(files.map{ it }.toList())
}
// FIXME RefreshQueue implements Runnable because of error on accessing
// private fields and methods from anonymous class (KT-1157 & KT-1159) (
override fun run() {
while (!workerThread.isInterrupted()) {
try {
takeAndRefreshFiles()
} catch (e : InterruptedException) {
}
}
}
}
// FIXME this method is used because of error on accessing
// private methods from anonymous class (KT-1157) (
private fun createTimerTask(task : () -> Unit) : TimerTask {
return object : TimerTask() {
override fun run() {
task()
}
}
}
+42
View File
@@ -0,0 +1,42 @@
package org.jetbrains.jet.samples.vfs.utils;
import java.util.concurrent.locks.Lock
import java.util.List
import std.util.*
/**
* Executes task with given lock acquired.
*/
private fun locked<T>(lock : Lock, body : () -> T) : T {
lock.lock()
try {
return body()
} finally {
lock.unlock();
}
}
/**
* Checks boolean value which should be true. If it is false, throws Assertion Error
*
* @param value value to be checked
*/
public fun assert(value : Boolean) {
if (!value) {
throw AssertionError()
}
}
/**
* Returns list containing all elements which first contains and second does not.
*/
public fun listDifference<T>(first : List<T>, second : List<T>) : List<T> {
return first.filter{ !second.contains(it) }.toList()
}
/**
* Returns list containing all elements which both lists contain.
*/
public fun listIntersection<T>(first : List<T>, second : List<T>) : List<T> {
return first.filter{ second.contains(it) }.toList()
}
+164
View File
@@ -0,0 +1,164 @@
package org.jetbrains.jet.samples.vfs;
import org.jetbrains.jet.samples.vfs.utils.*;
import java.io.File
import java.io.InputStream
import java.io.FileInputStream
import java.util.ArrayList
import java.util.List
import std.util.*
/**
* Abstract virtual file.
*/
public abstract class VirtualFile(public val path : String) {
// FIXME this method should be replaced with val (KT-1168, KT-1170)
protected abstract fun kind() : String
// FIXME these abstract methods should be replaced with vals (KT-1165)
/**
* Returns file size.
*/
public abstract fun size() : Long
/**
* Returns the time that the virtual file was last modified (milliseconds since
* the epoch (00:00:00 GMT, January 1, 1970).
*/
public abstract fun modificationTime() : Long
/**
* Returns if virtual file exists.
*/
public abstract fun exists() : Boolean
/**
* Returns if virtual file is directory
*/
public abstract fun isDirectory() : Boolean
/**
* Returns list of virtual files which are children for this.
*/
public abstract fun children() : List<VirtualFile>
/**
* Opens input stream for reading. After reading, stream should be closed.
* Reading from stream should be performed with read lock acquired.
*/
public abstract fun openInputStream() : InputStream
fun equals(other : Any?) : Boolean {
return other is VirtualFile && kind() == other.kind() && path == other.path
}
fun hashCode() : Int {
// FIXME rewrite without casting when it will be possible
return (kind() as java.lang.String).hashCode() * 31 + (path as java.lang.String).hashCode()
}
fun toString(): String {
return "${kind()}[path=$path]"
}
}
/**
* Type of virtual file which corresponds to real file in file system of OS.
*/
public class PhysicalVirtualFile(path : String) : VirtualFile(path) {
override fun kind() : String = "Physical"
private val ioFile : File
get() = File(this.path.toSystemDependentPath())
override fun exists(): Boolean {
FileSystem.assertCanRead()
return ioFile.exists()
}
override fun size(): Long {
FileSystem.assertCanRead()
return ioFile.length()
}
override fun modificationTime(): Long {
FileSystem.assertCanRead()
return ioFile.lastModified()
}
override fun isDirectory(): Boolean {
FileSystem.assertCanRead()
return ioFile.isDirectory()
}
override fun children(): List<VirtualFile> {
FileSystem.assertCanRead()
return (ioFile.listFiles() ?: Array<File>(0)).
map{ FileSystem.getFileByIoFile(it.sure()) }?.toList()
}
override fun openInputStream(): InputStream {
FileSystem.assertCanRead()
if (isDirectory()) {
throw IllegalArgumentException("Can't open directory for reading");
}
return CheckedInputStream(FileInputStream(ioFile))
}
}
private fun String.toSystemDependentPath() : String {
// FIXME constants should be extracted (NPE in compiler, KT-1111)
return this.replaceAll("/", java.io.File.separator.sure())
}
private fun String.toSystemIndependentPath() : String {
// FIXME constants should be extracted (NPE in compiler, KT-1111)
return this.replaceAll(java.io.File.separator.sure(), "/")
}
/**
* InputStream wrapper which checks that file system read lock is acquired on each operation.
*/
private class CheckedInputStream(private val wrapped : InputStream) : InputStream() {
override fun read(): Int {
FileSystem.assertCanRead()
return wrapped.read()
}
override fun read(b: ByteArray?, off: Int, len: Int) : Int {
FileSystem.assertCanRead()
return wrapped.read(b, off, len)
}
override fun markSupported(): Boolean {
FileSystem.assertCanRead()
return wrapped.markSupported()
}
override fun skip(n: Long): Long {
FileSystem.assertCanRead()
return wrapped.skip(n)
}
override fun close() {
FileSystem.assertCanRead()
return wrapped.close()
}
override fun mark(readlimit: Int) {
FileSystem.assertCanRead()
return wrapped.mark(readlimit)
}
override fun read(b: ByteArray?): Int {
FileSystem.assertCanRead()
return wrapped.read(b)
}
override fun reset() {
FileSystem.assertCanRead()
return wrapped.reset()
}
override fun available(): Int {
FileSystem.assertCanRead()
return wrapped.available()
}
}
@@ -0,0 +1,42 @@
package org.jetbrains.jet.samples.vfs;
/**
* Listener for receiving virtual file event
*/
public trait VirtualFileListener : java.util.EventListener {
fun eventHappened(val event : VirtualFileEvent)
}
/**
* Base type of virtual file events
* @property file affected by event
*/
public abstract class VirtualFileEvent(val file : VirtualFile) : Object() {
}
/**
* Event of creating file
*/
public class VirtualFileCreateEvent(file : VirtualFile) : VirtualFileEvent(file) {
override fun toString(): String? {
return "created ${file}"
}
}
/**
* Event of deleting file
*/
public class VirtualFileDeletedEvent(file : VirtualFile) : VirtualFileEvent(file) {
override fun toString(): String? {
return "deleted ${file}"
}
}
/**
* Event of changing file contents
*/
public class VirtualFileChangedEvent(file : VirtualFile) : VirtualFileEvent(file) {
override fun toString(): String? {
return "changed ${file}"
}
}