Index: src/test/java/org/codehaus/cargo/generic/FactoryRegistryTest.java
===================================================================
--- src/test/java/org/codehaus/cargo/generic/FactoryRegistryTest.java	(revision 0)
+++ src/test/java/org/codehaus/cargo/generic/FactoryRegistryTest.java	(revision 0)
@@ -0,0 +1,41 @@
+/*
+ * ========================================================================
+ *
+ * Copyright 2006-2008 Vincent Massol.
+ *
+ * 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.codehaus.cargo.generic;
+
+import junit.framework.TestCase;
+import org.codehaus.cargo.generic.deployable.DefaultDeployableFactory;
+import org.codehaus.cargo.container.deployable.DeployableType;
+import org.codehaus.cargo.container.deployable.Deployable;
+
+/**
+ * Tests the discovery behavior.
+ *
+ * The class name can't be {@code AbstractFactoryRegistryTest} or else the test will be skipped.
+ *
+ * @version $Id: $
+ */
+public class FactoryRegistryTest extends TestCase
+{
+    public void test1() {
+        DefaultDeployableFactory f = new DefaultDeployableFactory(getClass().getClassLoader());
+        Deployable war = f.createDeployable("super-container", ".", DeployableType.WAR);
+        assertTrue(war instanceof SuperContainerWar);
+    }
+}
Index: src/test/java/org/codehaus/cargo/generic/TestFactoryRegistry.java
===================================================================
--- src/test/java/org/codehaus/cargo/generic/TestFactoryRegistry.java	(revision 0)
+++ src/test/java/org/codehaus/cargo/generic/TestFactoryRegistry.java	(revision 0)
@@ -0,0 +1,36 @@
+/*
+ * ========================================================================
+ *
+ * Copyright 2006-2008 Vincent Massol.
+ *
+ * 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.codehaus.cargo.generic;
+
+import org.codehaus.cargo.generic.deployable.DeployableFactory;
+import org.codehaus.cargo.container.deployable.DeployableType;
+
+/**
+ * To be discovered by {@link AbstractFactoryRegistry}.
+ * 
+ * @version $Id: $
+ */
+public class TestFactoryRegistry extends AbstractFactoryRegistry
+{
+    protected void register(DeployableFactory factory)
+    {
+        factory.registerDeployable("super-container", DeployableType.WAR, SuperContainerWar.class);
+    }
+}
Index: src/test/java/org/codehaus/cargo/generic/SuperContainerWar.java
===================================================================
--- src/test/java/org/codehaus/cargo/generic/SuperContainerWar.java	(revision 0)
+++ src/test/java/org/codehaus/cargo/generic/SuperContainerWar.java	(revision 0)
@@ -0,0 +1,35 @@
+/*
+ * ========================================================================
+ *
+ * Copyright 2006-2008 Vincent Massol.
+ *
+ * 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.codehaus.cargo.generic;
+
+import org.codehaus.cargo.container.deployable.WAR;
+
+/**
+ * Used by {@link TestFactoryRegistry} to see if the discovery succeeds.
+ *
+ * @version $Id: $
+ */
+public class SuperContainerWar extends WAR
+{
+    public SuperContainerWar(String war)
+    {
+        super(war);
+    }
+}
Index: src/test/resources/META-INF/services/org.codehaus.cargo.generic.AbstractFactoryRegistry
===================================================================
--- src/test/resources/META-INF/services/org.codehaus.cargo.generic.AbstractFactoryRegistry	(revision 0)
+++ src/test/resources/META-INF/services/org.codehaus.cargo.generic.AbstractFactoryRegistry	(revision 0)
@@ -0,0 +1,2 @@
+# test for ABstractFactoryRegistry
+org.codehaus.cargo.generic.TestFactoryRegistry
\ No newline at end of file
Index: src/main/java/org/codehaus/cargo/generic/deployable/DefaultDeployableFactory.java
===================================================================
--- src/main/java/org/codehaus/cargo/generic/deployable/DefaultDeployableFactory.java	(revision 1677)
+++ src/main/java/org/codehaus/cargo/generic/deployable/DefaultDeployableFactory.java	(working copy)
@@ -30,6 +30,7 @@
 import org.codehaus.cargo.generic.spi.AbstractIntrospectionGenericHintFactory;
 import org.codehaus.cargo.generic.internal.util.RegistrationKey;
 import org.codehaus.cargo.generic.internal.util.SimpleContainerIdentity;
+import org.codehaus.cargo.generic.AbstractFactoryRegistry;
 
 import java.lang.reflect.Constructor;
 
@@ -60,12 +61,25 @@
          */
         public String deployable;
     }
-    
+
     /**
      * Register deployable classes mappings.
      */
     public DefaultDeployableFactory()
     {
+        this(null);
+    }
+
+    /**
+     * Register deployable classes mappings.
+     *
+     * @param classLoader
+     *      ClassLoader to discover implementations from. See
+     *      {@link AbstractFactoryRegistry#register(ClassLoader, DeployableFactory)}
+     *      for the details of what this value means.
+     */
+    public DefaultDeployableFactory(ClassLoader classLoader)
+    {
         // The WAR, EJB and EAR deployables are registered by default against all containers.
         // In order not to have to individually register against each container id we
         // create a fictitious default container id.
@@ -91,6 +105,8 @@
             "org.codehaus.cargo.container.geronimo.deployable.GeronimoEAR");
 
         // TODO: Register JBossWAR here when we add JBoss support
+
+        AbstractFactoryRegistry.register(classLoader, this);
     }
 
     /**
Index: src/main/java/org/codehaus/cargo/generic/AbstractFactoryRegistry.java
===================================================================
--- src/main/java/org/codehaus/cargo/generic/AbstractFactoryRegistry.java	(revision 0)
+++ src/main/java/org/codehaus/cargo/generic/AbstractFactoryRegistry.java	(revision 0)
@@ -0,0 +1,139 @@
+/*
+ * ========================================================================
+ *
+ * Copyright 2006-2008 Vincent Massol.
+ *
+ * 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.codehaus.cargo.generic;
+
+import org.apache.commons.discovery.jdk.JDKHooks;
+import org.apache.commons.discovery.resource.ClassLoaders;
+import org.apache.commons.discovery.tools.SPInterface;
+import org.apache.commons.discovery.tools.Service;
+import org.codehaus.cargo.generic.deployable.DeployableFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * SPI to be implemented by container implementation to register implementations
+ * to their factories.
+ *
+ * <p>
+ * This class also provides static methods (to be used primarily within Cargo
+ * but can be also called directly by client apps) to discover all the implementations
+ * and register them to factories.
+ *
+ * <p>
+ * Client apps should normally use {@code DefaultXXXFactory} classes,
+ * like {@link org.codehaus.cargo.generic.deployable.DefaultDeployableFactory},
+ * which internally uses the discovery mechanism
+ *
+ * <p>
+ * Container implementors should override the 1-arg {@code register} methods to register
+ * its implementations to the given factory.
+ *
+ * @version $Id: $
+ */
+public abstract class AbstractFactoryRegistry
+{
+    /**
+     * Discovers all the {@link org.codehaus.cargo.container.deployable.Deployable}s and
+     * adds them to the given {@link DeployableFactory}.
+     *
+     * <p>
+     * The discovery is done by
+     * <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html">the standard service loader
+     * mechanism</a>, by looking for
+     * <tt>/META-INF/services/org.codehaus.cargo.generic.AbstractFactoryRegistry</tt> files.
+     *
+     * @param classLoader
+     *      The class loader to be used to search service provide configuration files.
+     *      If null, the value defaults to the thread context classloader. If that's also null,
+     *      the value defaults to the class loader that loaded {@link FactoryRegistry}.
+     *      In the rare circumstance of that also being null (which means Cargo is loaded in the
+     *      bootstrap classloader), the value defaults to the system class loader.
+     * @param factory
+     *      The factory whose {@code register} method is invoked to receive
+     *      {@link org.codehaus.cargo.container.deployable.Deployable}s that
+     *      are discovered.
+     */
+    public static void register(ClassLoader classLoader, DeployableFactory factory)
+    {
+        for (Iterator itr = list(classLoader).iterator(); itr.hasNext();)
+        {
+            ((AbstractFactoryRegistry) itr.next()).register(factory);
+        }
+    }
+
+    /**
+     * Registers {@link org.codehaus.cargo.container.deployable.Deployable} implementations
+     * to the given {@link DeployableFactory}.
+     *
+     * @param factory
+     *      See {@link #register(ClassLoader, DeployableFactory)} 
+     */
+    protected abstract void register(DeployableFactory factory);
+
+    /**
+     * Lists up {@link FactoryRegistry}s that are discovered.
+     *
+     * @param classLoader
+     *      See {@link #register(ClassLoader, DeployableFactory)} for more details.
+     * @return always non-null but can be empty.
+     */
+    private static List list(ClassLoader classLoader)
+    {
+        ClassLoader cl = classLoader;
+        if (cl == null)
+        {
+            cl = Thread.currentThread().getContextClassLoader();
+        }
+        if (cl == null)
+        {
+            cl = AbstractFactoryRegistry.class.getClassLoader();
+        }
+        if (cl == null)
+        {
+            cl = JDKHooks.getJDKHooks().getSystemClassLoader();
+        }
+        if (cl == null)
+        {
+            // this is not our day. bail out.
+            return Collections.EMPTY_LIST;
+        }
+
+        ClassLoaders loaders = new ClassLoaders();
+        loaders.put(cl);
+
+        List registries = new ArrayList();
+        Enumeration providers = Service.providers(
+                new SPInterface(AbstractFactoryRegistry.class), loaders);
+        while (providers.hasMoreElements())
+        {
+            Object provider = providers.nextElement();
+            if (provider instanceof AbstractFactoryRegistry)
+            {
+                registries.add(provider);
+            }
+        }
+
+        return registries;
+    }
+}
Index: pom.xml
===================================================================
--- pom.xml	(revision 1677)
+++ pom.xml	(working copy)
@@ -35,6 +35,11 @@
       <scope>compile</scope>
     </dependency>
     <dependency>
+      <groupId>commons-discovery</groupId>
+      <artifactId>commons-discovery</artifactId>
+      <version>0.4</version>
+    </dependency>
+    <dependency>
       <groupId>org.codehaus.cargo</groupId>
       <artifactId>cargo-core-api-container</artifactId>
       <version>${version}</version>

