[jboss-svn-commits] JBoss Common SVN: r3703 - in shrinkwrap/trunk: impl-base/src/main/java/org/jboss/shrinkwrap/impl/base and 5 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sun Nov 15 06:28:27 EST 2009


Author: aslak
Date: 2009-11-15 06:28:27 -0500 (Sun, 15 Nov 2009)
New Revision: 3703

Added:
   shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/ExtensionLoader.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/SecurityActions.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ServiceExtensionLoader.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ServiceExtensionLoaderTestCase.java
   shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ServiceExtensionLoaderTestCase$Extension
   shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ServiceExtensionLoaderTestCase$WrongImplExtension
Removed:
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveExtensionLoader.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ArchiveExtensionLoaderTest.java
   shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$Extension
   shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$WrongImplExtension
Modified:
   shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/Archives.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveBase.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveBase.java
   shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveImpl.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ArchivesTestCase.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExplodedExporterTestCase.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExportTestBase.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/ArchiveTestBase.java
   shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/unit/MemoryMapArchiveTestCase.java
Log:
SHRINKWRAP-50 
- Added ExtensionLoader interface
- Exposed ExtensionLoader / Extension Overriding via Archives factory
- Changed testcases to use Archives factory instead of MemoryMap directly
- Renamed ArchiveExtensionLoader to ServiceExtensionLoader

Modified: shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/Archives.java
===================================================================
--- shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/Archives.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/Archives.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -16,7 +16,6 @@
  */
 package org.jboss.shrinkwrap.api;
 
-
 /**
  * Generic unified factory for archive creation.
  *
@@ -31,6 +30,10 @@
 
    private static final String ARCHIVE_IMPL = "org.jboss.shrinkwrap.impl.base.MemoryMapArchiveImpl";
    
+   private static final String EXTENSION_LOADER_IMPL = "org.jboss.shrinkwrap.impl.base.ServiceExtensionLoader";
+   
+   private static ExtensionLoader extensionLoader = null;
+   
    /**
     * Create a archive as a specific type.
     * 
@@ -47,14 +50,71 @@
       {
          throw new IllegalArgumentException("Type must be specified");
       }
+      
+      initializeExtensionLoader();
+      
       Archive<?> archive = SecurityActions.newInstance(
                                  ARCHIVE_IMPL,
-                                 new Class<?>[]{String.class},
-                                 new Object[]{archiveName},
+                                 new Class<?>[]{String.class, ExtensionLoader.class},
+                                 new Object[]{archiveName, extensionLoader},
                                  Archive.class); 
       return archive.as(type);
    }
 
+   /**
+    * Override the loading of a specific Extension.
+    * 
+    * @param <T>
+    * @param extensionClass The Extension interface
+    * @param extensionImplClass The Extension implementation class
+    */
+   public static <T extends Specializer> void addExtensionOverride(
+         Class<T> extensionClass, 
+         Class<? extends T> extensionImplClass)
+   {
+      initializeExtensionLoader();
+      extensionLoader.addOverride(extensionClass, extensionImplClass);
+   }
+
+   /**
+    * 
+    * @param loader The ExtensionLoader to use
+    * @throws IllegalArgumentException if loader is null
+    * @throws IllegalStateException if loader is already set
+    */
+   public synchronized static void setExtensionLoader(ExtensionLoader loader)
+   {
+      if(loader == null) 
+      {
+         throw new IllegalArgumentException("Loader must be specified");
+      }
+      if(extensionLoader != null) 
+      {
+         throw new IllegalStateException(
+               "Loader already specified, call setExtensionLoader " +
+         		"before calling create or addExtensionOverride");
+      }
+      extensionLoader = loader;
+   }
+   
+   private synchronized static void initializeExtensionLoader() 
+   {
+      if(extensionLoader == null) {
+         extensionLoader = SecurityActions.newInstance(
+                              EXTENSION_LOADER_IMPL,
+                              new Class<?>[]{}, 
+                              new Object[]{}, 
+                              ExtensionLoader.class);
+      }
+   }
+   
+   /**
+    * Used by ArchivesTestCase to reset the static state of the Factory. 
+    */
+   static void resetState() {
+      extensionLoader = null;
+   }
+   
    //-------------------------------------------------------------------------------------||
    // Constructor ------------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||

Added: shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/ExtensionLoader.java
===================================================================
--- shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/ExtensionLoader.java	                        (rev 0)
+++ shrinkwrap/trunk/api/src/main/java/org/jboss/shrinkwrap/api/ExtensionLoader.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -0,0 +1,54 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, 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.
+ *
+ * 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.jboss.shrinkwrap.api;
+
+/**
+ * ExtensionLoader
+ * 
+ * Describes a way for the {@link Archive} to load extensions.
+ *
+ * @author <a href="mailto:aslak at conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public interface ExtensionLoader
+{
+
+   /**
+    * Load a Extension.
+    * 
+    * @param <T>
+    * @param extensionClass The Extension interface
+    * @param baseArchive The base archive to use
+    * @return a 
+    */
+   public <T extends Specializer> T load(Class<T> extensionClass, Archive<?> baseArchive);
+   
+   /**
+    * Add a Override to the normal Extension loading. 
+    * 
+    * If a specific class is found to be overridden, the class will not be loaded
+    * using the normal strategy.
+    * 
+    * @param <T> The type of Extension
+    * @param extensionClass The Extension interface class
+    * @param extensionImplClass The Extension implementation class
+    * @return this ExtensionLoader
+    */
+   public <T extends Specializer> ExtensionLoader addOverride(
+         Class<T> extensionClass, 
+         Class<? extends T> extensionImplClass); 
+}

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveBase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveBase.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveBase.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -23,6 +23,7 @@
 
 import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.api.Asset;
+import org.jboss.shrinkwrap.api.ExtensionLoader;
 import org.jboss.shrinkwrap.api.Path;
 import org.jboss.shrinkwrap.api.Specializer;
 import org.jboss.shrinkwrap.impl.base.asset.ArchiveAsset;
@@ -61,6 +62,11 @@
     */
    private final String name;
 
+   /**
+    * Defines how the Specializer extensions are loaded. 
+    */
+   private ExtensionLoader extensionLoader = new ServiceExtensionLoader();
+   
    //-------------------------------------------------------------------------------------||
    // Constructor ------------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
@@ -71,15 +77,18 @@
     * Creates a new Archive with the specified name
     * 
     * @param name Name of the archive
+    * @param extensionLoader The extensionLoader to be used
     * @throws IllegalArgumentException If the name was not specified
     */
-   protected ArchiveBase(final String name) throws IllegalArgumentException
+   protected ArchiveBase(final String name, final ExtensionLoader extensionLoader) throws IllegalArgumentException
    {
       // Precondition checks
       Validate.notNullOrEmpty(name, "name must be specified");
+      Validate.notNull(extensionLoader, "extensionLoader must be specified");
 
       // Set
       this.name = name;
+      this.extensionLoader = extensionLoader;
    }
 
    //-------------------------------------------------------------------------------------||
@@ -219,7 +228,7 @@
    {
       Validate.notNull(clazz, "Class must be specified");
 
-      return new ArchiveExtensionLoader<TYPE>(clazz).load(this);
+      return extensionLoader.load(clazz, this);
    }
 
    //-------------------------------------------------------------------------------------||

Deleted: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveExtensionLoader.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveExtensionLoader.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ArchiveExtensionLoader.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -1,173 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, 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.
- *
- * 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.jboss.shrinkwrap.impl.base;
-
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.net.URL;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.impl.base.io.IOUtil;
-
-/**
- * ArchiveExtensionLoader responsible for loading the Archive extensions based on ShrinkWrap SPI.
- *
- * @author <a href="mailto:aslak at conduct.no">Aslak Knutsen</a>
- * @version $Revision: $
- * @param <T>
- */
-public class ArchiveExtensionLoader<T>
-{
-   private Class<T> extensionInterface;
-   
-   // TODO: generic clash, should be moved out, or only support overloading of Class<T> ?
-   private Map<Class<?>, Class<?>> extensionOverrides = new HashMap<Class<?>, Class<?>>();
-   
-   private ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-   
-   public ArchiveExtensionLoader(Class<T> extensionInterface) 
-   {
-      Validate.notNull(extensionInterface, "ExtensionInterface must be specified");
-      this.extensionInterface = extensionInterface;
-   }
-
-   public <X> ArchiveExtensionLoader<T> addExtesionOverride(
-         Class<X> extensionInterfaceClas, Class<? extends X> extensionImplClass) 
-   {
-      extensionOverrides.put(extensionInterfaceClas, extensionImplClass);
-      return this;
-   }
-   
-   public ArchiveExtensionLoader<T> setClassLoader(ClassLoader classLoader)
-   {
-      Validate.notNull(classLoader, "ClassLoader must be specified");
-      this.classLoader = classLoader;
-      return this;
-   }
-
-   public final ClassLoader getClassLoader()
-   {
-      return classLoader;
-   }
-   
-   public T load(Archive<?> archive) 
-   {
-      Validate.notNull(archive, "Archive must be specified");
-      try 
-      {
-         Class<T> extensionImplClass = null;
-         
-         if(hasExtensionOverride()) 
-         {
-            extensionImplClass = (Class<T>)getExtensionOverride();
-         } 
-         else 
-         {
-            List<URL> urls = findExtensions(extensionInterface);
-            if(urls.size() == 0) 
-            {
-               throw new RuntimeException(
-                     "No extension implementation found for " + extensionInterface.getName() + 
-                     ", please verify classpath or add a extensionOverride");
-            }
-            if(urls.size() > 1) 
-            {
-               throw new RuntimeException(
-                     "Multiple extension implementations found for " + extensionInterface.getName() + 
-                     ", please verify classpath or add a extensionOverride");
-            }
-
-            String extensionClassName = loadExtensionName(urls.get(0));
-            extensionImplClass = loadExtensionClass(extensionClassName);          
-         }
-
-         if(!extensionInterface.isAssignableFrom(extensionImplClass)) {
-               throw new RuntimeException(
-                     "Found extension implementation is not of same type " + extensionImplClass.getName() + 
-                     " as " + extensionInterface.getName());
-         }
-   
-         Constructor<T> extensionImplConstructor = findConstructor(extensionImplClass);
-         Class<?> constructorArg = extensionImplConstructor.getParameterTypes()[0];
-         if(constructorArg.isInstance(archive)) 
-         {
-            return extensionImplConstructor.newInstance(archive);   
-         } 
-         else 
-         {
-            return extensionImplConstructor.newInstance(
-                  new ArchiveExtensionLoader(constructorArg).load(archive)
-            );
-         }
-      } 
-      catch (Exception e) 
-      {
-         throw new RuntimeException("Could not load extension for " + extensionInterface.getName(), e);
-      }
-   }
-   
-   private boolean hasExtensionOverride() {
-      return extensionOverrides.containsKey(extensionInterface);
-   }
-   
-   private Class<?> getExtensionOverride() {
-      return extensionOverrides.get(extensionInterface);
-   }
-   
-   private List<URL> findExtensions(Class<T> extensionClass) throws IOException 
-   {
-      Enumeration<URL> urls  = getClassLoader().getResources(
-            "META-INF/services/" + extensionClass.getName());
-
-      return Collections.list(urls);
-   }
-   
-   private String loadExtensionName(URL extensionURL) throws IOException 
-   {
-      return new String(IOUtil.asByteArray(extensionURL.openStream()));
-   }
-
-   private Class<T> loadExtensionClass(String extensionClassName) throws ClassNotFoundException 
-   {
-      return (Class<T>)getClassLoader().loadClass(extensionClassName);      
-   }
-   
-   private Constructor<T> findConstructor(Class<T> implClass) 
-   {
-      Constructor<T>[] constructors = (Constructor<T>[])implClass.getConstructors();
-      for(Constructor<T> constructor : constructors) {
-         Class<?>[] parameters = constructor.getParameterTypes();
-         if(parameters.length != 1) 
-         {
-            continue;
-         }
-         Class<?> parameter = parameters[0];
-         if(Archive.class.isAssignableFrom(parameter)) 
-         {
-            return constructor;
-         }
-      }
-      throw new RuntimeException(
-            "No constructor with a single argument of type " + 
-            Archive.class.getName() + " could be found");
-   }
-}

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveBase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveBase.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveBase.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -27,6 +27,7 @@
 
 import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.api.Asset;
+import org.jboss.shrinkwrap.api.ExtensionLoader;
 import org.jboss.shrinkwrap.api.Path;
 import org.jboss.shrinkwrap.impl.base.asset.ArchiveAsset;
 import org.jboss.shrinkwrap.impl.base.path.BasicPath;
@@ -87,11 +88,11 @@
     * This constructor will generate a 
     * unique {@link Archive#getName()} per instance.
     *  
-    * @param actualType The {@link Archive} type.
+    * @param extensionLoader The extensionLoader to be used
     */
-   public MemoryMapArchiveBase()
+   public MemoryMapArchiveBase(ExtensionLoader extensionLoader)
    {
-      this("Archive-" + UUID.randomUUID().toString() + ".jar");
+      this("Archive-" + UUID.randomUUID().toString() + ".jar", extensionLoader);
    }
 
    /**
@@ -100,10 +101,11 @@
     * This constructor will generate an {@link Archive} with the provided name.
     *  
     * @param archiveName
+    * @param extensionLoader The extensionLoader to be used
     */
-   public MemoryMapArchiveBase(final String archiveName)
+   public MemoryMapArchiveBase(final String archiveName, ExtensionLoader extensionLoader)
    {
-      super(archiveName);
+      super(archiveName, extensionLoader);
    }
 
    //-------------------------------------------------------------------------------------||

Modified: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveImpl.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveImpl.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/MemoryMapArchiveImpl.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -17,6 +17,7 @@
 package org.jboss.shrinkwrap.impl.base;
 
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ExtensionLoader;
 import org.jboss.shrinkwrap.spi.MemoryMapArchive;
 
 /**
@@ -40,11 +41,11 @@
     * This constructor will generate a 
     * unique {@link Archive#getName()} per instance.
     *  
-    * @param actualType The {@link Archive} type.
+    * @param extensionLoader The extensionLoader to be used
     */
-   public MemoryMapArchiveImpl()
+   public MemoryMapArchiveImpl(ExtensionLoader extensionLoader)
    {
-      super();
+      super(extensionLoader);
    }
 
    /**
@@ -53,10 +54,11 @@
     * This constructor will generate an {@link Archive} with the provided name.
     *  
     * @param archiveName
+    * @param extensionLoader The extensionLoader to be used
     */
-   public MemoryMapArchiveImpl(String archiveName)
+   public MemoryMapArchiveImpl(String archiveName, ExtensionLoader extensionLoader)
    {
-      super(archiveName);
+      super(archiveName, extensionLoader);
    }
 
    /*

Added: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/SecurityActions.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/SecurityActions.java	                        (rev 0)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/SecurityActions.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -0,0 +1,190 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, 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.
+ *
+ * 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.jboss.shrinkwrap.impl.base;
+
+import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * SecurityActions
+ * 
+ * A set of privileged actions that are not to leak out
+ * of this package 
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+final class SecurityActions
+{
+
+   //-------------------------------------------------------------------------------||
+   // Constructor ------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------||
+
+   /**
+    * No instantiation
+    */
+   private SecurityActions()
+   {
+      throw new UnsupportedOperationException("No instantiation");
+   }
+
+   //-------------------------------------------------------------------------------||
+   // Utility Methods --------------------------------------------------------------||
+   //-------------------------------------------------------------------------------||
+
+   /**
+    * Obtains the Thread Context ClassLoader
+    */
+   static ClassLoader getThreadContextClassLoader()
+   {
+      return AccessController.doPrivileged(GetTcclAction.INSTANCE);
+   }
+
+   static Constructor<?>[] getConstructors(final Class<?> clazz) 
+   {
+      return AccessController.doPrivileged(new PrivilegedAction<Constructor<?>[]>() {
+         public Constructor<?>[] run() 
+         {
+            return clazz.getConstructors();
+         }
+      });
+   }
+   
+   /**
+    * Obtains the Constructor specified from the given Class and argument types
+    * @param clazz
+    * @param argumentTypes
+    * @return
+    * @throws NoSuchMethodException
+    */
+   static Constructor<?> getConstructor(final Class<?> clazz, final Class<?>... argumentTypes)
+         throws NoSuchMethodException
+   {
+      try
+      {
+         return AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>()
+         {
+            @Override
+            public Constructor<?> run() throws NoSuchMethodException
+            {
+               return clazz.getConstructor(argumentTypes);
+            }
+         });
+      }
+      // Unwrap
+      catch (final PrivilegedActionException pae)
+      {
+         final Throwable t = pae.getCause();
+         // Rethrow
+         if (t instanceof NoSuchMethodException)
+         {
+            throw (NoSuchMethodException) t;
+         }
+         else
+         {
+            // No other checked Exception thrown by Class.getConstructor
+            try
+            {
+               throw (RuntimeException) t;
+            }
+            // Just in case we've really messed up
+            catch (final ClassCastException cce)
+            {
+               throw new RuntimeException("Obtained unchecked Exception; this code should never be reached", t);
+            }
+         }
+      }
+   }
+
+   /**
+    * Create a new instance by finding a constructor that matches the argumentTypes signature 
+    * using the arguments for instantiation.
+    * 
+    * @param className Full classname of class to create
+    * @param argumentTypes The constructor argument types
+    * @param arguments The constructor arguments
+    * @return a new instance
+    * @throws IllegalArgumentException if className, argumentTypes, or arguments are null
+    * @throws RuntimeException if any exceptions during creation
+    * @author <a href="mailto:aslak at conduct.no">Aslak Knutsen</a>
+    * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+    */
+   static <T> T newInstance(final String className, final Class<?>[] argumentTypes, final Object[] arguments,
+         final Class<T> expectedType)
+   {
+      if (className == null)
+      {
+         throw new IllegalArgumentException("ClassName must be specified");
+      }
+      if (argumentTypes == null)
+      {
+         throw new IllegalArgumentException("ArgumentTypes must be specified. Use empty array if no arguments");
+      }
+      if (arguments == null)
+      {
+         throw new IllegalArgumentException("Arguments must be specified. Use empty array if no arguments");
+      }
+      final Object obj;
+      try
+      {
+         final ClassLoader tccl = getThreadContextClassLoader();
+         final Class<?> implClass = Class.forName(className, false, tccl);
+         Constructor<?> constructor = getConstructor(implClass, argumentTypes);
+         obj = constructor.newInstance(arguments);
+      }
+      catch (Exception e)
+      {
+         throw new RuntimeException("Could not create new instance of " + className
+               + ", missing package from classpath?", e);
+      }
+
+      // Cast
+      try
+      {
+         return expectedType.cast(obj);
+      }
+      catch (final ClassCastException cce)
+      {
+         // Reconstruct so we get some useful information
+         throw new ClassCastException("Incorrect expected type, " + expectedType.getName() + ", defined for "
+               + obj.getClass().getName());
+      }
+   }
+
+   //-------------------------------------------------------------------------------||
+   // Inner Classes ----------------------------------------------------------------||
+   //-------------------------------------------------------------------------------||
+
+   /**
+    * Single instance to get the TCCL
+    */
+   private enum GetTcclAction implements PrivilegedAction<ClassLoader> {
+      INSTANCE;
+
+      @Override
+      public ClassLoader run()
+      {
+         return Thread.currentThread().getContextClassLoader();
+      }
+
+   }
+
+}

Added: shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ServiceExtensionLoader.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ServiceExtensionLoader.java	                        (rev 0)
+++ shrinkwrap/trunk/impl-base/src/main/java/org/jboss/shrinkwrap/impl/base/ServiceExtensionLoader.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -0,0 +1,258 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, 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.
+ *
+ * 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.jboss.shrinkwrap.impl.base;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ExtensionLoader;
+import org.jboss.shrinkwrap.api.Specializer;
+import org.jboss.shrinkwrap.impl.base.io.IOUtil;
+
+/**
+ * ServiceExtensionLoader
+ *
+ * @author <a href="mailto:aslak at conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class ServiceExtensionLoader implements ExtensionLoader
+{
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Logger
+    */
+   private static final Logger log = Logger.getLogger(ServiceExtensionLoader.class.getName());
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+   
+   private ClassLoader classLoader = SecurityActions.getThreadContextClassLoader();
+   private Map<Class<?>, Class<?>> cache = new HashMap<Class<?>, Class<?>>();
+   
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations - ExtensionLoader -----------------------------------------||
+   //-------------------------------------------------------------------------------------||
+   
+   /* (non-Javadoc)
+    * @see org.jboss.shrinkwrap.api.ExtensionLoader#load(java.lang.Class, org.jboss.shrinkwrap.api.Archive)
+    */
+   @Override
+   public <T extends Specializer> T load(Class<T> extensionClass, Archive<?> baseArchive)
+   {
+      if(isCached(extensionClass))
+      {
+         return createFromCache(extensionClass, baseArchive);
+      }
+      T object = createFromLoadExtension(extensionClass, baseArchive);
+      
+      addToCache(extensionClass, object.getClass());
+      
+      return object;
+   }
+
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods - Cache ----------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   boolean isCached(Class<?> extensionClass) 
+   {
+      return cache.containsKey(extensionClass);
+   }
+   
+   private <T extends Specializer> T createFromCache(Class<T> extensionClass, Archive<?> archive) 
+   {
+      Class<T> extensionImplClass = getFromCache(extensionClass);
+      return createExtension(extensionImplClass, archive);
+   }
+
+   void addToCache(Class<?> extensionClass, Class<?> extensionImplClass)
+   {
+      cache.put(extensionClass, extensionImplClass);
+   }
+
+   @SuppressWarnings("unchecked")
+   <T extends Specializer> Class<T> getFromCache(Class<T> extensionClass) 
+   {
+      return (Class<T>)cache.get(extensionClass);
+   }
+   
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods - Override -------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /* (non-Javadoc)
+    * @see org.jboss.shrinkwrap.api.ExtensionLoader#addOverride(java.lang.Class, java.lang.Class)
+    */
+   public <T extends Specializer> ServiceExtensionLoader addOverride(Class<T> extensionClass, Class<? extends T> extensionImplClass)
+   {
+      addToCache(extensionClass, extensionImplClass);
+      return this;
+   }
+
+   /**
+    * Check to see if a specific extension interface is beeing overloaded
+    * 
+    * @param extensionClass The Extension interface class
+    * @return true if found
+    */
+   public boolean isOverriden(Class<?> extensionClass) 
+   {
+      return isCached(extensionClass);
+   }
+
+   
+   //-------------------------------------------------------------------------------------||
+   // Internal Helper Methods - Loading --------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+   
+   private <T extends Specializer> T createFromLoadExtension(Class<T> extensionClass, Archive<?> archive) 
+   {
+      Class<T> extensionImplClass = loadExtension(extensionClass);
+      if(!extensionClass.isAssignableFrom(extensionImplClass)) 
+      {
+         throw new RuntimeException(
+               "Found extension impl class " + extensionImplClass.getName() + 
+               " not assignable to extension interface " + extensionClass.getName());
+      }
+      return createExtension(extensionImplClass, archive);
+   }
+
+   private <T extends Specializer> Class<T> loadExtension(Class<T> extensionClass) 
+   {
+      URL extensionImplUrl = findExtensionImpl(extensionClass);
+      String extensionImplClassName = loadExtensionName(extensionImplUrl);
+      return loadExtensionClass(extensionImplClassName);
+   }
+   
+   private <T extends Specializer> URL findExtensionImpl(Class<T> extensionClass) 
+   {
+      try 
+      {
+         Enumeration<URL> urls  = getClassLoader().getResources(
+               "META-INF/services/" + extensionClass.getName());
+   
+         List<URL> foundExtensions = Collections.list(urls);
+         if(foundExtensions.size() == 0)
+         {
+            throw new RuntimeException(
+                  "No extension implementation found for " + extensionClass.getName() + 
+                  ", please verify classpath or add a extensionOverride");
+         }
+         if(foundExtensions.size() > 1) 
+         {
+            log.warning(
+                  "Multiple extension implementations found for " + extensionClass.getName() + 
+                   ", please verify classpath or add a extensionOverride");
+//            throw new RuntimeException(
+//                "Multiple extension implementations found for " + extensionClass.getName() + 
+//                ", please verify classpath or add a extensionOverride");
+         }
+         return foundExtensions.get(0);
+      } 
+      catch (Exception e) 
+      {
+         throw new RuntimeException("Could not find any mapping for extension " + extensionClass.getName(), e);
+      }
+   }
+
+   private String loadExtensionName(URL extensionURL) 
+   {
+      try 
+      {
+         return new String(IOUtil.asByteArray(extensionURL.openStream()));
+      } 
+      catch (IOException e) 
+      {
+         throw new RuntimeException("Could not read extension mapping " + extensionURL, e);
+      }
+   }
+
+   @SuppressWarnings("unchecked")
+   private <T extends Specializer> Class<T> loadExtensionClass(String extensionClassName)  
+   {
+      try 
+      {
+         return (Class<T>)getClassLoader().loadClass(extensionClassName);
+      }
+      catch (ClassNotFoundException e) {
+         throw new RuntimeException("Could not load class " + extensionClassName, e);
+      }
+   }
+
+   private <T extends Specializer> T createExtension(Class<T> extensionImplClass, Archive<?> archive) 
+   {
+      try
+      {
+         Constructor<T> extensionImplConstructor = findConstructor(extensionImplClass);
+         
+         @SuppressWarnings("unchecked")
+         Class<T> constructorArg = (Class<T>)extensionImplConstructor.getParameterTypes()[0];
+         if(constructorArg.isInstance(archive)) 
+         {
+            return extensionImplConstructor.newInstance(archive);
+         }
+         else 
+         {
+            return extensionImplConstructor.newInstance(
+                  load(constructorArg, archive));
+         }
+      }
+      catch(Exception e)
+      {
+         throw new RuntimeException("Could not create new instance of " + extensionImplClass, e);
+      }
+   }
+
+   @SuppressWarnings("unchecked")
+   private <T extends Specializer> Constructor<T> findConstructor(Class<T> extensionImplClass) 
+   {
+      Constructor<?>[] constructors = SecurityActions.getConstructors(extensionImplClass);
+      for(Constructor<?> constructor : constructors)
+      {
+         Class<?>[] parameters = constructor.getParameterTypes();
+         if(parameters.length != 1) 
+         {
+            continue;
+         }
+         Class<?> parameter = parameters[0];
+         if(Archive.class.isAssignableFrom(parameter)) 
+         {
+            return (Constructor<T>)constructor;
+         }
+      }
+      throw new RuntimeException(
+            "No constructor with a single argument of type " + 
+            Archive.class.getName() + " could be found");
+   }
+   
+   private ClassLoader getClassLoader() 
+   {
+      return classLoader;
+   }
+}

Deleted: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ArchiveExtensionLoaderTest.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ArchiveExtensionLoaderTest.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ArchiveExtensionLoaderTest.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -1,105 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, 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.
- *
- * 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.jboss.shrinkwrap.impl.base;
-
-import junit.framework.Assert;
-
-import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.api.Specializer;
-import org.junit.Test;
-
-
-/**
- * ArchiveExtensionLoaderTest to ensure extension loading correctness
- *
- * @author <a href="mailto:aslak at conduct.no">Aslak Knutsen</a>
- * @version $Revision: $
- */
-public class ArchiveExtensionLoaderTest
-{
-
-   @Test
-   public void shouldBeAbleToLoadExtension() throws Exception {
-      Extension extension = new ArchiveExtensionLoader<Extension>(Extension.class)
-               .load(new MemoryMapArchiveImpl());
-
-      Assert.assertNotNull(extension);
-      
-      Assert.assertTrue(extension.getClass() == ExtensionImpl.class);
-   }
-
-   @Test
-   public void shouldBeAbleToOverrideExtension() throws Exception {
-      Extension extension = new ArchiveExtensionLoader<Extension>(Extension.class)
-               .addExtesionOverride(Extension.class, ExtensionImpl2.class)
-               .load(new MemoryMapArchiveImpl());
-
-      Assert.assertNotNull(extension);
-   
-      Assert.assertTrue(extension.getClass() == ExtensionImpl2.class);
-   }
-   
-   @Test(expected = RuntimeException.class)
-   public void shouldThrowExceptionOnMissingExtension() throws Exception {
-      new ArchiveExtensionLoader<ArchiveExtensionLoaderTest>(ArchiveExtensionLoaderTest.class)
-         .load(new MemoryMapArchiveImpl());
-   }
-
-   @Test(expected = RuntimeException.class)
-   public void shouldThrowExceptionOnWrongImplType() throws Exception {
-      new ArchiveExtensionLoader<WrongImplExtension>(WrongImplExtension.class)
-         .load(new MemoryMapArchiveImpl());
-   }
-
-   public static interface WrongImplExtension extends Specializer {
-      
-   }
-   
-   public static interface Extension extends Specializer {
-      
-   }
-
-   public static class ExtensionImpl extends SpecializedBase implements Extension {
-
-      private Archive<?> archive;
-      public ExtensionImpl(Archive<?> archive)
-      {
-         this.archive = archive;
-      }
-      
-      @Override
-      protected Archive<?> getArchive()
-      {
-         return archive;
-      }
-   }
-
-   public static class ExtensionImpl2 extends SpecializedBase implements Extension {
-
-      private Archive<?> archive;
-      public ExtensionImpl2(Archive<?> archive)
-      {
-         this.archive = archive;
-      }
-      
-      @Override
-      protected Archive<?> getArchive()
-      {
-         return archive;
-      }
-   }
-}

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ArchivesTestCase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ArchivesTestCase.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ArchivesTestCase.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -16,10 +16,21 @@
  */
 package org.jboss.shrinkwrap.impl.base;
 
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+
 import junit.framework.Assert;
 
+import org.jboss.shrinkwrap.api.Archive;
 import org.jboss.shrinkwrap.api.Archives;
+import org.jboss.shrinkwrap.api.ExtensionLoader;
+import org.jboss.shrinkwrap.api.Path;
+import org.jboss.shrinkwrap.api.Paths;
+import org.jboss.shrinkwrap.api.Specializer;
 import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.impl.base.container.ContainerBase;
+import org.jboss.shrinkwrap.impl.base.spec.JavaArchiveImpl;
 import org.junit.Test;
 
 
@@ -31,11 +42,10 @@
  */
 public class ArchivesTestCase
 {
-
    @Test
    public void shouldBeAbleToCreateANewArchive() throws Exception {
       String archiveName = "test.war";
-      
+      reset();
       JavaArchive archive = Archives.create(archiveName, JavaArchive.class);
       
       Assert.assertNotNull(
@@ -46,4 +56,121 @@
             archiveName, 
             archive.getName());
    }
+   
+   @Test
+   public void shouldBeAbleToAddOverride() throws Exception {
+      reset();
+      Archives.addExtensionOverride(JavaArchive.class, MockJavaArchiveImpl.class);
+      
+      JavaArchive archive = Archives.create("test.jar", JavaArchive.class);
+      
+      Assert.assertEquals(
+            "Should have overridden normal JavaArchive impl", 
+            MockJavaArchiveImpl.class, archive.getClass());
+      
+   }
+
+   private static boolean extensionLoaderCalled = false;   
+   
+   @Test
+   public void shouldBeAbleToSetExtensionLoader() throws Exception {
+      reset();
+      Archives.setExtensionLoader(new ExtensionLoader()
+      {
+         @Override
+         public <T extends Specializer> T load(Class<T> extensionClass,
+               Archive<?> baseArchive)
+         {
+            extensionLoaderCalled = true;
+            return (T)new JavaArchiveImpl(baseArchive);
+         }
+         
+         @Override
+         public <T extends Specializer> ExtensionLoader addOverride(
+               Class<T> extensionClass, Class<? extends T> extensionImplClass)
+         {
+            return null;
+         }
+      });
+      Archives.create("test.jar", JavaArchive.class);
+
+      Assert.assertTrue(
+            "Specified ExtensionLoader should have been used", 
+            extensionLoaderCalled);
+   }
+
+   @Test(expected = IllegalArgumentException.class)
+   public void shouldNotBeAbleToSetExtensionLoaderNull() throws Exception {
+      reset();
+      Archives.setExtensionLoader(null);
+   }
+
+   @Test(expected = IllegalStateException.class)
+   public void shouldNotBeAbleToSetExtensionLoaderAfterInitialized() throws Exception {
+      reset();
+      Archives.create("test.jar", JavaArchive.class);
+      Archives.setExtensionLoader(new ExtensionLoader()
+      {
+         @Override
+         public <T extends Specializer> T load(Class<T> extensionClass,
+               Archive<?> baseArchive)
+         {
+            return null;
+         }
+         
+         @Override
+         public <T extends Specializer> ExtensionLoader addOverride(
+               Class<T> extensionClass, Class<? extends T> extensionImplClass)
+         {
+            return null;
+         }
+      });
+   }
+   
+   private void reset() throws Exception {
+      
+      Method method = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>()
+      {
+         @Override
+         public Method run() throws Exception
+         {
+            Method method = Archives.class.getDeclaredMethod("resetState", new Class<?>[]{});
+            method.setAccessible(true);
+            return method;
+         }
+      });
+      method.invoke(null);
+   }
+   
+   public static class MockJavaArchiveImpl extends ContainerBase<JavaArchive> implements JavaArchive {
+
+      public MockJavaArchiveImpl(Archive<?> archive)
+      {
+         super(JavaArchive.class, archive);
+      }
+
+      @Override
+      protected Path getClassesPath()
+      {
+         return Paths.root();
+      }
+
+      @Override
+      protected Path getLibraryPath()
+      {
+         return Paths.root();
+      }
+
+      @Override
+      protected Path getManinfestPath()
+      {
+         return Paths.root();
+      }
+
+      @Override
+      protected Path getResourcePath()
+      {
+         return Paths.root();
+      }
+   }
 }

Added: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ServiceExtensionLoaderTestCase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ServiceExtensionLoaderTestCase.java	                        (rev 0)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/ServiceExtensionLoaderTestCase.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, 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.
+ *
+ * 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.jboss.shrinkwrap.impl.base;
+
+import junit.framework.Assert;
+
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.Archives;
+import org.jboss.shrinkwrap.api.Specializer;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.Test;
+
+
+/**
+ * ServiceExtensionLoaderTestCase
+ * 
+ * Test to ensure the behaviour of ServiceExtensionLoader
+ *
+ * @author <a href="mailto:aslak at conduct.no">Aslak Knutsen</a>
+ * @version $Revision: $
+ */
+public class ServiceExtensionLoaderTestCase
+{
+
+   @Test
+   public void shouldBeAbleToLoadExtension() throws Exception {
+      Extension extension = new ServiceExtensionLoader()
+               .load(Extension.class, Archives.create("test.jar", JavaArchive.class));
+
+      Assert.assertNotNull(extension);
+      
+      Assert.assertTrue(extension.getClass() == ExtensionImpl.class);
+   }
+
+   @Test
+   public void shouldBeAbleToOverrideExtension() throws Exception {
+      Extension extension = new ServiceExtensionLoader()
+         .addOverride(Extension.class, ExtensionImpl2.class)
+         .load(Extension.class, Archives.create("test.jar", JavaArchive.class));
+
+      Assert.assertNotNull(extension);
+   
+      Assert.assertTrue(extension.getClass() == ExtensionImpl2.class);
+   }
+   
+   @Test
+   public void shouldBePlacedInCacheAfterLoad() throws Exception {
+      ServiceExtensionLoader loader = new ServiceExtensionLoader();
+      loader.load(Extension.class, Archives.create("test.jar", JavaArchive.class));
+      
+      Assert.assertTrue(
+            "Should be placed in cache",
+            loader.isCached(Extension.class)
+      );      
+   }
+   
+   @Test(expected = RuntimeException.class)
+   public void shouldThrowExceptionOnMissingExtension() throws Exception {
+      new ServiceExtensionLoader()
+         .load(MissingExtension.class, Archives.create("test.jar", JavaArchive.class));
+   }
+
+   @Test(expected = RuntimeException.class)
+   public void shouldThrowExceptionOnWrongImplType() throws Exception {
+      new ServiceExtensionLoader()
+         .load(WrongImplExtension.class, Archives.create("test.jar", JavaArchive.class));
+   }
+
+   
+   public static interface WrongImplExtension extends Specializer {
+      
+   }
+   
+   public static interface Extension extends Specializer {
+      
+   }
+
+   public static class ExtensionImpl extends SpecializedBase implements Extension {
+
+      private Archive<?> archive;
+      public ExtensionImpl(Archive<?> archive)
+      {
+         this.archive = archive;
+      }
+      
+      @Override
+      protected Archive<?> getArchive()
+      {
+         return archive;
+      }
+   }
+
+   public static class ExtensionImpl2 extends SpecializedBase implements Extension {
+
+      private Archive<?> archive;
+      public ExtensionImpl2(Archive<?> archive)
+      {
+         this.archive = archive;
+      }
+      
+      @Override
+      protected Archive<?> getArchive()
+      {
+         return archive;
+      }
+   }
+   
+   public static interface MissingExtension extends Specializer {
+      
+   }
+}

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExplodedExporterTestCase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExplodedExporterTestCase.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExplodedExporterTestCase.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -24,11 +24,11 @@
 import java.util.logging.Logger;
 
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.Archives;
 import org.jboss.shrinkwrap.api.Asset;
 import org.jboss.shrinkwrap.api.Path;
 import org.jboss.shrinkwrap.api.exporter.ArchiveExportException;
 import org.jboss.shrinkwrap.api.exporter.ExplodedExporter;
-import org.jboss.shrinkwrap.impl.base.MemoryMapArchiveImpl;
 import org.jboss.shrinkwrap.impl.base.io.IOUtil;
 import org.jboss.shrinkwrap.impl.base.path.BasicPath;
 import org.junit.Assert;
@@ -138,7 +138,7 @@
    {
       log.info("testExportExplodedRequiresBaseDirectroy");
 
-      new MemoryMapArchiveImpl().as(ExplodedExporter.class).exportExploded(null);
+      Archives.create("test.jar", ExplodedExporter.class).exportExploded(null);
    }
 
    /**
@@ -152,7 +152,7 @@
       log.info("testExportExplodedRequiresExisitingDirectroy");
 
       final File directory = this.getNonexistantDirectory();
-      new MemoryMapArchiveImpl().as(ExplodedExporter.class).exportExploded(directory);
+      Archives.create("test.jar", ExplodedExporter.class).exportExploded(directory);
    }
 
    /**
@@ -164,7 +164,7 @@
       log.info("testExportExplodedRequiresValidDirectory");
       final File nonDirectory = new File(this.getTarget(), "tempFile.txt");
       nonDirectory.createNewFile();
-      new MemoryMapArchiveImpl().as(ExplodedExporter.class).exportExploded(nonDirectory);
+      Archives.create("test.jar", ExplodedExporter.class).exportExploded(nonDirectory);
    }
 
    /**
@@ -178,7 +178,7 @@
       // Will cause the creation of Archive directory to fail
       final File existingFile = new File(directory, NAME_ARCHIVE);
       existingFile.createNewFile();
-      new MemoryMapArchiveImpl(NAME_ARCHIVE).as(ExplodedExporter.class).exportExploded(directory);
+      Archives.create(NAME_ARCHIVE, ExplodedExporter.class).exportExploded(directory);
    }
 
    /**

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExportTestBase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExportTestBase.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/exporter/ExportTestBase.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -21,13 +21,13 @@
 import java.util.logging.Logger;
 
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.Archives;
 import org.jboss.shrinkwrap.api.Asset;
 import org.jboss.shrinkwrap.api.Path;
-import org.jboss.shrinkwrap.impl.base.MemoryMapArchiveImpl;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
 import org.jboss.shrinkwrap.impl.base.asset.ClassLoaderAsset;
 import org.jboss.shrinkwrap.impl.base.io.IOUtil;
 import org.jboss.shrinkwrap.impl.base.path.BasicPath;
-import org.jboss.shrinkwrap.spi.MemoryMapArchive;
 import org.junit.Assert;
 
 /**
@@ -145,7 +145,7 @@
    protected Archive<?> createArchiveWithAssets()
    {
       // Create an archive
-      Archive<?> archive = new MemoryMapArchiveImpl(NAME_ARCHIVE);
+      Archive<?> archive = Archives.create(NAME_ARCHIVE, JavaArchive.class);
       // Add some content
       addContent(archive);
       // Return archive
@@ -161,7 +161,7 @@
       Archive<?> archive = createArchiveWithAssets();
 
       // Create a nested archive
-      MemoryMapArchive nestedArchive = new MemoryMapArchiveImpl(NAME_NESTED_ARCHIVE);
+      Archive<?> nestedArchive = Archives.create(NAME_NESTED_ARCHIVE, JavaArchive.class);
 
       // Add some content
       addContent(nestedArchive);
@@ -170,7 +170,7 @@
       archive.add(nestedArchive, new BasicPath());
 
       // Add an archive nested in a directory
-      MemoryMapArchive nestedArchiveTwo = new MemoryMapArchiveImpl(NAME_NESTED_ARCHIVE_2);
+      Archive<?> nestedArchiveTwo = Archives.create(NAME_NESTED_ARCHIVE_2, JavaArchive.class);
 
       // Add some content
       addContent(nestedArchiveTwo);

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/ArchiveTestBase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/ArchiveTestBase.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/test/ArchiveTestBase.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -17,14 +17,16 @@
 package org.jboss.shrinkwrap.impl.base.test;
 
 import java.util.Arrays;
+
 import java.util.Map;
 
 import junit.framework.Assert;
 
 import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.Archives;
 import org.jboss.shrinkwrap.api.Asset;
 import org.jboss.shrinkwrap.api.Path;
-import org.jboss.shrinkwrap.impl.base.MemoryMapArchiveImpl;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
 import org.jboss.shrinkwrap.impl.base.Validate;
 import org.jboss.shrinkwrap.impl.base.asset.ArchiveAsset;
 import org.jboss.shrinkwrap.impl.base.asset.ClassLoaderAsset;
@@ -438,7 +440,7 @@
       Archive<T> archive = getArchive();
       try
       {
-         archive.add(new MemoryMapArchiveImpl(), null);
+         archive.add(Archives.create("test.jar", JavaArchive.class), null);
          Assert.fail("Should have throw an IllegalArgumentException");
       }
       catch (IllegalArgumentException expectedException)

Modified: shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/unit/MemoryMapArchiveTestCase.java
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/unit/MemoryMapArchiveTestCase.java	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/test/java/org/jboss/shrinkwrap/impl/base/unit/MemoryMapArchiveTestCase.java	2009-11-15 11:28:27 UTC (rev 3703)
@@ -19,6 +19,7 @@
 import junit.framework.Assert;
 
 import org.jboss.shrinkwrap.impl.base.MemoryMapArchiveImpl;
+import org.jboss.shrinkwrap.impl.base.ServiceExtensionLoader;
 import org.jboss.shrinkwrap.impl.base.test.ArchiveTestBase;
 import org.jboss.shrinkwrap.spi.MemoryMapArchive;
 import org.junit.Before;
@@ -52,7 +53,7 @@
    @Override
    protected MemoryMapArchive createNewArchive()
    {
-      return new MemoryMapArchiveImpl();
+      return new MemoryMapArchiveImpl(new ServiceExtensionLoader());
    }
    
    /**
@@ -73,7 +74,7 @@
    public void testConstructorWithName() throws Exception
    {
       String name = "test.jar";
-      MemoryMapArchive tmp = new MemoryMapArchiveImpl(name);
+      MemoryMapArchive tmp = new MemoryMapArchiveImpl(name, new ServiceExtensionLoader());
       Assert.assertEquals("Should return the same name as construtor arg", name, tmp.getName());
    }
 
@@ -81,16 +82,19 @@
     * Test to ensure the MemoryMapArchive requires a name
     * @throws Exception
     */
-   @Test
+   @Test(expected = IllegalArgumentException.class)
    public void testConstructorRequiresName() throws Exception
    {
-      try
-      {
-         new MemoryMapArchiveImpl(null);
-         Assert.fail("Should throw an IllegalArgumentException");
-      }
-      catch (IllegalArgumentException expectedException)
-      {
-      }
+      new MemoryMapArchiveImpl(null);
    }
+
+   /**
+    * Test to ensure the MemoryMapArchive requires a name
+    * @throws Exception
+    */
+   @Test(expected = IllegalArgumentException.class)
+   public void testConstructorRequiresExtensionLoader() throws Exception
+   {
+      new MemoryMapArchiveImpl("test.jar", null);
+   }
 }

Deleted: shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$Extension
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$Extension	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$Extension	2009-11-15 11:28:27 UTC (rev 3703)
@@ -1 +0,0 @@
-org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$ExtensionImpl
\ No newline at end of file

Deleted: shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$WrongImplExtension
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$WrongImplExtension	2009-11-14 21:44:40 UTC (rev 3702)
+++ shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$WrongImplExtension	2009-11-15 11:28:27 UTC (rev 3703)
@@ -1 +0,0 @@
-org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$ExtensionImpl
\ No newline at end of file

Copied: shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ServiceExtensionLoaderTestCase$Extension (from rev 3702, shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$Extension)
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ServiceExtensionLoaderTestCase$Extension	                        (rev 0)
+++ shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ServiceExtensionLoaderTestCase$Extension	2009-11-15 11:28:27 UTC (rev 3703)
@@ -0,0 +1 @@
+org.jboss.shrinkwrap.impl.base.ServiceExtensionLoaderTestCase$ExtensionImpl
\ No newline at end of file

Copied: shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ServiceExtensionLoaderTestCase$WrongImplExtension (from rev 3702, shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ArchiveExtensionLoaderTest$WrongImplExtension)
===================================================================
--- shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ServiceExtensionLoaderTestCase$WrongImplExtension	                        (rev 0)
+++ shrinkwrap/trunk/impl-base/src/test/resources/META-INF/services/org.jboss.shrinkwrap.impl.base.ServiceExtensionLoaderTestCase$WrongImplExtension	2009-11-15 11:28:27 UTC (rev 3703)
@@ -0,0 +1 @@
+org.jboss.shrinkwrap.impl.base.ServiceExtensionLoaderTestCase$ExtensionImpl
\ No newline at end of file



More information about the jboss-svn-commits mailing list