Fix https://issues.apache.org/jira/browse/FELIX-3948

Provide the new extender model.

This work was mostly done by Guillaume Sauthier.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1453391 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/arch-gogo/pom.xml b/ipojo/arch-gogo/pom.xml
index afaad27..8d45776 100644
--- a/ipojo/arch-gogo/pom.xml
+++ b/ipojo/arch-gogo/pom.xml
@@ -40,7 +40,7 @@
         <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.ipojo</artifactId>
-            <version>1.6.2</version>
+            <version>1.9.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.felix</groupId>
diff --git a/ipojo/arch-gogo/src/main/java/org/apache/felix/ipojo/arch/gogo/Arch.java b/ipojo/arch-gogo/src/main/java/org/apache/felix/ipojo/arch/gogo/Arch.java
index ee75edd..6fb6d5e 100644
--- a/ipojo/arch-gogo/src/main/java/org/apache/felix/ipojo/arch/gogo/Arch.java
+++ b/ipojo/arch-gogo/src/main/java/org/apache/felix/ipojo/arch/gogo/Arch.java
@@ -19,6 +19,7 @@
 package org.apache.felix.ipojo.arch.gogo;
 
 import java.io.PrintStream;
+import java.util.Dictionary;
 
 import org.apache.felix.ipojo.ComponentInstance;
 import org.apache.felix.ipojo.Factory;
@@ -30,6 +31,9 @@
 import org.apache.felix.ipojo.annotations.ServiceProperty;
 import org.apache.felix.ipojo.architecture.Architecture;
 import org.apache.felix.ipojo.architecture.InstanceDescription;
+import org.apache.felix.ipojo.extender.ExtensionDeclaration;
+import org.apache.felix.ipojo.extender.InstanceDeclaration;
+import org.apache.felix.ipojo.extender.TypeDeclaration;
 import org.apache.felix.service.command.Descriptor;
 /**
  * iPOJO Arch command giving information about the current
@@ -56,7 +60,8 @@
         "instance",
         "factory",
         "factories",
-        "handlers"
+        "handlers",
+        "extensions"
     };
     
     /**
@@ -76,7 +81,16 @@
      */
     @Requires(optional = true)
     private HandlerFactory[] m_handlers;
-    
+
+    @Requires(optional = true)
+    private InstanceDeclaration[] m_instances;
+
+    @Requires(optional = true)
+    private TypeDeclaration[] m_types;
+
+    @Requires(optional = true)
+    private ExtensionDeclaration[] m_extensions;
+
     /**
      * Displays iPOJO instances.
      */
@@ -95,6 +109,15 @@
                 buffer.append("Instance " + instance.getName() + " -> stopped \n");
             }
         }
+
+        for (InstanceDeclaration instance : m_instances) {
+            // Only print unbound instances (others already printed above)
+            if (!instance.getStatus().isBound()) {
+                buffer.append("Instance " + name(instance.getConfiguration()) + " of type " + instance.getConfiguration().get("component") + " is not bound.\n");
+                buffer.append("  Reason: " + instance.getStatus().getMessage());
+                buffer.append("\n");
+            }
+        }
         
         if (buffer.length() == 0) {
             buffer.append("No instances \n");
@@ -102,7 +125,15 @@
         
         System.out.println(buffer.toString());   
     }
-    
+
+    private String name(Dictionary<String, Object> configuration) {
+        String name = (String) configuration.get("instance.name");
+        if (name == null) {
+            name = "unnamed";
+        }
+        return name;
+    }
+
     /**
      * Displays the architecture of a specific instance.
      * @param instance the instance name
@@ -116,6 +147,17 @@
                 return;
             }
         }
+
+        for (InstanceDeclaration instanceDeclaration : m_instances) {
+            if (!instanceDeclaration.getStatus().isBound()) {
+                if (instance.equals(name(instanceDeclaration.getConfiguration()))) {
+                    System.out.println("Instance " + instance + " not bound to its factory");
+                    System.out.println(" -> " + instanceDeclaration.getStatus().getMessage());
+                    return;
+                }
+            }
+        }
+
         System.err.println("Instance " + instance + " not found");
     }
     
@@ -140,7 +182,17 @@
                 found = true;
             }
         }
-        
+
+
+        for (TypeDeclaration type : m_types) {
+            if (!type.getStatus().isBound()) {
+                if (factory.equals(type.getComponentName())) {
+                    System.out.println("Factory " + factory + " not bound");
+                    System.out.println(" -> " + type.getStatus().getMessage());
+                    found = true;
+                }
+            }
+        }
         if (! found) {
             System.err.println("Factory " + factory + " not found");
         }
@@ -159,6 +211,14 @@
                 buffer.append("Factory " + m_factories[i].getName() + " (INVALID : " + m_factories[i].getMissingHandlers() + ") \n");
             }
         }
+
+        for (TypeDeclaration type : m_types) {
+            if (!type.getStatus().isBound()) {
+                buffer.append("Factory " + type.getComponentName() + " is not bound\n");
+                buffer.append("  Reason: " + type.getStatus().getMessage());
+                buffer.append("\n");
+            }
+        }
         
         if (buffer.length() == 0) {
             buffer.append("No factories \n");
@@ -166,7 +226,7 @@
         
         System.out.println(buffer.toString());
     }
-    
+
     /**
      * Displays the list of available handlers.
      */
@@ -184,6 +244,25 @@
                 out.println("Handler " + name + " (INVALID : " + m_handlers[i].getMissingHandlers() + ")");
             }
         }
+
+        for (TypeDeclaration type : m_types) {
+            if (!type.getStatus().isBound()) {
+                out.println("HandlerFactory " + type.getComponentName() + " is not bound");
+                out.println("  Reason: " + type.getStatus().getMessage());
+            }
+        }
+    }
+
+    /**
+     * Displays the list of available extensions.
+     */
+    @Descriptor("Display iPOJO extensions")
+    public void extensions() {
+        PrintStream out = System.out;
+        out.println("Available extensions:");
+        for (ExtensionDeclaration extension : m_extensions) {
+            out.println("  * " + extension.getExtensionName());
+        }
     }
 
 }
diff --git a/ipojo/runtime/composite-it/src/it/ipojo-composite-import-export-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java b/ipojo/runtime/composite-it/src/it/ipojo-composite-import-export-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
index b242001..1c93fa4 100644
--- a/ipojo/runtime/composite-it/src/it/ipojo-composite-import-export-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
+++ b/ipojo/runtime/composite-it/src/it/ipojo-composite-import-export-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
@@ -21,8 +21,10 @@
 import org.ops4j.pax.exam.spi.reactors.PerMethod;
 import org.ops4j.pax.tinybundles.core.TinyBundle;
 import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
 import org.ow2.chameleon.testing.helpers.IPOJOHelper;
 import org.ow2.chameleon.testing.helpers.OSGiHelper;
 import org.ow2.chameleon.testing.tinybundles.ipojo.IPOJOStrategy;
@@ -129,6 +131,8 @@
         }
         String version = (String) osgiHelper.getBundle(0).getHeaders().get(Constants.BUNDLE_VERSION);
         System.out.println("OSGi Framework : " + vendor + " - " + version);
+
+        waitForStability(bc);
     }
 
     @After
@@ -221,5 +225,75 @@
         fail("Assertion failed : " + s);
     }
 
+    /**
+     * Waits for stability:
+     * <ul>
+     * <li>all bundles are activated
+     * <li>service count is stable
+     * </ul>
+     * If the stability can't be reached after a specified time,
+     * the method throws a {@link IllegalStateException}.
+     * @param context the bundle context
+     * @throws IllegalStateException when the stability can't be reach after a several attempts.
+     */
+    private void waitForStability(BundleContext context) throws IllegalStateException {
+        // Wait for bundle initialization.
+        boolean bundleStability = getBundleStability(context);
+        int count = 0;
+        while (!bundleStability && count < 500) {
+            try {
+                Thread.sleep(5);
+            } catch (InterruptedException e) {
+                // Interrupted
+            }
+            count++;
+            bundleStability = getBundleStability(context);
+        }
+
+        if (count == 500) {
+            System.err.println("Bundle stability isn't reached after 500 tries");
+            throw new IllegalStateException("Cannot reach the bundle stability");
+        }
+
+        boolean serviceStability = false;
+        count = 0;
+        int count1 = 0;
+        int count2 = 0;
+        while (! serviceStability && count < 500) {
+            try {
+                ServiceReference[] refs = context.getServiceReferences((String) null, null);
+                count1 = refs.length;
+                Thread.sleep(500);
+                refs = context.getServiceReferences((String) null, null);
+                count2 = refs.length;
+                serviceStability = count1 == count2;
+            } catch (Exception e) {
+                System.err.println(e);
+                serviceStability = false;
+                // Nothing to do, while recheck the condition
+            }
+            count++;
+        }
+
+        if (count == 500) {
+            System.err.println("Service stability isn't reached after 500 tries (" + count1 + " != " + count2);
+            throw new IllegalStateException("Cannot reach the service stability");
+        }
+    }
+
+    /**
+     * Are bundle stables.
+     * @param bc the bundle context
+     * @return <code>true</code> if every bundles are activated.
+     */
+    private boolean getBundleStability(BundleContext bc) {
+        boolean stability = true;
+        Bundle[] bundles = bc.getBundles();
+        for (int i = 0; i < bundles.length; i++) {
+            stability = stability && (bundles[i].getState() == Bundle.ACTIVE);
+        }
+        return stability;
+    }
+
 
 }
diff --git a/ipojo/runtime/composite-it/src/it/ipojo-composite-instance-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java b/ipojo/runtime/composite-it/src/it/ipojo-composite-instance-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
index b242001..1c93fa4 100644
--- a/ipojo/runtime/composite-it/src/it/ipojo-composite-instance-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
+++ b/ipojo/runtime/composite-it/src/it/ipojo-composite-instance-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
@@ -21,8 +21,10 @@
 import org.ops4j.pax.exam.spi.reactors.PerMethod;
 import org.ops4j.pax.tinybundles.core.TinyBundle;
 import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
 import org.ow2.chameleon.testing.helpers.IPOJOHelper;
 import org.ow2.chameleon.testing.helpers.OSGiHelper;
 import org.ow2.chameleon.testing.tinybundles.ipojo.IPOJOStrategy;
@@ -129,6 +131,8 @@
         }
         String version = (String) osgiHelper.getBundle(0).getHeaders().get(Constants.BUNDLE_VERSION);
         System.out.println("OSGi Framework : " + vendor + " - " + version);
+
+        waitForStability(bc);
     }
 
     @After
@@ -221,5 +225,75 @@
         fail("Assertion failed : " + s);
     }
 
+    /**
+     * Waits for stability:
+     * <ul>
+     * <li>all bundles are activated
+     * <li>service count is stable
+     * </ul>
+     * If the stability can't be reached after a specified time,
+     * the method throws a {@link IllegalStateException}.
+     * @param context the bundle context
+     * @throws IllegalStateException when the stability can't be reach after a several attempts.
+     */
+    private void waitForStability(BundleContext context) throws IllegalStateException {
+        // Wait for bundle initialization.
+        boolean bundleStability = getBundleStability(context);
+        int count = 0;
+        while (!bundleStability && count < 500) {
+            try {
+                Thread.sleep(5);
+            } catch (InterruptedException e) {
+                // Interrupted
+            }
+            count++;
+            bundleStability = getBundleStability(context);
+        }
+
+        if (count == 500) {
+            System.err.println("Bundle stability isn't reached after 500 tries");
+            throw new IllegalStateException("Cannot reach the bundle stability");
+        }
+
+        boolean serviceStability = false;
+        count = 0;
+        int count1 = 0;
+        int count2 = 0;
+        while (! serviceStability && count < 500) {
+            try {
+                ServiceReference[] refs = context.getServiceReferences((String) null, null);
+                count1 = refs.length;
+                Thread.sleep(500);
+                refs = context.getServiceReferences((String) null, null);
+                count2 = refs.length;
+                serviceStability = count1 == count2;
+            } catch (Exception e) {
+                System.err.println(e);
+                serviceStability = false;
+                // Nothing to do, while recheck the condition
+            }
+            count++;
+        }
+
+        if (count == 500) {
+            System.err.println("Service stability isn't reached after 500 tries (" + count1 + " != " + count2);
+            throw new IllegalStateException("Cannot reach the service stability");
+        }
+    }
+
+    /**
+     * Are bundle stables.
+     * @param bc the bundle context
+     * @return <code>true</code> if every bundles are activated.
+     */
+    private boolean getBundleStability(BundleContext bc) {
+        boolean stability = true;
+        Bundle[] bundles = bc.getBundles();
+        for (int i = 0; i < bundles.length; i++) {
+            stability = stability && (bundles[i].getState() == Bundle.ACTIVE);
+        }
+        return stability;
+    }
+
 
 }
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-annotations-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/annotations/Common.java b/ipojo/runtime/core-it/src/it/ipojo-core-annotations-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/annotations/Common.java
index a4c431b..c83ad2c 100644
--- a/ipojo/runtime/core-it/src/it/ipojo-core-annotations-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/annotations/Common.java
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-annotations-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/annotations/Common.java
@@ -19,6 +19,7 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
 import org.ow2.chameleon.testing.helpers.IPOJOHelper;
 import org.ow2.chameleon.testing.helpers.OSGiHelper;
 import org.ow2.chameleon.testing.tinybundles.ipojo.IPOJOStrategy;
@@ -79,6 +80,8 @@
         }
         String version = (String) osgiHelper.getBundle(0).getHeaders().get(Constants.BUNDLE_VERSION);
         System.out.println("OSGi Framework : " + vendor + " - " + version);
+
+        waitForStability(bc);
     }
 
     @After
@@ -152,4 +155,74 @@
         }
     }
 
+    /**
+     * Waits for stability:
+     * <ul>
+     * <li>all bundles are activated
+     * <li>service count is stable
+     * </ul>
+     * If the stability can't be reached after a specified time,
+     * the method throws a {@link IllegalStateException}.
+     * @param context the bundle context
+     * @throws IllegalStateException when the stability can't be reach after a several attempts.
+     */
+    private void waitForStability(BundleContext context) throws IllegalStateException {
+        // Wait for bundle initialization.
+        boolean bundleStability = getBundleStability(context);
+        int count = 0;
+        while (!bundleStability && count < 500) {
+            try {
+                Thread.sleep(5);
+            } catch (InterruptedException e) {
+                // Interrupted
+            }
+            count++;
+            bundleStability = getBundleStability(context);
+        }
+
+        if (count == 500) {
+            System.err.println("Bundle stability isn't reached after 500 tries");
+            throw new IllegalStateException("Cannot reach the bundle stability");
+        }
+
+        boolean serviceStability = false;
+        count = 0;
+        int count1 = 0;
+        int count2 = 0;
+        while (! serviceStability && count < 500) {
+            try {
+                ServiceReference[] refs = context.getServiceReferences((String) null, null);
+                count1 = refs.length;
+                Thread.sleep(500);
+                refs = context.getServiceReferences((String) null, null);
+                count2 = refs.length;
+                serviceStability = count1 == count2;
+            } catch (Exception e) {
+                System.err.println(e);
+                serviceStability = false;
+                // Nothing to do, while recheck the condition
+            }
+            count++;
+        }
+
+        if (count == 500) {
+            System.err.println("Service stability isn't reached after 500 tries (" + count1 + " != " + count2);
+            throw new IllegalStateException("Cannot reach the service stability");
+        }
+    }
+
+    /**
+     * Are bundle stables.
+     * @param bc the bundle context
+     * @return <code>true</code> if every bundles are activated.
+     */
+    private boolean getBundleStability(BundleContext bc) {
+        boolean stability = true;
+        Bundle[] bundles = bc.getBundles();
+        for (int i = 0; i < bundles.length; i++) {
+            stability = stability && (bundles[i].getState() == Bundle.ACTIVE);
+        }
+        return stability;
+    }
+
 }
diff --git a/ipojo/runtime/core-it/src/it/ipojo-core-service-providing-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java b/ipojo/runtime/core-it/src/it/ipojo-core-service-providing-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
index d99d2c6..905b56f 100644
--- a/ipojo/runtime/core-it/src/it/ipojo-core-service-providing-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
+++ b/ipojo/runtime/core-it/src/it/ipojo-core-service-providing-test/src/test/java/org/apache/felix/ipojo/runtime/core/Common.java
@@ -18,8 +18,10 @@
 import org.ops4j.pax.exam.spi.reactors.PerMethod;
 import org.ops4j.pax.tinybundles.core.TinyBundle;
 import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
 import org.ow2.chameleon.testing.helpers.IPOJOHelper;
 import org.ow2.chameleon.testing.helpers.OSGiHelper;
 import org.ow2.chameleon.testing.tinybundles.ipojo.IPOJOStrategy;
@@ -126,6 +128,8 @@
         }
         String version = (String) osgiHelper.getBundle(0).getHeaders().get(Constants.BUNDLE_VERSION);
         System.out.println("OSGi Framework : " + vendor + " - " + version);
+
+        waitForStability(bc);
     }
 
     @After
@@ -212,5 +216,75 @@
         fail("Assertion failed : " + s);
     }
 
+    /**
+     * Waits for stability:
+     * <ul>
+     * <li>all bundles are activated
+     * <li>service count is stable
+     * </ul>
+     * If the stability can't be reached after a specified time,
+     * the method throws a {@link IllegalStateException}.
+     * @param context the bundle context
+     * @throws IllegalStateException when the stability can't be reach after a several attempts.
+     */
+    private void waitForStability(BundleContext context) throws IllegalStateException {
+        // Wait for bundle initialization.
+        boolean bundleStability = getBundleStability(context);
+        int count = 0;
+        while (!bundleStability && count < 500) {
+            try {
+                Thread.sleep(5);
+            } catch (InterruptedException e) {
+                // Interrupted
+            }
+            count++;
+            bundleStability = getBundleStability(context);
+        }
+
+        if (count == 500) {
+            System.err.println("Bundle stability isn't reached after 500 tries");
+            throw new IllegalStateException("Cannot reach the bundle stability");
+        }
+
+        boolean serviceStability = false;
+        count = 0;
+        int count1 = 0;
+        int count2 = 0;
+        while (! serviceStability && count < 500) {
+            try {
+                ServiceReference[] refs = context.getServiceReferences((String) null, null);
+                count1 = refs.length;
+                Thread.sleep(500);
+                refs = context.getServiceReferences((String) null, null);
+                count2 = refs.length;
+                serviceStability = count1 == count2;
+            } catch (Exception e) {
+                System.err.println(e);
+                serviceStability = false;
+                // Nothing to do, while recheck the condition
+            }
+            count++;
+        }
+
+        if (count == 500) {
+            System.err.println("Service stability isn't reached after 500 tries (" + count1 + " != " + count2);
+            throw new IllegalStateException("Cannot reach the service stability");
+        }
+    }
+
+    /**
+     * Are bundle stables.
+     * @param bc the bundle context
+     * @return <code>true</code> if every bundles are activated.
+     */
+    private boolean getBundleStability(BundleContext bc) {
+        boolean stability = true;
+        Bundle[] bundles = bc.getBundles();
+        for (int i = 0; i < bundles.length; i++) {
+            stability = stability && (bundles[i].getState() == Bundle.ACTIVE);
+        }
+        return stability;
+    }
+
 
 }
diff --git a/ipojo/runtime/core/pom.xml b/ipojo/runtime/core/pom.xml
index caf523b..90f7a48 100644
--- a/ipojo/runtime/core/pom.xml
+++ b/ipojo/runtime/core/pom.xml
@@ -84,15 +84,24 @@
                 </exclusion>
             </exclusions>
         </dependency>
+      <dependency>
+        <groupId>org.mockito</groupId>
+        <artifactId>mockito-all</artifactId>
+        <version>1.9.5</version>
+        <scope>test</scope>
+      </dependency>
     </dependencies>
     <build>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.0</version>
                 <configuration>
                     <target>1.5</target>
                     <source>1.5</source>
+                    <testTarget>1.5</testTarget>
+                    <testSource>1.5</testSource>
                 </configuration>
             </plugin>
             <plugin>
@@ -106,8 +115,7 @@
                         <Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
                         <Bundle-SymbolicName>org.apache.felix.ipojo;singleton:=true</Bundle-SymbolicName>
                         <Bundle-Description>iPOJO Core Framework</Bundle-Description>
-                        <Bundle-Activator>org.apache.felix.ipojo.Extender
-                        </Bundle-Activator>
+                        <Bundle-Activator>org.apache.felix.ipojo.extender.internal.Extender</Bundle-Activator>
                         <Bundle-DocURL>
                             http://felix.apache.org/site/apache-felix-ipojo.html
                         </Bundle-DocURL>
@@ -119,6 +127,7 @@
                             org.osgi.framework;version=1.3, <!-- To support KF 2 -->
                             org.osgi.service.cm,
                             org.osgi.service.log,
+                            org.osgi.util.tracker;version=1.3,
                             !sun.io,
                             !net.sourceforge.cobertura.*, <!--  To support code coverage -->
 
@@ -136,6 +145,7 @@
                             org.apache.felix.ipojo.handlers.architecture,
                             org.apache.felix.ipojo.handlers.lifecycle.callback,
                             org.apache.felix.ipojo.handlers.lifecycle.controller,
+                            org.apache.felix.ipojo.extender.internal*,
                             META-INF.services.*,
                             <!-- ASM (Manipulator dependencies) -->
                             org.objectweb.asm.commons,
@@ -147,6 +157,9 @@
                             org.apache.felix.ipojo; version="${ipojo.package.version}",
                             org.apache.felix.ipojo.metadata; version="${ipojo.package.version}",
                             org.apache.felix.ipojo.architecture; version="${ipojo.package.version}",
+                            org.apache.felix.ipojo.extender; version="${ipojo.package.version}",
+                            org.apache.felix.ipojo.extender.builder; version="${ipojo.package.version}",
+                            org.apache.felix.ipojo.extender.queue; version="${ipojo.package.version}",
                             org.apache.felix.ipojo.parser; version="${ipojo.package.version}",
                             org.apache.felix.ipojo.util; version="${ipojo.package.version}",
                             org.apache.felix.ipojo.handlers.dependency; version="${ipojo.package.version}",
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Extender.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Extender.java
deleted file mode 100644
index ed899a9..0000000
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Extender.java
+++ /dev/null
@@ -1,785 +0,0 @@
-/*

- * Licensed to the Apache Software Foundation (ASF) under one

- * or more contributor license agreements.  See the NOTICE file

- * distributed with this work for additional information

- * regarding copyright ownership.  The ASF licenses this file

- * to you under the Apache License, Version 2.0 (the

- * "License"); you may not use this file except in compliance

- * with the License.  You may obtain a copy of the License at

- *

- *   http://www.apache.org/licenses/LICENSE-2.0

- *

- * Unless required by applicable law or agreed to in writing,

- * software distributed under the License is distributed on an

- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY

- * KIND, either express or implied.  See the License for the

- * specific language governing permissions and limitations

- * under the License.

- */

-package org.apache.felix.ipojo;

-

-import java.io.IOException;

-import java.lang.reflect.Constructor;

-import java.lang.reflect.Field;

-import java.lang.reflect.InvocationTargetException;

-import java.lang.reflect.Method;

-import java.util.ArrayList;

-import java.util.Dictionary;

-import java.util.HashMap;

-import java.util.Iterator;

-import java.util.List;

-import java.util.Map;

-

-import org.apache.felix.ipojo.metadata.Element;

-import org.apache.felix.ipojo.parser.ManifestMetadataParser;

-import org.apache.felix.ipojo.parser.ParseException;

-import org.apache.felix.ipojo.parser.ParseUtils;

-import org.apache.felix.ipojo.util.Logger;

-import org.osgi.framework.Bundle;

-import org.osgi.framework.BundleActivator;

-import org.osgi.framework.BundleContext;

-import org.osgi.framework.BundleEvent;

-import org.osgi.framework.SynchronousBundleListener;

-

-/**

- * iPOJO Extender.

- * This class listens bundle arrivals and departures in order to detect and manage

- * iPOJO powered bundles. This class creates factories and ask for instance creation.

- * @see SynchronousBundleListener

- * @see BundleActivator

- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

- */

-public class Extender implements SynchronousBundleListener, BundleActivator {

-

-    /**

-     * Enables the iPOJO internal dispatcher.

-     * This internal dispatcher helps the OSGi framework to support large

-     * scale applications. The internal dispatcher is disabled by default.

-     */

-    static boolean DISPATCHER_ENABLED = true;

-

-    /**

-     * Disables the iPOJO asynchronous processing.

-     * When set to false, the bundles are processed in the listener thread

-     * making iPOJO usable on Google App Engine. By default, the processing

-     * is asynchronous.

-     */

-    static boolean SYNCHRONOUS_PROCESSING_ENABLED = false;

-

-    /**

-     * Property allowing to set if the internal dispatcher is enabled or disabled.

-     * Possible value are either <code>true</code> or <code>false</code>.

-     */

-    private static final String ENABLING_DISPATCHER = "ipojo.internal.dispatcher";

-

-    /**

-     * Property allowing to disable the asynchronous process (and so enables the

-     * synchronous processing).

-     * Possible value are either <code>true</code> or <code>false</code>.

-     */

-    private static final String SYNCHRONOUS_PROCESSING = "ipojo.processing.synchronous";

-

-    /**

-     * iPOJO Component Type and Instance declaration header.

-     */

-    private static final String IPOJO_HEADER = "iPOJO-Components";

-

-    /**

-     * iPOJO Component Type and Instance declaration header

-     * (alternative).

-     * This header was introduced because of BND supporting only header

-     * starting with an uppercase.

-     */

-    private static final String IPOJO_HEADER_ALT = "IPOJO-Components";

-

-    /**

-     * iPOJO Extension declaration header.

-     */

-    private static final String IPOJO_EXTENSION = "IPOJO-Extension";

-

-    /**

-     * The Bundle Context of the iPOJO Core bundle.

-     */

-    private static BundleContext m_context;

-

-    /**

-     * The iPOJO Extender logger.

-     */

-    private Logger m_logger;

-

-    /**

-     * The instance creator used to create instances.

-     * (Singleton)

-     */

-    private InstanceCreator m_creator;

-

-    /**

-     * The iPOJO Bundle.

-     */

-    private Bundle m_bundle;

-

-    /**

-     * The list of factory types.

-     */

-    private List m_factoryTypes = new ArrayList();

-

-    /**

-     * The list of unbound types.

-     * A type is unbound if the matching extension is not deployed.

-     */

-    private final List m_unboundTypes = new ArrayList();

-

-    /**

-     * The processor analyzing arriving bundles and creating iPOJO contributions.

-     */

-    private final CreatorThread m_processor = new CreatorThread();

-

-    /**

-     * Bundle Listener Notification.

-     * @param event the bundle event.

-     * @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent)

-     */

-    public void bundleChanged(final BundleEvent event) {

-        if (event.getBundle() == m_bundle) { return; }

-

-        switch (event.getType()) {

-            case BundleEvent.STARTED:

-                // Put the bundle in the queue

-                m_processor.addBundle(event.getBundle());

-                break;

-            case BundleEvent.STOPPING:

-                m_processor.removeBundle(event.getBundle());

-                //TODO Should be done in another thread in the asynchronous case.

-                closeManagementFor(event.getBundle());

-                break;

-            default:

-                break;

-        }

-

-    }

-

-    /**

-     * Ends the iPOJO Management for the given bundle.

-     * Generally the bundle is leaving. This method

-     * stops every factories declared is the bundle and

-     * disposed every declared instances.

-     * @param bundle the bundle.

-     */

-    private void closeManagementFor(Bundle bundle) {

-        List toRemove = new ArrayList();

-        // Delete instances declared in the leaving bundle.

-        m_creator.removeInstancesFromBundle(bundle.getBundleId());

-        for (int k = 0; k < m_factoryTypes.size(); k++) {

-            ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) m_factoryTypes.get(k);

-

-            // Look for component type created from this bundle.

-            if (mft.m_created != null) {

-                List cfs = (List) mft.m_created.remove(bundle);

-                for (int i = 0; cfs != null && i < cfs.size(); i++) {

-                    IPojoFactory factory = (IPojoFactory) cfs.get(i);

-                    m_creator.removeFactory(factory);

-                    factory.stop();

-                }

-            }

-

-            // If the leaving bundle has declared mft : destroy all created factories.

-            if (mft.m_bundle == bundle) {

-                if (mft.m_created != null) {

-                    Iterator iterator = mft.m_created.keySet().iterator();

-                    while (iterator.hasNext()) {

-                        Bundle key = (Bundle) iterator.next();

-                        List list = (List) mft.m_created.get(key);

-                        for (int i = 0; i < list.size(); i++) {

-                            IPojoFactory factory = (IPojoFactory) list.get(i);

-                            factory.stop();

-                            m_unboundTypes.add(new UnboundComponentType(mft.m_type, factory.m_componentMetadata, factory.getBundleContext()

-                                    .getBundle()));

-                        }

-                    }

-                }

-                toRemove.add(mft);

-            }

-        }

-

-        for (int i = 0; i < toRemove.size(); i++) {

-            ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) toRemove.get(i);

-            m_logger.log(Logger.INFO, "The factory type: " + mft.m_type + " is no more available");

-            mft.m_bundle = null;

-            mft.m_clazz = null;

-            mft.m_created = null;

-            mft.m_type = null;

-            m_factoryTypes.remove(mft);

-        }

-    }

-

-    /**

-     * Checks if the given bundle is an iPOJO bundle, and begin

-     * the iPOJO management is true.

-     * @param bundle the bundle to check.

-     */

-    private void startManagementFor(Bundle bundle) {

-        Dictionary dict = bundle.getHeaders();

-        // Check for abstract factory type

-        String typeHeader = (String) dict.get(IPOJO_EXTENSION);

-        if (typeHeader != null) {

-            parseAbstractFactoryType(bundle, typeHeader);

-        }

-

-        // Check bundle

-        String header = (String) dict.get(IPOJO_HEADER);

-        // Check the alternative header

-        if (header == null) {

-            header = (String) dict.get(IPOJO_HEADER_ALT);

-        }

-

-        if (header != null) {

-            try {

-                parse(bundle, header);

-            } catch (IOException e) {

-                m_logger.log(Logger.ERROR, "An exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);

-            } catch (ParseException e) {

-                m_logger.log(Logger.ERROR, "A parse exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);

-            }

-        }

-    }

-

-    /**

-     * Parses an IPOJO-Extension manifest header and then creates

-     * iPOJO extensions (factory types).

-     * @param bundle the bundle containing the header.

-     * @param header the header to parse.

-     */

-    private void parseAbstractFactoryType(Bundle bundle, String header) {

-        String[] arr = ParseUtils.split(header, ",");

-        for (int i = 0; arr != null && i < arr.length; i++) {

-            String[] arr2 = ParseUtils.split(arr[i], ":");

-            

-            /*

-             * Get the fully qualified type name.

-             * type = [namespace] name  

-             */

-            String[] nameparts = ParseUtils.split(arr2[0].trim(), " \t");

-            String type = nameparts.length == 1 ? nameparts[0] : nameparts[0]+":"+nameparts[1];

-            

-            Class clazz;

-            try {

-                clazz = bundle.loadClass(arr2[1]);

-            } catch (ClassNotFoundException e) {

-                m_logger.log(Logger.ERROR, "Cannot load the extension " + type, e);

-                return;

-            }

-            ManagedAbstractFactoryType mft = new ManagedAbstractFactoryType(clazz, type, bundle);

-            m_factoryTypes.add(mft);

-            m_logger.log(Logger.DEBUG, "New factory type available: " + type);

-

-            for (int j = m_unboundTypes.size() - 1; j >= 0; j--) {

-                UnboundComponentType unbound = (UnboundComponentType) m_unboundTypes.get(j);

-                if (unbound.m_type.equals(type)) {

-                    createAbstractFactory(unbound.m_bundle, unbound.m_description);

-                    m_unboundTypes.remove(unbound);

-                }

-            }

-        }

-    }

-

-    /**

-     * Parses the internal metadata (from the manifest

-     * (in the iPOJO-Components property)). This methods

-     * creates factories and add instances to the instance creator.

-     * @param bundle the owner bundle.

-     * @param components The iPOJO Header String.

-     * @throws IOException if the manifest can not be found

-     * @throws ParseException if the parsing process failed

-     */

-    private void parse(Bundle bundle, String components) throws IOException, ParseException {

-        ManifestMetadataParser parser = new ManifestMetadataParser();

-        parser.parseHeader(components);

-

-        // Get the component type declaration

-        Element[] metadata = parser.getComponentsMetadata();

-        for (int i = 0; i < metadata.length; i++) {

-            createAbstractFactory(bundle, metadata[i]);

-        }

-

-        Dictionary[] instances = parser.getInstances();

-        for (int i = 0; instances != null && i < instances.length; i++) {

-            m_creator.addInstance(instances[i], bundle.getBundleId());

-        }

-    }

-

-    /**

-     * iPOJO Start method.

-     * @param context the iPOJO bundle context.

-     * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)

-     */

-    public void start(BundleContext context) {

-        m_context = context;

-        m_bundle = context.getBundle();

-        m_creator = new InstanceCreator(context);

-

-        m_logger = new Logger(m_context, "IPOJO-Extender");

-

-        enablingDispatcher(context, m_logger);

-        enablingSynchronousProcessing(context, m_logger);

-

-        // Create the dispatcher only if required.

-        if (DISPATCHER_ENABLED) {

-            EventDispatcher.create(context);

-        }

-

-        // Begin by initializing core handlers

-        startManagementFor(m_bundle);

-

-        if (! SYNCHRONOUS_PROCESSING_ENABLED) {

-            new Thread(m_processor).start();

-        }

-

-        synchronized (this) {

-            // listen to any changes in bundles.

-            m_context.addBundleListener(this);

-            // compute already started bundles.

-            for (int i = 0; i < context.getBundles().length; i++) {

-                if (context.getBundles()[i].getState() == Bundle.ACTIVE) {

-                    m_processor.addBundle(context.getBundles()[i]); // Bundles are processed in another thread.

-                }

-            }

-        }

-

-        m_logger.log(Logger.INFO, "iPOJO Runtime started");

-    }

-

-    /**

-     * Stops the iPOJO Bundle.

-     * @param context the bundle context.

-     * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)

-     */

-    public void stop(BundleContext context) {

-        m_processor.stop(); // Stop the thread processing bundles.

-        m_context.removeBundleListener(this);

-

-        if (DISPATCHER_ENABLED) {

-            EventDispatcher.dispose();

-        }

-

-        for (int k = 0; k < m_factoryTypes.size(); k++) {

-            ManagedAbstractFactoryType mft = (ManagedAbstractFactoryType) m_factoryTypes.get(k);

-

-            if (mft.m_created != null) {

-                Iterator iterator = mft.m_created.keySet().iterator();

-                while (iterator.hasNext()) {

-                    Bundle key = (Bundle) iterator.next();

-                    List list = (List) mft.m_created.get(key);

-                    for (int i = 0; i < list.size(); i++) {

-                        IPojoFactory factory = (IPojoFactory) list.get(i);

-                        m_creator.removeFactory(factory);

-                        factory.dispose();

-                    }

-                }

-            }

-        }

-

-        m_factoryTypes = null;

-        m_creator = null;

-

-        m_logger.log(Logger.INFO, "iPOJO Runtime stopped");

-        m_context = null;

-    }

-

-    /**

-     * Gets iPOJO bundle context.

-     * @return the iPOJO Bundle Context

-     */

-    public static BundleContext getIPOJOBundleContext() {

-        return m_context;

-    }

-

-    /**

-     * Enables or disables the internal dispatcher, so sets the

-     * {@link Extender#DISPATCHER_ENABLED} flag.

-     * This method checks if the {@link Extender#ENABLING_DISPATCHER}

-     * property is set to <code>true</code>. Otherwise, the internal

-     * dispatcher is disabled. The property can be set as a system

-     * property (<code>ipojo.internal.dispatcher</code>) or inside the

-     * iPOJO bundle manifest (<code>ipojo-internal-dispatcher</code>).

-     * @param context the bundle context.

-     * @param logger the logger to indicates if the internal dispatcher is set.

-     */

-    private static void enablingDispatcher(BundleContext context, Logger logger) {

-        // First check in the framework and in the system properties

-        String flag = context.getProperty(ENABLING_DISPATCHER);

-

-        // If null, look in bundle manifest

-        if (flag == null) {

-            String key = ENABLING_DISPATCHER.replace('.', '-');

-            flag = (String) context.getBundle().getHeaders().get(key);

-        }

-

-        if (flag != null) {

-            if (flag.equalsIgnoreCase("true")) {

-                Extender.DISPATCHER_ENABLED = true;

-                logger.log(Logger.INFO, "iPOJO Internal Event Dispatcher enables");

-                return;

-            }

-        }

-

-        // Either l is null, or the specified value was false

-        Extender.DISPATCHER_ENABLED = false;

-        logger.log(Logger.INFO, "iPOJO Internal Event Dispatcher disables");

-

-    }

-

-    /**

-     * Enables or disables the asynchronous processing, so sets the

-     * {@link Extender#SYNCHRONOUS_PROCESSING_ENABLED} flag.

-     * Disabling asynchronous processing avoids iPOJO to create a new

-     * thread to process bundles. So, iPOJO can be used on the

-     * Google App Engine.

-     * This method checks if the {@link Extender#SYNCHRONOUS_PROCESSING}

-     * property is set to <code>true</code>. Otherwise, asynchronous processing

-     * is used (default). The property can be set as a system

-     * property (<code>ipojo.processing.synchronous</code>) or inside the

-     * iPOJO bundle manifest.

-     * @param context the bundle context.

-     * @param logger the logger to indicates if the internal dispatcher is set.

-     */

-    private static void enablingSynchronousProcessing(BundleContext context, Logger logger) {

-        String flag = context.getProperty(SYNCHRONOUS_PROCESSING);

-

-        // If null, look in bundle manifest

-        if (flag == null) {

-            String key = SYNCHRONOUS_PROCESSING.replace('.', '-');

-            flag = (String) context.getBundle().getHeaders().get(key);

-        }

-

-        if (flag != null) {

-            if (flag.equalsIgnoreCase("true")) {

-                Extender.SYNCHRONOUS_PROCESSING_ENABLED = true;

-                logger.log(Logger.INFO, "iPOJO Asynchronous processing disabled");

-                return;

-            }

-        }

-

-        // Either l is null, or the specified value was false

-        Extender.SYNCHRONOUS_PROCESSING_ENABLED = false;

-        logger.log(Logger.INFO, "iPOJO synchrnous processing disables");

-

-    }

-

-    /**

-     * Adds a component factory to the factory list.

-     * @param metadata the new component metadata.

-     * @param bundle the bundle.

-     */

-    private void createAbstractFactory(Bundle bundle, Element metadata) {

-        ManagedAbstractFactoryType factoryType = null;

-        // First, look for factory-type (component, handler, composite ...)

-        

-        // TODO : Should Element.getQualifiedName() be public ?

-        String typeName = metadata.getNameSpace() == null ? metadata.getName() : metadata.getNameSpace()+":"+metadata.getName();

-        

-        for (int i = 0; i < m_factoryTypes.size(); i++) {

-            ManagedAbstractFactoryType type = (ManagedAbstractFactoryType) m_factoryTypes.get(i);

-            if (type.m_type.equals(typeName)) {

-                factoryType = type;

-                break;

-            }

-        }

-

-        // If not found, return. It will wait for a new component type factory.

-        if (factoryType == null) {

-            m_logger.log(Logger.WARNING, "Type of component not available: " + typeName);

-            m_unboundTypes.add(new UnboundComponentType(typeName, metadata, bundle));

-            return;

-        }

-

-        // Once found, we invoke the AbstractFactory constructor to create the component factory.

-        Class clazz = factoryType.m_clazz;

-        try {

-            // Look for the constructor, and invoke it.

-            Constructor cst = clazz.getConstructor(new Class[] { BundleContext.class, Element.class });

-            IPojoFactory factory = (IPojoFactory) cst.newInstance(new Object[] { getBundleContext(bundle), metadata });

-

-            // Add the created factory in the m_createdFactories map.

-            if (factoryType.m_created == null) {

-                factoryType.m_created = new HashMap();

-                List list = new ArrayList();

-                list.add(factory);

-                factoryType.m_created.put(bundle, list);

-            } else {

-                List list = (List) factoryType.m_created.get(bundle);

-                if (list == null) {

-                    list = new ArrayList();

-                    list.add(factory);

-                    factoryType.m_created.put(bundle, list);

-                } else {

-                    list.add(factory);

-                }

-            }

-

-            // Start the created factory.

-            factory.start();

-            // Then add the factory to the instance creator.

-            m_creator.addFactory(factory);

-

-        } catch (SecurityException e) {

-            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);

-        } catch (NoSuchMethodException e) {

-            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName() + ": the given class constructor cannot be found");

-        } catch (IllegalArgumentException e) {

-            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);

-        } catch (InstantiationException e) {

-            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);

-        } catch (IllegalAccessException e) {

-            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);

-        } catch (InvocationTargetException e) {

-            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e.getTargetException());

-        } catch(Throwable e) {

-            // Intercepts everything else to avoid complete crash.

-            m_logger.log(Logger.ERROR, "Cannot instantiate an abstract factory from " + clazz.getName(), e);

-        }

-    }

-

-    /**

-     * Structure storing an iPOJO extension.

-     */

-    private static final class ManagedAbstractFactoryType {

-        /**

-         * The type (i.e.) name of the extension.

-         */

-        String m_type;

-

-        /**

-         * The abstract Factory class.

-         */

-        Class m_clazz;

-

-        /**

-         * The bundle object containing the declaration of the extension.

-         */

-        Bundle m_bundle;

-

-        /**

-         * The factories created by this extension.

-         */

-        private Map m_created;

-

-        /**

-         * Creates a ManagedAbstractFactoryType.

-         * @param factory the abstract factory class.

-         * @param type the name of the extension.

-         * @param bundle the bundle declaring the extension.

-         */

-        protected ManagedAbstractFactoryType(Class factory, String type, Bundle bundle) {

-            m_bundle = bundle;

-            m_clazz = factory;

-            m_type = type;

-        }

-    }

-

-    /**

-     * Structure storing unbound component type declarations.

-     * Unbound means that there is no extension able to manage the extension.

-     */

-    private static final class UnboundComponentType {

-        /**

-         * The component type description.

-         */

-        private final Element m_description;

-

-        /**

-         * The bundle declaring this type.

-         */

-        private final Bundle m_bundle;

-

-        /**

-         * The required extension name.

-         */

-        private final String m_type;

-

-        /**

-         * Creates a UnboundComponentType.

-         * @param description the description of the component type.

-         * @param bundle the bundle declaring this type.

-         * @param type the required extension name.

-         */

-        protected UnboundComponentType(String type, Element description, Bundle bundle) {

-            m_type = type;

-            m_description = description;

-            m_bundle = bundle;

-        }

-    }

-

-    /**

-     * Computes the bundle context from the bundle class by introspection.

-     * @param bundle the bundle.

-     * @return the bundle context object or <code>null</code> if not found.

-     */

-    public BundleContext getBundleContext(Bundle bundle) {

-        if (bundle == null) { return null; }

-

-        // getBundleContext (OSGi 4.1)

-        Method meth = null;

-        try {

-            meth = bundle.getClass().getMethod("getBundleContext", new Class[0]); // This method is public and is specified in the Bundle interface.

-        } catch (SecurityException e) {

-            // Nothing do to, will try the Equinox method

-        } catch (NoSuchMethodException e) {

-            // Nothing do to, will try the Equinox method

-        }

-

-        // try Equinox getContext if not found.

-        if (meth == null) {

-            try {

-                meth = bundle.getClass().getMethod("getContext", new Class[0]);

-            } catch (SecurityException e) {

-                // Nothing do to, will try field inspection

-            } catch (NoSuchMethodException e) {

-                // Nothing do to, will try field inspection

-            }

-        }

-

-        if (meth != null) {

-            if (! meth.isAccessible()) {

-                // If not accessible, try to set the accessibility.

-                meth.setAccessible(true);

-            }

-            try {

-                return (BundleContext) meth.invoke(bundle, new Object[0]);

-            } catch (IllegalArgumentException e) {

-                m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);

-                return null;

-            } catch (IllegalAccessException e) {

-                m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e);

-                return null;

-            } catch (InvocationTargetException e) {

-                m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + meth.getName(), e.getTargetException());

-                return null;

-            }

-        }

-

-        // Else : Field inspection (KF and Prosyst)

-        Field[] fields = bundle.getClass().getDeclaredFields();

-        for (int i = 0; i < fields.length; i++) {

-            if (BundleContext.class.isAssignableFrom(fields[i].getType())) {

-                if (!fields[i].isAccessible()) {

-                    fields[i].setAccessible(true);

-                }

-                try {

-                    return (BundleContext) fields[i].get(bundle);

-                } catch (IllegalArgumentException e) {

-                    m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + fields[i].getName(), e);

-                    return null;

-                } catch (IllegalAccessException e) {

-                    m_logger.log(Logger.ERROR, "Cannot get the BundleContext by invoking " + fields[i].getName(), e);

-                    return null;

-                }

-            }

-        }

-        m_logger.log(Logger.ERROR, "Cannot find the BundleContext for " + bundle.getSymbolicName(), null);

-        return null;

-    }

-

-

-    /**

-     * The creator thread analyzes arriving bundles to create iPOJO contribution.

-     */

-    private class CreatorThread implements Runnable {

-

-        /**

-         * Is the creator thread started?

-         */

-        private boolean m_started = true;

-

-        /**

-         * The list of bundle that are going to be analyzed.

-         */

-        private List m_bundles = new ArrayList();

-

-        /**

-         * A bundle is arriving.

-         * This method is synchronized to avoid concurrent modification of the waiting list.

-         * @param bundle the new bundle

-         */

-        public synchronized void addBundle(Bundle bundle) {

-            if (SYNCHRONOUS_PROCESSING_ENABLED) {

-                m_logger.log(Logger.DEBUG, "Analyzing " + bundle.getBundleId());

-                startManagementFor(bundle);

-            } else {

-                // Asynchronous case, we add the bundle to the queue

-                m_bundles.add(bundle);

-                notifyAll(); // Notify the thread to force the process.

-                m_logger.log(Logger.DEBUG, "Creator thread is going to analyze the bundle " + bundle.getBundleId() + " List : " + m_bundles);

-            }

-        }

-

-        /**

-         * A bundle is leaving.

-         * If the bundle was not already processed, the bundle is remove from the waiting list.

-         * This method is synchronized to avoid concurrent modification of the waiting list.

-         * @param bundle the leaving bundle.

-         */

-        public synchronized void removeBundle(Bundle bundle) {

-            m_bundles.remove(bundle);

-        }

-

-        /**

-         * Stops the creator thread.

-         */

-        public synchronized void stop() {

-            m_started = false;

-            m_bundles.clear();

-            notifyAll();

-        }

-

-        /**

-         * Creator thread's run method.

-         * While the list is not empty, the thread launches the bundle analyzing on the next bundle.

-         * When the list is empty, the thread sleeps until the arrival of a new bundle

-         * or until iPOJO stops.

-         * @see java.lang.Runnable#run()

-         */

-        public void run() {

-            m_logger.log(Logger.DEBUG, "Creator thread is starting");

-            boolean started;

-            synchronized (this) {

-                started = m_started;

-            }

-            while (started) {

-                Bundle bundle;

-                synchronized (this) {

-                    while (m_started && m_bundles.isEmpty()) {

-                        try {

-                            m_logger.log(Logger.DEBUG, "Creator thread is waiting - Nothing to do");

-                            wait();

-                        } catch (InterruptedException e) {

-                            // Interruption, re-check the condition

-                        }

-                    }

-                    if (!m_started) {

-                        m_logger.log(Logger.DEBUG, "Creator thread is stopping");

-                        return; // The thread must be stopped immediately.

-                    } else {

-                        // The bundle list is not empty, get the bundle.

-                        // The bundle object is collected inside the synchronized block to avoid

-                        // concurrent modification. However the real process is made outside the

-                        // mutual exclusion area

-                        bundle = (Bundle) m_bundles.remove(0);

-                    }

-                }

-                // Process ...

-                m_logger.log(Logger.DEBUG, "Creator thread is processing " + bundle.getBundleId());

-                try {

-                    startManagementFor(bundle);

-                } catch (Throwable e) {

-                    // To be sure to not kill the thread, we catch all exceptions and errors

-                    m_logger.log(Logger.ERROR, "An error occurs when analyzing the content or starting the management of " + bundle.getBundleId(), e);

-                }

-                synchronized (this) {

-                    started = m_started;

-                }

-            }

-        }

-

-    }

-

-}

diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Factory.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Factory.java
index f18c1d3..8ffc9de 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Factory.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/Factory.java
@@ -44,6 +44,17 @@
      */
     int INVALID = 0;
 
+
+    /**
+     * Instance configuration can set the instance name using this property.
+     */
+    String INSTANCE_NAME_PROPERTY = "instance.name";
+
+    /**
+     * Instance configuration can set the factory version they target using this property.
+     */
+    String FACTORY_VERSION_PROPERTY = "factory.version";
+
     /**
      * Creates an instance manager (i.e. component type instance).
      * @param configuration the configuration properties for this component.
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
index ade4045..0d13551 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
@@ -18,18 +18,9 @@
  */

 package org.apache.felix.ipojo;

 

-import java.util.ArrayList;

-import java.util.Collections;

-import java.util.Dictionary;

-import java.util.HashMap;

-import java.util.Iterator;

-import java.util.List;

-import java.util.Map;

-import java.util.Properties;

-import java.util.Set;

-

 import org.apache.felix.ipojo.architecture.ComponentTypeDescription;

 import org.apache.felix.ipojo.architecture.PropertyDescription;

+import org.apache.felix.ipojo.extender.internal.Extender;

 import org.apache.felix.ipojo.metadata.Element;

 import org.apache.felix.ipojo.util.Logger;

 import org.apache.felix.ipojo.util.SecurityHelper;

@@ -39,6 +30,8 @@
 import org.osgi.framework.ServiceRegistration;

 import org.osgi.service.cm.ManagedServiceFactory;

 

+import java.util.*;

+

 /**

  * This class defines common mechanisms of iPOJO component factories

  * (i.e. component type).

@@ -276,12 +269,12 @@
 

         // Find name in the configuration

         String name;

-        if (configuration.get("instance.name") == null && configuration.get("name") == null) {

+        if (configuration.get(Factory.INSTANCE_NAME_PROPERTY) == null && configuration.get("name") == null) {

             // No name provided

             name = null;

         } else {

             // Support both instance.name & name

-            name = (String) configuration.get("instance.name");

+            name = (String) configuration.get(Factory.INSTANCE_NAME_PROPERTY);

             if (name == null) {

                 name = (String) configuration.get("name");

                 getLogger().log(Logger.WARNING, "The 'name' (" + name + ") attribute, used as the instance name, is deprecated, please use the 'instance.name' attribute");

@@ -292,9 +285,9 @@
         // Generate a unique name if required and verify uniqueness

         // We extract the version from the configuration because it may help to compute a unique name by appending

         // the version to the given name.

-        String version = (String) configuration.get("factory.version");

+        String version = (String) configuration.get(Factory.FACTORY_VERSION_PROPERTY);

         name = m_generator.generate(name, version);

-        configuration.put("instance.name", name);

+        configuration.put(Factory.INSTANCE_NAME_PROPERTY, name);

 

         // Here we are sure to be valid until the end of the method.

         HandlerManager[] handlers = new HandlerManager[m_requiredHandlers.size()];

@@ -478,11 +471,11 @@
      * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)

      */

     public synchronized void reconfigure(Dictionary properties) throws UnacceptableConfiguration, MissingHandlerException {

-        if (properties == null || (properties.get("instance.name") == null && properties.get("name") == null)) { // Support both instance.name and name

+        if (properties == null || (properties.get(Factory.INSTANCE_NAME_PROPERTY) == null && properties.get("name") == null)) { // Support both instance.name and name

             throw new UnacceptableConfiguration("The configuration does not contains the \"instance.name\" property");

         }

 

-        String name = (String) properties.get("instance.name");

+        String name = (String) properties.get(Factory.INSTANCE_NAME_PROPERTY);

         if (name == null) {

             name = (String) properties.get("name");

         }

@@ -653,7 +646,7 @@
 

         if (instance == null) {

             try {

-                properties.put("instance.name", name); // Add the name in the configuration

+                properties.put(Factory.INSTANCE_NAME_PROPERTY, name); // Add the name in the configuration

                 // If an instance with this name was created before, this creation will failed.

                 createComponentInstance(properties);

             } catch (UnacceptableConfiguration e) {

@@ -668,7 +661,7 @@
             }

         } else {

             try {

-                properties.put("instance.name", name); // Add the name in the configuration

+                properties.put(Factory.INSTANCE_NAME_PROPERTY, name); // Add the name in the configuration

                 reconfigure(properties); // re-configure the component

             } catch (UnacceptableConfiguration e) {

                 m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());

diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
deleted file mode 100644
index d66e301..0000000
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.ipojo;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.felix.ipojo.util.Logger;
-import org.osgi.framework.BundleContext;
-
-/**
- * The instance creator creates instances and tracks their factories.
- * It allows creating instances from external factories.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class InstanceCreator implements FactoryStateListener {
-
-    /**
-     * The logger to log messages if errors occur.
-     */
-    private Logger m_logger;
-
-    /**
-     * The configurations to create and to maintain.
-     */
-    private List m_idle = new ArrayList();
-
-    /**
-     * The map storing created instances.
-     * This map contains [AbstractFactory, List [ManagedInstance]] couples.
-     */
-    private Map m_attached = new HashMap();
-
-    /**
-     * The abstract factory list.
-     */
-    private List m_factories = new ArrayList();
-
-    /**
-     * Creates the instance creator.
-     * This object is generally a singleton.
-     * @param context the bundle context of the iPOJO bundle.
-     */
-    public InstanceCreator(BundleContext context) {
-        m_logger = new Logger(context, "iPOJO Instance Creator");
-    }
-
-    /**
-     * Adds an instance to manage.
-     * @param instance the instance configuration
-     * @param bundle the bundle id declaring the instance
-     */
-    synchronized void addInstance(Dictionary instance, long bundle) {
-        if (instance.get("factory.version") != null) {
-            m_logger.log(Logger.DEBUG, "New instance to managed, looking for " + instance.get("component") + "-" + instance.get("factory.version"));
-        } else {
-            m_logger.log(Logger.DEBUG, "New instance to managed, looking for " + instance.get("component"));
-        }
-
-        ManagedInstance managed = new ManagedInstance(instance, bundle);
-        for (int i = 0; i < m_factories.size(); i++) {
-            IPojoFactory factory = (IPojoFactory) m_factories.get(i);
-            if (managed.matchNameAndVersion(factory)) {
-                // Subscribe to the factory state change
-                m_logger.log(Logger.DEBUG, "Listen factory " + factory.getName() + " events");
-                factory.addFactoryStateListener(this);
-                if (factory.getState() == Factory.VALID && managed.match(factory)) {
-                    managed.create(factory);
-                    List list = (List) m_attached.get(factory);
-                    if (list == null) {
-                        list = new ArrayList();
-                        list.add(managed);
-                        m_attached.put(factory, list);
-                    } else {
-                        list.add(managed);
-                    }
-                    return;
-                }
-            }
-        }
-        // If there is no matching factory, add the instance to the idle list
-        m_idle.add(managed);
-    }
-
-    /**
-     * Disposes all instances declared by the given (leaving) bundle.
-     * @param bundle the bundle.
-     */
-    void removeInstancesFromBundle(long bundle) {
-        // Disposes instance from attached instances
-        Map copy = null;
-
-        // To avoid concurrent modification exception, we create a copy.
-        synchronized (this) {
-            copy = new HashMap(m_attached);
-        }
-
-        Collection col = copy.keySet();
-        Iterator iterator = col.iterator();
-        List instanceToRemove = new ArrayList();
-        List factoryToRemove = new ArrayList();
-        while (iterator.hasNext()) {
-            IPojoFactory factory = (IPojoFactory) iterator.next();
-            List list = (List) copy.get(factory);
-            for (int i = 0; i < list.size(); i++) {
-                ManagedInstance managed = (ManagedInstance) list.get(i);
-                if (managed.m_bundleId == bundle) {
-                    managed.dispose();
-                    instanceToRemove.add(managed);
-                }
-            }
-            if (!instanceToRemove.isEmpty()) {
-                list.removeAll(instanceToRemove);
-                if (list.isEmpty()) {
-                    factory.removeFactoryStateListener(this);
-                    factoryToRemove.add(factory);
-                }
-            }
-        }
-
-        // We remove from the original map
-        for (int i = 0; i < factoryToRemove.size(); i++) {
-            m_attached.remove(factoryToRemove.get(i));
-        }
-
-        // Delete idle instances
-        List list = null;
-        synchronized (this) {
-            list = new ArrayList(m_idle);
-        }
-        instanceToRemove.clear();
-        for (int i = 0; i < list.size(); i++) {
-            ManagedInstance managed = (ManagedInstance) list.get(i);
-            if (managed.m_bundleId == bundle) {
-                instanceToRemove.add(managed);
-            }
-        }
-        m_idle.removeAll(instanceToRemove);
-    }
-
-    /**
-     * This method is called when a factory appears.
-     * @param factory the new factory.
-     */
-    public synchronized void addFactory(IPojoFactory factory) {
-        List createdInstances = new ArrayList(1);
-        m_logger.log(Logger.DEBUG, "Add the factory " + factory.getName());
-        m_factories.add(factory);
-        for (int i = 0; i < m_idle.size(); i++) {
-            ManagedInstance managed = (ManagedInstance) m_idle.get(i);
-            if (managed.matchNameAndVersion(factory)) {
-                // We have to subscribe to the factory.
-                factory.addFactoryStateListener(this);
-                if (factory.getState() == Factory.VALID && managed.match(factory)) {
-                    managed.create(factory);
-                    List list = (List) m_attached.get(factory);
-                    if (list == null) {
-                        list = new ArrayList();
-                        list.add(managed);
-                        m_attached.put(factory, list);
-                    } else {
-                        list.add(managed);
-                    }
-                    createdInstances.add(managed);
-                }
-            }
-        }
-        if (!createdInstances.isEmpty()) {
-            m_idle.removeAll(createdInstances);
-        }
-    }
-
-    /**
-     * This method is called when a factory is leaving.
-     * @param factory the leaving factory
-     */
-    void removeFactory(IPojoFactory factory) {
-        factory.removeFactoryStateListener(this);
-        m_factories.remove(factory);
-        onInvalidation(factory);
-        m_attached.remove(factory);
-    }
-
-    /**
-     * This method is called when the given factory becomes valid.
-     * @param factory the factory becoming valid.
-     */
-    private void onValidation(IPojoFactory factory) {
-        List toRemove = new ArrayList();
-        for (int i = 0; i < m_idle.size(); i++) {
-            ManagedInstance managed = (ManagedInstance) m_idle.get(i);
-            if (managed.match(factory)) {
-                managed.create(factory);
-                List list = (List) m_attached.get(factory);
-                if (list == null) {
-                    list = new ArrayList();
-                    list.add(managed);
-                    m_attached.put(factory, list);
-                } else {
-                    list.add(managed);
-                }
-                toRemove.add(managed);
-            }
-        }
-        if (!toRemove.isEmpty()) {
-            m_idle.removeAll(toRemove);
-        }
-    }
-
-    /**
-     * This method is called when the given factory becomes invalid.
-     * @param factory the factory becoming invalid.
-     */
-    private void onInvalidation(IPojoFactory factory) {
-        List instances = (List) m_attached.remove(factory);
-        if (instances != null) {
-            for (int i = 0; i < instances.size(); i++) {
-                ManagedInstance managed = (ManagedInstance) instances.get(i);
-                managed.dispose();
-                m_idle.add(managed);
-            }
-        }
-    }
-
-    /**
-     * This method is called when the state of a factory changes.
-     * @param factory the factory.
-     * @param newState the new state.
-     * @see org.apache.felix.ipojo.FactoryStateListener#stateChanged(org.apache.felix.ipojo.Factory, int)
-     */
-    public void stateChanged(Factory factory, int newState) {
-        if (newState == Factory.VALID) {
-            m_logger.log(Logger.DEBUG, "A factory is becoming valid : " + factory.getName());
-            onValidation((IPojoFactory) factory);
-        } else {
-            m_logger.log(Logger.DEBUG, "A factory is becoming invalid : " + factory.getName());
-            onInvalidation((IPojoFactory) factory);
-        }
-    }
-
-    /**
-     * This structure aims to manage a configuration.
-     * It stores all necessary information to create an instance
-     * and to track the factory.
-     */
-    private class ManagedInstance {
-        /**
-         * The configuration of the instance to create.
-         */
-        private Dictionary m_configuration;
-
-        /**
-         * The bundle which creates the instance.
-         */
-        private long m_bundleId;
-
-        /**
-         * The factory used to create the instance.
-         */
-        private IPojoFactory m_factory;
-
-        /**
-         * The created instance.
-         */
-        private ComponentInstance m_instance;
-
-        /**
-         * Creates a ManagedInstance.
-         * @param conf the configuration to create.
-         * @param bundle the bundle in which the instance is declared.
-         */
-        ManagedInstance(Dictionary conf, long bundle) {
-            m_configuration = conf;
-            m_bundleId = bundle;
-        }
-
-        /**
-         * Checks if the required factory name match with the given factory.
-         * This methods checks only the name, and not the configuration.
-         * @param factory the factory to test
-         * @return <code>true</code> if the factory name and the version (if set) match, <code>false</code>
-         * otherwise.
-         */
-        public boolean matchNameAndVersion(IPojoFactory factory) {
-            String component = (String) m_configuration.get("component");
-            String v = (String) m_configuration.get("factory.version");
-            if (v == null) {
-                return factory.getName().equals(component) || factory.getClassName().equalsIgnoreCase(component);
-            } else {
-                return (factory.getName().equals(component) || factory.getClassName().equalsIgnoreCase(component))
-                    && v.equals(factory.getVersion());
-            }
-        }
-
-        /**
-         * Checks if the given factory match with the factory
-         * required by this instance. A factory matches if its
-         * name or its class name is equals to the 'component'
-         * property of the instance. Then the acceptability of
-         * the configuration is checked.
-         * @param factory the factory to confront against the current instance.
-         * @return <code>true</code> if the factory matches.
-         */
-        public boolean match(IPojoFactory factory) {
-            // Test factory name (and classname)
-            if (matchNameAndVersion(factory)) {
-                // Test factory accessibility
-                if (factory.m_isPublic || factory.getBundleContext().getBundle().getBundleId() == m_bundleId) {
-                    // Test the configuration validity.
-                    try {
-                        factory.checkAcceptability(m_configuration);
-                        return true;
-                    } catch (UnacceptableConfiguration e) {
-                        m_logger.log(Logger.ERROR, "An instance can be bound to a matching factory, however the configuration seems unacceptable : "
-                                + e.getMessage());
-                        return false;
-                    } catch (MissingHandlerException e) {
-                        m_logger.log(Logger.ERROR, "An instance can be bound to a matching factory, but this factory cannot be used : "
-                                + e.getMessage());
-                        return false;
-                    }
-                }
-            }
-            return false;
-        }
-
-        /**
-         * Creates the instance by using the given factory.
-         * @param factory the factory to use to create the instance. The factory must match.
-         */
-        public void create(IPojoFactory factory) {
-            try {
-                m_factory = factory;
-                m_instance = m_factory.createComponentInstance(m_configuration);
-                m_logger.log(Logger.INFO, "Instance created");
-            } catch (UnacceptableConfiguration e) {
-                m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
-                        + e.getMessage());
-            } catch (MissingHandlerException e) {
-                m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
-                        + e.getMessage());
-            } catch (ConfigurationException e) {
-                m_logger.log(Logger.ERROR, "A matching factory was found for " + m_configuration + ", but the instantiation failed : "
-                        + e.getMessage());
-            }
-        }
-
-        /**
-         * Disposes the current instance if not <code>null</code>.
-         */
-        public void dispose() {
-            if (m_instance != null) {
-                m_instance.dispose();
-            }
-            m_instance = null;
-            m_factory = null;
-        }
-    }
-
-}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
index 1ea6cdc..23f8c31 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
@@ -186,7 +186,7 @@
         m_className = metadata.getAttribute("classname");
 
         // Add the name
-        m_name = (String) configuration.get("instance.name");
+        m_name = (String) configuration.get(Factory.INSTANCE_NAME_PROPERTY);
 
         // Check if an object is injected in the instance
         Object obj = configuration.get("instance.object");
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
index 2a7dc4a..a2d02d6 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
@@ -214,7 +214,7 @@
         // Add the version if set
         String v = getVersion();
         if (v != null) {
-            props.put("factory.version", v);
+            props.put(Factory.FACTORY_VERSION_PROPERTY, v);
         }
 
         props.put("component.providedServiceSpecifications", m_providedServiceSpecification);
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/Declaration.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/Declaration.java
new file mode 100644
index 0000000..e22a1d2
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/Declaration.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender;
+
+/**
+ * A declaration is a creation instruction of an entity (Component type, Factory, Instance...).
+ * All declarations are exposed as services. <em>Processors</em> are tracking the adequate declaration type and create
+ * the entity.
+ * <p/>
+ * Declaration can be <em>bound</em> or <em>unbound</em> whether they are fulfilled. When they are unbound,
+ * a message or/and an error can be set.
+ */
+public interface Declaration {
+    /**
+     * Gets the declaration status.
+     *
+     * @return the current status. As Status are immutable, it returns a new object every time.
+     */
+    Status getStatus();
+
+    /**
+     * Marks the declaration bound.
+     */
+    void bind();
+
+    /**
+     * Unbinds the declaration.
+     *
+     * @param message an explanation
+     */
+    void unbind(String message);
+
+    /**
+     * Unbinds the declaration
+     *
+     * @param message   an explanation
+     * @param throwable an error
+     */
+    void unbind(String message, Throwable throwable);
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/ExtensionDeclaration.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/ExtensionDeclaration.java
new file mode 100644
index 0000000..2a1f5c3
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/ExtensionDeclaration.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender;
+
+import org.apache.felix.ipojo.extender.builder.FactoryBuilder;
+
+/**
+ * iPOJO's extension declaration.
+ * This service interface is published to instruct the extender to create a new iPOJO extension (like composite or
+ * handler).
+ */
+public interface ExtensionDeclaration extends Declaration {
+    /**
+     * The service property specifying the extension name.
+     */
+    String EXTENSION_NAME_PROPERTY = "ipojo.extension.name";
+
+    /**
+     * Gets the factory builder to use to create the factories bound to this extension.
+     *
+     * @return the factory builder.
+     */
+    FactoryBuilder getFactoryBuilder();
+
+    /**
+     * Gets the extension name. This name must be unique.
+     *
+     * @return the extension name.
+     */
+    String getExtensionName();
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/InstanceDeclaration.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/InstanceDeclaration.java
new file mode 100644
index 0000000..1d804a0
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/InstanceDeclaration.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender;
+
+import java.util.Dictionary;
+
+/**
+ * Service published to instruct an instance creation.
+ */
+public interface InstanceDeclaration extends Declaration {
+    /**
+     * Service property specifying the component type's name.
+     */
+    String COMPONENT_NAME_PROPERTY = "ipojo.component.name";
+
+    /**
+     * Service property specifying the component type's version.
+     */
+    String COMPONENT_VERSION_PROPERTY = "ipojo.component.version";
+
+    /**
+     * Service property specifying the instance name.
+     */
+    String INSTANCE_NAME = "ipojo.instance.name";
+
+    /**
+     * Value used when an instance configuration does not declare its name.
+     */
+    String UNNAMED_INSTANCE = "unnamed";
+
+    /**
+     * The instance configuration.
+     *
+     * @return the instance configuration
+     */
+    Dictionary<String, Object> getConfiguration();
+
+    /**
+     * @return the component type's name.
+     */
+    String getComponentName();
+
+    /**
+     * @return the component type's version, {@literal null} if not set.
+     */
+    String getComponentVersion();
+
+    /**
+     * Gets the instance name.
+     *
+     * @return the instance name, {@literal unnamed} if not specified.
+     */
+    String getInstanceName();
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/Status.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/Status.java
new file mode 100644
index 0000000..c9a98db
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/Status.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender;
+
+/**
+ * The declaration status.
+ * A declaration may be fulfilled or not (bound or not).
+ * When the declaration is unbound, a message can be given to explain the reason.
+ * Implementation are immutable.
+ */
+public interface Status {
+    /**
+     * Is the declaration fulfilled ?
+     *
+     * @return {@literal true} if the declaration is bound, {@literal false} otherwise.
+     */
+    boolean isBound();
+
+    /**
+     * Gets the unbound message if any.
+     *
+     * @return the unbound message, <code>null</code> if no message.
+     */
+    String getMessage();
+
+    /**
+     * Gets the unbound error if any.
+     *
+     * @return the unbound error, <code>null</code> if no error were set.
+     */
+    Throwable getThrowable();
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/TypeDeclaration.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/TypeDeclaration.java
new file mode 100644
index 0000000..167aa2a
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/TypeDeclaration.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender;
+
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Service exposed to instruct a factory creation.
+ */
+public interface TypeDeclaration extends Declaration {
+
+    /**
+     * Get the component metadata description.
+     *
+     * @return the component metadata description.
+     */
+    Element getComponentMetadata();
+
+    /**
+     * Returns {@literal true} if the type is public
+     *
+     * @return {@literal true} if the type is public
+     */
+    boolean isPublic();
+
+    /**
+     * Gets the component type's name.
+     *
+     * @return the component type's name.
+     */
+    String getComponentName();
+
+    /**
+     * Gets the component type's version.
+     *
+     * @return the component type's version
+     */
+    String getComponentVersion();
+
+    /**
+     * Gets the targeted iPOJO Extension (primitive, composite, handler...)
+     *
+     * @return the targeted extension
+     */
+    String getExtension();
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/builder/FactoryBuilder.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/builder/FactoryBuilder.java
new file mode 100644
index 0000000..167187b
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/builder/FactoryBuilder.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.builder;
+
+import org.apache.felix.ipojo.IPojoFactory;
+import org.apache.felix.ipojo.metadata.Element;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Interface defining the method used to build {@link IPojoFactory} instances.
+ * As each type of iPOJO factories can be different, factory builder are the common facade of all those types.
+ */
+public interface FactoryBuilder {
+
+    /**
+     * Creates an iPOJO Factory.
+     *
+     * @param bundleContext the bundle context of the bundle declaring the component type
+     * @param metadata      the metadata of the component type (<code>component</code> element).
+     * @return the iPOJO Factory instance.
+     * @throws FactoryBuilderException if the factory cannot be created.
+     */
+    IPojoFactory build(BundleContext bundleContext, Element metadata) throws FactoryBuilderException;
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/builder/FactoryBuilderException.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/builder/FactoryBuilderException.java
new file mode 100644
index 0000000..bec872b
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/builder/FactoryBuilderException.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.builder;
+
+/**
+ * Exception thrown by {@link FactoryBuilder} when a {@link org.apache.felix.ipojo.IPojoFactory} instance cannot be
+ * created correctly.
+ */
+public class FactoryBuilderException extends Exception {
+
+    /**
+     * Creates the exception instance with the given message.
+     *
+     * @param message the message
+     */
+    public FactoryBuilderException(String message) {
+        super(message);
+    }
+
+    /**
+     * Creates the exception instance with the given message and cause.
+     *
+     * @param message the message
+     * @param cause   the cause
+     */
+    public FactoryBuilderException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/AbstractService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/AbstractService.java
new file mode 100644
index 0000000..1fa48f0
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/AbstractService.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import java.util.Dictionary;
+
+/**
+ * Common code wrapping an OSGi service.
+ */
+public abstract class AbstractService implements Lifecycle {
+
+    /**
+     * The bundle context.
+     */
+    private final BundleContext m_bundleContext;
+
+    /**
+     * The service specification.
+     */
+    private final Class<?> m_type;
+
+    /**
+     * The service registration.
+     */
+    private ServiceRegistration<?> m_registration;
+
+
+    /**
+     * Constructor.
+     * This constructor checks that the current class and the service specification are compatible.
+     *
+     * @param bundleContext the bundle context
+     * @param type          the specification
+     */
+    protected AbstractService(BundleContext bundleContext, Class<?> type) {
+        m_bundleContext = bundleContext;
+        if (!type.isAssignableFrom(getClass())) {
+            throw new IllegalArgumentException("This object is not an instance of " + type.getName());
+        }
+        m_type = type;
+    }
+
+    /**
+     * On start, registers the service.
+     */
+    public void start() {
+        m_registration = m_bundleContext.registerService(m_type.getName(), this, getServiceProperties());
+    }
+
+    /**
+     * On stop, un-registers the service.
+     */
+    public void stop() {
+        if (m_registration != null) {
+            m_registration.unregister();
+            m_registration = null;
+        }
+    }
+
+    /**
+     * @return the service properties, {@literal null} by default.
+     */
+    protected Dictionary<String, ?> getServiceProperties() {
+        return null;
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/BundleProcessor.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/BundleProcessor.java
new file mode 100644
index 0000000..740b401
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/BundleProcessor.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * Main Processor interface.
+ * A bundle processor is an extender fragment, it analyzes the bundle content and creates the entities.
+ * <p/>
+ * Notice the difference between the <code>activate / deactivate </code> methods called when a bundle is starting
+ * and stopping, and <code>start / stop</code> called when the iPOJO bundle is started and stopped.
+ */
+public interface BundleProcessor extends Lifecycle {
+    /**
+     * A bundle is started.
+     *
+     * @param bundle the bundle
+     */
+    void activate(Bundle bundle);
+
+    /**
+     * A bundle is stopping. This call is made during the stopping phase.
+     *
+     * @param bundle the bundle
+     */
+    void deactivate(Bundle bundle);
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java
new file mode 100644
index 0000000..7fc4427
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Extender.java
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal;
+
+import org.apache.felix.ipojo.EventDispatcher;
+import org.apache.felix.ipojo.extender.internal.linker.DeclarationLinker;
+import org.apache.felix.ipojo.extender.internal.processor.ChainedBundleProcessor;
+import org.apache.felix.ipojo.extender.internal.processor.ComponentsBundleProcessor;
+import org.apache.felix.ipojo.extender.internal.processor.ExtensionBundleProcessor;
+import org.apache.felix.ipojo.extender.internal.processor.QueuingActivationProcessor;
+import org.apache.felix.ipojo.extender.internal.queue.ExecutorQueueService;
+import org.apache.felix.ipojo.extender.internal.queue.PrefixedThreadFactory;
+import org.apache.felix.ipojo.extender.internal.queue.SynchronousQueueService;
+import org.apache.felix.ipojo.extender.internal.queue.pref.HeaderPreferenceSelection;
+import org.apache.felix.ipojo.extender.internal.queue.pref.Preference;
+import org.apache.felix.ipojo.extender.internal.queue.pref.PreferenceQueueService;
+import org.apache.felix.ipojo.extender.internal.queue.pref.enforce.EnforcedQueueService;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.*;
+
+/**
+ * iPOJO main activator.
+ */
+public class Extender implements BundleActivator, SynchronousBundleListener {
+    /**
+     * Enables the iPOJO internal dispatcher.
+     * This internal dispatcher helps the OSGi framework to support large
+     * scale applications. The internal dispatcher is disabled by default.
+     */
+    static boolean DISPATCHER_ENABLED = true;
+
+    /**
+     * Disables the iPOJO asynchronous processing.
+     * When set to false, the bundles are processed in the listener thread
+     * making iPOJO usable on Google App Engine. By default, the processing
+     * is asynchronous.
+     */
+    static boolean SYNCHRONOUS_PROCESSING_ENABLED = false;
+
+    /**
+     * Property allowing to set if the internal dispatcher is enabled or disabled.
+     * Possible value are either {@literal true} or {@literal false}.
+     */
+    private static final String ENABLING_DISPATCHER = "ipojo.internal.dispatcher";
+
+    /**
+     * Property allowing to disable the asynchronous process (and so enables the
+     * synchronous processing).
+     * Possible value are either {@literal true} or {@literal false}.
+     */
+    private static final String SYNCHRONOUS_PROCESSING = "ipojo.processing.synchronous";
+
+    /**
+     * The Bundle Context of the iPOJO Core bundle.
+     */
+    private static BundleContext m_context;
+
+    /**
+     * The iPOJO Extender logger.
+     */
+    private Logger m_logger;
+
+    /**
+     * The iPOJO Bundle.
+     */
+    private Bundle m_bundle;
+
+    /**
+     * The chained processor containing all the true bundle processor.
+     */
+    private ChainedBundleProcessor m_processor;
+
+    /**
+     * Binds Instances to Factories to Extensions.
+     */
+    private DeclarationLinker m_linker;
+
+    private LifecycleQueueService m_queueService;
+
+    /**
+     * The iPOJO bundle is starting.
+     * This method configures the iPOJO system (internal dispatcher and bundle processing). Then it initiates the
+     * bundle processing.
+     * <p/>
+     * To optimize the processing, we process the iPOJO bundle first.
+     *
+     * @param context the iPOJO's bundle bundle context
+     * @throws Exception something terrible happen during startup
+     */
+    public void start(BundleContext context) throws Exception {
+        m_context = context;
+        m_bundle = context.getBundle();
+
+        m_logger = new Logger(m_context, "IPOJO-Main-Extender");
+
+        enablingDispatcher(context, m_logger);
+        enablingSynchronousProcessing(context, m_logger);
+
+        // Create the dispatcher only if required.
+        if (DISPATCHER_ENABLED) {
+            EventDispatcher.create(context);
+        }
+
+        BundleProcessor extensionBundleProcessor = new ExtensionBundleProcessor(m_logger);
+        BundleProcessor componentsProcessor = new ComponentsBundleProcessor(m_logger);
+        if (SYNCHRONOUS_PROCESSING_ENABLED) {
+            m_queueService = new EnforcedQueueService(
+                    new HeaderPreferenceSelection(),
+                    new SynchronousQueueService(context),
+                    Preference.SYNC,
+                    m_logger);
+        } else {
+            SynchronousQueueService sync = new SynchronousQueueService(context);
+            ExecutorQueueService async = new ExecutorQueueService(context, 1, new PrefixedThreadFactory("[iPOJO] "));
+            m_queueService = new PreferenceQueueService(new HeaderPreferenceSelection(), sync, async);
+
+            extensionBundleProcessor = new QueuingActivationProcessor(extensionBundleProcessor, m_queueService);
+            componentsProcessor = new QueuingActivationProcessor(componentsProcessor, m_queueService);
+        }
+        m_queueService.start();
+
+        // Start linking
+        m_linker = new DeclarationLinker(context, m_queueService);
+        m_linker.start();
+
+        m_processor = ChainedBundleProcessor.create(extensionBundleProcessor, componentsProcessor);
+
+        m_processor.start();
+
+        // Begin by initializing core handlers
+        m_processor.activate(m_bundle);
+
+        synchronized (this) {
+            // listen to any changes in bundles.
+            m_context.addBundleListener(this);
+            // compute already started bundles.
+            for (int i = 0; i < context.getBundles().length; i++) {
+                if (context.getBundles()[i].getState() == Bundle.ACTIVE) {
+                    m_processor.activate(context.getBundles()[i]);
+                }
+            }
+        }
+
+        m_logger.log(Logger.INFO, "iPOJO Main Extender started");
+    }
+
+    /**
+     * The iPOJO bundle is stopping.
+     *
+     * @param context the bundle context
+     * @throws Exception something terrible happen
+     */
+    public void stop(BundleContext context) throws Exception {
+        context.removeBundleListener(this);
+
+        m_processor.stop();
+
+        if (DISPATCHER_ENABLED) {
+            EventDispatcher.dispose();
+        }
+
+        m_linker.stop();
+        m_queueService.stop();
+
+        m_logger.log(Logger.INFO, "iPOJO Main Extender stopped");
+        m_context = null;
+    }
+
+    /**
+     * A bundle event was caught.
+     *
+     * @param event the event
+     */
+    public void bundleChanged(BundleEvent event) {
+        if (m_bundle.getBundleId() != (event.getBundle().getBundleId())) {
+            // Do not process our-self (already done)
+            switch (event.getType()) {
+                case BundleEvent.STARTED:
+                    // Put the bundle in the queue
+                    m_processor.activate(event.getBundle());
+                    break;
+                case BundleEvent.STOPPING:
+                    m_processor.deactivate(event.getBundle());
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Gets iPOJO bundle context.
+     *
+     * @return the iPOJO Bundle Context
+     */
+    public static BundleContext getIPOJOBundleContext() {
+        return m_context;
+    }
+
+    /**
+     * Enables or disables the internal dispatcher, so sets the
+     * {@link Extender#DISPATCHER_ENABLED} flag.
+     * This method checks if the {@link Extender#ENABLING_DISPATCHER}
+     * property is set to {@literal true}. Otherwise, the internal
+     * dispatcher is disabled. The property can be set as a system
+     * property ({@literal ipojo.internal.dispatcher}) or inside the
+     * iPOJO bundle manifest ({@literal ipojo-internal-dispatcher}).
+     *
+     * @param context the bundle context.
+     * @param logger  the logger to indicates if the internal dispatcher is set.
+     */
+    private static void enablingDispatcher(BundleContext context, Logger logger) {
+        // First check in the framework and in the system properties
+        String flag = context.getProperty(ENABLING_DISPATCHER);
+
+        // If null, look in bundle manifest
+        if (flag == null) {
+            String key = ENABLING_DISPATCHER.replace('.', '-');
+            flag = (String) context.getBundle().getHeaders().get(key);
+        }
+
+        if (flag != null) {
+            if (flag.equalsIgnoreCase("true")) {
+                Extender.DISPATCHER_ENABLED = true;
+                logger.log(Logger.INFO, "iPOJO Internal Event Dispatcher enables");
+                return;
+            }
+        }
+
+        // Either l is null, or the specified value was false
+        Extender.DISPATCHER_ENABLED = false;
+        logger.log(Logger.INFO, "iPOJO Internal Event Dispatcher disables");
+
+    }
+
+    /**
+     * Enables or disables the asynchronous processing, so sets the
+     * {@link Extender#SYNCHRONOUS_PROCESSING_ENABLED} flag.
+     * Disabling asynchronous processing avoids iPOJO to create a new
+     * thread to process bundles. So, iPOJO can be used on the
+     * Google App Engine.
+     * This method checks if the {@link Extender#SYNCHRONOUS_PROCESSING}
+     * property is set to {@literal true}. Otherwise, asynchronous processing
+     * is used (default). The property can be set as a system
+     * property ({@literal ipojo.processing.synchronous}) or inside the
+     * iPOJO bundle manifest.
+     *
+     * @param context the bundle context.
+     * @param logger  the logger to indicates if the internal dispatcher is set.
+     */
+    private static void enablingSynchronousProcessing(BundleContext context, Logger logger) {
+        String flag = context.getProperty(SYNCHRONOUS_PROCESSING);
+
+        // If null, look in bundle manifest
+        if (flag == null) {
+            String key = SYNCHRONOUS_PROCESSING.replace('.', '-');
+            flag = (String) context.getBundle().getHeaders().get(key);
+        }
+
+        if (flag != null) {
+            if (flag.equalsIgnoreCase("true")) {
+                Extender.SYNCHRONOUS_PROCESSING_ENABLED = true;
+                logger.log(Logger.INFO, "iPOJO Asynchronous processing disabled");
+                return;
+            }
+        }
+
+        // Either l is null, or the specified value was false
+        Extender.SYNCHRONOUS_PROCESSING_ENABLED = false;
+        logger.log(Logger.INFO, "iPOJO synchronous processing disabled");
+
+    }
+
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Lifecycle.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Lifecycle.java
new file mode 100644
index 0000000..2706ca1
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/Lifecycle.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal;
+
+/**
+ * Simple start/stop interface.
+ */
+public interface Lifecycle {
+
+    /**
+     * Start the service.
+     */
+    void start();
+
+    /**
+     * Stop the service.
+     */
+    void stop();
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/LifecycleQueueService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/LifecycleQueueService.java
new file mode 100644
index 0000000..97024f3
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/LifecycleQueueService.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal;
+
+import org.apache.felix.ipojo.extender.queue.QueueService;
+
+/**
+ * An interface composing {@link QueueService} and {@link Lifecycle}.
+ */
+public interface LifecycleQueueService extends QueueService, Lifecycle {
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/ReferenceableCallable.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/ReferenceableCallable.java
new file mode 100644
index 0000000..1c0dece
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/ReferenceableCallable.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleReference;
+
+import java.util.concurrent.Callable;
+
+/**
+ * A callable object implementing Bundle Reference.
+ * It makes the Bundle object accessible by the processing job.
+ * This class is intended to be extended.
+ */
+public abstract class ReferenceableCallable<T> implements Callable<T>, BundleReference {
+    /**
+     * The bundle object.
+     */
+    private final Bundle m_bundle;
+
+    /**
+     * Creates the ReferenceableCallable instance.
+     *
+     * @param bundle the associated bundle
+     */
+    protected ReferenceableCallable(Bundle bundle) {
+        m_bundle = bundle;
+    }
+
+    /**
+     * Gets the bundle object.
+     *
+     * @return the bundle
+     */
+    public Bundle getBundle() {
+        return m_bundle;
+    }
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/builder/ReflectiveFactoryBuilder.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/builder/ReflectiveFactoryBuilder.java
new file mode 100644
index 0000000..c7b0f55
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/builder/ReflectiveFactoryBuilder.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.builder;
+
+import org.apache.felix.ipojo.IPojoFactory;
+import org.apache.felix.ipojo.extender.builder.FactoryBuilder;
+import org.apache.felix.ipojo.extender.builder.FactoryBuilderException;
+import org.apache.felix.ipojo.metadata.Element;
+import org.osgi.framework.BundleContext;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * An Factory builder using a reflective call to build the factory.
+ * <p/>
+ * This builder is compatible with the original iPOJO method consisting in calling a constructor receiving the bundle
+ * context and the metadata as parameters.
+ * <p/>
+ * This factory builder need the constructor to be called.
+ */
+public class ReflectiveFactoryBuilder implements FactoryBuilder {
+
+    /**
+     * The constructor to call.
+     */
+    private final Constructor<? extends IPojoFactory> m_constructor;
+
+    /**
+     * Creates the factory builder.
+     *
+     * @param constructor the constructor that will be called when a new component factory will be created.
+     */
+    public ReflectiveFactoryBuilder(Constructor<? extends IPojoFactory> constructor) {
+        m_constructor = constructor;
+    }
+
+    /**
+     * Calls the wrapped constructor to create an iPOJO factory.
+     *
+     * @param bundleContext the bundle context of the bundle declaring the component type
+     * @param metadata      the metadata of the component type (<code>component</code> element).
+     * @return the created iPOJO factory
+     * @throws FactoryBuilderException if the constructor cannot be called or throws an error.
+     */
+    public IPojoFactory build(BundleContext bundleContext, Element metadata) throws FactoryBuilderException {
+        try {
+            return m_constructor.newInstance(bundleContext, metadata);
+        } catch (InstantiationException e) {
+            throw new FactoryBuilderException("Cannot create instance of " + m_constructor.getDeclaringClass(), e);
+        } catch (IllegalAccessException e) {
+            throw new FactoryBuilderException(m_constructor.getDeclaringClass() + " constructor is not " +
+                    "accessible (not public)", e);
+        } catch (InvocationTargetException e) {
+            throw new FactoryBuilderException("Cannot create instance of " + m_constructor.getDeclaringClass(), e);
+        }
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/AbstractDeclaration.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/AbstractDeclaration.java
new file mode 100644
index 0000000..acca635
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/AbstractDeclaration.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.declaration;
+
+import org.apache.felix.ipojo.extender.Declaration;
+import org.apache.felix.ipojo.extender.Status;
+import org.apache.felix.ipojo.extender.internal.AbstractService;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Common code to all Declaration objects.
+ */
+public abstract class AbstractDeclaration extends AbstractService implements Declaration, Status {
+
+    /**
+     * The message used when a declaration is bound.
+     */
+
+    public static final String DECLARATION_BOUND_MESSAGE = "Declaration bound";
+    /**
+     * Is the declaration bound (i.e. successfully fulfilled), or not.
+     */
+    private boolean m_bound = false;
+
+    /**
+     * When not bound, the reason, otherwise {@link #DECLARATION_BOUND_MESSAGE}
+     */
+    private String m_message;
+
+    /**
+     * If an error was thrown during the binding, the error.
+     */
+    private Throwable m_throwable;
+
+    protected AbstractDeclaration(BundleContext bundleContext, Class<?> type) {
+        super(bundleContext, type);
+    }
+
+    /**
+     * @return whether the declaration is bound or not.
+     */
+    public boolean isBound() {
+        return m_bound;
+    }
+
+    /**
+     * @return the message. The message contains the not-bound reason.
+     */
+    public String getMessage() {
+        return m_message;
+    }
+
+    /**
+     * @return the error if something went wrong during the binding process.
+     */
+    public Throwable getThrowable() {
+        return m_throwable;
+    }
+
+    /**
+     * Gets the status of the declaration. This method returns an immutable object.
+     *
+     * @return the declaration status.
+     */
+    public Status getStatus() {
+        // We return an immutable object, created on the fly.
+        return new Status() {
+            final boolean m_bound = AbstractDeclaration.this.m_bound;
+            final String m_message = AbstractDeclaration.this.m_message;
+            final Throwable m_throwable = AbstractDeclaration.this.m_throwable;
+
+            public boolean isBound() {
+                return this.m_bound;
+            }
+
+            public String getMessage() {
+                return this.m_message;
+            }
+
+            public Throwable getThrowable() {
+                return this.m_throwable;
+            }
+        };
+    }
+
+    /**
+     * Binds the declaration.
+     * This method just set the status, message and error.
+     */
+    public void bind() {
+        m_bound = true;
+        m_message = DECLARATION_BOUND_MESSAGE;
+        m_throwable = null;
+    }
+
+    /**
+     * Unbinds the declaration.
+     *
+     * @param message an explanation
+     * @see #unbind(String, Throwable)
+     */
+    public void unbind(String message) {
+        unbind(message, null);
+    }
+
+    /**
+     * Unbinds the declaration.
+     * The flag, message and error are set.
+     *
+     * @param message   an explanation
+     * @param throwable an error
+     */
+    public void unbind(String message, Throwable throwable) {
+        m_bound = false;
+        m_message = message;
+        m_throwable = throwable;
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultExtensionDeclaration.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultExtensionDeclaration.java
new file mode 100644
index 0000000..2d91ef7
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultExtensionDeclaration.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.declaration;
+
+import org.apache.felix.ipojo.extender.ExtensionDeclaration;
+import org.apache.felix.ipojo.extender.builder.FactoryBuilder;
+import org.osgi.framework.BundleContext;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+/**
+ * Default implementation of the iPOJO Extension Declaration.
+ */
+public class DefaultExtensionDeclaration extends AbstractDeclaration implements ExtensionDeclaration {
+
+    private final FactoryBuilder m_factoryBuilder;
+    private final String m_type;
+
+    public DefaultExtensionDeclaration(BundleContext bundleContext, FactoryBuilder factoryBuilder, String type) {
+        super(bundleContext, ExtensionDeclaration.class);
+        m_factoryBuilder = factoryBuilder;
+        m_type = type;
+    }
+
+    public FactoryBuilder getFactoryBuilder() {
+        return m_factoryBuilder;
+    }
+
+    public String getExtensionName() {
+        return m_type;
+    }
+
+    @Override
+    public void start() {
+        super.start();
+        bind();
+    }
+
+    @Override
+    protected Dictionary<String, ?> getServiceProperties() {
+        Hashtable<String, Object> properties = new Hashtable<String, Object>();
+        properties.put(ExtensionDeclaration.EXTENSION_NAME_PROPERTY, m_type);
+        return properties;
+    }
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultInstanceDeclaration.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultInstanceDeclaration.java
new file mode 100644
index 0000000..18d8922
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultInstanceDeclaration.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.declaration;
+
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.extender.InstanceDeclaration;
+import org.osgi.framework.BundleContext;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+/**
+ * Default implementation of the instance declaration.
+ */
+public class DefaultInstanceDeclaration extends AbstractDeclaration implements InstanceDeclaration {
+
+    private static final Dictionary<String, Object> EMPTY_DICTIONARY = new Hashtable<String, Object>();
+
+    private final String m_componentName;
+    private final Dictionary<String, Object> m_configuration;
+    private final String m_componentVersion;
+    private final String m_instanceName;
+
+    public DefaultInstanceDeclaration(BundleContext bundleContext, String componentName) {
+        this(bundleContext, componentName, EMPTY_DICTIONARY);
+    }
+
+    public DefaultInstanceDeclaration(BundleContext bundleContext, String componentName, Dictionary<String, Object> configuration) {
+        super(bundleContext, InstanceDeclaration.class);
+        m_componentName = componentName;
+        m_configuration = configuration;
+        m_componentVersion = initComponentVersion();
+        m_instanceName = initInstanceName();
+    }
+
+    private String initInstanceName() {
+        String name = (String) m_configuration.get(Factory.INSTANCE_NAME_PROPERTY);
+        if (name == null) {
+            name = UNNAMED_INSTANCE;
+        }
+        return name;
+    }
+
+    private String initComponentVersion() {
+        return (String) m_configuration.get(Factory.FACTORY_VERSION_PROPERTY);
+    }
+
+    public Dictionary<String, Object> getConfiguration() {
+        return m_configuration;
+    }
+
+    public String getComponentName() {
+        return m_componentName;
+    }
+
+    public String getComponentVersion() {
+        return m_componentVersion;
+    }
+
+    public String getInstanceName() {
+        return m_instanceName;
+    }
+
+    @Override
+    protected Dictionary<String, ?> getServiceProperties() {
+        Hashtable<String, Object> properties = new Hashtable<String, Object>();
+        properties.put(InstanceDeclaration.COMPONENT_NAME_PROPERTY, m_componentName);
+
+        String version = getComponentVersion();
+        if (version != null) {
+            properties.put(InstanceDeclaration.COMPONENT_VERSION_PROPERTY, version);
+        }
+
+        properties.put(InstanceDeclaration.INSTANCE_NAME, m_instanceName);
+
+        return properties;
+    }
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultTypeDeclaration.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultTypeDeclaration.java
new file mode 100644
index 0000000..42b1958
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultTypeDeclaration.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.declaration;
+
+import org.apache.felix.ipojo.extender.TypeDeclaration;
+import org.apache.felix.ipojo.metadata.Element;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+/**
+ * Default implementation of the component type declaration.
+ */
+public class DefaultTypeDeclaration extends AbstractDeclaration implements TypeDeclaration {
+
+    private final Element m_componentMetadata;
+    private final String m_componentName;
+    private final String m_componentVersion;
+    private final String m_extension;
+    private boolean visible = true;
+
+    public DefaultTypeDeclaration(BundleContext bundleContext, Element componentMetadata) {
+        super(bundleContext, TypeDeclaration.class);
+        m_componentMetadata = componentMetadata;
+        visible = initVisible();
+        m_componentName = initComponentName();
+        m_componentVersion = initComponentVersion(bundleContext);
+        m_extension = initExtension();
+    }
+
+    private String initExtension() {
+        if (m_componentMetadata.getNameSpace() == null) {
+            return m_componentMetadata.getName();
+        }
+        return m_componentMetadata.getNameSpace() + ":" + m_componentMetadata.getName();
+    }
+
+    private String initComponentVersion(BundleContext bundleContext) {
+        String version = m_componentMetadata.getAttribute("version");
+        if (version != null) {
+            if ("bundle".equalsIgnoreCase(version)) {
+                return bundleContext.getBundle().getHeaders().get(Constants.BUNDLE_VERSION);
+            }
+        }
+        return version;
+    }
+
+    private String initComponentName() {
+        String name = m_componentMetadata.getAttribute("name");
+        if (name == null) {
+            name = m_componentMetadata.getAttribute("classname");
+        }
+        return name;
+    }
+
+    private boolean initVisible() {
+        String publicAttribute = m_componentMetadata.getAttribute("public");
+        return (publicAttribute == null) || !publicAttribute.equalsIgnoreCase("false");
+    }
+
+    public String getComponentName() {
+        return m_componentName;
+    }
+
+    public String getComponentVersion() {
+        return m_componentVersion;
+    }
+
+    public String getExtension() {
+        return m_extension;
+    }
+
+    public Element getComponentMetadata() {
+        return m_componentMetadata;
+    }
+
+    public boolean isPublic() {
+        return visible;
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/DeclarationLinker.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/DeclarationLinker.java
new file mode 100644
index 0000000..7630cea
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/DeclarationLinker.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.linker;
+
+import org.apache.felix.ipojo.extender.TypeDeclaration;
+import org.apache.felix.ipojo.extender.internal.Lifecycle;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+/**
+ * The linker is responsible to bind extension declaration to type declaration.
+ * It tracks TypeDeclaration, and reifies them as factory.
+ */
+public class DeclarationLinker implements ServiceTrackerCustomizer, Lifecycle {
+    /**
+     * The bundle context. It uses the iPOJO bundle context.
+     */
+    private final BundleContext m_bundleContext;
+
+    /**
+     * The queue service on which we delegate the binding process.
+     */
+    private final QueueService m_queueService;
+
+    /**
+     * The service tracker looking for TypeDeclaration.
+     */
+    private final ServiceTracker m_typeTracker;
+
+    /**
+     * Creates the linker.
+     *
+     * @param bundleContext the bundle context
+     * @param queueService  the queue service
+     */
+    public DeclarationLinker(BundleContext bundleContext, QueueService queueService) {
+        m_bundleContext = bundleContext;
+        m_queueService = queueService;
+        m_typeTracker = new ServiceTracker(m_bundleContext, TypeDeclaration.class.getName(), this);
+    }
+
+    /**
+     * When the iPOJO management starts, we look for type declaration.
+     */
+    public void start() {
+        m_typeTracker.open(true);
+    }
+
+    /**
+     * When iPOJO stops, we close the tracker.
+     */
+    public void stop() {
+        m_typeTracker.close();
+    }
+
+    /**
+     * A new type declaration was published.
+     *
+     * @param reference the service reference of the type declaration
+     * @return the managed type object wrapping the service object.
+     */
+    public Object addingService(ServiceReference reference) {
+        TypeDeclaration declaration = (TypeDeclaration) m_bundleContext.getService(reference);
+        ManagedType managedType = new ManagedType(reference.getBundle().getBundleContext(), m_queueService, declaration);
+        managedType.start();
+        return managedType;
+    }
+
+    /**
+     * Type declaration cannot be modified.
+     *
+     * @param reference the reference
+     * @param service   the object returned by {@link #addingService(org.osgi.framework.ServiceReference)}
+     */
+    public void modifiedService(ServiceReference reference, Object service) {
+        // Ignored
+    }
+
+    /**
+     * A type declaration service was withdrawn from the  service registry.
+     *
+     * @param reference the leaving reference
+     * @param service   the object returned by {@link #addingService(org.osgi.framework.ServiceReference)}
+     */
+    public void removedService(ServiceReference reference, Object service) {
+        ManagedType managedType = (ManagedType) service;
+        managedType.stop();
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java
new file mode 100644
index 0000000..bc40b7e
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/linker/ManagedType.java
@@ -0,0 +1,340 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.linker;
+
+import org.apache.felix.ipojo.*;
+import org.apache.felix.ipojo.extender.ExtensionDeclaration;
+import org.apache.felix.ipojo.extender.InstanceDeclaration;
+import org.apache.felix.ipojo.extender.TypeDeclaration;
+import org.apache.felix.ipojo.extender.builder.FactoryBuilderException;
+import org.apache.felix.ipojo.extender.internal.Lifecycle;
+import org.apache.felix.ipojo.extender.internal.ReferenceableCallable;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * This class is responsible to create the factory for a given type declaration. It also instructs the factories to
+ * create
+ * the instance for each instance declaration targeting the managed factory.
+ */
+public class ManagedType implements FactoryStateListener, Lifecycle {
+    /**
+     * The bundle context
+     */
+    private final BundleContext m_bundleContext;
+    /**
+     * The queue service used for the creation.
+     */
+    private final QueueService m_queueService;
+    /**
+     * The type declaration that we have to handle.
+     */
+    private final TypeDeclaration m_declaration;
+    /**
+     * The service tracker tracking {@link ExtensionDeclaration} services.
+     */
+    private ServiceTracker m_extensionTracker;
+
+    /**
+     * The service tracker tracking the {@link InstanceDeclaration} services.
+     */
+    private ServiceTracker m_instanceTracker;
+
+    /**
+     * The job used to instantiate the factory.
+     */
+    private Future<IPojoFactory> m_future;
+
+    /**
+     * If the Managed Type cannot be initializes, sets this flag to true and no links will be created.
+     */
+    private boolean m_frozen;
+
+    /**
+     * Constructs a Managed Type object for the given type declaration.
+     *
+     * @param bundleContext the bundle context
+     * @param queueService  the queue service
+     * @param declaration   the declaration
+     */
+    public ManagedType(BundleContext bundleContext, QueueService queueService, TypeDeclaration declaration) {
+        m_bundleContext = bundleContext;
+        m_queueService = queueService;
+        m_declaration = declaration;
+        try {
+            initExtensionTracker();
+            initInstanceTracker();
+        } catch (InvalidSyntaxException e) {
+            // Error during filter creation, freeze the declaration and add a meaningful message
+            m_frozen = true;
+            m_declaration.unbind("Filter creation error", e);
+        }
+    }
+
+    /**
+     * Initializes the extension declaration tracker.
+     *
+     * @throws InvalidSyntaxException cannot happen
+     */
+    private void initExtensionTracker() throws InvalidSyntaxException {
+        String filter = String.format(
+                "(&(objectclass=%s)(%s=%s))",
+                ExtensionDeclaration.class.getName(),
+                ExtensionDeclaration.EXTENSION_NAME_PROPERTY,
+                m_declaration.getExtension()
+        );
+        m_extensionTracker = new ServiceTracker(m_bundleContext, m_bundleContext.createFilter(filter), new ExtensionSupport());
+    }
+
+    /**
+     * Initializes the instance declaration tracker.
+     *
+     * @throws InvalidSyntaxException cannot happen
+     */
+    private void initInstanceTracker() throws InvalidSyntaxException {
+
+        String filter;
+        String version = m_declaration.getComponentVersion();
+        if (version != null) {
+            // Track instance for:
+            // * this component AND
+            // * this component's version OR no version
+            filter = String.format(
+                    "(&(objectClass=%s)(%s=%s)(|(%s=%s)(!(%s=*))))",
+                    InstanceDeclaration.class.getName(),
+                    InstanceDeclaration.COMPONENT_NAME_PROPERTY,
+                    m_declaration.getComponentName(),
+                    InstanceDeclaration.COMPONENT_VERSION_PROPERTY,
+                    version,
+                    InstanceDeclaration.COMPONENT_VERSION_PROPERTY
+            );
+        } else {
+            // Track instance for:
+            // * this component AND no version
+            filter = String.format(
+                    "(&(objectClass=%s)(%s=%s)(!(%s=*)))",
+                    InstanceDeclaration.class.getName(),
+                    InstanceDeclaration.COMPONENT_NAME_PROPERTY,
+                    m_declaration.getComponentName(),
+                    InstanceDeclaration.COMPONENT_VERSION_PROPERTY
+            );
+        }
+        m_instanceTracker = new ServiceTracker(m_bundleContext, m_bundleContext.createFilter(filter), new InstanceSupport());
+    }
+
+    /**
+     * Starting the management.
+     * We open only the extension tracker.
+     */
+    public void start() {
+        if (!m_frozen) {
+            m_extensionTracker.open(true);
+        }
+    }
+
+    /**
+     * Stopping the management.
+     */
+    public void stop() {
+        m_instanceTracker.close();
+        m_extensionTracker.close();
+    }
+
+    /**
+     * The factory we have built has a state in his change.
+     *
+     * @param factory  the changing factory
+     * @param newState the new factory state
+     */
+    public void stateChanged(Factory factory, int newState) {
+        if (Factory.VALID == newState) {
+            // Start tracking instances
+            m_instanceTracker.open(true);
+        } else {
+            // Un-track all instances
+            m_instanceTracker.close();
+        }
+    }
+
+    /**
+     * The service tracker customizer for extension declaration.
+     * It submits a factory building job when an extension matching our type declaration is found.
+     */
+    private class ExtensionSupport implements ServiceTrackerCustomizer {
+        public Object addingService(ServiceReference reference) {
+            // TODO Check if we can cast the instance
+            final Object service = m_bundleContext.getService(reference);
+            if (service instanceof ExtensionDeclaration) {
+                m_future = m_queueService.submit(new ReferenceableCallable<IPojoFactory>(reference.getBundle()) {
+
+                    /**
+                     * The factory creation job.
+                     * @return the IPojoFactory
+                     * @throws Exception the factory cannot be created
+                     */
+                    public IPojoFactory call() throws Exception {
+                        ExtensionDeclaration declaration = (ExtensionDeclaration) service;
+                        try {
+                            // Build and start the factory instance
+                            IPojoFactory factory = declaration.getFactoryBuilder().build(m_bundleContext, m_declaration.getComponentMetadata());
+                            factory.addFactoryStateListener(ManagedType.this);
+                            factory.start();
+
+                            // Change the status
+                            m_declaration.bind();
+
+                            return factory;
+                        } catch (FactoryBuilderException e) {
+                            m_declaration.unbind(String.format("Cannot build '%s' factory instance", m_declaration.getExtension()), e);
+                        } catch (Throwable t) {
+                            m_declaration.unbind(String.format("Error during '%s' factory instance creation", m_declaration.getExtension()), t);
+                        }
+
+                        return null;
+                    }
+                });
+            }
+
+            return null;
+        }
+
+        public void modifiedService(ServiceReference reference, Object o) {
+        }
+
+        public void removedService(ServiceReference reference, Object o) {
+
+            // Then stop the factory
+            try {
+                IPojoFactory factory = m_future.get();
+                // It is possible that the factory couldn't be created
+                if (factory != null) {
+                    factory.stop();
+                    factory.removeFactoryStateListener(ManagedType.this);
+                    m_declaration.unbind("Extension '%s' is missing");
+                }
+            } catch (InterruptedException e) {
+                m_declaration.unbind("Could not create Factory", e);
+            } catch (ExecutionException e) {
+                m_declaration.unbind("Factory creation throw an Exception", e);
+            }
+            m_future = null;
+        }
+    }
+
+    private class InstanceSupport implements ServiceTrackerCustomizer {
+        public Object addingService(final ServiceReference reference) {
+            // TODO Check if we can cast the instance
+            Object service = m_bundleContext.getService(reference);
+            if (service instanceof InstanceDeclaration) {
+                final InstanceDeclaration instanceDeclaration = (InstanceDeclaration) service;
+
+                // Check that instance is not already bound
+                if (instanceDeclaration.getStatus().isBound()) {
+                    return null;
+                }
+
+                // Handle visibility (private/public factories)
+                if (!m_declaration.isPublic()) {
+                    if (!reference.getBundle().equals(m_bundleContext.getBundle())) {
+                        Bundle origin = m_bundleContext.getBundle();
+                        instanceDeclaration.unbind(
+                                String.format("Component '%s/%s' is private. It only accept instances " +
+                                        "from bundle %s/%s [%d] (instance bundle origin: %d)",
+                                        m_declaration.getComponentName(),
+                                        m_declaration.getComponentVersion(),
+                                        origin.getSymbolicName(),
+                                        origin.getVersion(),
+                                        origin.getBundleId(),
+                                        reference.getBundle().getBundleId())
+                        );
+                        return null;
+                    }
+                }
+
+                return m_queueService.submit(new ReferenceableCallable<ComponentInstance>(reference.getBundle()) {
+                    public ComponentInstance call() throws Exception {
+                        try {
+                            // Create the component's instance
+                            // It is automatically started
+                            // Future.get should never be null since this tracker is started when the factory has been created
+                            ComponentInstance instance = m_future.get().createComponentInstance(instanceDeclaration.getConfiguration());
+
+                            // Notify the declaration that everything is fine
+                            instanceDeclaration.bind();
+
+                            return instance;
+                        } catch (UnacceptableConfiguration c) {
+                            m_declaration.unbind(String.format("Instance configuration is invalid (component:%s/%s, bundle:%d)",
+                                    m_declaration.getComponentName(),
+                                    m_declaration.getComponentVersion(),
+                                    reference.getBundle().getBundleId()),
+                                    c);
+                        } catch (MissingHandlerException e) {
+                            m_declaration.unbind(String.format("Component '%s/%s' is missing some handlers", m_declaration.getComponentName(), m_declaration.getComponentVersion()), e);
+                        } catch (ConfigurationException e) {
+                            m_declaration.unbind(String.format("Component '%s/%s' is incorrect", m_declaration.getComponentName(), m_declaration.getComponentVersion()), e);
+                        }
+
+                        return null;
+                    }
+                });
+            }
+
+            return null;
+        }
+
+        public void modifiedService(ServiceReference reference, Object o) {
+        }
+
+        public void removedService(ServiceReference reference, Object o) {
+            InstanceDeclaration instanceDeclaration = (InstanceDeclaration) m_bundleContext.getService(reference);
+            Future<ComponentInstance> future = (Future<ComponentInstance>) o;
+            ComponentInstance instance = null;
+            try {
+                instance = future.get();
+                // It is possible that the instance couldn't be created
+                if (instance != null) {
+                    String message = String.format("Factory for Component '%s/%s' is missing",
+                            instance.getFactory().getName(),
+                            m_declaration.getComponentVersion());
+                    instanceDeclaration.unbind(message);
+
+                    instance.stop();
+                    instance.dispose();
+                }
+
+            } catch (InterruptedException e) {
+                instanceDeclaration.unbind("Could not create ComponentInstance", e);
+            } catch (ExecutionException e) {
+                instanceDeclaration.unbind("ComponentInstance creation throw an Exception", e);
+            }
+        }
+    }
+
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ChainedBundleProcessor.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ChainedBundleProcessor.java
new file mode 100644
index 0000000..1139928
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ChainedBundleProcessor.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.osgi.framework.Bundle;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A bundle processor chaining others processor.
+ * It composes the <em>extender</em> mechanism.
+ * <p/>
+ * Instance must be created using the {@link #create(org.apache.felix.ipojo.extender.internal.BundleProcessor...)}
+ * method.
+ */
+public class ChainedBundleProcessor implements BundleProcessor {
+
+    /**
+     * The list of processors.
+     * Be aware that the order if important, as processors will be called in the insertion order.
+     * <p/>
+     * Once the chained bundle processor is created, this list cannot be modified.
+     */
+    private final List<BundleProcessor> m_processors = new ArrayList<BundleProcessor>();
+
+    private ChainedBundleProcessor() {
+        // Just here to avoid direct creation.
+    }
+
+    /**
+     * Creates a new chained bundle processor.
+     *
+     * @param processors the set of processor to chain. Cannot be <code>null</code> or empty.
+     * @return the created bundle processor
+     * @throws IllegalArgumentException if the given processor list is <code>null</code> or empty.
+     */
+    public static ChainedBundleProcessor create(BundleProcessor... processors) {
+        if (processors == null || processors.length == 0) {
+            throw new IllegalArgumentException("Chained processor cannot be created without processors");
+        }
+        ChainedBundleProcessor chain = new ChainedBundleProcessor();
+        Collections.addAll(chain.m_processors, processors);
+        return chain;
+    }
+
+    /**
+     * Gets the list of processors.
+     * This method returns a copy of the list of processor.
+     *
+     * @return a copy of the processor list
+     */
+    public List<BundleProcessor> getProcessors() {
+        List<BundleProcessor> list = new ArrayList<BundleProcessor>();
+        list.addAll(m_processors);
+        return list;
+    }
+
+    /**
+     * A bundle is starting.
+     * Call the {@link BundleProcessor#activate(org.osgi.framework.Bundle)} method on all chained processors.
+     *
+     * @param bundle the bundle
+     */
+    public void activate(Bundle bundle) {
+        for (BundleProcessor processor : m_processors) {
+            processor.activate(bundle);
+        }
+    }
+
+    /**
+     * A bundle is stopping.
+     * Call the {@link BundleProcessor#deactivate(org.osgi.framework.Bundle)} method on all chained processors.
+     *
+     * @param bundle the bundle
+     */
+    public void deactivate(Bundle bundle) {
+        List<BundleProcessor> reverse = new ArrayList<BundleProcessor>(m_processors);
+        Collections.reverse(reverse);
+        for (BundleProcessor processor : reverse) {
+            processor.deactivate(bundle);
+        }
+    }
+
+    /**
+     * The iPOJO bundle is starting.
+     * Call the {@link org.apache.felix.ipojo.extender.internal.BundleProcessor#start()}  method on all chained
+     * processors.
+     */
+    public void start() {
+        for (BundleProcessor processor : m_processors) {
+            processor.start();
+        }
+    }
+
+    /**
+     * The iPOJO bundle is stopping.
+     * Call the {@link org.apache.felix.ipojo.extender.internal.BundleProcessor#stop()} method on all chained
+     * processors.
+     */
+    public void stop() {
+        List<BundleProcessor> reverse = new ArrayList<BundleProcessor>(m_processors);
+        Collections.reverse(reverse);
+        for (BundleProcessor processor : reverse) {
+            processor.stop();
+        }
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ComponentsBundleProcessor.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ComponentsBundleProcessor.java
new file mode 100644
index 0000000..066ce81
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ComponentsBundleProcessor.java
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.apache.felix.ipojo.extender.internal.declaration.DefaultInstanceDeclaration;
+import org.apache.felix.ipojo.extender.internal.declaration.DefaultTypeDeclaration;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.ManifestMetadataParser;
+import org.apache.felix.ipojo.parser.ParseException;
+import org.apache.felix.ipojo.util.Log;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.Bundle;
+
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * Processor handling the {@link #IPOJO_HEADER} and {@link #IPOJO_HEADER_ALT}
+ * header from the bundle manifest.
+ */
+public class ComponentsBundleProcessor implements BundleProcessor {
+
+    /**
+     * iPOJO Component Type and Instance declaration header.
+     */
+    public static final String IPOJO_HEADER = "iPOJO-Components";
+
+    /**
+     * iPOJO Component Type and Instance declaration header
+     * (alternative).
+     * This header was introduced because of BND supporting only header
+     * starting with an uppercase.
+     */
+    public static final String IPOJO_HEADER_ALT = "IPOJO-Components";
+
+    /**
+     * The attribute used in instance configuration specifying the targeted component (i.e. factory).
+     */
+    public static final String COMPONENT_INSTANCE_ATTRIBUTE = "component";
+
+    /**
+     * The logger.
+     */
+    private final Log m_logger;
+
+    /**
+     * Registry storing the bundle to components and instances declared within this bundle.
+     */
+    private final Map<Bundle, ComponentsAndInstances> m_registry = new HashMap<Bundle, ComponentsAndInstances>();
+
+    /**
+     * Creates the component bundle processor.
+     *
+     * @param logger the logger.
+     */
+    public ComponentsBundleProcessor(Log logger) {
+        m_logger = logger;
+    }
+
+    /**
+     * A bundle is starting.
+     *
+     * @param bundle the bundle
+     */
+    public void activate(Bundle bundle) {
+        Dictionary dict = bundle.getHeaders();
+        // Check bundle
+        String header = (String) dict.get(IPOJO_HEADER);
+        // Check the alternative header
+        if (header == null) {
+            header = (String) dict.get(IPOJO_HEADER_ALT);
+        }
+
+        if (header != null) {
+            try {
+                parse(bundle, header);
+            } catch (IOException e) {
+                m_logger.log(Logger.ERROR, "An exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
+            } catch (ParseException e) {
+                m_logger.log(Logger.ERROR, "A parse exception occurs during the parsing of the bundle " + bundle.getBundleId(), e);
+            }
+        }
+
+    }
+
+    /**
+     * A bundle is stopping.
+     *
+     * @param bundle the bundle
+     */
+    public void deactivate(Bundle bundle) {
+        ComponentsAndInstances cai = m_registry.remove(bundle);
+        if (cai != null) {
+            cai.stop();
+        }
+    }
+
+    /**
+     * {@inheritDoc BundleProcessor#start}
+     */
+    public void start() {
+        // Nothing to do
+    }
+
+    /**
+     * {@inheritDoc BundleProcessor#stop}
+     * <p/>
+     * This method cleans up all created factories and instances.
+     */
+    public void stop() {
+        // Ignored, for a simple ordered shutdown, use ReverseBundleProcessor
+    }
+
+    /**
+     * Parses the internal metadata (from the manifest
+     * (in the iPOJO-Components property)). This methods
+     * creates factories and add instances to the instance creator.
+     *
+     * @param bundle     the owner bundle.
+     * @param components The iPOJO Header String.
+     * @throws IOException    if the manifest can not be found
+     * @throws ParseException if the parsing process failed
+     */
+    private void parse(Bundle bundle, String components) throws IOException, ParseException {
+        ManifestMetadataParser parser = new ManifestMetadataParser();
+        parser.parseHeader(components);
+
+        // Get the component type declaration
+        Element[] metadata = parser.getComponentsMetadata();
+        for (int i = 0; i < metadata.length; i++) {
+            handleTypeDeclaration(bundle, metadata[i]);
+        }
+
+        Dictionary[] instances = parser.getInstances();
+        for (int i = 0; instances != null && i < instances.length; i++) {
+            handleInstanceDeclaration(bundle, instances[i]);
+        }
+    }
+
+    /**
+     * Extracts and builds the declaration attached to an instance.
+     *
+     * @param bundle   the bundle declaring the instance
+     * @param instance the instance configuration (parsed from the header)
+     */
+    private void handleInstanceDeclaration(Bundle bundle, Dictionary instance) {
+
+        String component = (String) instance.get(COMPONENT_INSTANCE_ATTRIBUTE);
+        //String v = (String) instance.get(Factory.FACTORY_VERSION_PROPERTY); //TODO CES to GSA, why this is commented ?
+
+        DefaultInstanceDeclaration declaration = new DefaultInstanceDeclaration(bundle.getBundleContext(),
+                component, instance);
+        declaration.start();
+
+        getComponentsAndInstances(bundle).m_instances.add(declaration);
+
+    }
+
+    /**
+     * Adds a component factory to the factory list.
+     *
+     * @param metadata the new component metadata.
+     * @param bundle   the bundle.
+     */
+    private void handleTypeDeclaration(Bundle bundle, Element metadata) {
+
+        DefaultTypeDeclaration declaration = new DefaultTypeDeclaration(bundle.getBundleContext(), metadata);
+        declaration.start();
+
+        getComponentsAndInstances(bundle).m_types.add(declaration);
+
+    }
+
+    /**
+     * Gets the {@link ComponentsAndInstances} declared by the given bundle.
+     *
+     * @param bundle the bundle
+     * @return the set of component and instances declared by the bundle, <code>null</code> otherwise
+     */
+    private ComponentsAndInstances getComponentsAndInstances(Bundle bundle) {
+        ComponentsAndInstances cai = m_registry.get(bundle);
+        if (cai == null) {
+            cai = new ComponentsAndInstances();
+            m_registry.put(bundle, cai);
+        }
+        return cai;
+    }
+
+    /**
+     * Container storing the components and instances declared by a bundle.
+     * This class is not intended to be used outside from the current processor.
+     */
+    private static class ComponentsAndInstances {
+        List<DefaultTypeDeclaration> m_types = new ArrayList<DefaultTypeDeclaration>();
+        List<DefaultInstanceDeclaration> m_instances = new ArrayList<DefaultInstanceDeclaration>();
+
+        /**
+         * Stops all declarations.
+         */
+        void stop() {
+            for (DefaultInstanceDeclaration instance : m_instances) {
+                instance.stop();
+            }
+            for (DefaultTypeDeclaration declaration : m_types) {
+                declaration.stop();
+            }
+            m_instances.clear();
+            m_types.clear();
+        }
+    }
+
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ExtensionBundleProcessor.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ExtensionBundleProcessor.java
new file mode 100644
index 0000000..e48584c
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ExtensionBundleProcessor.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.apache.felix.ipojo.extender.internal.builder.ReflectiveFactoryBuilder;
+import org.apache.felix.ipojo.extender.internal.declaration.DefaultExtensionDeclaration;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.ParseUtils;
+import org.apache.felix.ipojo.util.Log;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import java.util.*;
+
+/**
+ * Bundle processor handling the {@link #IPOJO_EXTENSION} header.
+ */
+public class ExtensionBundleProcessor implements BundleProcessor {
+
+    /**
+     * iPOJO Extension declaration header.
+     */
+    public static final String IPOJO_EXTENSION = "IPOJO-Extension";
+
+    /**
+     * Logger.
+     */
+    private final Log m_logger;
+
+    /**
+     * The map storing the association between bundles and the list of extension declaration.
+     */
+    private Map<Bundle, List<DefaultExtensionDeclaration>> m_extensions = new HashMap<Bundle, List<DefaultExtensionDeclaration>>();
+
+    /**
+     * Creates the processor.
+     *
+     * @param logger the logger
+     */
+    public ExtensionBundleProcessor(Log logger) {
+        m_logger = logger;
+    }
+
+    /**
+     * A bundle is starting.
+     *
+     * @param bundle the bundle
+     */
+    public void activate(Bundle bundle) {
+        Dictionary dict = bundle.getHeaders();
+        // Check for abstract factory type
+        String extension = (String) dict.get(IPOJO_EXTENSION);
+        if (extension != null) {
+            activateExtensions(bundle, extension);
+        }
+    }
+
+    /**
+     * A bundle is stopping.
+     *
+     * @param bundle the bundle
+     */
+    public void deactivate(Bundle bundle) {
+        List<DefaultExtensionDeclaration> declarations = m_extensions.get(bundle);
+        if (declarations != null) {
+            for (DefaultExtensionDeclaration declaration : declarations) {
+                declaration.stop();
+            }
+            m_extensions.remove(bundle);
+        }
+    }
+
+    /**
+     * iPOJO is starting.
+     * Nothing to do.
+     */
+    public void start() {
+        // Nothing to do
+    }
+
+    /**
+     * iPOJO is stopping.
+     * We clean up all extension in the reverse order of their installation.
+     */
+    public void stop() {
+        // Construct a new instance to avoid ConcurrentModificationException since deactivate also change the extensions
+        // list
+        // Ignored, for a simple ordered shutdown, use ReverseBundleProcessor
+    }
+
+    /**
+     * Parses an IPOJO-Extension manifest header and then creates
+     * iPOJO extensions (factory types).
+     *
+     * @param bundle the bundle containing the header.
+     * @param header the header to parse.
+     */
+    private void activateExtensions(Bundle bundle, String header) {
+        String[] extensions = ParseUtils.split(header, ",");
+        for (int i = 0; extensions != null && i < extensions.length; i++) {
+            String[] segments = ParseUtils.split(extensions[i], ":");
+
+            /*
+             * Get the fully qualified type name.
+             * type = [namespace] name
+             */
+            String[] nameparts = ParseUtils.split(segments[0].trim(), " \t");
+            String type = nameparts.length == 1 ? nameparts[0] : nameparts[0] + ":" + nameparts[1];
+
+            Class clazz;
+            try {
+                clazz = bundle.loadClass(segments[1]);
+            } catch (ClassNotFoundException e) {
+                m_logger.log(Logger.ERROR, "Cannot load the extension " + type, e);
+                return;
+            }
+
+            try {
+                ReflectiveFactoryBuilder builder = new ReflectiveFactoryBuilder(clazz.getConstructor(BundleContext.class, Element.class));
+                DefaultExtensionDeclaration declaration = new DefaultExtensionDeclaration(bundle.getBundleContext(), builder, type);
+
+                getBundleDeclarations(bundle).add(declaration);
+
+                declaration.start();
+
+                m_logger.log(Logger.DEBUG, "New factory type available: " + type);
+            } catch (NoSuchMethodException e) {
+                m_logger.log(Logger.ERROR,
+                        String.format("Extension '%s' is missing the required (BundleContext, Element) public " +
+                                "constructor", clazz.getName()));
+            }
+        }
+    }
+
+    /**
+     * Gets the list of declaration for the given method.
+     *
+     * @param bundle the bundle
+     * @return the list of extension declaration associated to the given bundle, <code>null</code> otherwise.
+     */
+    private List<DefaultExtensionDeclaration> getBundleDeclarations(Bundle bundle) {
+        List<DefaultExtensionDeclaration> declarations = m_extensions.get(bundle);
+        if (declarations == null) {
+            declarations = new ArrayList<DefaultExtensionDeclaration>();
+            m_extensions.put(bundle, declarations);
+        }
+        return declarations;
+    }
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ForwardingBundleProcessor.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ForwardingBundleProcessor.java
new file mode 100644
index 0000000..f11d7e1
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ForwardingBundleProcessor.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.osgi.framework.Bundle;
+
+/**
+ * A bundle processor delegating to a wrapped processor.
+ * Implementation defined how we retrieve the delegate.
+ */
+public abstract class ForwardingBundleProcessor implements BundleProcessor {
+    /**
+     * Implementation must implement this method to retrieve the wrapped bundle processor.
+     *
+     * @return the wrapped bundle processor on which we delegate all calls.
+     */
+    protected abstract BundleProcessor delegate();
+
+    public void activate(Bundle bundle) {
+        delegate().activate(bundle);
+    }
+
+    public void deactivate(Bundle bundle) {
+        delegate().deactivate(bundle);
+    }
+
+    public void start() {
+        delegate().start();
+    }
+
+    public void stop() {
+        delegate().stop();
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/QueuingActivationProcessor.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/QueuingActivationProcessor.java
new file mode 100644
index 0000000..13561a3
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/QueuingActivationProcessor.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.apache.felix.ipojo.extender.internal.ReferenceableCallable;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.osgi.framework.Bundle;
+
+/**
+ * A bundle processor submitting the activating job to the queue service.
+ * The submitted job relies on a delegated bundle processor.
+ */
+public class QueuingActivationProcessor extends ForwardingBundleProcessor {
+    /**
+     * The wrapped bundle processor used by the job.
+     */
+    private final BundleProcessor m_delegate;
+
+    /**
+     * The queue service.
+     */
+    private final QueueService m_queueService;
+
+    /**
+     * Creates an instance of the queuing bundle processor
+     *
+     * @param delegate     the bundle processor used by the submitted job
+     * @param queueService the used queue service
+     */
+    public QueuingActivationProcessor(BundleProcessor delegate, QueueService queueService) {
+        m_delegate = delegate;
+        m_queueService = queueService;
+    }
+
+    @Override
+    protected BundleProcessor delegate() {
+        return m_delegate;
+    }
+
+    /**
+     * A bundle is starting.
+     * The processing of the bundle is wrapped in a job submitted to the queue service.
+     *
+     * @param bundle the bundle
+     */
+    public void activate(final Bundle bundle) {
+        m_queueService.submit(new ReferenceableCallable<Boolean>(bundle) {
+            public Boolean call() throws Exception {
+                QueuingActivationProcessor.super.activate(bundle);
+                return true;
+            }
+        });
+    }
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ReverseBundleProcessor.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ReverseBundleProcessor.java
new file mode 100644
index 0000000..90d0ec0
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/processor/ReverseBundleProcessor.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.osgi.framework.Bundle;
+
+import java.util.LinkedList;
+
+/**
+ * A bundle processor delegating a wrapped bundle processor. On stop, the bundles are processed in reverse.
+ */
+public class ReverseBundleProcessor extends ForwardingBundleProcessor {
+
+    /**
+     * The wrapped bundle processor.
+     */
+    private final BundleProcessor m_delegate;
+
+    /**
+     * A list of bundle to process.
+     */
+    private LinkedList<Bundle> m_bundles = new LinkedList<Bundle>();
+
+    /**
+     * Creates the processor.
+     *
+     * @param delegate the processor on which call are delegated
+     */
+    public ReverseBundleProcessor(BundleProcessor delegate) {
+        m_delegate = delegate;
+    }
+
+    /**
+     * @return the wrapped processor.
+     */
+    @Override
+    protected BundleProcessor delegate() {
+        return m_delegate;
+    }
+
+    /**
+     * A bundle is starting.
+     * The bundle is added to the list, and the processing delegated to the wrapped processor.
+     *
+     * @param bundle the bundle
+     */
+    @Override
+    public void activate(Bundle bundle) {
+        m_bundles.addLast(bundle);
+        super.activate(bundle);
+    }
+
+    /**
+     * A bundle is stopping.
+     * The bundle is removed from the list and the processing delegated to the wrapped processor.
+     *
+     * @param bundle the bundle
+     */
+    @Override
+    public void deactivate(Bundle bundle) {
+        m_bundles.remove(bundle);
+        super.deactivate(bundle);
+    }
+
+    /**
+     * iPOJO is stopping.
+     * The bundle that are still in the list are processed in the <strong>reverse</strong> order by the wrapped
+     * processor.
+     */
+    @Override
+    public void stop() {
+        // deactivate in reverse order
+        while (!m_bundles.isEmpty()) {
+            super.deactivate(m_bundles.pollLast());
+        }
+        super.stop();
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/ExecutorQueueService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/ExecutorQueueService.java
new file mode 100644
index 0000000..0da4057
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/ExecutorQueueService.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue;
+
+import org.apache.felix.ipojo.extender.internal.AbstractService;
+import org.apache.felix.ipojo.extender.internal.LifecycleQueueService;
+import org.apache.felix.ipojo.extender.queue.Callback;
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.osgi.framework.BundleContext;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ * An asynchronous implementation of the queue service. This implementation relies on an executor service.
+ */
+public class ExecutorQueueService extends AbstractService implements LifecycleQueueService {
+
+    /**
+     * The default thread pool size (3).
+     */
+    private final static int DEFAULT_QUEUE_SIZE = 3;
+
+    /**
+     * The executor service.
+     */
+    private final ExecutorService m_executorService;
+
+    /**
+     * The statistics populated by this queue service.
+     */
+    private final Statistic m_statistic = new Statistic();
+
+    /**
+     * Creates the queue service using the default pool size.
+     *
+     * @param bundleContext the bundle context.
+     */
+    public ExecutorQueueService(BundleContext bundleContext) {
+        this(bundleContext, DEFAULT_QUEUE_SIZE);
+    }
+
+    /**
+     * Creates the queue service.
+     *
+     * @param bundleContext the bundle context.
+     * @param size          the thread pool size.
+     */
+    public ExecutorQueueService(BundleContext bundleContext, int size) {
+        this(bundleContext, Executors.newFixedThreadPool(size));
+    }
+
+    /**
+     * Creates the queue service.
+     *
+     * @param bundleContext the bundle context.
+     * @param size          the thread pool size
+     * @param threadFactory the thread factory
+     */
+    public ExecutorQueueService(BundleContext bundleContext, int size, ThreadFactory threadFactory) {
+        this(bundleContext, Executors.newFixedThreadPool(size, threadFactory));
+    }
+
+
+    /**
+     * Creates the queue service.
+     * All others constructors delegates to this one.
+     *
+     * @param bundleContext   the bundle context
+     * @param executorService the executor service we have to use
+     */
+    private ExecutorQueueService(BundleContext bundleContext, ExecutorService executorService) {
+        super(bundleContext, QueueService.class);
+        m_executorService = executorService;
+    }
+
+    /**
+     * Stops the service.
+     */
+    public void stop() {
+        m_executorService.shutdown();
+        super.stop();
+    }
+
+    @Override
+    protected Dictionary<String, ?> getServiceProperties() {
+        Hashtable<String, Object> properties = new Hashtable<String, Object>();
+        properties.put(QueueService.QUEUE_MODE_PROPERTY, QueueService.ASYNCHRONOUS_QUEUE_MODE);
+        return properties;
+    }
+
+    public int getFinished() {
+        return m_statistic.getFinishedCounter().get();
+    }
+
+    public int getWaiters() {
+        return m_statistic.getWaiters().size();
+    }
+
+    public int getCurrents() {
+        return m_statistic.getCurrentsCounter().get();
+    }
+
+    public List<JobInfo> getWaitersInfo() {
+        List<JobInfo> snapshot;
+        synchronized (m_statistic.getWaiters()) {
+            snapshot = new ArrayList<JobInfo>(m_statistic.getWaiters());
+        }
+        return Collections.unmodifiableList(snapshot);
+    }
+
+    /**
+     * Submits a job to the queue. The submitted job is wrapped into a {@link JobInfoCallable} to collect the
+     * statistics.
+     *
+     * @param callable    the job
+     * @param callback    callback called when the job is processed
+     * @param description a description of the job
+     * @return the reference on the submitted job
+     */
+    public <T> Future<T> submit(Callable<T> callable, Callback<T> callback, String description) {
+        return m_executorService.submit(new JobInfoCallable<T>(m_statistic, callable, callback, description));
+    }
+
+    public <T> Future<T> submit(Callable<T> callable, String description) {
+        return submit(callable, null, description);
+    }
+
+    public <T> Future<T> submit(Callable<T> callable) {
+        return submit(callable, "No description");
+    }
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/JobInfoCallable.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/JobInfoCallable.java
new file mode 100644
index 0000000..2b98ca9
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/JobInfoCallable.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue;
+
+import org.apache.felix.ipojo.extender.queue.Callback;
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+
+import java.util.concurrent.Callable;
+
+/**
+ * A callable computing job statistics. The job is given as another callable.
+ * The statistics are global, so must be used carefully.
+ */
+public class JobInfoCallable<T> implements Callable<T>, JobInfo {
+
+    /**
+     * The statistic object.
+     */
+    private final Statistic m_statistic;
+
+    /**
+     * The genuine job.
+     */
+    private final Callable<T> m_delegate;
+
+    /**
+     * A callback notified when the job is processed.
+     */
+    private final Callback<T> m_callback;
+
+    /**
+     * The job description.
+     */
+    private final String m_description;
+
+    /**
+     * The date (in milli) when this object is created.
+     */
+    private long enlistmentTime = System.currentTimeMillis();
+
+    /**
+     * The date when the job processing started.
+     */
+    private long startTime = -1;
+
+    /**
+     * The date when the job processing is completed.
+     */
+    private long endTime = -1;
+
+    /**
+     * Creates the job info callable.
+     *
+     * @param statistic   the statistics that will be populated
+     * @param delegate    the real job
+     * @param callback    the callback notified when the job is completed
+     * @param description the job description
+     */
+    public JobInfoCallable(Statistic statistic,
+                           Callable<T> delegate,
+                           Callback<T> callback,
+                           String description) {
+        m_statistic = statistic;
+        m_delegate = delegate;
+        m_callback = callback;
+        m_description = description;
+        m_statistic.getWaiters().add(this);
+    }
+
+    /**
+     * Executes the job.
+     * This method updates the statistics.
+     *
+     * @return the job result
+     * @throws Exception the job execution failed
+     */
+    public T call() throws Exception {
+        m_statistic.getWaiters().remove(this);
+        startTime = System.currentTimeMillis();
+        m_statistic.getCurrentsCounter().incrementAndGet();
+        T result = null;
+        try {
+            result = m_delegate.call();
+            return result;
+        } catch (Exception e) {
+            if (m_callback != null) {
+                m_callback.error(this, e);
+            }
+            throw e;
+        } finally {
+            m_statistic.getCurrentsCounter().decrementAndGet();
+            m_statistic.getFinishedCounter().incrementAndGet();
+            endTime = System.currentTimeMillis();
+            if (m_callback != null) {
+                m_callback.success(this, result);
+            }
+        }
+    }
+
+    /**
+     * @return the enlistment date.
+     */
+    public long getEnlistmentTime() {
+        return enlistmentTime;
+    }
+
+    /**
+     * @return the job start date.
+     */
+    public long getStartTime() {
+        return startTime;
+    }
+
+    /**
+     * @return the job completion date.
+     */
+    public long getEndTime() {
+        return endTime;
+    }
+
+    /**
+     * Computes the time spent in the waiting queue
+     *
+     * @return the waited time, if the job is still waiting, gets the current waited time
+     */
+    public long getWaitDuration() {
+        long end = startTime;
+        if (end == -1) {
+            // Not yet started
+            // Still waiting
+            end = System.currentTimeMillis();
+        }
+        return end - enlistmentTime;
+    }
+
+    /**
+     * Computes the time spent to execute the job (this does not include the waiting).
+     * If the job is not executed yet, or is still executing, {@literal -1} is returned
+     *
+     * @return the execution duration, or {@literal -1}.
+     */
+    public long getExecutionDuration() {
+        if ((startTime == -1) || (endTime == -1)) {
+            return -1;
+        }
+        return endTime - startTime;
+    }
+
+    /**
+     * @return the job description
+     */
+    public String getDescription() {
+        return m_description;
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/PrefixedThreadFactory.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/PrefixedThreadFactory.java
new file mode 100644
index 0000000..2c0dc46
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/PrefixedThreadFactory.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * A thread factory setting the name of the created thread.
+ * This thread factory delegates the thread creation on another factory, it just set the thread name (actually just
+ * set a prefix).
+ */
+public class PrefixedThreadFactory implements ThreadFactory {
+
+    /**
+     * The wrapped thread factory on which creation is delegated.
+     */
+    private final ThreadFactory m_threadFactory;
+
+    /**
+     * The prefix.
+     */
+    private final String m_prefix;
+
+    /**
+     * Creates the object using the default thread factory.
+     *
+     * @param prefix the prefix
+     */
+    public PrefixedThreadFactory(String prefix) {
+        this(Executors.defaultThreadFactory(), prefix);
+    }
+
+    /**
+     * Creates the object delegating to the given thread factory.
+     *
+     * @param threadFactory the thread factory
+     * @param prefix        the prefix
+     */
+    public PrefixedThreadFactory(ThreadFactory threadFactory, String prefix) {
+        m_threadFactory = threadFactory;
+        m_prefix = prefix;
+    }
+
+    /**
+     * Creates a new thread.
+     * Prepend the prefix to the thread name
+     *
+     * @param r the runnable
+     * @return the thread object
+     */
+    public Thread newThread(Runnable r) {
+        Thread thread = m_threadFactory.newThread(r);
+        thread.setName(m_prefix + thread.getName());
+        return thread;
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/Statistic.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/Statistic.java
new file mode 100644
index 0000000..52e232a
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/Statistic.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue;
+
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Objects wrapping the {@link org.apache.felix.ipojo.extender.queue.QueueService} statistics.
+ */
+public class Statistic {
+    /**
+     * The synchronized list of waiting jobs.
+     */
+    private final List<JobInfo> m_waiters = Collections.synchronizedList(new ArrayList<JobInfo>());
+
+    /**
+     * The number of completed jobs.
+     */
+    private final AtomicInteger m_finished = new AtomicInteger(0);
+
+    /**
+     * The number of job being processed.
+     */
+    private final AtomicInteger m_currents = new AtomicInteger(0);
+
+    /**
+     * @return the number of completed jobs.
+     */
+    public AtomicInteger getFinishedCounter() {
+        return m_finished;
+    }
+
+    /**
+     * @return the list of waiting jobs.
+     */
+    public List<JobInfo> getWaiters() {
+        return m_waiters;
+    }
+
+    /**
+     * @return the number of jobs under processing.
+     */
+    public AtomicInteger getCurrentsCounter() {
+        return m_currents;
+    }
+
+
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/SynchronousQueueService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/SynchronousQueueService.java
new file mode 100644
index 0000000..6800b29
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/SynchronousQueueService.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue;
+
+import org.apache.felix.ipojo.extender.internal.AbstractService;
+import org.apache.felix.ipojo.extender.internal.LifecycleQueueService;
+import org.apache.felix.ipojo.extender.queue.Callback;
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.osgi.framework.BundleContext;
+
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.concurrent.*;
+
+/**
+ * An implementation of the Lifecycle Queue Service for synchronous processing.
+ */
+public class SynchronousQueueService extends AbstractService implements LifecycleQueueService {
+
+    private final Statistic m_statistic = new Statistic();
+
+    public SynchronousQueueService(BundleContext bundleContext) {
+        super(bundleContext, QueueService.class);
+    }
+
+    @Override
+    protected Dictionary<String, ?> getServiceProperties() {
+        Hashtable<String, Object> properties = new Hashtable<String, Object>();
+        properties.put(QueueService.QUEUE_MODE_PROPERTY, QueueService.SYNCHRONOUS_QUEUE_MODE);
+        return properties;
+    }
+
+    public int getFinished() {
+        return m_statistic.getFinishedCounter().get();
+    }
+
+    public int getWaiters() {
+        return 0;
+    }
+
+    public int getCurrents() {
+        return m_statistic.getCurrentsCounter().get();
+    }
+
+    public List<JobInfo> getWaitersInfo() {
+        return Collections.emptyList();
+    }
+
+    public <T> Future<T> submit(Callable<T> callable, Callback<T> callback, String description) {
+        JobInfoCallable<T> exec = new JobInfoCallable<T>(m_statistic, callable, callback, description);
+        try {
+            return new ImmediateFuture<T>(exec.call());
+        } catch (Exception e) {
+            return new ExceptionFuture<T>(e);
+        }
+
+    }
+
+    public <T> Future<T> submit(Callable<T> callable, String description) {
+        return submit(callable, null, description);
+    }
+
+    public <T> Future<T> submit(Callable<T> callable) {
+        return submit(callable, "No description");
+    }
+
+    private class ImmediateFuture<T> implements Future<T> {
+        private T m_result;
+
+        public ImmediateFuture(T result) {
+            m_result = result;
+        }
+
+        public boolean cancel(boolean mayInterruptIfRunning) {
+            return false;
+        }
+
+        public boolean isCancelled() {
+            return false;
+        }
+
+        public boolean isDone() {
+            return true;
+        }
+
+        public T get() throws InterruptedException, ExecutionException {
+            return m_result;
+        }
+
+        public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+            return get();
+        }
+    }
+
+    private class ExceptionFuture<T> extends ImmediateFuture<T> {
+        private ExecutionException m_exception;
+
+        public ExceptionFuture(Exception e) {
+            super(null);
+            m_exception = new ExecutionException(e);
+        }
+
+        @Override
+        public T get() throws InterruptedException, ExecutionException {
+            throw m_exception;
+        }
+
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/HeaderPreferenceSelection.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/HeaderPreferenceSelection.java
new file mode 100644
index 0000000..c7cb3d7
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/HeaderPreferenceSelection.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue.pref;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * A preference selection strategy based on a manifest header.
+ * By default, the {@literal IPOJO-Queue-Preference} header is used.
+ */
+public class HeaderPreferenceSelection implements PreferenceSelection {
+
+    private final String name;
+
+    public HeaderPreferenceSelection() {
+        this("IPOJO-Queue-Preference");
+    }
+
+    public HeaderPreferenceSelection(String name) {
+        this.name = name;
+    }
+
+    public Preference select(Bundle source) {
+        String header = source.getHeaders().get(name);
+
+        // No preference specified, return default
+        if (header == null) {
+            return Preference.DEFAULT;
+        }
+
+        header = header.trim();
+        try {
+            return Preference.valueOf(header.toUpperCase());
+        } catch (IllegalArgumentException e) {
+            return Preference.DEFAULT;
+        }
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/Preference.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/Preference.java
new file mode 100644
index 0000000..3a245f8
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/Preference.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue.pref;
+
+/**
+ * The processing preference.
+ * <p/>
+ * Each bundle can set the desired processing strategy, however the system can override this choice.
+ * <p/>
+ * 3 strategies are possible:
+ * <ul>
+ * <li>SYNC: for synchronous processing</li>
+ * <li>ASYNC: for asynchronous processing</li>
+ * <li>DEFAULT: using the default behavior</li>
+ * </ul>
+ */
+public enum Preference {
+    SYNC, ASYNC, DEFAULT
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/PreferenceQueueService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/PreferenceQueueService.java
new file mode 100644
index 0000000..b1317cc
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/PreferenceQueueService.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue.pref;
+
+import org.apache.felix.ipojo.extender.internal.LifecycleQueueService;
+import org.apache.felix.ipojo.extender.queue.Callback;
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleReference;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+
+/**
+ * An implementation of the queue service delegating on the synchronous and asynchronous implementations according to
+ * the processing preference.
+ */
+public class PreferenceQueueService implements LifecycleQueueService {
+
+    /**
+     * The preference selection strategy.
+     */
+    private final PreferenceSelection m_strategy;
+
+    /**
+     * The synchronous queue service.
+     */
+    private final LifecycleQueueService m_syncQueue;
+
+    /**
+     * The asynchronous queue service.
+     */
+    private final LifecycleQueueService m_asyncQueue;
+
+    /**
+     * The default queue service (chosen using the global preference).
+     */
+    private QueueService m_defaultQueue;
+
+    /**
+     * Creates the preference queue service.
+     *
+     * @param strategy   the preference strategy
+     * @param syncQueue  the synchronous queue service
+     * @param asyncQueue the asynchronous queue service
+     */
+    public PreferenceQueueService(PreferenceSelection strategy, LifecycleQueueService syncQueue, LifecycleQueueService asyncQueue) {
+        m_strategy = strategy;
+        m_syncQueue = syncQueue;
+        m_asyncQueue = asyncQueue;
+
+        // By default, system queue is asynchronous
+        m_defaultQueue = asyncQueue;
+    }
+
+    /**
+     * Starting queues.
+     */
+    public void start() {
+        m_syncQueue.start();
+        m_asyncQueue.start();
+    }
+
+    /**
+     * Stopping queues.
+     */
+    public void stop() {
+        m_syncQueue.stop();
+        m_asyncQueue.stop();
+    }
+
+    /**
+     * @return the number of completed jobs.
+     */
+    public int getFinished() {
+        return m_syncQueue.getFinished() + m_asyncQueue.getFinished();
+    }
+
+    /**
+     * @return the number of waiting jobs.
+     */
+    public int getWaiters() {
+        return m_syncQueue.getWaiters() + m_asyncQueue.getWaiters();
+    }
+
+    /**
+     * @return the number of jobs being processed.
+     */
+    public int getCurrents() {
+        return m_syncQueue.getCurrents() + m_asyncQueue.getCurrents();
+    }
+
+    /**
+     * Gets the number of waiting job. Notice that the synchronous queue does not have a waiting queue.
+     *
+     * @return the number of waiting job.
+     */
+    public List<JobInfo> getWaitersInfo() {
+        // synchronous queue as no waiters, so snapshot is always empty and can be ignored
+        return m_asyncQueue.getWaitersInfo();
+    }
+
+    /**
+     * Submits a job to the right queue.
+     * The queue selection works as follow:
+     * If the bundle submitting the queue has a preference, use this preference, otherwise use the default preference.
+     *
+     * @param callable    the job
+     * @param callback    callback called when the job is processed
+     * @param description a description of the job
+     * @return the reference of the submitted job
+     */
+    public <T> Future<T> submit(Callable<T> callable, Callback<T> callback, String description) {
+        // Argghhh, how can I choose between the 2 QueueService ?
+        // I was expecting to have the source Bundle to make a decision
+        Preference preference = Preference.DEFAULT;
+        if (callable instanceof BundleReference) {
+            Bundle bundle = ((BundleReference) callable).getBundle();
+            preference = m_strategy.select(bundle);
+        }
+
+        QueueService selected = m_defaultQueue;
+        switch (preference) {
+            case ASYNC:
+                selected = m_asyncQueue;
+                break;
+            case SYNC:
+                selected = m_syncQueue;
+                break;
+        }
+
+        return selected.submit(callable, callback, description);
+    }
+
+    public <T> Future<T> submit(Callable<T> callable, String description) {
+        return submit(callable, null, description);
+    }
+
+    public <T> Future<T> submit(Callable<T> callable) {
+        return submit(callable, "No description");
+    }
+}
\ No newline at end of file
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/PreferenceSelection.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/PreferenceSelection.java
new file mode 100644
index 0000000..e07f451
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/PreferenceSelection.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue.pref;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * An interface to choose the processing preference.
+ */
+public interface PreferenceSelection {
+    Preference select(Bundle source);
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/enforce/EnforcedQueueService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/enforce/EnforcedQueueService.java
new file mode 100644
index 0000000..ffbb26d
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/enforce/EnforcedQueueService.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue.pref.enforce;
+
+import org.apache.felix.ipojo.extender.internal.LifecycleQueueService;
+import org.apache.felix.ipojo.extender.internal.queue.pref.Preference;
+import org.apache.felix.ipojo.extender.internal.queue.pref.PreferenceSelection;
+import org.apache.felix.ipojo.extender.queue.Callback;
+import org.apache.felix.ipojo.util.Log;
+import org.apache.felix.ipojo.util.Logger;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleReference;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+
+/**
+ * A queue service implementation enforcing the processing preference choice for the bundle.
+ */
+public class EnforcedQueueService extends ForwardingQueueService {
+
+    /**
+     * The preference strategy selection.
+     */
+    private final PreferenceSelection m_strategy;
+
+    /**
+     * The lifecycle queue service on which the job are delegated.
+     */
+    private final LifecycleQueueService m_queueService;
+
+    /**
+     * The preference.
+     */
+    private final Preference m_enforced;
+
+    /**
+     * The logger.
+     */
+    private final Log m_logger;
+
+    /**
+     * Constructor.
+     *
+     * @param strategy     the strategy
+     * @param queueService the queue service
+     * @param enforced     the preference we want to enforce
+     * @param logger       the logger
+     */
+    public EnforcedQueueService(PreferenceSelection strategy, LifecycleQueueService queueService, Preference enforced, Log logger) {
+        m_strategy = strategy;
+        m_queueService = queueService;
+        m_enforced = enforced;
+        m_logger = logger;
+    }
+
+    @Override
+    protected LifecycleQueueService delegate() {
+        return m_queueService;
+    }
+
+    @Override
+    public <T> Future<T> submit(Callable<T> callable, Callback<T> callback, String description) {
+        checkBundlePreference(callable);
+        return super.submit(callable, callback, description);
+    }
+
+    @Override
+    public <T> Future<T> submit(Callable<T> callable, String description) {
+        checkBundlePreference(callable);
+        return super.submit(callable, description);
+    }
+
+    @Override
+    public <T> Future<T> submit(Callable<T> callable) {
+        checkBundlePreference(callable);
+        return super.submit(callable);
+    }
+
+    /**
+     * Checks the bundle processing preference and compare with the enforced preference.
+     *
+     * @param callable the callable
+     */
+    private void checkBundlePreference(Callable<?> callable) {
+        if (callable instanceof BundleReference) {
+            Bundle bundle = ((BundleReference) callable).getBundle();
+            Preference preference = m_strategy.select(bundle);
+
+            if (!isCompatible(preference)) {
+                // Log a warning, Bundle asked for a synchronous processing,
+                // but we will enforce parametrised processing
+                String message = String.format(
+                        "Enforcing %s mode for Bundle %s/%s [%d] (asking for %s)",
+                        m_enforced.name(),
+                        bundle.getSymbolicName(),
+                        bundle.getVersion(),
+                        bundle.getBundleId(),
+                        preference
+                );
+                m_logger.log(Logger.WARNING, message);
+            }
+        }
+    }
+
+    /**
+     * @param preference the preference.
+     * @return is the given preference compatible with the enforced one.
+     */
+    private boolean isCompatible(Preference preference) {
+        return ((preference == m_enforced) || (preference == Preference.DEFAULT));
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/enforce/ForwardingQueueService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/enforce/ForwardingQueueService.java
new file mode 100644
index 0000000..33139ae
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/internal/queue/pref/enforce/ForwardingQueueService.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue.pref.enforce;
+
+import org.apache.felix.ipojo.extender.internal.LifecycleQueueService;
+import org.apache.felix.ipojo.extender.queue.Callback;
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+
+/**
+ * A queue service implementation delegating to a {@link LifecycleQueueService}.
+ */
+public abstract class ForwardingQueueService implements LifecycleQueueService {
+
+    protected abstract LifecycleQueueService delegate();
+
+    public void start() {
+        delegate().start();
+    }
+
+    public void stop() {
+        delegate().stop();
+    }
+
+    public int getFinished() {
+        return delegate().getFinished();
+    }
+
+    public int getWaiters() {
+        return delegate().getWaiters();
+    }
+
+    public int getCurrents() {
+        return delegate().getCurrents();
+    }
+
+    public List<JobInfo> getWaitersInfo() {
+        return delegate().getWaitersInfo();
+    }
+
+    public <T> Future<T> submit(Callable<T> callable, Callback<T> callback, String description) {
+        return delegate().submit(callable, callback, description);
+    }
+
+    public <T> Future<T> submit(Callable<T> callable, String description) {
+        return delegate().submit(callable, description);
+    }
+
+    public <T> Future<T> submit(Callable<T> callable) {
+        return delegate().submit(callable);
+    }
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/queue/Callback.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/queue/Callback.java
new file mode 100644
index 0000000..5a8dded
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/queue/Callback.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.queue;
+
+/**
+ * When submitting a processing job, a callback object can be passed to the submission process. This callback is
+ * notified when the job processing is completed.
+ */
+public interface Callback<T> {
+    /**
+     * The job was completed successfully.
+     *
+     * @param info   the job info
+     * @param result the job result
+     */
+    void success(JobInfo info, T result);
+
+    /**
+     * The job was not completed successfully.
+     *
+     * @param info      the job info
+     * @param exception the thrown exception
+     */
+    void error(JobInfo info, Exception exception);
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/queue/JobInfo.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/queue/JobInfo.java
new file mode 100644
index 0000000..3c78db8
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/queue/JobInfo.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.queue;
+
+/**
+ * Interface to retrieve information about the job execution.
+ */
+public interface JobInfo {
+
+    /**
+     * Gets the submission time of the job.
+     *
+     * @return the submission time
+     */
+    long getEnlistmentTime();
+
+    /**
+     * Gets the starting time. This is the date when the job execution starts.
+     *
+     * @return the start time
+     */
+    long getStartTime();
+
+    /**
+     * Gets the completion time. This is the date when the job execution ends.
+     *
+     * @return the end time
+     */
+    long getEndTime();
+
+    /**
+     * Gets the time spent in the waiting queue.
+     *
+     * @return the waited time
+     */
+    long getWaitDuration();
+
+    /**
+     * Gets the execution duration.
+     *
+     * @return the execution duration, {@literal -1} is this duration cannot be computed
+     */
+    long getExecutionDuration();
+
+    /**
+     * Gets the job description
+     *
+     * @return the description
+     */
+    String getDescription();
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/queue/QueueService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/queue/QueueService.java
new file mode 100644
index 0000000..e66ba47
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/extender/queue/QueueService.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.queue;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+
+/**
+ * Definition of the queue service.
+ * The queue service is used to enqueue the bundle processing job.
+ * The processing order is depending of the implementation.
+ */
+public interface QueueService {
+    /**
+     * The service property specifying the queue mode (sync/async/pref).
+     */
+    String QUEUE_MODE_PROPERTY = "ipojo.queue.mode";
+
+    /**
+     * Synchronous queue mode.
+     */
+    String SYNCHRONOUS_QUEUE_MODE = "sync";
+
+    /**
+     * Asynchronous queue mode.
+     */
+    String ASYNCHRONOUS_QUEUE_MODE = "async";
+
+    /**
+     * Preference queue mode.
+     */
+    String PREFERENCE_QUEUE_MODE = "pref";
+
+    /**
+     * The service property specifying the queue scope (global/...).
+     */
+    String QUEUE_SCOPE_PROPERTY = "ipojo.queue.scope";
+
+    /**
+     * Global queue scope.
+     */
+    String GLOABL_QUEUE_SCOPE = "global";
+
+    /**
+     * @return the number of jobs that have been executed entirely
+     *         (including successful and erroneous jobs).
+     */
+    int getFinished();
+
+    /**
+     * @return the number of jobs scheduled but not yet started.
+     */
+    int getWaiters();
+
+    /**
+     * @return the number of jobs currently executed (started but not finished).
+     */
+    int getCurrents();
+
+    /**
+     * @return a snapshot of the currently waiting jobs.
+     */
+    List<JobInfo> getWaitersInfo();
+
+    // Note: I don't want us to store error reports there
+    // Maybe we should use EventAdmin to send notifications ?
+    // getErrors
+
+    /**
+     * Submits a job to the queue service.
+     *
+     * @param callable    the job
+     * @param callback    callback called when the job is processed
+     * @param description a description of the job
+     * @return the future object to retrieve the result
+     */
+    <T> Future<T> submit(Callable<T> callable, Callback<T> callback, String description);
+
+    /**
+     * Submits a job to the queue service.
+     *
+     * @param callable    the job
+     * @param description a description of the job
+     * @return the future object to retrieve the result
+     */
+    <T> Future<T> submit(Callable<T> callable, String description);
+
+    /**
+     * Submits a job to the queue service.
+     *
+     * @param callable the job
+     * @return the future object to retrieve the result
+     */
+    <T> Future<T> submit(Callable<T> callable);
+
+
+    // TODO Add a way to add global callbacks
+    //<T> void addGlobalCallback(Callback<T> callback);
+    // <T> void removeGlobalCallback(Callback<T> callback);
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java
index a5f6c7e..8d3dbe1 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/architecture/ArchitectureHandler.java
@@ -20,6 +20,7 @@
 
 import java.util.Dictionary;
 
+import org.apache.felix.ipojo.Factory;
 import org.apache.felix.ipojo.PrimitiveHandler;
 import org.apache.felix.ipojo.architecture.Architecture;
 import org.apache.felix.ipojo.architecture.InstanceDescription;
@@ -43,7 +44,7 @@
      * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
      */
     public void configure(Element metadata, Dictionary configuration) {
-        m_name = (String) configuration.get("instance.name");
+        m_name = (String) configuration.get(Factory.INSTANCE_NAME_PROPERTY);
     }
 
     /**
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
index 37e1b83..fc3955d 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
@@ -21,6 +21,7 @@
 import java.util.*;
 
 import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.Factory;
 import org.apache.felix.ipojo.HandlerFactory;
 import org.apache.felix.ipojo.PrimitiveHandler;
 import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
@@ -352,7 +353,7 @@
         if (m_managedServicePID != null && m_sr == null) {
             Properties props = new Properties();
             props.put(Constants.SERVICE_PID, m_managedServicePID);
-            props.put("instance.name", getInstanceManager().getInstanceName());
+            props.put(Factory.INSTANCE_NAME_PROPERTY, getInstanceManager().getInstanceName());
             props.put("factory.name", getInstanceManager().getFactory().getFactoryName());
 
             // Security Check
@@ -562,7 +563,7 @@
                 Enumeration e = m_propagatedFromCA.keys();
                 while (e.hasMoreElements()) {
                     String k = (String) e.nextElement();
-                    if (! k.equals("instance.name")) {
+                    if (! k.equals(Factory.INSTANCE_NAME_PROPERTY)) {
                         props.put(k, m_propagatedFromCA.get(k));
                     }
                 }
@@ -572,7 +573,7 @@
                 Enumeration e = m_propagatedFromInstance.keys();
                 while (e.hasMoreElements()) {
                     String k = (String) e.nextElement();
-                    if (! k.equals("instance.name")) { // Skip instance.name
+                    if (! k.equals(Factory.INSTANCE_NAME_PROPERTY)) { // Skip instance.name
                         props.put(k, m_propagatedFromInstance.get(k));
                     }
                 }
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
index 0e6d77d..daa50cc 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandlerDescription.java
@@ -21,6 +21,7 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.felix.ipojo.Factory;
 import org.apache.felix.ipojo.architecture.HandlerDescription;
 import org.apache.felix.ipojo.metadata.Attribute;
 import org.apache.felix.ipojo.metadata.Element;
@@ -148,10 +149,10 @@
                 while (iterator.hasNext()) {
                     Element use = new Element("Uses", "");
                     ServiceReference ref = (ServiceReference) iterator.next();
-                    use.addAttribute(new Attribute("service.id", ref.getProperty(Constants.SERVICE_ID).toString()));                
-                    String instance = (String) ref.getProperty("instance.name");
+                    use.addAttribute(new Attribute(Constants.SERVICE_ID, ref.getProperty(Constants.SERVICE_ID).toString()));
+                    String instance = (String) ref.getProperty(Factory.INSTANCE_NAME_PROPERTY);
                     if (instance != null) {
-                        use.addAttribute(new Attribute("instance.name", instance));
+                        use.addAttribute(new Attribute(Factory.INSTANCE_NAME_PROPERTY, instance));
                     }
                     dep.addElement(use);
                 }
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
index a539984..62d53b2 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
@@ -32,10 +32,7 @@
 import java.util.Map;
 import java.util.Properties;
 
-import org.apache.felix.ipojo.ComponentInstance;
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.IPOJOServiceFactory;
-import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.*;
 import org.apache.felix.ipojo.util.Callback;
 import org.apache.felix.ipojo.util.Property;
 import org.apache.felix.ipojo.util.SecurityHelper;
@@ -152,11 +149,11 @@
 
         // Add instance name, factory name and factory version is set.
         try {
-            addProperty(new Property("instance.name", null, null, handler.getInstanceManager().getInstanceName(), String.class.getName(), handler.getInstanceManager(), handler));
+            addProperty(new Property(Factory.INSTANCE_NAME_PROPERTY, null, null, handler.getInstanceManager().getInstanceName(), String.class.getName(), handler.getInstanceManager(), handler));
             addProperty(new Property("factory.name", null, null, handler.getInstanceManager().getFactory().getFactoryName(), String.class.getName(), handler.getInstanceManager(), handler));
 
             if (handler.getInstanceManager().getFactory().getVersion() != null) {
-                addProperty(new Property("factory.version", null, null, handler.getInstanceManager().getFactory().getVersion(), String.class.getName(), handler.getInstanceManager(), handler));
+                addProperty(new Property(Factory.FACTORY_VERSION_PROPERTY, null, null, handler.getInstanceManager().getFactory().getVersion(), String.class.getName(), handler.getInstanceManager(), handler));
             }
 
             // Add the service.* if defined
@@ -485,8 +482,8 @@
             Dictionary newProps = (Dictionary) (updated.clone());
 
             // Remove keys that must not be compared
-            newProps.remove("instance.name");
-            oldProps.remove("instance.name");
+            newProps.remove(Factory.INSTANCE_NAME_PROPERTY);
+            oldProps.remove(Factory.INSTANCE_NAME_PROPERTY);
             newProps.remove(Constants.SERVICE_ID);
             oldProps.remove(Constants.SERVICE_ID);
             newProps.remove(Constants.SERVICE_PID);
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java
index 1acbfe1..e5bd89e 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java
@@ -25,6 +25,7 @@
 import java.util.Map;
 import java.util.Properties;
 
+import org.apache.felix.ipojo.Factory;
 import org.apache.felix.ipojo.metadata.Attribute;
 import org.apache.felix.ipojo.metadata.Element;
 
@@ -91,7 +92,7 @@
         String version = instance.getAttribute("version");
 
         if (name != null) {
-            dict.put("instance.name", instance.getAttribute("name"));
+            dict.put(Factory.INSTANCE_NAME_PROPERTY, instance.getAttribute("name"));
         }
 
         if (comp == null) {
@@ -101,7 +102,7 @@
         dict.put("component", comp);
 
         if (version != null) {
-            dict.put("factory.version", version);
+            dict.put(Factory.FACTORY_VERSION_PROPERTY, version);
         }
 
         Element[] props = instance.getElements("property");
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Log.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Log.java
new file mode 100644
index 0000000..5730053
--- /dev/null
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Log.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.util;
+
+/**
+ * API for the iPOJO internal Log system.
+ */
+public interface Log {
+    /**
+     * The Log Level ERROR.
+     */
+    int ERROR = 1;
+    /**
+     * The Log Level WARNING.
+     */
+    int WARNING = 2;
+    /**
+     * The Log Level INFO.
+     */
+    int INFO = 3;
+    /**
+     * The Log Level DEBUG.
+     */
+    int DEBUG = 4;
+
+    void log(int level, String msg);
+
+    void log(int level, String msg, Throwable exception);
+}
diff --git a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Logger.java b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
index e28009b..b7d6760 100644
--- a/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
+++ b/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/util/Logger.java
@@ -20,7 +20,7 @@
 
 import org.apache.felix.ipojo.ComponentInstance;
 import org.apache.felix.ipojo.ErrorHandler;
-import org.apache.felix.ipojo.Extender;
+import org.apache.felix.ipojo.extender.internal.Extender;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.log.LogService;
@@ -32,7 +32,7 @@
  *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class Logger {
+public class Logger implements Log {
 
     /**
      * The iPOJO default log level property.
@@ -50,22 +50,22 @@
     /**
      * The Log Level ERROR.
      */
-    public static final int ERROR = 1;
+    public static final int ERROR = Log.ERROR;
 
     /**
      * The Log Level WARNING.
      */
-    public static final int WARNING = 2;
+    public static final int WARNING = Log.WARNING;
 
     /**
      * The Log Level INFO.
      */
-    public static final int INFO = 3;
+    public static final int INFO = Log.INFO;
 
     /**
      * The Log Level DEBUG.
      */
-    public static final int DEBUG = 4;
+    public static final int DEBUG = Log.DEBUG;
 
     /**
      * The Bundle Context used to get the
@@ -332,7 +332,6 @@
                     handler.onWarning(m_instance, msg, error);
                 } // The others case are not supported
                 m_context.ungetService(ref);
-                return;
             } // Else do nothing...
         } catch (IllegalStateException e) {
             // Ignore
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultExtensionDeclarationTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultExtensionDeclarationTestCase.java
new file mode 100644
index 0000000..61e29ee
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultExtensionDeclarationTestCase.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.declaration;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import java.util.Hashtable;
+
+import org.apache.felix.ipojo.extender.ExtensionDeclaration;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.BundleContext;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the behavior of the devault extension declaration.
+ */
+public class DefaultExtensionDeclarationTestCase extends TestCase {
+
+    @Mock
+    private BundleContext m_bundleContext;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testRegistration() throws Exception {
+        m_bundleContext = mock(BundleContext.class);
+        DefaultExtensionDeclaration declaration = new DefaultExtensionDeclaration(m_bundleContext, null, "component");
+
+        // Before start, declaration is not bound
+        assertFalse(declaration.getStatus().isBound());
+        declaration.start();
+
+        // After start, declaration is bound
+        assertTrue(declaration.getStatus().isBound());
+
+        // Verify service registration
+        ArgumentCaptor<Hashtable> argument = ArgumentCaptor.forClass(Hashtable.class);
+        verify(m_bundleContext).registerService(eq(ExtensionDeclaration.class.getName()), eq(declaration), argument.capture());
+        assertEquals(argument.getValue().get(ExtensionDeclaration.EXTENSION_NAME_PROPERTY), "component");
+
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultInstanceDeclarationTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultInstanceDeclarationTestCase.java
new file mode 100644
index 0000000..e372f00
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultInstanceDeclarationTestCase.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.declaration;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+
+import java.util.Hashtable;
+
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.extender.InstanceDeclaration;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.osgi.framework.BundleContext;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the behavior of the default instance declaration.
+ */
+public class DefaultInstanceDeclarationTestCase extends TestCase {
+
+    @Mock
+    private BundleContext m_bundleContext;
+
+    @Captor
+    private ArgumentCaptor<Hashtable<String, Object>> argument;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testRegistrationWithEmptyConfiguration() throws Exception {
+        DefaultInstanceDeclaration declaration = new DefaultInstanceDeclaration(m_bundleContext, "component.Hello");
+        declaration.start();
+
+        // Declaration is not bound
+        assertFalse(declaration.getStatus().isBound());
+
+        // Verify service registration
+        verify(m_bundleContext).registerService(eq(InstanceDeclaration.class.getName()), eq(declaration), argument.capture());
+        assertEquals(argument.getValue().get(InstanceDeclaration.COMPONENT_NAME_PROPERTY), "component.Hello");
+        assertNull(argument.getValue().get(InstanceDeclaration.COMPONENT_VERSION_PROPERTY));
+
+    }
+
+    public void testRegistrationWithVersionedConfiguration() throws Exception {
+        Hashtable<String, Object> configuration = new Hashtable<String, Object>();
+        configuration.put(Factory.FACTORY_VERSION_PROPERTY, "1.0.0");
+        DefaultInstanceDeclaration declaration = new DefaultInstanceDeclaration(m_bundleContext, "component.Hello", configuration);
+
+        declaration.start();
+
+        // Declaration is not bound
+        assertFalse(declaration.getStatus().isBound());
+
+        // Verify service registration
+        verify(m_bundleContext).registerService(eq(InstanceDeclaration.class.getName()), eq(declaration), argument.capture());
+        assertEquals(argument.getValue().get(InstanceDeclaration.COMPONENT_NAME_PROPERTY), "component.Hello");
+        assertEquals(argument.getValue().get(InstanceDeclaration.COMPONENT_VERSION_PROPERTY), "1.0.0");
+
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultTypeDeclarationTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultTypeDeclarationTestCase.java
new file mode 100644
index 0000000..acf123b
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/declaration/DefaultTypeDeclarationTestCase.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.declaration;
+
+import junit.framework.TestCase;
+import org.apache.felix.ipojo.IPojoFactory;
+import org.apache.felix.ipojo.extender.ExtensionDeclaration;
+import org.apache.felix.ipojo.extender.TypeDeclaration;
+import org.apache.felix.ipojo.extender.builder.FactoryBuilder;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Checks the behavior of {@link TypeDeclaration}.
+ */
+public class DefaultTypeDeclarationTestCase extends TestCase {
+
+    @Mock
+    private BundleContext m_bundleContext;
+    @Mock
+    private Filter filter;
+    @Mock
+    private ServiceReference extensionReference;
+    @Mock
+    private ExtensionDeclaration m_extension;
+    @Mock
+    private FactoryBuilder m_builder;
+    @Mock
+    private IPojoFactory factory;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testRegistration() throws Exception {
+        when(m_bundleContext.createFilter(anyString())).thenReturn(filter);
+
+        DefaultTypeDeclaration declaration = new DefaultTypeDeclaration(m_bundleContext, element("component", "component.Hello"));
+        declaration.start();
+
+        // Declaration is not bound
+        assertFalse(declaration.getStatus().isBound());
+
+        // Verify service registration
+        verify(m_bundleContext).registerService(TypeDeclaration.class.getName(), declaration, null);
+
+    }
+
+    private Element element(String type, String name) {
+        Element root = new Element(type, null);
+        root.addAttribute(new Attribute("name", name));
+        return root;
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/linker/DeclarationLinkerTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/linker/DeclarationLinkerTestCase.java
new file mode 100644
index 0000000..5845772
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/linker/DeclarationLinkerTestCase.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.linker;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
+
+import org.apache.felix.ipojo.extender.internal.declaration.DefaultTypeDeclaration;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the linker behavior.
+ */
+public class DeclarationLinkerTestCase extends TestCase {
+    @Mock
+    private Bundle m_bundle;
+
+    @Mock
+    private BundleContext m_bundleContext;
+
+    @Mock
+    private Filter filter;
+
+    @Mock
+    private ServiceReference m_reference;
+
+    @Mock
+    private QueueService m_queueService;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testActivationDeactivation() throws Exception {
+/*
+        when(filter.match(m_reference)).thenReturn(true);
+        when(m_bundleContext.getService(m_reference)).thenReturn(m_extension);
+        when(m_extension.getFactoryBuilder()).thenReturn(m_builder);
+        when(m_builder.build(any(BundleContext.class), any(Element.class))).thenReturn(factory);
+*/
+        when(m_bundleContext.getService(m_reference)).thenReturn(new DefaultTypeDeclaration(m_bundleContext, element("component", "test.Hello")));
+        when(m_bundleContext.createFilter(anyString())).thenReturn(filter);
+        when(m_reference.getBundle()).thenReturn(m_bundle);
+        when(m_bundle.getBundleContext()).thenReturn(m_bundleContext);
+
+        DeclarationLinker linker = new DeclarationLinker(m_bundleContext, m_queueService);
+        assertNotNull(linker.addingService(m_reference));
+
+/*
+        DefaultTypeDeclaration declaration = new DefaultTypeDeclaration(m_bundleContext, element("component", "component.Hello"));
+        declaration.start();
+
+        // Declaration is not bound
+        assertFalse(declaration.getStatus().isBound());
+
+        verify(m_bundleContext).addServiceListener(captor.capture(), anyString());
+
+        ServiceListener listener = captor.getValue();
+        ServiceEvent e = new ServiceEvent(ServiceEvent.REGISTERED, m_reference);
+        listener.serviceChanged(e);
+
+        verify(factory).addFactoryStateListener(fslCaptor.capture());
+        FactoryStateListener fsl = fslCaptor.getValue();
+        fsl.stateChanged(factory, Factory.VALID);
+
+        assertTrue(declaration.getStatus().isBound());
+
+        // The 2nd tracker should have registered its own listener
+        verify(m_bundleContext, times(2)).addServiceListener(captor.capture(), anyString());
+        ServiceListener listener2 = captor.getValue();
+        assertNotSame(listener, listener2);
+
+        ServiceEvent e2 = new ServiceEvent(ServiceEvent.UNREGISTERING, m_reference);
+        listener.serviceChanged(e2);
+
+        // After extension removal, the declaration should be unbound
+        assertFalse(declaration.getStatus().isBound());
+*/
+    }
+
+
+    private Element element(String type, String name) {
+        Element root = new Element(type, null);
+        root.addAttribute(new Attribute("name", name));
+        return root;
+    }
+
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/processor/ChainedBundleProcessorTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/processor/ChainedBundleProcessorTestCase.java
new file mode 100644
index 0000000..0ba895c
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/processor/ChainedBundleProcessorTestCase.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.processor;
+
+import static org.mockito.Mockito.inOrder;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the behavior of the chained bundle processor.
+ */
+public class ChainedBundleProcessorTestCase extends TestCase {
+
+    @Mock
+    private BundleProcessor m_delegate1;
+
+    @Mock
+    private BundleProcessor m_delegate2;
+
+    @Mock
+    private Bundle m_bundle;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testActivationThenDeactivateAreCalledWithReversedProcessorsList() throws Exception {
+        ChainedBundleProcessor chain = ChainedBundleProcessor.create(m_delegate1, m_delegate2);
+
+        chain.activate(m_bundle);
+        chain.deactivate(m_bundle);
+
+        InOrder order = inOrder(m_delegate1, m_delegate2);
+        order.verify(m_delegate1).activate(m_bundle);
+        order.verify(m_delegate2).activate(m_bundle);
+        order.verify(m_delegate2).deactivate(m_bundle);
+        order.verify(m_delegate1).deactivate(m_bundle);
+    }
+
+    public void testStartStopIsCalledWithReversedProcessorsList() throws Exception {
+        ChainedBundleProcessor chain = ChainedBundleProcessor.create(m_delegate1, m_delegate2);
+
+        chain.start();
+        chain.stop();
+
+        InOrder order = inOrder(m_delegate1, m_delegate2);
+        order.verify(m_delegate1).start();
+        order.verify(m_delegate2).start();
+        order.verify(m_delegate2).stop();
+        order.verify(m_delegate1).stop();
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/processor/ExtensionBundleProcessorTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/processor/ExtensionBundleProcessorTestCase.java
new file mode 100644
index 0000000..b87f8c0
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/processor/ExtensionBundleProcessorTestCase.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.processor;
+
+import junit.framework.TestCase;
+import org.apache.felix.ipojo.ComponentFactory;
+import org.apache.felix.ipojo.extender.ExtensionDeclaration;
+import org.apache.felix.ipojo.util.Logger;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.*;
+
+/**
+ * Tests the extension bundle processor.
+ */
+public class ExtensionBundleProcessorTestCase extends TestCase {
+
+    @Mock
+    private BundleContext m_bundleContext;
+    @Mock
+    private Logger m_logger;
+    @Mock
+    private Bundle m_bundle;
+
+    @Override
+    public void setUp() throws Exception {
+        Dictionary<String, String> headers = new Hashtable<String, String>();
+        MockitoAnnotations.initMocks(this);
+
+        when(m_bundle.getBundleContext()).thenReturn(m_bundleContext);
+        when(m_bundleContext.getBundle()).thenReturn(m_bundle);
+        when(m_bundle.getHeaders()).thenReturn(headers);
+    }
+
+    public void testEmptyExtensionBundle() throws Exception {
+        ExtensionBundleProcessor processor = new ExtensionBundleProcessor(m_logger);
+        processor.activate(m_bundle);
+        verify(m_bundleContext, never()).registerService((Class<?>) null, null, null);
+    }
+
+    public void testSimpleExtensionBundle() throws Exception {
+        Dictionary<String, String> headers = new Hashtable<String, String>();
+        headers.put(ExtensionBundleProcessor.IPOJO_EXTENSION, "component:" + ComponentFactory.class.getName());
+        when(m_bundle.getHeaders()).thenReturn(headers);
+        Mockito.<Class<?>>when(m_bundle.loadClass(anyString())).thenReturn(ComponentFactory.class);
+
+        ExtensionBundleProcessor processor = new ExtensionBundleProcessor(m_logger);
+        processor.activate(m_bundle);
+        verify(m_bundleContext).registerService(eq(ExtensionDeclaration.class.getName()), any(ExtensionDeclaration.class), any(Dictionary.class));
+    }
+
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/processor/ReverseBundleProcessorTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/processor/ReverseBundleProcessorTestCase.java
new file mode 100644
index 0000000..7a7ded2
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/processor/ReverseBundleProcessorTestCase.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.processor;
+
+import org.apache.felix.ipojo.extender.internal.BundleProcessor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the behavior of the reverse bundle processor.
+ */
+public class ReverseBundleProcessorTestCase extends TestCase {
+
+    @Mock
+    private Bundle m_bundle1;
+
+    @Mock
+    private Bundle m_bundle2;
+
+    @Mock
+    private Bundle m_bundle3;
+
+    @Mock
+    private BundleProcessor m_delegate;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testReverseOrderWhenStopped() throws Exception {
+        ReverseBundleProcessor reverse = new ReverseBundleProcessor(m_delegate);
+        reverse.activate(m_bundle1);
+        reverse.activate(m_bundle2);
+        reverse.activate(m_bundle3);
+
+        reverse.stop();
+
+        InOrder order = Mockito.inOrder(m_delegate);
+        order.verify(m_delegate).deactivate(m_bundle3);
+        order.verify(m_delegate).deactivate(m_bundle2);
+        order.verify(m_delegate).deactivate(m_bundle1);
+
+    }
+
+    public void testReverseOrderWhenStoppedAndRemovedElements() throws Exception {
+        ReverseBundleProcessor reverse = new ReverseBundleProcessor(m_delegate);
+        reverse.activate(m_bundle1);
+        reverse.activate(m_bundle2);
+        reverse.activate(m_bundle3);
+
+        reverse.deactivate(m_bundle2);
+
+        reverse.stop();
+
+        InOrder order = Mockito.inOrder(m_delegate);
+        order.verify(m_delegate).deactivate(m_bundle2);
+        order.verify(m_delegate).deactivate(m_bundle3);
+        order.verify(m_delegate).deactivate(m_bundle1);
+
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/ExecutorQueueServiceTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/ExecutorQueueServiceTestCase.java
new file mode 100644
index 0000000..363eaab
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/ExecutorQueueServiceTestCase.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import java.util.Dictionary;
+import java.util.concurrent.Future;
+
+import org.apache.felix.ipojo.extender.internal.queue.callable.SleepingCallable;
+import org.apache.felix.ipojo.extender.internal.queue.callable.StringCallable;
+import org.apache.felix.ipojo.extender.queue.Callback;
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the Executor Queue Service.
+ */
+public class ExecutorQueueServiceTestCase extends TestCase {
+
+    @Mock
+    private BundleContext m_bundleContext;
+
+    @Mock
+    private ServiceRegistration<?> m_registration;
+
+    @Mock
+    private Callback<String> m_callback;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testQueueServiceRegistration() throws Exception {
+        ExecutorQueueService queueService = new ExecutorQueueService(m_bundleContext);
+
+        Mockito.<ServiceRegistration<?>>when(m_bundleContext.registerService(eq(QueueService.class.getName()), eq(queueService), any(Dictionary.class))).thenReturn(m_registration);
+
+        queueService.start();
+
+        verify(m_bundleContext).registerService(eq(QueueService.class.getName()), eq(queueService), any(Dictionary.class));
+
+        queueService.stop();
+
+        verify(m_registration).unregister();
+
+    }
+
+    public void testCallbackIsInvoked() throws Exception {
+        ExecutorQueueService queueService = new ExecutorQueueService(m_bundleContext);
+        queueService.start();
+
+        Future<String> future = queueService.submit(new StringCallable(), m_callback, "hello");
+
+        // Wait for callable to finish
+        assertEquals("hello", future.get());
+        verify(m_callback).success(any(JobInfo.class), eq("hello"));
+        verify(m_callback, never()).error(any(JobInfo.class), any(Exception.class));
+
+        queueService.stop();
+    }
+
+    public void testStatistics() throws Exception {
+        ExecutorQueueService queueService = new ExecutorQueueService(m_bundleContext, 2);
+        queueService.start();
+
+        // We create 4 job, so that we have the 2 first execution while the 2 others are waiting
+        Future<String> one = queueService.submit(new SleepingCallable(50, "1"), m_callback, "First");
+        Future<String> two = queueService.submit(new SleepingCallable(50, "2"), m_callback, "Second");
+        Future<String> three = queueService.submit(new SleepingCallable(50, "3"), m_callback, "Third");
+        Future<String> four = queueService.submit(new SleepingCallable(50, "4"), m_callback, "Fourth");
+
+        // Wait for callable to finish
+        one.get();
+        two.get();
+        assertEquals(2, queueService.getFinished());
+        assertEquals(2, queueService.getCurrents());
+
+        three.get();
+        four.get();
+
+        assertEquals(4, queueService.getFinished());
+        assertEquals(0, queueService.getCurrents());
+        assertEquals(0, queueService.getWaiters());
+
+        queueService.stop();
+    }
+
+}
+
+
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/JobInfoCallableTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/JobInfoCallableTestCase.java
new file mode 100644
index 0000000..1b1541a
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/JobInfoCallableTestCase.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue;
+
+import org.apache.felix.ipojo.extender.internal.queue.callable.StringCallable;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the job info callable.
+ */
+public class JobInfoCallableTestCase extends TestCase {
+    public void testCall() throws Exception {
+        Statistic stat = new Statistic();
+        long mark = System.currentTimeMillis();
+        JobInfoCallable<String> info = new JobInfoCallable<String>(stat, new StringCallable(), null, null);
+
+        // Before execution
+        assertTrue(info.getEnlistmentTime() >= mark);
+        assertEquals(-1, info.getExecutionDuration());
+        assertTrue(info.getWaitDuration() <= (System.currentTimeMillis() - mark));
+
+        assertTrue(stat.getWaiters().contains(info));
+        assertEquals(0, stat.getCurrentsCounter().get());
+        assertEquals(0, stat.getFinishedCounter().get());
+
+        info.call();
+
+        assertTrue(info.getExecutionDuration() != -1);
+
+        assertTrue(stat.getWaiters().isEmpty());
+        assertEquals(0, stat.getCurrentsCounter().get());
+        assertEquals(1, stat.getFinishedCounter().get());
+
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/PrefixedThreadFactoryTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/PrefixedThreadFactoryTestCase.java
new file mode 100644
index 0000000..ec00530
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/PrefixedThreadFactoryTestCase.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.ThreadFactory;
+
+import org.apache.felix.ipojo.extender.internal.queue.PrefixedThreadFactory;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the behavior of the {@link PrefixedThreadFactory}.
+ */
+public class PrefixedThreadFactoryTestCase extends TestCase {
+    public void testNewThread() throws Exception {
+        PrefixedThreadFactory factory = new PrefixedThreadFactory("test ");
+        Thread t = factory.newThread(mock(Runnable.class));
+        assertTrue(t.getName().startsWith("test "));
+    }
+    public void testNewThreadDelegation() throws Exception {
+        ThreadFactory delegate = mock(ThreadFactory.class);
+        when(delegate.newThread(any(Runnable.class))).thenReturn(new Thread("thread"));
+        PrefixedThreadFactory factory = new PrefixedThreadFactory(delegate, "test ");
+        Thread t = factory.newThread(mock(Runnable.class));
+        verify(delegate).newThread(any(Runnable.class));
+        assertEquals(t.getName(), "test thread");
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/SynchronousQueueServiceTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/SynchronousQueueServiceTestCase.java
new file mode 100644
index 0000000..cb2bf37
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/SynchronousQueueServiceTestCase.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.verify;
+
+import java.util.Dictionary;
+
+import org.apache.felix.ipojo.extender.internal.queue.callable.StringCallable;
+import org.apache.felix.ipojo.extender.queue.Callback;
+import org.apache.felix.ipojo.extender.queue.JobInfo;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the synchronous queue behavior
+ */
+public class SynchronousQueueServiceTestCase extends TestCase {
+
+    @Mock
+    private BundleContext m_bundleContext;
+
+    @Mock
+    private ServiceRegistration<?> m_registration;
+
+    @Mock
+    private Callback<String> m_callback;
+
+    @Captor
+    private ArgumentCaptor<JobInfo> infos;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testRegistration() throws Exception {
+        SynchronousQueueService queueService = new SynchronousQueueService(m_bundleContext);
+
+        Mockito.<ServiceRegistration<?>>when(m_bundleContext.registerService(eq(QueueService.class.getName()), eq(queueService), any(Dictionary.class))).thenReturn(m_registration);
+
+        queueService.start();
+
+        verify(m_bundleContext).registerService(eq(QueueService.class.getName()), eq(queueService), any(Dictionary.class));
+
+        queueService.stop();
+
+        verify(m_registration).unregister();
+    }
+
+    public void testSubmitsAreSequential() throws Exception {
+
+        SynchronousQueueService queueService = new SynchronousQueueService(m_bundleContext);
+
+        queueService.submit(new StringCallable("one"), m_callback, null);
+        queueService.submit(new StringCallable("two"), m_callback, null);
+
+        InOrder order = inOrder(m_callback);
+        order.verify(m_callback).success(infos.capture(), eq("one"));
+        order.verify(m_callback).success(infos.capture(), eq("two"));
+
+        JobInfo one = infos.getAllValues().get(0);
+        JobInfo two = infos.getAllValues().get(1);
+
+        assertTrue(two.getEnlistmentTime() >= one.getEndTime());
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/callable/SleepingCallable.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/callable/SleepingCallable.java
new file mode 100644
index 0000000..95bed29
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/callable/SleepingCallable.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue.callable;
+
+import java.util.concurrent.Callable;
+
+/**
+* A dummy job taking some time to complete....
+*/
+public class SleepingCallable implements Callable<String> {
+    private int m_time;
+    private String m_value;
+
+    public SleepingCallable(int time, String value) {
+        m_time = time;
+        m_value = value;
+    }
+
+    public String call() throws Exception {
+        Thread.sleep(m_time);
+        return m_value;
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/callable/StringCallable.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/callable/StringCallable.java
new file mode 100644
index 0000000..6940a01
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/callable/StringCallable.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue.callable;
+
+import java.util.concurrent.Callable;
+
+/**
+* A dummy job.
+*/
+public class StringCallable implements Callable<String> {
+
+    private final String m_hello;
+
+    public StringCallable() {
+        this("hello");
+    }
+
+    public StringCallable(String hello) {
+        m_hello = hello;
+    }
+
+    public String call() throws Exception {
+        return m_hello;
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/pref/HeaderPreferenceSelectionTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/pref/HeaderPreferenceSelectionTestCase.java
new file mode 100644
index 0000000..c187928
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/pref/HeaderPreferenceSelectionTestCase.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue.pref;
+
+import static org.mockito.Mockito.when;
+
+import java.util.Hashtable;
+
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the selection of the job processing preference from the bundle manifest.
+ */
+public class HeaderPreferenceSelectionTestCase extends TestCase {
+
+    public static final String HEADER = "Header";
+
+    @Mock
+    private Bundle m_bundle;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testMissingHeader() throws Exception {
+        Hashtable<String, String> headers = new Hashtable<String, String>();
+        when(m_bundle.getHeaders()).thenReturn(headers);
+        HeaderPreferenceSelection selection = new HeaderPreferenceSelection(HEADER);
+        assertEquals(Preference.DEFAULT, selection.select(m_bundle));
+    }
+
+    public void testUnrecognizedHeader() throws Exception {
+        Hashtable<String, String> headers = new Hashtable<String, String>();
+        headers.put(HEADER, "invalid");
+        when(m_bundle.getHeaders()).thenReturn(headers);
+        HeaderPreferenceSelection selection = new HeaderPreferenceSelection(HEADER);
+        assertEquals(Preference.DEFAULT, selection.select(m_bundle));
+    }
+
+    public void testSyncHeader() throws Exception {
+        Hashtable<String, String> headers = new Hashtable<String, String>();
+        // We should ignore case
+        headers.put(HEADER, "SyNc");
+        when(m_bundle.getHeaders()).thenReturn(headers);
+        HeaderPreferenceSelection selection = new HeaderPreferenceSelection(HEADER);
+        assertEquals(Preference.SYNC, selection.select(m_bundle));
+    }
+
+    public void testAsyncHeader() throws Exception {
+        Hashtable<String, String> headers = new Hashtable<String, String>();
+        // We should ignore case
+        headers.put(HEADER, "aSyNc");
+        when(m_bundle.getHeaders()).thenReturn(headers);
+        HeaderPreferenceSelection selection = new HeaderPreferenceSelection(HEADER);
+        assertEquals(Preference.ASYNC, selection.select(m_bundle));
+    }
+}
diff --git a/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/pref/enforce/EnforcedQueueServiceTestCase.java b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/pref/enforce/EnforcedQueueServiceTestCase.java
new file mode 100644
index 0000000..21a3bb7
--- /dev/null
+++ b/ipojo/runtime/core/src/test/java/org/apache/felix/ipojo/extender/internal/queue/pref/enforce/EnforcedQueueServiceTestCase.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.ipojo.extender.internal.queue.pref.enforce;
+
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import java.util.concurrent.Callable;
+
+import org.apache.felix.ipojo.extender.internal.LifecycleQueueService;
+import org.apache.felix.ipojo.extender.internal.queue.callable.StringCallable;
+import org.apache.felix.ipojo.extender.internal.queue.pref.Preference;
+import org.apache.felix.ipojo.extender.internal.queue.pref.PreferenceSelection;
+import org.apache.felix.ipojo.extender.queue.QueueService;
+import org.apache.felix.ipojo.util.Log;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleReference;
+
+import junit.framework.TestCase;
+
+/**
+ * Checks the enforced queue service.
+ */
+public class EnforcedQueueServiceTestCase extends TestCase {
+
+    @Mock
+    private LifecycleQueueService delegate;
+
+    @Mock
+    private Bundle m_bundle;
+
+    @Mock
+    private Log m_log;
+
+    @Mock
+    private PreferenceSelection m_selection;
+
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    public void testNoEnforcement() throws Exception {
+        when(m_selection.select(m_bundle)).thenReturn(Preference.DEFAULT);
+        EnforcedQueueService queueService = new EnforcedQueueService(m_selection, delegate, Preference.ASYNC, m_log);
+        queueService.submit(new ReferenceCallable());
+        verifyZeroInteractions(m_log);
+    }
+
+    public void testNoEnforcementBecauseNoBundleReference() throws Exception {
+        EnforcedQueueService queueService = new EnforcedQueueService(m_selection, delegate, Preference.ASYNC, m_log);
+        queueService.submit(new StringCallable());
+        verifyZeroInteractions(m_log);
+    }
+
+    public void testIncompatibleEnforcement() throws Exception {
+        when(m_selection.select(m_bundle)).thenReturn(Preference.SYNC);
+        EnforcedQueueService queueService = new EnforcedQueueService(m_selection, delegate, Preference.ASYNC, m_log);
+        queueService.submit(new ReferenceCallable());
+
+        verify(m_log).log(eq(Log.WARNING), anyString());
+    }
+
+    public void testCompatibleEnforcement() throws Exception {
+        when(m_selection.select(m_bundle)).thenReturn(Preference.ASYNC);
+        EnforcedQueueService queueService = new EnforcedQueueService(m_selection, delegate, Preference.ASYNC, m_log);
+        queueService.submit(new ReferenceCallable());
+        verifyZeroInteractions(m_log);
+    }
+
+    private class ReferenceCallable implements Callable<String>, BundleReference {
+        public String call() throws Exception {
+            return "hello";
+        }
+
+        public Bundle getBundle() {
+            return m_bundle;
+        }
+    }
+}