[jboss-svn-commits] JBoss Common SVN: r4708 - in shrinkwrap/trunk/extension-classloader/src: test/java/org/jboss/shrinkwrap/classloader and 1 other directory.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Jul 9 01:02:22 EDT 2010


Author: ALRubinger
Date: 2010-07-09 01:02:21 -0400 (Fri, 09 Jul 2010)
New Revision: 4708

Modified:
   shrinkwrap/trunk/extension-classloader/src/main/java/org/jboss/shrinkwrap/classloader/ShrinkWrapClassLoader.java
   shrinkwrap/trunk/extension-classloader/src/test/java/org/jboss/shrinkwrap/classloader/ShrinkWrapClassLoaderTestCase.java
Log:
[SHRINKWRAP-161] Bug fixes, test fixes, documentation for ShrinkWrapClassLoader.  Still has pending TODOs before resolution.

Modified: shrinkwrap/trunk/extension-classloader/src/main/java/org/jboss/shrinkwrap/classloader/ShrinkWrapClassLoader.java
===================================================================
--- shrinkwrap/trunk/extension-classloader/src/main/java/org/jboss/shrinkwrap/classloader/ShrinkWrapClassLoader.java	2010-07-08 22:35:20 UTC (rev 4707)
+++ shrinkwrap/trunk/extension-classloader/src/main/java/org/jboss/shrinkwrap/classloader/ShrinkWrapClassLoader.java	2010-07-09 05:02:21 UTC (rev 4708)
@@ -26,6 +26,7 @@
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
+import java.util.logging.Logger;
 
 import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.vfs3.ArchiveFileSystem;
@@ -38,15 +39,40 @@
  * Extension that will create a ClassLoader based on a Array of Archives
  *
  * @author <a href="mailto:aslak at redhat.com">Aslak Knutsen</a>
- * @version $Revision: $
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  */
 public class ShrinkWrapClassLoader extends URLClassLoader implements Closeable
 {
-   private Set<Closeable> vfsHandlers = new HashSet<Closeable>();
-   
-   private Set<ExecutorService> executorServices = new HashSet<ExecutorService>();
-   
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
    /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(ShrinkWrapClassLoader.class.getName());
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * All open VFS handles to close when {@link ShrinkWrapClassLoader#close()}
+    * is invoked
+    */
+   private Set<Closeable> vfsHandlesToClose = new HashSet<Closeable>();
+
+   /**
+    * {@link ExecutorService}s to shutdown when {@link ShrinkWrapClassLoader#close()}
+    * is invoked
+    */
+   private Set<ExecutorService> executorServicesToShutdown = new HashSet<ExecutorService>();
+
+   //-------------------------------------------------------------------------------------||
+   // Constructors -----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
     * Constructs a new ShrinkWrapClassLoader for the specified {@link Archive}s using the
     * default delegation parent <code>ClassLoader</code>. The {@link Archive}s will
     * be searched in the order specified for classes and resources after
@@ -56,15 +82,16 @@
     */
    public ShrinkWrapClassLoader(final Archive<?>... archives)
    {
-      super(new URL[]{});
-      
-      if(archives == null) 
+      super(new URL[]
+      {});
+
+      if (archives == null)
       {
-         throw new IllegalArgumentException("Archives must be specified");   
+         throw new IllegalArgumentException("Archives must be specified");
       }
       addArchives(archives);
    }
-   
+
    /**
     * Constructs a new ShrinkWrapClassLoader for the given {@link Archive}s. The {@link Archive}s will be
     * searched in the order specified for classes and resources after first
@@ -73,81 +100,83 @@
     * @param parent the parent class loader for delegation
     * @param archives the {@link Archive}s from which to load classes and resources
     */
-   public ShrinkWrapClassLoader(ClassLoader parent, final Archive<?>... archives)
+   public ShrinkWrapClassLoader(final ClassLoader parent, final Archive<?>... archives)
    {
-      super(new URL[]{}, parent);
-      
-      if(archives == null) 
+      super(new URL[]
+      {}, parent);
+
+      if (archives == null)
       {
-         throw new IllegalArgumentException("Archives must be specified");   
+         throw new IllegalArgumentException("Archives must be specified");
       }
       addArchives(archives);
    }
-   
-   protected void addArchives(Archive<?>[] archives) 
+
+   private void addArchives(final Archive<?>[] archives)
    {
-      for(Archive<?> archive : archives)
+      for (final Archive<?> archive : archives)
       {
          addArchive(archive);
       }
    }
-   
-   protected void addArchive(Archive<?> archive) 
+
+   private void addArchive(final Archive<?> archive)
    {
       // TODO: Wrap a ExecutorService in a ScheduledExecutorService 
       //Configuration configuration = archive.as(Configurable.class).getConfiguration();
       ScheduledExecutorService executorService = null; //configuration.getExecutorService();
-      if(executorService == null)
+      if (executorService == null)
       {
          executorService = Executors.newScheduledThreadPool(2);
 
          // TODO: only add to 'managed' executor services if it was created here..
-         
+
          // add to list of resources to cleanup during close()
-         executorServices.add(executorService); 
+         executorServicesToShutdown.add(executorService);
       }
-      
+
       try
       {
-         TempFileProvider tempFileProvider = TempFileProvider.create("shrinkwrap-classloader", executorService);
-         
+         final TempFileProvider tempFileProvider = TempFileProvider.create("shrinkwrap-classloader", executorService);
+
          final TempDir tempDir = tempFileProvider.createTempDir(archive.getName());
          final VirtualFile virtualFile = VFS.getChild(UUID.randomUUID().toString()).getChild(archive.getName());
-         
-         Closeable handle = VFS.mount(virtualFile, new ArchiveFileSystem(archive, tempDir));
-         
+
+         final Closeable handle = VFS.mount(virtualFile, new ArchiveFileSystem(archive, tempDir));
+
          // add to list of resources to cleanup during close()
-         vfsHandlers.add(handle); 
-         
+         vfsHandlesToClose.add(handle);
+
          addURL(virtualFile.toURL());
-         
+
       }
-      catch (Exception e) 
+      catch (final IOException e)
       {
          throw new RuntimeException("Could not create ClassLoader from archive: " + archive.getName(), e);
       }
    }
 
-   /* (non-Javadoc)
+   /**
+    * {@inheritDoc}
     * @see java.io.Closeable#close()
     */
    public void close() throws IOException
    {
       // Unmount all VFS3 mount points
-      for(Closeable handle : vfsHandlers)
+      for (final Closeable handle : vfsHandlesToClose)
       {
          try
          {
             handle.close();
-         } 
-         catch (Exception e) 
+         }
+         catch (final IOException e)
          {
-            e.printStackTrace(); // TODO: handle exception
+            log.warning("Could not close VFS handle: " + e);
          }
       }
-      
+
       // Shutdown all created Executor Services.
-      for(ExecutorService executorService : executorServices)
+      for (final ExecutorService executorService : executorServicesToShutdown)
       {
          executorService.shutdownNow();
       }

Modified: shrinkwrap/trunk/extension-classloader/src/test/java/org/jboss/shrinkwrap/classloader/ShrinkWrapClassLoaderTestCase.java
===================================================================
--- shrinkwrap/trunk/extension-classloader/src/test/java/org/jboss/shrinkwrap/classloader/ShrinkWrapClassLoaderTestCase.java	2010-07-08 22:35:20 UTC (rev 4707)
+++ shrinkwrap/trunk/extension-classloader/src/test/java/org/jboss/shrinkwrap/classloader/ShrinkWrapClassLoaderTestCase.java	2010-07-09 05:02:21 UTC (rev 4708)
@@ -1,6 +1,6 @@
 /*
  * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
  * by the @authors tag. See the copyright.txt in the distribution for a
  * full listing of individual contributors.
  *
@@ -16,67 +16,149 @@
  */
 package org.jboss.shrinkwrap.classloader;
 
+import java.io.Closeable;
+import java.io.IOException;
 import java.net.URL;
+import java.util.logging.Logger;
 
 import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.importer.ExplodedImporter;
 import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 /**
- * ShrinkWrapClassLoaderTestCase
+ * Ensures the {@link ShrinkWrapClassLoader}
+ * is working as contracted
  *
  * @author <a href="mailto:aslak at redhat.com">Aslak Knutsen</a>
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $
  */
 public class ShrinkWrapClassLoaderTestCase
 {
 
-   private Archive<?> createArchive() 
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(ShrinkWrapClassLoaderTestCase.class.getName());
+
+   /**
+    * Class to be accessed via a ShrinkWrap ClassLoader
+    */
+   private static final Class<?> applicationClassLoaderClass = LoadedTestClass.class;
+
+   /**
+    * Archive to be read via a {@link ShrinkWrapClassLoaderTestCase#shrinkWrapClassLoader}
+    */
+   private static final JavaArchive archive = ShrinkWrap.create(JavaArchive.class)
+         .addClass(applicationClassLoaderClass);
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * ClassLoader used to load {@link ShrinkWrapClassLoaderTestCase#applicationClassLoaderClass}
+    */
+   private ClassLoader shrinkWrapClassLoader;
+
+   //-------------------------------------------------------------------------------------||
+   // Lifecycle --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Creates the {@link ShrinkWrapClassLoaderTestCase#shrinkWrapClassLoader}
+    * used to load classes from an {@link Archive}.  The {@link ClassLoader}
+    * will be isolated from the application classpath by specifying a
+    * null parent explicitly.
+    */
+   @Before
+   public void createClassLoader()
    {
-      return ShrinkWrap.create(JavaArchive.class)
-                              .as(ExplodedImporter.class)
-                              .importDirectory("target/test-classes")
-                              .as(JavaArchive.class);
+      shrinkWrapClassLoader = new ShrinkWrapClassLoader((ClassLoader) null, archive);
    }
-   
-   @Test
-   public void shouldBeAbleToLoadClassFromArchive() throws Exception
+
+   /**
+    * Closes resources associated with the 
+    * {@link ShrinkWrapClassLoaderTestCase#shrinkWrapClassLoader}
+    */
+   @After
+   public void closeClassLoader()
    {
-      ShrinkWrapClassLoader archiveClassLoader = new ShrinkWrapClassLoader((ClassLoader)null, createArchive());
-      
-      try
+      if (shrinkWrapClassLoader instanceof Closeable)
       {
-         Class<?> loadedTestClass = archiveClassLoader.loadClass(
-               "org.jboss.shrinkwrap.classloader.LoadedTestClass");
-         
-         Assert.assertNotNull(loadedTestClass);
-         
-         Assert.assertFalse(LoadedTestClass.class == loadedTestClass.newInstance());
-      } 
-      finally
-      {
-         archiveClassLoader.close();
+         try
+         {
+            ((Closeable) shrinkWrapClassLoader).close();
+         }
+         catch (final IOException e)
+         {
+            log.warning("Could not close the " + shrinkWrapClassLoader + ": " + e);
+         }
       }
    }
 
+   //-------------------------------------------------------------------------------------||
+   // Tests ------------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Ensures we can load a Class instance from the {@link ShrinkWrapClassLoader}
+    */
    @Test
-   public void shouldBeAbleToLoadResourceFromArchive() throws Exception
+   public void shouldBeAbleToLoadClassFromArchive() throws ClassNotFoundException
    {
-      ShrinkWrapClassLoader archiveClassLoader = new ShrinkWrapClassLoader((ClassLoader)null, createArchive());
-      
-      try
-      {
-         URL resource = archiveClassLoader.getResource(
-               "org/jboss/shrinkwrap/classloader/LoadedTestClass.class");
+      // Load the test class from the CL
+      final Class<?> loadedTestClass = Class.forName(applicationClassLoaderClass.getName(), false,
+            shrinkWrapClassLoader);
+      final ClassLoader loadedTestClassClassLoader = loadedTestClass.getClassLoader();
+      log.info("Got " + loadedTestClass + " from " + loadedTestClassClassLoader);
 
-         Assert.assertNotNull(resource);
-      } 
-      finally
-      {
-         archiveClassLoader.close();
-      }
+      // Assertions
+      Assert.assertNotNull("Test class could not be found via the ClassLoader", loadedTestClass);
+      Assert.assertSame("Test class should have been loaded via the archive ClassLoader", shrinkWrapClassLoader,
+            loadedTestClassClassLoader);
+      Assert.assertNotSame("Class Loaded from the CL should not be the same as the one on the appCL", loadedTestClass,
+            applicationClassLoaderClass);
+
    }
+
+   /**
+    * Ensures we can load a resource by name from the {@link ShrinkWrapClassLoader}
+    */
+   @Test
+   public void shouldBeAbleToLoadResourceFromArchive()
+   {
+
+      // Load the class as a resource
+      final URL resource = shrinkWrapClassLoader.getResource(getResourceNameOfClass(applicationClassLoaderClass));
+
+      // Assertions
+      Assert.assertNotNull(resource);
+
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods ------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Obtains the resource name for a given class
+    */
+   private static String getResourceNameOfClass(final Class<?> clazz)
+   {
+      assert clazz != null : "clazz must be specified";
+      final StringBuilder sb = new StringBuilder();
+      final String className = clazz.getName().replace('.', '/');
+      sb.append(className);
+      sb.append(".class");
+      return sb.toString();
+   }
 }
\ No newline at end of file



More information about the jboss-svn-commits mailing list