You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by tc...@apache.org on 2005/08/11 01:33:48 UTC

svn commit: r231354 - in /jakarta/commons/sandbox/jci/trunk/src: java/org/apache/commons/jci/ReloadingClassLoader.java java/org/apache/commons/jci/monitor/FilesystemAlterationMonitor.java test/org/apache/commons/jci/CompilingClassLoaderTestCase.java

Author: tcurdt
Date: Wed Aug 10 16:33:40 2005
New Revision: 231354

URL: http://svn.apache.org/viewcvs?rev=231354&view=rev
Log:
make the reloading classloader stoppable,
properly test the compiling classloader

Modified:
    jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/ReloadingClassLoader.java
    jakarta/commons/sandbox/jci/trunk/src/java/org/apache/commons/jci/monitor/FilesystemAlterationMonitor.java
    jakarta/commons/sandbox/jci/trunk/src/test/org/apache/commons/jci/CompilingClassLoaderTestCase.java

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=231354&r1=231353&r2=231354&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 Wed Aug 10 16:33:40 2005
@@ -45,8 +45,8 @@
     private final ClassLoader parent;
     private final ResourceStore store;
     private final FilesystemAlterationMonitor fam;
-    private final Thread thread;
     private final Collection reloadingListeners = new HashSet();
+    private Thread thread;
     private ClassLoader delegate;
 
     protected final ResourceReader reader;
@@ -68,16 +68,23 @@
         fam = new FilesystemAlterationMonitor(); 
         fam.addListener(createListener(repository), repository);
 
-        thread = new Thread(fam); 
-        
         delegate = new ResourceStoreClassLoader(parent, store);
     }
     
     public void start() {
+        thread = new Thread(fam);         
         thread.start();
         reload();        
     }
 
+    public void stop() {
+        fam.stop();
+        try {
+            thread.join();
+        } catch (InterruptedException e) {
+            ;
+        }
+    }
     protected FilesystemAlterationListener createListener(final File pRepository) {
         return new FilesystemAlterationListener() {
 

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=231354&r1=231353&r2=231354&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 Wed Aug 10 16:33:40 2005
@@ -53,7 +53,8 @@
 
 
         public boolean hasChanged() {
-            return file.lastModified() != lastModified;
+            final long modified = file.lastModified();
+            return modified != lastModified;
         }
 
 
@@ -143,16 +144,19 @@
     private Map directories = new MultiHashMap();
     private Map entries = new HashMap();
 
-    private final Object mutex = new Object();
+    private final Object mutexListeners = new Object();
+    private final Object mutexRunning = new Object();
     
     private long delay = 3000;
-    private volatile boolean running = true;
+    private boolean running = true;
     
     public FilesystemAlterationMonitor() {
     }
 
     public void stop() {
-        running = false;
+        synchronized(mutexRunning) {
+            running = false;
+        }
     }
     
     public void setInterval( final long pDelay ) {
@@ -161,7 +165,7 @@
 
 
     public void addListener( final FilesystemAlterationListener listener, final File directory ) {
-        synchronized (mutex) {
+        synchronized (mutexListeners) {
             // listerner -> dir1, dir2, dir3
 
             final MultiHashMap newListeners = new MultiHashMap(listeners);
@@ -177,7 +181,7 @@
 
 
     public void removeListener( final FilesystemAlterationListener listener ) {
-        synchronized (mutex) {
+        synchronized (mutexListeners) {
             // listerner -> dir1, dir2, dir3
             final MultiHashMap newListeners = new MultiHashMap(listeners);
             Collection d = (Collection) newListeners.remove(listener);
@@ -199,7 +203,7 @@
         log.debug("start checking " + root);
 
         Map directories;
-        synchronized(mutex) {
+        synchronized(mutexListeners) {
             directories = this.directories;
         }
         final Collection l = (Collection) directories.get(root);
@@ -216,7 +220,7 @@
         log.debug("stop checking " + root);
                 
         Map directories;
-        synchronized(mutex) {
+        synchronized(mutexListeners) {
             directories = this.directories;
         }
         final Collection l = (Collection) directories.get(root);
@@ -234,7 +238,7 @@
         log.debug("created " + ((entry.isDirectory())?"dir ":"file ") + entry);
         
         Map directories;
-        synchronized(mutex) {
+        synchronized(mutexListeners) {
             directories = this.directories;
         }
 
@@ -262,7 +266,7 @@
         log.debug("changed " + ((entry.isDirectory())?"dir ":"file ") + entry);
         
         Map directories;
-        synchronized(mutex) {
+        synchronized(mutexListeners) {
             directories = this.directories;
         }
 
@@ -290,7 +294,7 @@
         log.debug("deleted " + ((entry.isDirectory())?"dir ":"file ") + entry);
         
         Map directories;
-        synchronized(mutex) {
+        synchronized(mutexListeners) {
             directories = this.directories;
         }
 
@@ -314,6 +318,8 @@
 
 
     private void check( final File root, final Entry entry, final boolean create ) {
+        log.debug("checking " + entry);
+        
         if (entry.isDirectory()) {
             final Entry[] currentChilds = entry.getChilds();
             if (entry.hasChanged() || create) {
@@ -362,10 +368,18 @@
 
     public void run() {
         log.info("fam running");
-        while (running) {
+        
+        while (true) {
+            
+            synchronized(mutexRunning) {
+                if (!running) {
+                    break;
+                }
+            }
+            
             Map directories;
             
-            synchronized (mutex) {
+            synchronized (mutexListeners) {
                 directories = this.directories;
             }
 
@@ -375,7 +389,7 @@
                     onStart(directory);
                     
                     Entry root;
-                    synchronized (mutex) {
+                    synchronized (mutexListeners) {
                         root = (Entry)entries.get(directory);
                         if (root == null) {
                             root = new Entry(directory, directory);
@@ -393,6 +407,7 @@
             } catch (InterruptedException e) {
             }
         }
+        
         log.info("fam exiting");
     }
 }

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=231354&r1=231353&r2=231354&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 Wed Aug 10 16:33:40 2005
@@ -3,66 +3,94 @@
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import junit.framework.TestCase;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import junit.framework.TestCase;
 
 
 public final class CompilingClassLoaderTestCase extends TestCase {
 
     private final static Log log = LogFactory.getLog(CompilingClassLoaderTestCase.class);
     
+    private final Object signal = new Object();
+
     private CompilingClassLoader cl;
     private ReloadingListener listener;
     private File repository;
-    private boolean reloaded; //FIXME
     
-    protected void setUp() throws Exception {
+    private boolean reloaded;
+    private void waitForReload() {
+        log.debug("waiting for reload signal");
+        int i = 0;
+        while(true) {
+            synchronized(signal) {
+                if (!reloaded) {
+                    try {
+                        signal.wait(1000);
+                    } catch (InterruptedException e) {
+                        ;
+                    }
+                    if (++i > 7) {
+                        fail("timeout");
+                    }
+                } else {
+                    reloaded = false;
+                    break;
+                }
+            }
+        }
         
-        repository = createTempDirectory();
+        log.debug("caught reload signal");
+    }
+    
+    protected void setUp() throws Exception {
+         repository = createTempDirectory();
         assertTrue(repository.exists());
         assertTrue(repository.isDirectory());
 
         listener = new ReloadingListener() {
             public void reload() {
-                log.debug("notifying about the reload");
-                reloaded = true; //FIXME
+                synchronized(signal) {
+                    reloaded = true;
+                    signal.notify();
+                }
             }
         };
 
         cl = new CompilingClassLoader(this.getClass().getClassLoader(), repository);
         cl.addListener(listener);
         cl.start();
-        
-        Thread.sleep(1000);
-
-        reloaded = false;
     }
-    
-    public void testCreateCompilation() throws Exception {
 
-        log.debug("creating java files");
-        
+    private void initialCompile() throws Exception {
+
+        waitForReload();
+
         writeFile(new File(repository, "jci/Simple.java"),
-                  "package jci;\n"
+                "package jci;\n"
                 + "public class Simple { \n"
                 + "  public String toString() { \n"
                 + "    return \"Simple\"; \n"
                 + "  } \n"
                 + "} \n"
-                );
-
+        );
+        
         writeFile(new File(repository, "jci/Extended.java"),
                 "package jci;\n"
-              + "public class Extended extends Simple { \n"
-              + "  public String toString() { \n"
-              + "    return \"Extended:\" + super.toString(); \n"
-              + "  } \n"
-              + "} \n"
-              );
+                + "public class Extended extends Simple { \n"
+                + "  public String toString() { \n"
+                + "    return \"Extended:\" + super.toString(); \n"
+                + "  } \n"
+                + "} \n"
+        );
         
-        Thread.sleep(4000);
+        waitForReload();
+    }
+    
+    
+    public void testCreate() throws Exception {
+        initialCompile();
         
         Object o;
         
@@ -73,14 +101,88 @@
         assertTrue("Extended:Simple".equals(o.toString()));
     }
 
-    public void testChangeCompilation() {        
+    public void testChange() throws Exception {        
+        initialCompile();
+
+        Object o;
+        
+        o = cl.loadClass("jci.Simple").newInstance();        
+        assertTrue("Simple".equals(o.toString()));
+        
+        o = cl.loadClass("jci.Extended").newInstance();        
+        assertTrue("Extended:Simple".equals(o.toString()));
+
+        writeFile(new File(repository, "jci/Simple.java"),
+                "package jci;\n"
+                + "public class Simple { \n"
+                + "  public String toString() { \n"
+                + "    return \"SIMPLE\"; \n"
+                + "  } \n"
+                + "} \n"
+        );
+
+        waitForReload();
+    
+        o = cl.loadClass("jci.Simple").newInstance();        
+        assertTrue("SIMPLE".equals(o.toString()));
+        
+        o = cl.loadClass("jci.Extended").newInstance();        
+        assertTrue("Extended:SIMPLE".equals(o.toString()));
     }
 
-    public void testDeleteCompilation() {        
+    public void testDelete() throws Exception {
+        initialCompile();
+
+        Object o;
+        
+        o = cl.loadClass("jci.Simple").newInstance();        
+        assertTrue("Simple".equals(o.toString()));
+        
+        o = cl.loadClass("jci.Extended").newInstance();        
+        assertTrue("Extended:Simple".equals(o.toString()));
+        
+        assertTrue(new File(repository, "jci/Extended.java").delete());
+        
+        waitForReload();
+
+        o = cl.loadClass("jci.Simple").newInstance();        
+        assertTrue("Simple".equals(o.toString()));
+
+        try {
+            o = cl.loadClass("jci.Extended").newInstance();
+            fail();
+        } catch(final ClassNotFoundException e) {
+            assertTrue("jci.Extended".equals(e.getMessage()));
+        }
+        
     }
 
+    public void testDeleteDependency() throws Exception {        
+        initialCompile();
+
+        Object o;
+        
+        o = cl.loadClass("jci.Simple").newInstance();        
+        assertTrue("Simple".equals(o.toString()));
+        
+        o = cl.loadClass("jci.Extended").newInstance();        
+        assertTrue("Extended:Simple".equals(o.toString()));
+        
+        assertTrue(new File(repository, "jci/Simple.java").delete());
+        
+        waitForReload();
+
+        try {
+            o = cl.loadClass("jci.Extended").newInstance();
+            fail();
+        } catch(final NoClassDefFoundError e) {
+            assertTrue("jci/Simple".equals(e.getMessage()));
+        }
+        
+    }
     
     protected void tearDown() throws Exception {
+        cl.stop();
         FileUtils.deleteDirectory(repository);
     }
     
@@ -91,10 +193,13 @@
             if (!parent.mkdirs()) {
                 throw new IOException("could not create" + parent);
             }
+            log.debug("created directory " + parent.getAbsolutePath());
         }
         final FileWriter writer = new FileWriter(pFile);
         writer.write(pText);
         writer.close();
+        
+        assertTrue(pFile.exists());
     }
     
     private static File createTempDirectory() throws IOException {



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org