|
|
@ -35,6 +35,8 @@ import com.jme3.asset.AssetEventListener; |
|
|
|
import com.jme3.asset.AssetKey; |
|
|
|
import com.jme3.asset.AssetKey; |
|
|
|
import com.jme3.asset.AssetManager; |
|
|
|
import com.jme3.asset.AssetManager; |
|
|
|
import com.jme3.asset.DesktopAssetManager; |
|
|
|
import com.jme3.asset.DesktopAssetManager; |
|
|
|
|
|
|
|
import java.beans.PropertyChangeEvent; |
|
|
|
|
|
|
|
import java.beans.PropertyChangeListener; |
|
|
|
import java.io.FileNotFoundException; |
|
|
|
import java.io.FileNotFoundException; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.net.URL; |
|
|
|
import java.net.URL; |
|
|
@ -64,6 +66,7 @@ import org.openide.filesystems.FileRenameEvent; |
|
|
|
import org.openide.filesystems.XMLFileSystem; |
|
|
|
import org.openide.filesystems.XMLFileSystem; |
|
|
|
import org.openide.util.Exceptions; |
|
|
|
import org.openide.util.Exceptions; |
|
|
|
import org.openide.util.Lookup; |
|
|
|
import org.openide.util.Lookup; |
|
|
|
|
|
|
|
import org.openide.util.Mutex; |
|
|
|
import org.openide.util.lookup.Lookups; |
|
|
|
import org.openide.util.lookup.Lookups; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -78,8 +81,10 @@ public class ProjectAssetManager extends DesktopAssetManager { |
|
|
|
private final List<AssetEventListener> assetEventListeners = Collections.synchronizedList(new LinkedList<AssetEventListener>()); |
|
|
|
private final List<AssetEventListener> assetEventListeners = Collections.synchronizedList(new LinkedList<AssetEventListener>()); |
|
|
|
private final List<ClassPathChangeListener> classPathListeners = Collections.synchronizedList(new LinkedList<ClassPathChangeListener>()); |
|
|
|
private final List<ClassPathChangeListener> classPathListeners = Collections.synchronizedList(new LinkedList<ClassPathChangeListener>()); |
|
|
|
private URLClassLoader loader; |
|
|
|
private URLClassLoader loader; |
|
|
|
|
|
|
|
private final List<ClassPath> classPaths = Collections.synchronizedList(new LinkedList<ClassPath>()); |
|
|
|
|
|
|
|
private final List<ClassPathItem> classPathItems = Collections.synchronizedList(new LinkedList<ClassPathItem>()); |
|
|
|
private LinkedList<FileObject> jarItems = new LinkedList<FileObject>(); |
|
|
|
private LinkedList<FileObject> jarItems = new LinkedList<FileObject>(); |
|
|
|
private LinkedList<ClassPathItem> classPathItems = new LinkedList<ClassPathItem>(); |
|
|
|
private final Mutex mutex = new Mutex(); |
|
|
|
|
|
|
|
|
|
|
|
public ProjectAssetManager(Project prj, String folderName) { |
|
|
|
public ProjectAssetManager(Project prj, String folderName) { |
|
|
|
super(true); |
|
|
|
super(true); |
|
|
@ -88,11 +93,7 @@ public class ProjectAssetManager extends DesktopAssetManager { |
|
|
|
di.prepareManager(this); |
|
|
|
di.prepareManager(this); |
|
|
|
} |
|
|
|
} |
|
|
|
addFolderLocator(folderName); |
|
|
|
addFolderLocator(folderName); |
|
|
|
ProjectManager.mutex().postWriteRequest(new Runnable() { |
|
|
|
updateClassLoader(); |
|
|
|
public void run() { |
|
|
|
|
|
|
|
updateClassLoader(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
prepAssetEventListeners(); |
|
|
|
prepAssetEventListeners(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -117,17 +118,25 @@ public class ProjectAssetManager extends DesktopAssetManager { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void clearClassLoader() { |
|
|
|
private void clearClassLoader() { |
|
|
|
|
|
|
|
if (jarItems.isEmpty() && classPathItems.isEmpty()) { |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Logger.getLogger(ProjectAssetManager.class.getName()).log(Level.INFO, "Clear {0} classpath entries and {1} url locators for project {2}", new Object[]{classPathItems.size(), jarItems.size(), project.toString()}); |
|
|
|
for (FileObject fileObject : jarItems) { |
|
|
|
for (FileObject fileObject : jarItems) { |
|
|
|
Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Remove locator:{0}", fileObject.toURL()); |
|
|
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Remove locator:{0}", fileObject.toURL()); |
|
|
|
unregisterLocator(fileObject.toURL().toExternalForm(), |
|
|
|
unregisterLocator(fileObject.toURL().toExternalForm(), |
|
|
|
com.jme3.asset.plugins.UrlLocator.class); |
|
|
|
com.jme3.asset.plugins.UrlLocator.class); |
|
|
|
} |
|
|
|
} |
|
|
|
jarItems.clear(); |
|
|
|
jarItems.clear(); |
|
|
|
for (ClassPathItem fileObject : classPathItems) { |
|
|
|
for (ClassPathItem fileObject : classPathItems) { |
|
|
|
Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Remove classpath:{0}", fileObject.object); |
|
|
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Remove classpath:{0}", fileObject.object); |
|
|
|
fileObject.object.removeRecursiveListener(fileObject.listener); |
|
|
|
fileObject.object.removeRecursiveListener(fileObject.listener); |
|
|
|
} |
|
|
|
} |
|
|
|
classPathItems.clear(); |
|
|
|
classPathItems.clear(); |
|
|
|
|
|
|
|
for (ClassPath classPath : classPaths) { |
|
|
|
|
|
|
|
classPath.removePropertyChangeListener(classPathListener); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
classPaths.clear(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private synchronized void loadClassLoader() { |
|
|
|
private synchronized void loadClassLoader() { |
|
|
@ -141,45 +150,18 @@ public class ProjectAssetManager extends DesktopAssetManager { |
|
|
|
for (SourceGroup sourceGroup : groups) { |
|
|
|
for (SourceGroup sourceGroup : groups) { |
|
|
|
ClassPath path = ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.EXECUTE); |
|
|
|
ClassPath path = ClassPath.getClassPath(sourceGroup.getRootFolder(), ClassPath.EXECUTE); |
|
|
|
if (path != null) { |
|
|
|
if (path != null) { |
|
|
|
|
|
|
|
classPaths.add(path); |
|
|
|
|
|
|
|
path.addPropertyChangeListener(classPathListener); |
|
|
|
FileObject[] roots = path.getRoots(); |
|
|
|
FileObject[] roots = path.getRoots(); |
|
|
|
for (FileObject fileObject : roots) { |
|
|
|
for (FileObject fileObject : roots) { |
|
|
|
if (!fileObject.equals(getAssetFolder())) { |
|
|
|
if (!fileObject.equals(getAssetFolder())) { |
|
|
|
FileChangeListener listener = new FileChangeListener() { |
|
|
|
|
|
|
|
public void fileFolderCreated(FileEvent fe) { |
|
|
|
|
|
|
|
// notifyClassPathListeners();
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void fileDataCreated(FileEvent fe) { |
|
|
|
|
|
|
|
if (!fe.isExpected()) { |
|
|
|
|
|
|
|
notifyClassPathListeners(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void fileChanged(FileEvent fe) { |
|
|
|
|
|
|
|
if (!fe.isExpected()) { |
|
|
|
|
|
|
|
notifyClassPathListeners(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void fileDeleted(FileEvent fe) { |
|
|
|
|
|
|
|
// notifyClassPathListeners();
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void fileRenamed(FileRenameEvent fre) { |
|
|
|
|
|
|
|
// notifyClassPathListeners();
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void fileAttributeChanged(FileAttributeEvent fae) { |
|
|
|
|
|
|
|
// notifyClassPathListeners();
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
fileObject.addRecursiveListener(listener); |
|
|
|
fileObject.addRecursiveListener(listener); |
|
|
|
Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Add classpath:{0}", fileObject); |
|
|
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Add classpath:{0}", fileObject); |
|
|
|
classPathItems.add(new ClassPathItem(fileObject, listener)); |
|
|
|
classPathItems.add(new ClassPathItem(fileObject, listener)); |
|
|
|
urls.add(fileObject.toURL()); |
|
|
|
urls.add(fileObject.toURL()); |
|
|
|
} |
|
|
|
} |
|
|
|
if (fileObject.toURL().toExternalForm().startsWith("jar")) { |
|
|
|
if (fileObject.toURL().toExternalForm().startsWith("jar")) { |
|
|
|
Logger.getLogger(this.getClass().getName()).log(Level.INFO, "Add locator:{0}", fileObject.toURL()); |
|
|
|
Logger.getLogger(this.getClass().getName()).log(Level.FINE, "Add locator:{0}", fileObject.toURL()); |
|
|
|
jarItems.add(fileObject); |
|
|
|
jarItems.add(fileObject); |
|
|
|
registerLocator(fileObject.toURL().toExternalForm(), |
|
|
|
registerLocator(fileObject.toURL().toExternalForm(), |
|
|
|
"com.jme3.asset.plugins.UrlLocator"); |
|
|
|
"com.jme3.asset.plugins.UrlLocator"); |
|
|
@ -189,12 +171,62 @@ public class ProjectAssetManager extends DesktopAssetManager { |
|
|
|
} |
|
|
|
} |
|
|
|
loader = new URLClassLoader(urls.toArray(new URL[urls.size()]), getClass().getClassLoader()); |
|
|
|
loader = new URLClassLoader(urls.toArray(new URL[urls.size()]), getClass().getClassLoader()); |
|
|
|
addClassLoader(loader); |
|
|
|
addClassLoader(loader); |
|
|
|
|
|
|
|
Logger.getLogger(ProjectAssetManager.class.getName()).log(Level.INFO, "Updated {0} classpath entries and {1} url locators for project {2}", new Object[]{classPathItems.size(), jarItems.size(), project.toString()}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
FileChangeListener listener = new FileChangeListener() { |
|
|
|
|
|
|
|
public void fileFolderCreated(FileEvent fe) { |
|
|
|
|
|
|
|
fireChange(fe); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void fileDataCreated(FileEvent fe) { |
|
|
|
|
|
|
|
fireChange(fe); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void fileChanged(FileEvent fe) { |
|
|
|
|
|
|
|
fireChange(fe); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void fileDeleted(FileEvent fe) { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void fileRenamed(FileRenameEvent fe) { |
|
|
|
|
|
|
|
fireChange(fe); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void fileAttributeChanged(FileAttributeEvent fae) { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void fireChange(FileEvent fe) { |
|
|
|
|
|
|
|
Logger.getLogger(ProjectAssetManager.class.getName()).log(Level.FINE, "Classpath item changed: {0}", fe); |
|
|
|
|
|
|
|
// if (!fe.isExpected()) {
|
|
|
|
|
|
|
|
updateClassLoader(); |
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
private PropertyChangeListener classPathListener = new PropertyChangeListener() { |
|
|
|
|
|
|
|
public void propertyChange(PropertyChangeEvent evt) { |
|
|
|
|
|
|
|
Logger.getLogger(ProjectAssetManager.class.getName()).log(Level.FINE, "Classpath event: {0}", evt); |
|
|
|
|
|
|
|
if (ClassPath.PROP_ROOTS.equals(evt.getPropertyName())) { |
|
|
|
|
|
|
|
updateClassLoader(); |
|
|
|
|
|
|
|
} else if (ClassPath.PROP_ENTRIES.equals(evt.getPropertyName())) { |
|
|
|
|
|
|
|
updateClassLoader(); |
|
|
|
|
|
|
|
} else if (ClassPath.PROP_INCLUDES.equals(evt.getPropertyName())) { |
|
|
|
|
|
|
|
updateClassLoader(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
private synchronized void updateClassLoader() { |
|
|
|
private synchronized void updateClassLoader() { |
|
|
|
clearClassLoader(); |
|
|
|
ProjectManager.mutex().postWriteRequest(new Runnable() { |
|
|
|
loadClassLoader(); |
|
|
|
public void run() { |
|
|
|
|
|
|
|
synchronized (classPathItems) { |
|
|
|
|
|
|
|
clearClassLoader(); |
|
|
|
|
|
|
|
loadClassLoader(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
notifyClassPathListeners(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
@ -338,22 +370,24 @@ public class ProjectAssetManager extends DesktopAssetManager { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (classPathItems != null) { |
|
|
|
if (classPathItems != null) { |
|
|
|
// TODO I need to find out if classPathItems contains all jars added to a project
|
|
|
|
synchronized (classPathItems) { |
|
|
|
Iterator<ClassPathItem> classPathItemsIter = classPathItems.iterator(); |
|
|
|
// TODO I need to find out if classPathItems contains all jars added to a project
|
|
|
|
while (classPathItemsIter.hasNext()) { |
|
|
|
Iterator<ClassPathItem> classPathItemsIter = classPathItems.iterator(); |
|
|
|
ClassPathItem classPathItem = classPathItemsIter.next(); |
|
|
|
while (classPathItemsIter.hasNext()) { |
|
|
|
FileObject jarFile = classPathItem.object; |
|
|
|
ClassPathItem classPathItem = classPathItemsIter.next(); |
|
|
|
|
|
|
|
FileObject jarFile = classPathItem.object; |
|
|
|
Enumeration<FileObject> jarEntry = (Enumeration<FileObject>) jarFile.getChildren(true); |
|
|
|
|
|
|
|
while (jarEntry.hasMoreElements()) { |
|
|
|
Enumeration<FileObject> jarEntry = (Enumeration<FileObject>) jarFile.getChildren(true); |
|
|
|
FileObject jarEntryAsset = jarEntry.nextElement(); |
|
|
|
while (jarEntry.hasMoreElements()) { |
|
|
|
if (jarEntryAsset.getExt().equalsIgnoreCase(suffix)) { |
|
|
|
FileObject jarEntryAsset = jarEntry.nextElement(); |
|
|
|
if (!jarEntryAsset.getPath().startsWith("/")) { |
|
|
|
if (jarEntryAsset.getExt().equalsIgnoreCase(suffix)) { |
|
|
|
list.add(jarEntryAsset.getPath()); |
|
|
|
if (!jarEntryAsset.getPath().startsWith("/")) { |
|
|
|
|
|
|
|
list.add(jarEntryAsset.getPath()); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -362,29 +396,29 @@ public class ProjectAssetManager extends DesktopAssetManager { |
|
|
|
|
|
|
|
|
|
|
|
public InputStream getResourceAsStream(String name) { |
|
|
|
public InputStream getResourceAsStream(String name) { |
|
|
|
InputStream in = null;//JmeSystem.getResourceAsStream(name);
|
|
|
|
InputStream in = null;//JmeSystem.getResourceAsStream(name);
|
|
|
|
|
|
|
|
synchronized (classPathItems) { |
|
|
|
if (in == null && classPathItems != null) { |
|
|
|
if (in == null && classPathItems != null) { |
|
|
|
// TODO I need to find out if classPathItems contains all jars added to a project
|
|
|
|
// TODO I need to find out if classPathItems contains all jars added to a project
|
|
|
|
Iterator<ClassPathItem> classPathItemsIter = classPathItems.iterator(); |
|
|
|
Iterator<ClassPathItem> classPathItemsIter = classPathItems.iterator(); |
|
|
|
while (classPathItemsIter.hasNext()) { |
|
|
|
while (classPathItemsIter.hasNext()) { |
|
|
|
ClassPathItem classPathItem = classPathItemsIter.next(); |
|
|
|
ClassPathItem classPathItem = classPathItemsIter.next(); |
|
|
|
FileObject jarFile = classPathItem.object; |
|
|
|
FileObject jarFile = classPathItem.object; |
|
|
|
|
|
|
|
|
|
|
|
Enumeration<FileObject> jarEntry = (Enumeration<FileObject>) jarFile.getChildren(true); |
|
|
|
Enumeration<FileObject> jarEntry = (Enumeration<FileObject>) jarFile.getChildren(true); |
|
|
|
while (jarEntry.hasMoreElements()) { |
|
|
|
while (jarEntry.hasMoreElements()) { |
|
|
|
FileObject jarEntryAsset = jarEntry.nextElement(); |
|
|
|
FileObject jarEntryAsset = jarEntry.nextElement(); |
|
|
|
if (jarEntryAsset.getPath().equalsIgnoreCase(name)) { |
|
|
|
if (jarEntryAsset.getPath().equalsIgnoreCase(name)) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
in = jarEntryAsset.getInputStream(); |
|
|
|
in = jarEntryAsset.getInputStream(); |
|
|
|
} catch (FileNotFoundException ex) { |
|
|
|
} catch (FileNotFoundException ex) { |
|
|
|
Exceptions.printStackTrace(ex); |
|
|
|
Exceptions.printStackTrace(ex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return in; |
|
|
|
return in; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -443,24 +477,31 @@ public class ProjectAssetManager extends DesktopAssetManager { |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void addAssetEventListener(AssetEventListener listener) { |
|
|
|
public void addAssetEventListener(AssetEventListener listener) { |
|
|
|
assetEventListeners.add(listener); |
|
|
|
synchronized (assetEventListeners) { |
|
|
|
|
|
|
|
assetEventListeners.add(listener); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void removeAssetEventListener(AssetEventListener listener) { |
|
|
|
public void removeAssetEventListener(AssetEventListener listener) { |
|
|
|
assetEventListeners.remove(listener); |
|
|
|
synchronized (assetEventListeners) { |
|
|
|
|
|
|
|
assetEventListeners.remove(listener); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void addClassPathEventListener(ClassPathChangeListener listener) { |
|
|
|
public void addClassPathEventListener(ClassPathChangeListener listener) { |
|
|
|
classPathListeners.add(listener); |
|
|
|
synchronized (classPathListeners) { |
|
|
|
|
|
|
|
classPathListeners.add(listener); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void removeClassPathEventListener(ClassPathChangeListener listener) { |
|
|
|
public void removeClassPathEventListener(ClassPathChangeListener listener) { |
|
|
|
classPathListeners.remove(listener); |
|
|
|
synchronized (classPathListeners) { |
|
|
|
|
|
|
|
classPathListeners.remove(listener); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void notifyClassPathListeners() { |
|
|
|
private void notifyClassPathListeners() { |
|
|
|
updateClassLoader(); |
|
|
|
|
|
|
|
final ProjectAssetManager pm = this; |
|
|
|
final ProjectAssetManager pm = this; |
|
|
|
java.awt.EventQueue.invokeLater(new Runnable() { |
|
|
|
java.awt.EventQueue.invokeLater(new Runnable() { |
|
|
|
public void run() { |
|
|
|
public void run() { |
|
|
@ -473,6 +514,10 @@ public class ProjectAssetManager extends DesktopAssetManager { |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public Mutex mutex() { |
|
|
|
|
|
|
|
return mutex; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* For situations with no Project |
|
|
|
* For situations with no Project |
|
|
|
*/ |
|
|
|
*/ |
|
|
@ -505,6 +550,7 @@ public class ProjectAssetManager extends DesktopAssetManager { |
|
|
|
|
|
|
|
|
|
|
|
private static class ClassPathItem { |
|
|
|
private static class ClassPathItem { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ClassPath path; |
|
|
|
FileObject object; |
|
|
|
FileObject object; |
|
|
|
FileChangeListener listener; |
|
|
|
FileChangeListener listener; |
|
|
|
|
|
|
|
|
|
|
|