Author: tcurdt Date: Sat Sep 24 04:53:44 2005 New Revision: 291284 URL: http://svn.apache.org/viewcvs?rev=291284&view=rev Log: further refactoring and consolidation
Added: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/FileChangeListener.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/NotificationListener.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/NotifyingListener.java - copied, changed from r290987, jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/AbstractListener.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/ResourceStoringListener.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/ResourceStoreClassLoader.java Removed: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/AbstractListener.java Modified: jakarta/commons/sandbox/jci/trunk/TODO jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoader.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoaderListener.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/compilers/groovy/GroovyJavaCompiler.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/CompilingListener.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/ReloadingListener.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationListener.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationMonitor.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/FileResourceStore.java jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/MemoryResourceStore.java jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/AbstractTestCase.java jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/CompilingClassLoaderTestCase.java jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/ReloadingClassLoaderTestCase.java jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/compilers/GroovySources.java jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/monitor/FilesystemAlterationMonitorTestCase.java Modified: jakarta/commons/sandbox/jci/trunk/TODO URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/TODO?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/TODO (original) +++ jakarta/commons/sandbox/jci/trunk/TODO Sat Sep 24 04:53:44 2005 @@ -8,3 +8,4 @@ o turn the JavaCompilerFactory into an interface and maybe provide a simple default impl o documentation o dependency analysis for proper re-try after errors +o store resources as org/apache/my.class instead of org.apache.my Modified: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoader.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoader.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoader.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoader.java Sat Sep 24 04:53:44 2005 @@ -18,7 +18,8 @@ import java.io.File; import java.io.InputStream; import java.net.URL; -import org.apache.commons.jci.listeners.AbstractListener; +import org.apache.commons.jci.listeners.NotificationListener; +import org.apache.commons.jci.listeners.ReloadingListener; import org.apache.commons.jci.stores.ResourceStore; import org.apache.commons.jci.stores.ResourceStoreClassLoader; import org.apache.commons.logging.Log; @@ -28,7 +29,7 @@ * @author tcurdt * */ -public class ReloadingClassLoader extends ClassLoader { +public class ReloadingClassLoader extends ClassLoader implements NotificationListener { private final static Log log = LogFactory.getLog(ReloadingClassLoader.class); @@ -44,14 +45,14 @@ delegate = new ResourceStoreClassLoader(parent, stores); } - public void addListener(final AbstractListener pListener) { - pListener.setReloadingClassLoader(this); + public void addListener(final ReloadingListener pListener) { + pListener.setNotificationListener(this); addResourceStore(pListener.getStore()); } - public void removeListener(final AbstractListener pListener) { + public void removeListener(final ReloadingListener pListener) { removeResourceStore(pListener.getStore()); - pListener.setReloadingClassLoader(null); + pListener.setNotificationListener(null); } private void addResourceStore(final ResourceStore pStore) { @@ -100,22 +101,17 @@ } } */ - public void reload(final boolean pReload) { - if (pReload) { - log.debug("reloading"); - delegate = new ResourceStoreClassLoader(parent, stores); - //notifyReloadingListeners(true); - } else { - log.debug("not reloading"); - //notifyReloadingListeners(false); - } + public void handleNotification() { + log.debug("reloading"); + delegate = new ResourceStoreClassLoader(parent, stores); + //notifyReloadingListeners(); } /* - private void notifyReloadingListeners(final boolean pReload) { + private void notifyReloadingListeners() { synchronized (reloadingListeners) { for (final Iterator it = reloadingListeners.iterator(); it.hasNext();) { final ReloadingClassLoaderListener listener = (ReloadingClassLoaderListener) it.next(); - listener.hasReloaded(pReload); + listener.hasReloaded(); } } } Modified: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoaderListener.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoaderListener.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoaderListener.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoaderListener.java Sat Sep 24 04:53:44 2005 @@ -20,5 +20,5 @@ * @author tcurdt */ public interface ReloadingClassLoaderListener { - void hasReloaded(final boolean pReload); + void hasReloaded(); } Modified: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/compilers/groovy/GroovyJavaCompiler.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/compilers/groovy/GroovyJavaCompiler.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/compilers/groovy/GroovyJavaCompiler.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/compilers/groovy/GroovyJavaCompiler.java Sat Sep 24 04:53:44 2005 @@ -62,6 +62,7 @@ store.write(name, bytes); } } catch (final CompilationFailedException e) { + e.printStackTrace(); final ErrorCollector col = e.getUnit().getErrorCollector(); final Collection warnings = col.getWarnings(); Modified: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/CompilingListener.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/CompilingListener.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/CompilingListener.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/CompilingListener.java Sat Sep 24 04:53:44 2005 @@ -33,14 +33,10 @@ import org.apache.commons.logging.LogFactory; -public class CompilingListener extends AbstractListener { +public class CompilingListener extends ReloadingListener { private final static Log log = LogFactory.getLog(CompilingListener.class); - private final Collection created = new ArrayList(); - private final Collection changed = new ArrayList(); - private final Collection deleted = new ArrayList(); - private final JavaCompiler compiler; private final ResourceReader reader; private final TransactionalResourceStore transactionalStore; @@ -75,18 +71,18 @@ } public void onStart() { - created.clear(); - changed.clear(); - deleted.clear(); + super.onStart(); transactionalStore.onStart(); } - public void onStop() { - log.debug( - created.size() + " created, " + - changed.size() + " changed, " + - deleted.size() + " deleted"); + public void onStop() { boolean reload = false; + + log.debug("created:" + created.size() + + " changed:" + changed.size() + + " deleted:" + deleted.size() + + " resources"); + if (deleted.size() > 0) { for (Iterator it = deleted.iterator(); it.hasNext();) { @@ -97,15 +93,29 @@ } final Collection compileables = new ArrayList(); - // FIXME: only compile ".java" resources to support resource reloading - compileables.addAll(created); - compileables.addAll(changed); - - final String[] clazzes = new String[compileables.size()]; + for (final Iterator it = created.iterator(); it.hasNext();) { + final File createdFile = (File) it.next(); + if (createdFile.getName().endsWith(".java")) { + compileables.add(createdFile); + } + } + + for (final Iterator it = changed.iterator(); it.hasNext();) { + final File changedFile = (File) it.next(); + if (changedFile.getName().endsWith(".java")) { + compileables.add(changedFile); + } + } + if (compileables.size() > 0) { - + + log.debug(compileables.size() + + " classes to compile" + ); + int i = 0; + final String[] clazzes = new String[compileables.size()]; for (Iterator it = compileables.iterator(); it.hasNext();) { final File file = (File) it.next(); clazzes[i] = ReloadingClassLoader.clazzName(repository, file); @@ -133,6 +143,7 @@ if (errors.length > 0) { // FIXME: they need to be marked for re-compilation + // and then added as compileables again for (int j = 0; j < clazzes.length; j++) { transactionalStore.remove(clazzes[j]); } @@ -143,32 +154,6 @@ transactionalStore.onStop(); - needsReload(reload); - } - - public void onCreateFile( final File file ) { - // FIXME: to support resource reloading do the suffix filtering in onStop - if (file.getName().endsWith(".java")) { - created.add(file); - } - } - public void onChangeFile( final File file ) { - // FIXME: to support resource reloading do the suffix filtering in onStop - if (file.getName().endsWith(".java")) { - changed.add(file); - } - } - public void onDeleteFile( final File file ) { - // FIXME: to support resource reloading do the suffix filtering in onStop - if (file.getName().endsWith(".java")) { - deleted.add(file); - } - } - - public void onCreateDirectory( final File file ) { - } - public void onChangeDirectory( final File file ) { - } - public void onDeleteDirectory( final File file ) { + checked(reload); } } Added: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/FileChangeListener.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/FileChangeListener.java?rev=291284&view=auto ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/FileChangeListener.java (added) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/FileChangeListener.java Sat Sep 24 04:53:44 2005 @@ -0,0 +1,47 @@ +package org.apache.commons.jci.listeners; + +import java.io.File; + + +public class FileChangeListener extends NotifyingListener { + + private boolean changed; + + public FileChangeListener(final File pRepository) { + super(pRepository); + } + + public void onStart() { + changed = false; + } + + public void onStop() { + checked(changed); + } + + + public void onChangeFile( File pFile ) { + changed = true; + } + + + public void onCreateFile( File pFile ) { + changed = true; + } + + + public void onDeleteFile( File pFile ) { + changed = true; + } + + + public void onChangeDirectory( File pDir ) { + } + + public void onCreateDirectory( File pDir ) { + } + + public void onDeleteDirectory( File pDir ) { + } + +} Added: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/NotificationListener.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/NotificationListener.java?rev=291284&view=auto ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/NotificationListener.java (added) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/NotificationListener.java Sat Sep 24 04:53:44 2005 @@ -0,0 +1,6 @@ +package org.apache.commons.jci.listeners; + + +public interface NotificationListener { + void handleNotification(); +} Copied: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/NotifyingListener.java (from r290987, jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/AbstractListener.java) URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/NotifyingListener.java?p2=jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/NotifyingListener.java&p1=jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/AbstractListener.java&r1=290987&r2=291284&rev=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/AbstractListener.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/NotifyingListener.java Sat Sep 24 04:53:44 2005 @@ -1,31 +1,112 @@ package org.apache.commons.jci.listeners; import java.io.File; -import org.apache.commons.jci.ReloadingClassLoader; import org.apache.commons.jci.monitor.FilesystemAlterationListener; -import org.apache.commons.jci.stores.ResourceStore; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; -public abstract class AbstractListener implements FilesystemAlterationListener { +public abstract class NotifyingListener implements FilesystemAlterationListener { + + private final static Log log = LogFactory.getLog(NotifyingListener.class); + + public final static class Signal { + public boolean triggered; + } protected final File repository; - protected ReloadingClassLoader reloader; + protected NotificationListener notificationListener; + private final Signal notificationSignal = new Signal(); + private final Signal checkSignal = new Signal(); - public AbstractListener(final File pRepository) { + public NotifyingListener(final File pRepository) { repository = pRepository; } + + public File getRepository() { + return repository; + } - public void setReloadingClassLoader(final ReloadingClassLoader pReloader) { - reloader = pReloader; + public void setNotificationListener(final NotificationListener pNotificationListener) { + notificationListener = pNotificationListener; + } + + protected void checked( final boolean pNotify ) { + if (pNotify) { + if (notificationListener != null) { + notificationListener.handleNotification(); + } + synchronized(notificationSignal) { + notificationSignal.triggered = true; + notificationSignal.notifyAll(); + } + } + synchronized(checkSignal) { + checkSignal.triggered = true; + checkSignal.notifyAll(); + } } - public abstract ResourceStore getStore(); - public File getRepository() { - return repository; + public void waitForNotification() throws Exception { + synchronized(notificationSignal) { + notificationSignal.triggered = false; + } + log.debug("waiting for reload signal"); + if (!waitForSignal(notificationSignal, 10)) { + throw new Exception("timeout"); + } + } + + /* + * we don't reset the signal + * so if there was a check it is + * already true and exit immediatly + * otherwise it will behave just + * like waitForCheck() + */ + public void waitForFirstCheck() throws Exception { + log.debug("waiting for first signal"); + if (!waitForSignal(checkSignal, 10)) { + throw new Exception("timeout"); + } } - protected void needsReload( final boolean pReload ) { - reloader.reload(pReload); + public void waitForCheck() throws Exception { + synchronized(checkSignal) { + checkSignal.triggered = false; + } + log.debug("waiting for check signal"); + if (!waitForSignal(checkSignal, 10)) { + throw new Exception("timeout"); + } + } + + private boolean waitForSignal(final Signal pSignal, final int pSecondsTimeout) { + int i = 0; + while(true) { + synchronized(pSignal) { + //log.debug("loop"); + if (!pSignal.triggered) { + try { + //log.debug("waiting"); + pSignal.wait(1000); + } catch (InterruptedException e) { + ; + } + if (++i > pSecondsTimeout) { + log.error("timeout after " + pSecondsTimeout + "s"); + return false; + } + } else { + pSignal.triggered = false; + break; + } + } + } + + log.debug("caught signal"); + return true; } + } Modified: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/ReloadingListener.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/ReloadingListener.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/ReloadingListener.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/ReloadingListener.java Sat Sep 24 04:53:44 2005 @@ -28,15 +28,17 @@ import org.apache.commons.logging.LogFactory; -public class ReloadingListener extends AbstractListener{ +public class ReloadingListener extends ResourceStoringListener { private final static Log log = LogFactory.getLog(ReloadingListener.class); - private final Collection created = new ArrayList(); - private final Collection changed = new ArrayList(); - private final Collection deleted = new ArrayList(); + protected final Collection created = new ArrayList(); + protected final Collection changed = new ArrayList(); + protected final Collection deleted = new ArrayList(); private final ResourceStore store; + + protected ReloadingClassLoader reloader; public ReloadingListener(final File pRepository) { this(pRepository, new MemoryResourceStore()); @@ -46,27 +48,32 @@ super(pRepository); store = pStore; } - + public ResourceStore getStore() { return store; } - + public void onStart() { created.clear(); changed.clear(); deleted.clear(); } + public void onStop() { boolean reload = false; log.debug("created:" + created.size() - + " changed:" + changed.size() - + " deleted:" + deleted.size()); + + " changed:" + changed.size() + + " deleted:" + deleted.size() + + " resources"); if (deleted.size() > 0) { for (Iterator it = deleted.iterator(); it.hasNext();) { final File file = (File) it.next(); - store.remove(ReloadingClassLoader.clazzName(repository, file)); + final String resourceName = ReloadingClassLoader.clazzName(repository, file); + //if (resourceName.endsWith(".class")) { + store.remove(resourceName); + //} } reload = true; } @@ -76,7 +83,10 @@ final File file = (File) it.next(); try { final byte[] bytes = IOUtils.toByteArray(new FileReader(file)); - store.write(ReloadingClassLoader.clazzName(repository, file), bytes); + final String resourceName = ReloadingClassLoader.clazzName(repository, file); + //if (resourceName.endsWith(".class")) { + store.write(resourceName, bytes); + //} } catch(final Exception e) { log.error("could not load " + file, e); } @@ -90,7 +100,10 @@ final File file = (File) it.next(); try { final byte[] bytes = IOUtils.toByteArray(new FileReader(file)); - store.write(ReloadingClassLoader.clazzName(repository, file), bytes); + final String resourceName = ReloadingClassLoader.clazzName(repository, file); + //if (resourceName.endsWith(".class")) { + store.write(resourceName, bytes); + //} } catch(final Exception e) { log.error("could not load " + file, e); } @@ -98,26 +111,17 @@ reload = true; } - needsReload(reload); + checked(reload); } public void onCreateFile( final File file ) { - // FIXME: for resource reloading remove the filtering - if (file.getName().endsWith(".class")) { - created.add(file); - } + created.add(file); } public void onChangeFile( final File file ) { - // FIXME: for resource reloading remove the filtering - if (file.getName().endsWith(".class")) { - changed.add(file); - } + changed.add(file); } public void onDeleteFile( final File file ) { - // FIXME: for resource reloading remove the filtering - if (file.getName().endsWith(".class")) { - deleted.add(file); - } + deleted.add(file); } public void onCreateDirectory( final File file ) { @@ -126,5 +130,4 @@ } public void onDeleteDirectory( final File file ) { } - } Added: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/ResourceStoringListener.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/ResourceStoringListener.java?rev=291284&view=auto ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/ResourceStoringListener.java (added) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/listeners/ResourceStoringListener.java Sat Sep 24 04:53:44 2005 @@ -0,0 +1,14 @@ +package org.apache.commons.jci.listeners; + +import java.io.File; +import org.apache.commons.jci.stores.ResourceStore; + + +public abstract class ResourceStoringListener extends NotifyingListener { + + public ResourceStoringListener(final File pRepository) { + super(pRepository); + } + + public abstract ResourceStore getStore(); +} Modified: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationListener.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationListener.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationListener.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationListener.java Sat Sep 24 04:53:44 2005 @@ -22,7 +22,7 @@ * */ public interface FilesystemAlterationListener { - File getRepository(); + File getRepository(); // FIXME: ugly!!!! void onStart(); void onCreateFile( final File file ); void onChangeFile( final File file ); Modified: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationMonitor.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationMonitor.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationMonitor.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationMonitor.java Sat Sep 24 04:53:44 2005 @@ -129,8 +129,27 @@ } } - private Map listeners = new MultiHashMap(); - private Map directories = new MultiHashMap(); + public static class UniqueMultiHashMap extends MultiHashMap { + + public UniqueMultiHashMap() { + super(); + } + + public UniqueMultiHashMap(Map copy) { + super(copy); + } + + protected Collection createCollection( Collection copy ) { + if (copy != null) { + return new HashSet(copy); + } + return new HashSet(); + } + + } + + private Map listeners = new UniqueMultiHashMap(); + private Map directories = new UniqueMultiHashMap(); private Map entries = new HashMap(); private final Object mutexListeners = new Object(); private final Object mutexRunning = new Object(); @@ -169,26 +188,37 @@ final File directory = pListener.getRepository(); synchronized (mutexListeners) { // listerner -> dir1, dir2, dir3 - final MultiHashMap newListeners = new MultiHashMap(listeners); + final UniqueMultiHashMap newListeners = new UniqueMultiHashMap(listeners); newListeners.put(pListener, directory); listeners = newListeners; // directory -> listener1, listener2, listener3 - final MultiHashMap newDirectories = new MultiHashMap(directories); + final UniqueMultiHashMap newDirectories = new UniqueMultiHashMap(directories); newDirectories.put(directory, pListener); directories = newDirectories; } } + public Collection getListeners() { + synchronized (mutexListeners) { + return listeners.keySet(); + } + } + + public Collection getListenersFor( final File pRepository ) { + synchronized (mutexListeners) { + return (Collection) directories.get(pRepository); + } + } public void removeListener( final FilesystemAlterationListener listener ) { synchronized (mutexListeners) { // listerner -> dir1, dir2, dir3 - final MultiHashMap newListeners = new MultiHashMap(listeners); + final UniqueMultiHashMap newListeners = new UniqueMultiHashMap(listeners); Collection d = (Collection) newListeners.remove(listener); listeners = newListeners; if (d != null) { // directory -> listener1, listener2, listener3 - final MultiHashMap newDirectories = new MultiHashMap(directories); + final UniqueMultiHashMap newDirectories = new UniqueMultiHashMap(directories); for (Iterator it = d.iterator(); it.hasNext();) { newDirectories.remove(it.next()); entries.remove(d); @@ -393,4 +423,12 @@ } log.info("fam exiting"); } + + + + public String toString() { + return listeners.toString() + directories.toString(); + } + + } Modified: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/FileResourceStore.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/FileResourceStore.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/FileResourceStore.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/FileResourceStore.java Sat Sep 24 04:53:44 2005 @@ -87,5 +87,10 @@ final String fileName = pResourceName.replace('.', File.separatorChar) + ".class"; return new File(root, fileName); } + + public String toString() { + return this.getClass().getName() + root.toString(); + } + } Modified: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/MemoryResourceStore.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/MemoryResourceStore.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/MemoryResourceStore.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/MemoryResourceStore.java Sat Sep 24 04:53:44 2005 @@ -47,6 +47,6 @@ } public String toString() { - return store.keySet().toString(); + return this.getClass().getName() + store.toString(); } } Added: jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/ResourceStoreClassLoader.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/ResourceStoreClassLoader.java?rev=291284&view=auto ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/ResourceStoreClassLoader.java (added) +++ jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/stores/ResourceStoreClassLoader.java Sat Sep 24 04:53:44 2005 @@ -0,0 +1,93 @@ +/* + * Copyright 1999-2004 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.jci.stores; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + + +/** + * @author tcurdt + * + */ +public final class ResourceStoreClassLoader extends ClassLoader { + + private final static Log log = LogFactory.getLog(ResourceStoreClassLoader.class); + + private final ResourceStore[] stores; + private final ClassLoader parent; + + public ResourceStoreClassLoader( final ClassLoader pParent, final ResourceStore[] pStores ) { + super(pParent); + parent = pParent; + stores = pStores; + } + + private Class fastFindClass(final String name) { + + if (stores != null) { + for (int i = 0; i < stores.length; i++) { + final ResourceStore store = stores[i]; + final byte[] clazzBytes = store.read(name); + if (clazzBytes != null) { + log.debug("found class " + name + " (" + clazzBytes.length + " bytes)"); + return defineClass(name, clazzBytes, 0, clazzBytes.length); + } + } + } + + log.debug("did not find class " + name); + + return null; + } + + protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + log.debug("looking for " + name); + Class clazz = findLoadedClass(name); + + if (clazz == null) { + clazz = fastFindClass(name); + + if (clazz == null) { + + final ClassLoader parent = getParent(); + if (parent != null) { + clazz = parent.loadClass(name); + log.debug("loaded from parent: " + name); + } else { + throw new ClassNotFoundException(name); + } + + } else { + log.debug("loaded from store: " + name); + } + } + + if (resolve) { + resolveClass(clazz); + } + + return clazz; + } + + protected Class findClass( final String name ) throws ClassNotFoundException { + final Class clazz = fastFindClass(name); + if (clazz == null) { + throw new ClassNotFoundException(name); + } + return clazz; + } +} Modified: jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/AbstractTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/AbstractTestCase.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/AbstractTestCase.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/AbstractTestCase.java Sat Sep 24 04:53:44 2005 @@ -32,10 +32,6 @@ protected File directory; - public final class Signal { - public boolean triggered; - } - /* public void runBare() throws Throwable { try { @@ -47,33 +43,6 @@ } */ - protected void waitForSignal(final Signal pSignal) { - log.debug("waiting for signal"); - int i = 0; - while(true) { - synchronized(pSignal) { - if (!pSignal.triggered) { - try { - pSignal.wait(1000); - } catch (InterruptedException e) { - ; - } - if (++i > 7) { - log.error("timeout"); - fail("timeout"); - } - } else { - pSignal.triggered = false; - break; - } - } - } - - log.debug("caught signal"); - } - - - protected void setUp() throws Exception { directory = createTempDirectory(); assertTrue(directory.exists()); @@ -118,6 +87,7 @@ throw new IOException("could not create" + parent); } } + log.debug("writing " + file); final FileWriter writer = new FileWriter(file); writer.write(pText); writer.close(); Modified: jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/CompilingClassLoaderTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/CompilingClassLoaderTestCase.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/CompilingClassLoaderTestCase.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/CompilingClassLoaderTestCase.java Sat Sep 24 04:53:44 2005 @@ -14,8 +14,6 @@ private final static Log log = LogFactory.getLog(CompilingClassLoaderTestCase.class); - private final Signal reloadSignal = new Signal(); - private ReloadingClassLoader classloader; private CompilingListener listener; private FilesystemAlterationMonitor fam; @@ -24,17 +22,7 @@ super.setUp(); classloader = new ReloadingClassLoader(this.getClass().getClassLoader()); - listener = new CompilingListener(directory) { - protected void needsReload(final boolean pReload) { - super.needsReload(pReload); - if (pReload) { - synchronized(reloadSignal) { - reloadSignal.triggered = true; - reloadSignal.notify(); - } - } - } - }; + listener = new CompilingListener(directory); classloader.addListener(listener); fam = new FilesystemAlterationMonitor(); @@ -46,14 +34,14 @@ delay(); writeFile("jci/Simple.java", JavaSources.simple); writeFile("jci/Extended.java", JavaSources.extended); - waitForSignal(reloadSignal); + listener.waitForNotification(); } public void testCompileProblems() throws Exception { delay(); writeFile("jci/Simple.java", JavaSources.error); - waitForSignal(reloadSignal); + listener.waitForNotification(); // FIXME } @@ -79,7 +67,7 @@ delay(); writeFile("jci/Simple.java", JavaSources.SIMPLE); - waitForSignal(reloadSignal); + listener.waitForNotification(); final Object SIMPLE = classloader.loadClass("jci.Simple").newInstance(); assertTrue("SIMPLE".equals(SIMPLE.toString())); @@ -99,7 +87,7 @@ delay(); assertTrue(new File(directory, "jci/Extended.java").delete()); - waitForSignal(reloadSignal); + listener.waitForNotification(); final Object oldSimple = classloader.loadClass("jci.Simple").newInstance(); assertTrue("Simple".equals(oldSimple.toString())); @@ -113,7 +101,7 @@ delay(); FileUtils.deleteDirectory(new File(directory, "jci")); - waitForSignal(reloadSignal); + listener.waitForNotification(); try { classloader.loadClass("jci.Simple").newInstance(); @@ -135,7 +123,7 @@ delay(); assertTrue(new File(directory, "jci/Simple.java").delete()); - waitForSignal(reloadSignal); + listener.waitForNotification(); try { classloader.loadClass("jci.Extended").newInstance(); Modified: jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/ReloadingClassLoaderTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/ReloadingClassLoaderTestCase.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/ReloadingClassLoaderTestCase.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/ReloadingClassLoaderTestCase.java Sat Sep 24 04:53:44 2005 @@ -27,9 +27,6 @@ private final static Log log = LogFactory.getLog(ReloadingClassLoaderTestCase.class); - private final Signal reloadSignal = new Signal(); - private final Signal checkedSignal = new Signal(); - private ReloadingClassLoader classloader; private ReloadingListener listener; private FilesystemAlterationMonitor fam; @@ -54,22 +51,9 @@ super.setUp(); classloader = new ReloadingClassLoader(this.getClass().getClassLoader()); - listener = new ReloadingListener(directory) { - protected void needsReload(final boolean pReload) { - super.needsReload(pReload); - if (pReload) { - synchronized(reloadSignal) { - reloadSignal.triggered = true; - reloadSignal.notify(); - } - } else { - synchronized(checkedSignal) { - checkedSignal.triggered = true; - checkedSignal.notify(); - } - } - } - }; + listener = new ReloadingListener(directory); + + // listener.addListener(classloader); classloader.addListener(listener); fam = new FilesystemAlterationMonitor(); @@ -78,26 +62,26 @@ } public void testCreate() throws Exception { - waitForSignal(checkedSignal); + listener.waitForCheck(); log.debug("creating class"); delay(); writeFile("jci/Simple.class", clazzSimple); - waitForSignal(checkedSignal); + listener.waitForCheck(); final Object simple = classloader.loadClass("jci.Simple").newInstance(); assertTrue("Simple".equals(simple.toString())); } public void testChange() throws Exception { - waitForSignal(checkedSignal); + listener.waitForCheck(); log.debug("creating class"); delay(); writeFile("jci/Simple.class", clazzSimple); - waitForSignal(checkedSignal); + listener.waitForCheck(); final Object simple = classloader.loadClass("jci.Simple").newInstance(); assertTrue("Simple".equals(simple.toString())); @@ -106,20 +90,20 @@ delay(); writeFile("jci/Simple.class", clazzSIMPLE); - waitForSignal(reloadSignal); + listener.waitForNotification(); final Object SIMPLE = classloader.loadClass("jci.Simple").newInstance(); assertTrue("SIMPLE".equals(SIMPLE.toString())); } public void testDelete() throws Exception { - waitForSignal(checkedSignal); + listener.waitForCheck(); log.debug("creating class"); delay(); writeFile("jci/Simple.class", clazzSimple); - waitForSignal(checkedSignal); + listener.waitForCheck(); final Object simple = classloader.loadClass("jci.Simple").newInstance(); assertTrue("Simple".equals(simple.toString())); @@ -128,7 +112,7 @@ assertTrue(new File(directory, "jci/Simple.class").delete()); - waitForSignal(reloadSignal); + listener.waitForNotification(); try { classloader.loadClass("jci.Simple").newInstance(); @@ -139,14 +123,14 @@ } public void testDeleteDependency() throws Exception { - waitForSignal(checkedSignal); + listener.waitForCheck(); log.debug("creating classes"); delay(); writeFile("jci/Simple.class", clazzSimple); writeFile("jci/Extended.class", clazzExtended); - waitForSignal(checkedSignal); + listener.waitForCheck(); final Object simple = classloader.loadClass("jci.Simple").newInstance(); assertTrue("Simple".equals(simple.toString())); @@ -158,7 +142,7 @@ assertTrue(new File(directory, "jci/Simple.class").delete()); - waitForSignal(reloadSignal); + listener.waitForNotification(); try { classloader.loadClass("jci.Extended").newInstance(); Modified: jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/compilers/GroovySources.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/compilers/GroovySources.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/compilers/GroovySources.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/compilers/GroovySources.java Sat Sep 24 04:53:44 2005 @@ -40,7 +40,7 @@ String error = "package jci;\n" - + "public class Simple { \n" + + "public clss Simple { \n" + " public String toString() { \n" + " return 1; \n" + " } \n" Modified: jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/monitor/FilesystemAlterationMonitorTestCase.java URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/monitor/FilesystemAlterationMonitorTestCase.java?rev=291284&r1=291283&r2=291284&view=diff ============================================================================== --- jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/monitor/FilesystemAlterationMonitorTestCase.java (original) +++ jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/monitor/FilesystemAlterationMonitorTestCase.java Sat Sep 24 04:53:44 2005 @@ -18,7 +18,7 @@ import java.io.File; import org.apache.commons.io.FileUtils; import org.apache.commons.jci.AbstractTestCase; -import org.apache.commons.jci.listeners.AbstractListener; +import org.apache.commons.jci.listeners.NotifyingListener; import org.apache.commons.jci.stores.ResourceStore; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -29,12 +29,10 @@ private final static Log log = LogFactory.getLog(FilesystemAlterationMonitorTestCase.class); - private final Signal signal = new Signal(); - private FilesystemAlterationMonitor fam; private MyFilesystemAlterationListener listener; - private class MyFilesystemAlterationListener extends AbstractListener { + private class MyFilesystemAlterationListener extends NotifyingListener { private int started; private int stopped; private int createdFiles; @@ -43,6 +41,7 @@ private int createdDirs; private int changedDirs; private int deletedDirs; + private boolean changed; public MyFilesystemAlterationListener(final File pRepository) { super(pRepository); @@ -52,10 +51,6 @@ return null; } - protected void needsReload( boolean pReload ) { - // prevent NPE - } - public int getChangedDirs() { return changedDirs; } @@ -82,47 +77,93 @@ } public void onStart() { + changed = false; ++started; + log.debug("onStart"); } public void onStop() { ++stopped; - synchronized(signal) { - signal.triggered = true; - signal.notify(); - } + log.debug("onStop"); + + checked(changed); } public void onCreateFile( final File file ) { ++createdFiles; + changed = true; + log.debug("onCreateFile " + file); } public void onChangeFile( final File file ) { ++changedFiles; + changed = true; + log.debug("onChangeFile " + file); } public void onDeleteFile( final File file ) { ++deletedFiles; + changed = true; + log.debug("onDeleteFile " + file); } public void onCreateDirectory( final File file ) { ++createdDirs; + changed = true; + log.debug("onCreateDirectory " + file); } public void onChangeDirectory( final File file ) { ++changedDirs; + changed = true; + log.debug("onChangeDirectory " + file); } public void onDeleteDirectory( final File file ) { ++deletedDirs; - } + changed = true; + log.debug("onDeleteDirectory " + file); + } } - private void start() { + private void start() throws Exception { fam = new FilesystemAlterationMonitor(); listener = new MyFilesystemAlterationListener(directory); fam.addListener(listener); fam.start(); - waitForSignal(signal); + listener.waitForFirstCheck(); } private void stop() { fam.stop(); } + public void testListenerDoublication() throws Exception { + fam = new FilesystemAlterationMonitor(); + listener = new MyFilesystemAlterationListener(directory); + + fam.addListener(listener); + log.debug(fam); + assertTrue(fam.getListeners().size() == 1); + + fam.addListener(listener); + log.debug(fam); + assertTrue(fam.getListeners().size() == 1); + } + + public void testDirectoryDoublication() throws Exception { + fam = new FilesystemAlterationMonitor(); + + fam.addListener(new MyFilesystemAlterationListener(directory)); + log.debug(fam); + assertTrue(fam.getListenersFor(directory).size() == 1); + + fam.addListener(new MyFilesystemAlterationListener(directory)); + log.debug(fam); + assertTrue(fam.getListenersFor(directory).size() == 2); + } + + public void testListener() throws Exception { + start(); + log.debug(fam); + fam.removeListener(listener); + log.debug(fam); + stop(); + } + public void testCreateFileDetection() throws Exception { start(); @@ -130,7 +171,7 @@ writeFile("file", "file"); - waitForSignal(signal); + listener.waitForNotification(); assertTrue(listener.createdFiles == 1); @@ -144,7 +185,7 @@ createDirectory("dir"); - waitForSignal(signal); + listener.waitForNotification(); assertTrue(listener.createdDirs == 1); @@ -158,14 +199,14 @@ final File file = writeFile("file", "file"); - waitForSignal(signal); + listener.waitForNotification(); assertTrue(listener.createdFiles == 1); file.delete(); assertTrue(!file.exists()); - waitForSignal(signal); + listener.waitForNotification(); assertTrue(listener.deletedFiles == 1); @@ -180,18 +221,16 @@ final File dir = createDirectory("dir"); createDirectory("dir/sub"); - waitForSignal(signal); + listener.waitForNotification(); assertTrue(listener.createdDirs == 2); - waitForSignal(signal); - delay(); FileUtils.deleteDirectory(dir); assertTrue(!dir.exists()); - waitForSignal(signal); + listener.waitForNotification(); assertTrue(listener.deletedDirs == 2); @@ -205,15 +244,15 @@ writeFile("file", "file"); - waitForSignal(signal); + listener.waitForNotification(); assertTrue(listener.createdFiles == 1); - waitForSignal(signal); + delay(); writeFile("file", "changed file"); - waitForSignal(signal); + listener.waitForNotification(); assertTrue(listener.changedFiles == 1); @@ -266,14 +305,7 @@ public void testInterval() throws Exception { start(); - fam.setInterval(1000); + fam.setInterval(100); stop(); - } - - public void testListener() throws Exception { - start(); - fam.removeListener(listener); - stop(); - } - + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]