Fix issue Felix-1159
Add a 'version' attribute to component type and instances allowing to select the component type version when an instance is declared.
<component classname="..." version="1.0"/>
<component classname="..." version="1.1"/>
<instance component="..." version="1.0"/> -> Use the version 1.0
<instance component="..." version="1.1"/> -> Use the version 1.1
<instance component="..."/> -> Any version

This commit also define the "bundle" constant reusing the bundle version:
<component classname="..." version="bundle"/> -> Use the bundle version

The API also supports the version API, add a getVersion method in the ComponentTypeDescription and in the Factory interface.




git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@775456 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java
index c1529dd..df2b63e 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -42,83 +42,88 @@
      * The bundle context.
      */
     private BundleContext m_context;
-    
+
     /**
-     * The implementation class name. 
+     * The implementation class name.
      */
     private String m_classname;
-    
+
     /**
-     * The component type name. 
+     * The component type name.
      */
     private String m_name;
-    
+
     /**
-     * Is the component type immediate. 
+     * The component type version.
+     */
+    private String m_version;
+
+    /**
+     * Is the component type immediate.
      */
     private boolean m_immediate;
-    
+
     /**
-     * Manipulation metadata of the component type.  
+     * Manipulation metadata of the component type.
      */
     private Element m_manipulation;
-    
+
     /**
      * Component factory attached to the component
-     * type. 
+     * type.
      */
     private ComponentFactory m_factory;
-    
+
     /**
-     * Component type metadata. 
+     * Component type metadata.
      */
     private Element m_metadata;
-    
+
     /**
-     * List of provided services. 
+     * List of provided services.
      */
     private List m_services = new ArrayList(1);
-    
+
     /**
-     * List of service dependencies. 
+     * List of service dependencies.
      */
     private List m_dependencies = new ArrayList();
-    
+
     /**
-     * List of configuration properties. 
+     * List of configuration properties.
      */
     private List m_properties = new ArrayList();
-    
+
     /**
-     * The validate callback. 
+     * The validate callback.
      */
     private String m_validate;
-    
+
     /**
-     * The invalidate callback. 
+     * The invalidate callback.
      */
     private String m_invalidate;
-    
+
     /**
      * The udpated callback.
      */
     private String m_updated;
-    
+
     /**
-     * Are the properties propagated to provided services? 
+     * Are the properties propagated to provided services?
      */
     private boolean m_propagation;
-    
+
     /**
-     * The factory method. 
+     * The factory method.
      */
     private String m_factoryMethod;
-    
+
     /**
-     * Is the factory public? 
+     * Is the factory public?
      */
     private boolean m_public = true;
-    
+
     /**
      * The Managed Service PID.
      */
@@ -128,13 +133,13 @@
      * The temporal dependencies.
      */
     private ArrayList m_temporals = new ArrayList();
-    
+
     /**
      * List of Handler representing external
      * handler configuration.
      */
     private List m_handlers = new ArrayList();
-    
+
     /**
      * Checks that the component type is not already
      * started.
@@ -144,7 +149,7 @@
             throw new IllegalStateException("The component type was already initialized, cannot modify metadata");
         }
     }
-    
+
     /**
      * Checks that the component type description is valid.
      */
@@ -184,7 +189,7 @@
         initializeFactory();
         m_factory.stop();
     }
-    
+
     /**
      * Initializes the factory.
      */
@@ -193,7 +198,7 @@
             createFactory();
         }
     }
-    
+
     /**
      * Sets the bundle context.
      * @param bc the bundle context
@@ -204,10 +209,10 @@
         m_context = bc;
         return this;
     }
-    
+
     /**
      * Sets the implementation class.
-     * @param classname the class name 
+     * @param classname the class name
      * @return the current component type
      */
     public PrimitiveComponentType setClassName(String classname) {
@@ -215,7 +220,7 @@
         m_classname = classname;
         return this;
     }
-    
+
     /**
      * Sets the component type name.
      * @param name the factory name
@@ -226,7 +231,19 @@
         m_name = name;
         return this;
     }
-    
+
+    /**
+     * Sets the component type version.
+     * @param version the factory version or "bundle" to use the
+     * bundle version.
+     * @return the current component type
+     */
+    public PrimitiveComponentType setComponentTypeVersion(String version) {
+        ensureNotInitialized();
+        m_version = version;
+        return this;
+    }
+
     /**
      * Sets if the component type is immediate or not.
      * @param immediate <code>true</code> to set the component
@@ -238,7 +255,7 @@
         m_immediate = immediate;
         return this;
     }
-    
+
     /**
      * Sets the dependency factory method.
      * @param method the method used to create pojo object.
@@ -249,7 +266,7 @@
         m_factoryMethod = method;
         return this;
     }
-    
+
     /**
      * Sets if the component type propagates properties to service properties.
      * @param propagation <code>true</code> to enable propagation
@@ -260,10 +277,10 @@
         m_propagation = propagation;
         return this;
     }
-    
+
     /**
      * Sets the factory public aspect.
-     * @param visible <code>false</code> to create a private factory. 
+     * @param visible <code>false</code> to create a private factory.
      * @return the current component type
      */
     public PrimitiveComponentType setPublic(boolean visible) {
@@ -271,7 +288,7 @@
         m_public = visible;
         return this;
     }
-    
+
     /**
      * Sets the managed service pid.
      * @param pid the managed service pid
@@ -282,7 +299,7 @@
         m_msPID = pid;
         return this;
     }
-    
+
     /**
      * Sets the validate method.
      * @param method the validate method
@@ -293,7 +310,7 @@
         m_validate = method;
         return this;
     }
-    
+
     /**
      * Sets the invalidate method.
      * @param method the invalidate method
@@ -304,7 +321,7 @@
         m_invalidate = method;
         return this;
     }
-    
+
     /**
      * Sets the updated method.
      * @param method the updated method
@@ -315,10 +332,10 @@
         m_updated = method;
         return this;
     }
-    
+
     /**
      * Generates the component description.
-     * @return the component type description of 
+     * @return the component type description of
      * the current component type
      */
     private Element generateComponentMetadata() {
@@ -327,6 +344,9 @@
         if (m_name != null) {
             element.addAttribute(new Attribute("name", m_name));
         }
+        if (m_version != null) {
+            element.addAttribute(new Attribute("version", m_version));
+        }
         if (m_factoryMethod != null) {
             element.addAttribute(new Attribute("factory-method", m_factoryMethod));
         }
@@ -360,7 +380,7 @@
             callback.addAttribute(new Attribute("method", m_invalidate));
             element.addElement(callback);
         }
-        
+
         // Properties
         // First determine if we need the properties element
         if (m_propagation || m_msPID != null || ! m_properties.isEmpty()) {
@@ -380,16 +400,16 @@
             }
             element.addElement(properties);
         }
-        
+
         // External handlers
         for (int i = 0; i < m_handlers.size(); i++) {
             HandlerConfiguration hc = (HandlerConfiguration) m_handlers.get(i);
             element.addElement(hc.getElement());
         }
-        
+
         return element;
     }
-    
+
 
     /**
      * Adds an HandlerConfiguration to the component type. Each component type
@@ -402,7 +422,7 @@
         m_handlers.add(handler);
         return this;
     }
-    
+
     /**
      * Creates the component factory.
      */
@@ -422,9 +442,9 @@
         } catch (ConfigurationException e) {
             throw new IllegalStateException("An exception occurs during factory initialization : " + e.getMessage());
         }
-       
+
     }
-    
+
     /**
      * Manipulates the implementation class.
      * @return the manipulated class
@@ -440,7 +460,7 @@
             throw new IllegalStateException("An exception occurs during implementation class manipulation : " + e.getMessage());
         }
     }
-    
+
     /**
      * Gets a class file as a byte array.
      * @return the byte array.
@@ -456,8 +476,8 @@
         if (is == null) {
             throw new IllegalStateException("An exception occurs during implementation class manipulation : cannot read the class file " + url);
         }
-        byte[] b = new byte[is.available()]; 
-        is.read(b); 
+        byte[] b = new byte[is.available()];
+        is.read(b);
         return b;
     }
 
@@ -471,7 +491,7 @@
         m_services.add(svc);
         return this;
     }
-    
+
     /**
      * Adds a service dependency.
      * @param dep the dependency to add
@@ -482,7 +502,7 @@
         m_dependencies.add(dep);
         return this;
     }
-    
+
     /**
      * Adds a temporal service dependency.
      * @param dep the temporal dependency to add
@@ -493,7 +513,7 @@
         m_temporals.add(dep);
         return this;
     }
-    
+
     /**
      * Adds a configuration property.
      * @param prop the property to add
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/CompositeComponentType.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/CompositeComponentType.java
index 9d33c28..be3dcc6 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/CompositeComponentType.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/CompositeComponentType.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -36,50 +36,50 @@
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class CompositeComponentType extends ComponentType {
-    
+
     /**
      * The bundle context.
      */
     private BundleContext m_context;
-    
+
     /**
      * Component factory attached to the component
-     * type. 
+     * type.
      */
     private ComponentFactory m_factory;
-    
+
     /**
-     * Component type metadata. 
+     * Component type metadata.
      */
     private Element m_metadata;
-    
+
     /**
-     * List of provided services. 
+     * List of provided services.
      */
     private List m_provided = new ArrayList(1);
-    
+
     /**
-     * List of exported services. 
+     * List of exported services.
      */
     private List m_exported = new ArrayList(1);
-    
+
     /**
-     * List of imported services. 
+     * List of imported services.
      */
     private List m_imported = new ArrayList(1);
-    
+
     /**
-     * List of instantiated services. 
+     * List of instantiated services.
      */
     private List m_instantiated = new ArrayList();
-    
+
     /**
      * List of contained instance.
      */
-    private List m_contained = new ArrayList(); 
-    
+    private List m_contained = new ArrayList();
+
     /**
-     * Is the factory public? 
+     * Is the factory public?
      */
     private boolean m_public = true;
 
@@ -87,7 +87,12 @@
      * Component type name.
      */
     private String m_name;
-    
+
+    /**
+     * Component type version.
+     */
+    private String m_version;
+
     /**
      * List of Handler representing external.
      * handler configuration
@@ -103,7 +108,7 @@
             throw new IllegalStateException("The component type was already initialized, cannot modify metadata");
         }
     }
-    
+
     /**
      * Checks that the component type description is valid.
      */
@@ -140,7 +145,7 @@
         initializeFactory();
         m_factory.stop();
     }
-    
+
     /**
      * Initializes the factory.
      */
@@ -149,7 +154,7 @@
             createFactory();
         }
     }
-    
+
     /**
      * Sets the bundle context.
      * @param bc the bundle context
@@ -160,10 +165,10 @@
         m_context = bc;
         return this;
     }
-    
+
     /**
      * Sets the factory public aspect.
-     * @param visible <code>false</code> to create a private factory. 
+     * @param visible <code>false</code> to create a private factory.
      * @return the current component type
      */
     public CompositeComponentType setPublic(boolean visible) {
@@ -171,7 +176,7 @@
         m_public = visible;
         return this;
     }
-    
+
     /**
      * Sets the component type name.
      * @param name the factory name
@@ -182,7 +187,19 @@
         m_name = name;
         return this;
     }
-    
+
+    /**
+     * Sets the component type version.
+     * @param version the factory version or "bundle" to use the
+     * bundle version.
+     * @return the current component type
+     */
+    public CompositeComponentType setComponentTypeVersion(String version) {
+        ensureNotInitialized();
+        m_version = version;
+        return this;
+    }
+
     /**
      * Adds a contained instance.
      * @param inst the instance to add
@@ -192,7 +209,7 @@
         m_contained.add(inst);
         return this;
     }
-    
+
     /**
      * Adds an imported (sub-)service.
      * @param is the imported service to add
@@ -202,7 +219,7 @@
         m_imported.add(is);
         return this;
     }
-    
+
     /**
      * Adds an instantiated sub-service.
      * @param is the instantiated service to add
@@ -212,7 +229,7 @@
         m_instantiated.add(is);
         return this;
     }
-    
+
     /**
      * Adds an exported service.
      * @param es the exported service to add
@@ -222,7 +239,7 @@
         m_exported.add(es);
         return this;
     }
-    
+
     /**
      * Adds a provided service.
      * @param es the provided service to add
@@ -232,7 +249,7 @@
         m_provided.add(es);
         return this;
     }
-    
+
     /**
      * Adds an HandlerConfiguration to the component type. Each component type
      * implementation must uses the populated list (m_handlers) when generating
@@ -244,10 +261,10 @@
         m_handlers.add(handler);
         return this;
     }
-    
+
     /**
      * Generates the component description.
-     * @return the component type description of 
+     * @return the component type description of
      * the current component type
      */
     private Element generateComponentMetadata() {
@@ -255,6 +272,9 @@
         if (m_name != null) {
             element.addAttribute(new Attribute("name", m_name));
         }
+        if (m_version != null) {
+            element.addAttribute(new Attribute("version", m_version));
+        }
         if (! m_public) {
             element.addAttribute(new Attribute("public", "false"));
         }
@@ -278,16 +298,16 @@
             ProvidedService inst = (ProvidedService) m_provided.get(i);
             element.addElement(inst.getElement());
         }
-        
+
         // External handlers
         for (int i = 0; i < m_handlers.size(); i++) {
             HandlerConfiguration hc = (HandlerConfiguration) m_handlers.get(i);
             element.addElement(hc.getElement());
         }
-        
+
         return element;
     }
-    
+
     /**
      * Creates the component factory.
      */
@@ -300,10 +320,10 @@
         } catch (ConfigurationException e) {
             throw new IllegalStateException("An exception occurs during factory initialization : " + e.getMessage());
         }
-       
-    }
-    
 
-    
+    }
+
+
+
 
 }
diff --git a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java
index a2a67ba..81d2f7c 100644
--- a/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java
+++ b/ipojo/composite/src/main/java/org/apache/felix/ipojo/composite/FactoryProxy.java
@@ -1,4 +1,4 @@
-/* 

+/*

  * 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

@@ -170,4 +170,8 @@
         return m_delegate.getBundleContext();

     }

 

+    public String getVersion() {

+        return m_delegate.getVersion();

+    }

+

 }

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
index 91578fc..4016e1d 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/ComponentFactory.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -40,7 +40,7 @@
 
 /**
  * The component factory manages component instance objects. This management
- * consists to create and manage component instances build with the current 
+ * consists to create and manage component instances build with the current
  * component factory. This class could export Factory and ManagedServiceFactory
  * services.
  * @see IPojoFactory
@@ -149,7 +149,7 @@
      */
     public ComponentInstance createInstance(Dictionary config, IPojoContext context, HandlerManager[] handlers) throws org.apache.felix.ipojo.ConfigurationException {
         InstanceManager instance = new InstanceManager(this, context, handlers);
-        
+
         try {
             instance.configure(m_componentMetadata, config);
             instance.start();
@@ -175,7 +175,7 @@
 
     /**
      * Defines a class.
-     * This method needs to be synchronized to avoid that the classloader 
+     * This method needs to be synchronized to avoid that the classloader
      * is created twice.
      * This method delegate the <code>define</code> method invocation to the
      * factory classloader.
@@ -193,7 +193,7 @@
 
     /**
      * Returns the URL of a resource.
-     * This methods delegates the invocation to the 
+     * This methods delegates the invocation to the
      * {@link Bundle#getResource(String)} method.
      * @param resName the resource name
      * @return the URL of the resource
@@ -256,7 +256,7 @@
      * Computes the factory name. The factory name is computed from
      * the 'name' and 'classname' attributes.
      * This method does not manipulate any non-immutable fields,
-     * so does not need to be synchronized. 
+     * so does not need to be synchronized.
      * @return the factory name.
      */
     public String getFactoryName() {
@@ -270,7 +270,7 @@
 
     /**
      * Computes required handlers.
-     * This method does not manipulate any non-immutable fields, 
+     * This method does not manipulate any non-immutable fields,
      * so does not need to be synchronized.
      * @return the required handler list.
      */
@@ -292,8 +292,8 @@
         if (arch == null || arch.equalsIgnoreCase("true")) {
             list.add(new RequiredHandler("architecture", null));
         }
-        
-        
+
+
         // Determine if the component must be immediate.
         // A component becomes immediate if it doesn't provide a service,
         // and does not specified that the component is not immediate.
@@ -323,13 +323,13 @@
     /**
      * This method is called when a new handler factory is detected.
      * Test if the factory can be used or not.
-     * This method need to be synchronized as it accesses to the content 
+     * This method need to be synchronized as it accesses to the content
      * of required handlers.
      * @param reference the new service reference.
      * @return <code>true</code> if the given factory reference matches with a required handler.
      * @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
      */
-    public synchronized boolean addingService(ServiceReference reference) {        
+    public synchronized boolean addingService(ServiceReference reference) {
         for (int i = 0; i < m_requiredHandlers.size(); i++) {
             RequiredHandler req = (RequiredHandler) m_requiredHandlers.get(i);
             if (req.getReference() == null && match(req, reference)) {
@@ -347,8 +347,8 @@
     }
 
     /**
-     * This method is called when a matching service has been added to the tracker, 
-     * we can no compute the factory state. This method is synchronized to avoid 
+     * This method is called when a matching service has been added to the tracker,
+     * we can no compute the factory state. This method is synchronized to avoid
      * concurrent calls to method modifying the factory state.
      * @param reference the added service reference.
      * @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
@@ -361,7 +361,7 @@
 
     /**
      * This method is called when a used handler factory disappears.
-     * This method is synchronized to avoid concurrent calls to method modifying 
+     * This method is synchronized to avoid concurrent calls to method modifying
      * the factory state.
      * @param reference the leaving service reference.
      * @param service  the handler factory object.
@@ -400,6 +400,15 @@
     }
 
     /**
+     * Gets the version of the component type
+     * @return the version of </code>null</code> if not set.
+     * @see org.apache.felix.ipojo.Factory#getVersion()
+     */
+    public String getVersion() {
+        return m_version;
+    }
+
+    /**
      * this class defines the classloader attached to a factory.
      * This class loader is used to load the implementation (e.g. manipulated)
      * class.
@@ -453,7 +462,7 @@
 
     /**
      * This class defines the description of primitive (non-composite) component
-     * types. An instance of this class will be returned when invoking the 
+     * types. An instance of this class will be returned when invoking the
      * {@link ComponentFactory#getComponentDescription()} method.
      * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
      */
@@ -468,7 +477,7 @@
         }
 
         /**
-         * Computes the properties to publish. 
+         * Computes the properties to publish.
          * The <code>component.class</code> property contains the implementation class name.
          * @return the dictionary of properties to publish
          * @see org.apache.felix.ipojo.architecture.ComponentTypeDescription#getPropertiesToPublish()
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java
index 84ccf65..d5c0b95 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/Factory.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -32,13 +32,13 @@
 public interface Factory {
 
     /**
-     * Factory State. 
+     * Factory State.
      * A valid factory is a factory where all required handlers are available.
      */
     int VALID = 1;
 
     /**
-     * Factory State. 
+     * Factory State.
      * An invalid factory is a factory where at least one required handler is
      * unavailable. Creating an instance with an invalid factory failed.
      */
@@ -67,7 +67,7 @@
     ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException;
 
     /**
-     * Gets the component type information containing provided service, 
+     * Gets the component type information containing provided service,
      * configuration properties ...
      * @return the component type information.
      */
@@ -94,7 +94,7 @@
     String getName();
 
     /**
-     * Reconfigures an instance already created. This configuration needs to 
+     * Reconfigures an instance already created. This configuration needs to
      * have the name property to identify the instance.
      * @param conf the configuration to reconfigure the instance.
      * @throws UnacceptableConfiguration  if the given configuration is not consistent for the targeted instance.
@@ -117,14 +117,14 @@
     /**
      * Gets the list of missing handlers.
      * The handlers are given under the form namespace:name
-     * @return the list containing the name of missing handlers 
+     * @return the list containing the name of missing handlers
      */
     List getMissingHandlers();
 
     /**
      * Get the list of required handlers.
      * The handlers are given under the form namespace:name
-     * @return the list containing the name of required handlers 
+     * @return the list containing the name of required handlers
      */
     List getRequiredHandlers();
 
@@ -148,4 +148,11 @@
      */
     BundleContext getBundleContext();
 
+    /**
+     * Gets the version of the component type.
+     * @return the component type version or <code>null</code> if
+     * not specified.
+     */
+    String getVersion();
+
 }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
index b3da972..a3e3f2e 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/IPojoFactory.java
@@ -1,4 +1,4 @@
-/* 

+/*

  * 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

@@ -32,6 +32,7 @@
 import org.apache.felix.ipojo.metadata.Element;

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

 import org.osgi.framework.BundleContext;

+import org.osgi.framework.Constants;

 import org.osgi.framework.ServiceReference;

 import org.osgi.framework.ServiceRegistration;

 import org.osgi.service.cm.ManagedServiceFactory;

@@ -62,7 +63,7 @@
     protected ComponentTypeDescription m_componentDesc;

 

     /**

-     * The list of the managed instance managers. 

+     * The list of the managed instance managers.

      * The key of this map is the name (i.e. instance names) of the created instance

      */

     protected final Map m_componentInstances = new HashMap();

@@ -78,7 +79,7 @@
     protected final BundleContext m_context;

 

     /**

-     * The factory name. 

+     * The factory name.

      * Could be the component class name if the factory name is not set.

      * Immutable once set.

      */

@@ -106,6 +107,11 @@
     protected final boolean m_isPublic;

 

     /**

+     * The version of the component type.

+     */

+    protected final String m_version;

+

+    /**

      * The service registration of this factory (Factory & ManagedServiceFactory).

      * @see ManagedServiceFactory

      * @see Factory

@@ -129,7 +135,7 @@
     private long m_index = 0;

 

     /**

-     * The flag indicating if this factory has already a 

+     * The flag indicating if this factory has already a

      * computed description or not.

      */

     private boolean m_described;

@@ -149,6 +155,15 @@
         String fac = metadata.getAttribute("public");

         m_isPublic = fac == null || !fac.equalsIgnoreCase("false");

         m_logger = new Logger(m_context, m_factoryName);

+

+        // Compute the component type version.

+        String version = metadata.getAttribute("version");

+        if ("bundle".equalsIgnoreCase(version)) { // Handle the "bundle" constant: use the bundle version.

+            m_version = (String) m_context.getBundle().getHeaders().get(Constants.BUNDLE_VERSION);

+        } else {

+            m_version = version;

+        }

+

         m_requiredHandlers = getRequiredHandlerList(); // Call sub-class to get the list of required handlers.

     }

 

@@ -181,7 +196,7 @@
 

     /**

      * Computes the factory name.

-     * Each sub-type must override this method. 

+     * Each sub-type must override this method.

      * @return the factory name.

      */

     public abstract String getFactoryName();

@@ -239,7 +254,7 @@
         if (configuration == null) {

             configuration = new Properties();

         }

-        

+

         IPojoContext context = null;

         if (serviceContext == null) {

             context = new IPojoContext(m_context);

@@ -417,7 +432,7 @@
         }

 

         // Check that the configuration does not override immutable properties.

-        

+

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

             // Is the property immutable

             if (props[i].isImmutable() && conf.get(props[i].getName()) != null) {

@@ -433,7 +448,7 @@
     /**

      * Reconfigures an existing instance.

      * The acceptability of the configuration is checked before the reconfiguration. Moreover,

-     * the configuration must contain the 'instance.name' property specifying the instance 

+     * the configuration must contain the 'instance.name' property specifying the instance

      * to reconfigure.

      * This method is synchronized to assert the validity of the factory during the reconfiguration.

      * @param properties the new configuration to push.

@@ -450,12 +465,12 @@
         if (name == null) {

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

         }

-        

+

         ComponentInstance instance = (ComponentInstance) m_componentInstances.get(name);

         if (instance == null) { // The instance does not exists.

             return;

         }

-        

+

         checkAcceptability(properties); // Test if the configuration is acceptable

         instance.reconfigure(properties); // re-configure the instance

     }

@@ -472,7 +487,7 @@
     }

 

     /**

-     * Stopping method. 

+     * Stopping method.

      * This method is call when the factory is stopping.

      * This method is called when holding the lock on the factory.

      */

@@ -483,7 +498,7 @@
      * This method calls the {@link IPojoFactory#stopping()} method,

      * notifies listeners, and disposes created instances. Moreover,

      * if the factory is public, services are also unregistered.

-     *  

+     *

      */

     public synchronized void stop() {

         ComponentInstance[] instances;

@@ -527,7 +542,7 @@
     }

 

     /**

-     * Destroys the factory. 

+     * Destroys the factory.

      * The factory cannot be restarted. Only the {@link Extender} can call this method.

      */

     synchronized void dispose() {

@@ -537,7 +552,7 @@
     }

 

     /**

-     * Starting method. 

+     * Starting method.

      * This method is called when the factory is starting.

      * This method is called when holding the lock on the factory.

      */

@@ -580,7 +595,7 @@
         synchronized (this) {

             instance = (InstanceManager) m_componentInstances.get(name);

         }

-        

+

         if (instance == null) {

             try {

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

@@ -637,9 +652,9 @@
 

     /**

      * Computes the component type description.

-     * To do this, it creates a 'ghost' instance of the handler 

+     * To do this, it creates a 'ghost' instance of the handler

      * and calls the {@link Handler#initializeComponentFactory(ComponentTypeDescription, Element)}

-     * method. The handler instance is then deleted. 

+     * method. The handler instance is then deleted.

      * The factory must be valid when calling this method.

      * This method is called with the lock.

      */

@@ -849,7 +864,7 @@
             }

 

         }

-        

+

         /**

          * Hashcode method.

          * This method delegates to the {@link Object#hashCode()}.

@@ -861,7 +876,7 @@
         }

 

         /**

-         * Gets the factory object used for this handler. 

+         * Gets the factory object used for this handler.

          * The object is get when used for the first time.

          * This method is called with the lock avoiding concurrent modification and on a valid factory.

          * @return the factory object.

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
index 988b1f0..48c3b29 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceCreator.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -30,7 +30,7 @@
 import org.osgi.framework.BundleContext;
 
 /**
- * The instance creator creates instances and tracks their factories. 
+ * 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>
  */
@@ -72,11 +72,16 @@
      * @param bundle the bundle id declaring the instance
      */
     synchronized void addInstance(Dictionary instance, long bundle) {
-        m_logger.log(Logger.DEBUG, "New instance to managed, looking for " + instance.get("component"));
+        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.matchName(factory)) {
+            if (managed.matchNameAndVersion(factory)) {
                 // Subscribe to the factory state change
                 m_logger.log(Logger.DEBUG, "Listen factory " + factory.getName() + " events");
                 factory.addFactoryStateListener(this);
@@ -86,7 +91,7 @@
                     if (list == null) {
                         list = new ArrayList();
                         list.add(managed);
-                        m_attached.put(factory, list);  
+                        m_attached.put(factory, list);
                     } else {
                         list.add(managed);
                     }
@@ -152,7 +157,7 @@
         m_factories.add(factory);
         for (int i = 0; i < m_idle.size(); i++) {
             ManagedInstance managed = (ManagedInstance) m_idle.get(i);
-            if (managed.matchName(factory)) {
+            if (managed.matchNameAndVersion(factory)) {
                 // We have to subscribe to the factory.
                 factory.addFactoryStateListener(this);
                 if (factory.getState() == Factory.VALID && managed.match(factory)) {
@@ -243,8 +248,8 @@
     }
 
     /**
-     * This structure aims to manage a configuration. 
-     * It stores all necessary information to create an instance 
+     * This structure aims to manage a configuration.
+     * It stores all necessary information to create an instance
      * and to track the factory.
      */
     private class ManagedInstance {
@@ -293,32 +298,38 @@
         ComponentInstance getInstance() {
             return m_instance;
         }
-        
-        
+
+
         /**
          * 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 matches, <code>false</code>
+         * @return <code>true</code> if the factory name and the version (if set) match, <code>false</code>
          * otherwise.
          */
-        public boolean matchName(IPojoFactory factory) {
+        public boolean matchNameAndVersion(IPojoFactory factory) {
             String component = (String) m_configuration.get("component");
-            return factory.getName().equals(component) || factory.getClassName().equalsIgnoreCase(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 
+         * 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 (matchName(factory)) {
+            if (matchNameAndVersion(factory)) {
                 // Test factory accessibility
                 if (factory.m_isPublic || factory.getBundleContext().getBundle().getBundleId() == m_bundleId) {
                     // Test the configuration validity.
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
index cb26e98..8a636f4 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/architecture/ComponentTypeDescription.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -50,7 +50,7 @@
      * Represented factory.
      */
     private final IPojoFactory m_factory;
-    
+
     /**
      * Constructor.
      * @param factory : represented factory.
@@ -58,7 +58,7 @@
     public ComponentTypeDescription(IPojoFactory factory) {
         m_factory = factory;
     }
-    
+
     /**
      * Gets the attached factory.
      * @return the factory
@@ -86,6 +86,15 @@
     }
 
     /**
+     * Gets the component type version.
+     * @return the component type version or
+     * <code>null</code> if not set.
+     */
+    public String getVersion() {
+        return m_factory.getVersion();
+    }
+
+    /**
      * Gets component-type properties.
      * @return the list of configuration properties accepted by the component type type.
      */
@@ -101,7 +110,7 @@
     public void addProperty(String name, String value) {
         addProperty(name, value, false);
     }
-    
+
     /**
      * Adds a String property in the component type.
      * @param name : property name.
@@ -118,8 +127,8 @@
      * @param pd : the property to add
      */
     public void addProperty(PropertyDescription pd) { //NOPMD remove the instance name of the 'name' property.
-        String name = pd.getName(); 
-        
+        String name = pd.getName();
+
         // Check if the property is not already in the array
         for (int i = 0; i < m_properties.length; i++) {
             PropertyDescription desc = m_properties[i];
@@ -158,9 +167,9 @@
     public String getName() {
         return m_factory.getName();
     }
-    
+
     /**
-     * Computes the default service properties to publish : 
+     * Computes the default service properties to publish :
      * factory.name, service.pid, component.providedServiceSpecification, component.properties, component.description, factory.State.
      * @return : the dictionary of properties to publish.
      */
@@ -170,10 +179,16 @@
         props.put("factory.name", m_factory.getName());
         props.put(Constants.SERVICE_PID, m_factory.getName()); // Service PID is required for the integration in the configuration admin.
 
+        // Add the version if set
+        String v = getVersion();
+        if (v != null) {
+            props.put("factory.version", v);
+        }
+
         props.put("component.providedServiceSpecifications", m_providedServiceSpecification);
         props.put("component.properties", m_properties);
         props.put("component.description", this);
-        
+
         // add every immutable property
         for (int i = 0; i < m_properties.length; i++) {
             if (m_properties[i].isImmutable() && m_properties[i].getValue() != null) {
@@ -187,7 +202,7 @@
         return props;
 
     }
-    
+
     /**
      * Gets the interfaces published by the factory.
      * By default publish both {@link Factory} and {@link ManagedServiceFactory}.
@@ -196,7 +211,7 @@
     public String[] getFactoryInterfacesToPublish() {
         return new String[] {Factory.class.getName(), ManagedServiceFactory.class.getName()};
     }
-    
+
     /**
      * Gets the component type description.
      * @return : the description
@@ -206,7 +221,7 @@
 
         desc.addAttribute(new Attribute("name", m_factory.getName()));
         desc.addAttribute(
-                          new Attribute("bundle", 
+                          new Attribute("bundle",
                                           Long.toString(((ComponentFactory) m_factory).getBundleContext().getBundle().getBundleId())));
 
         String state = "valid";
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
index 58f8091..4db3d6c 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedService.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -44,7 +44,7 @@
 
 /**
  * Provided Service represent a provided service by the component.
- * 
+ *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class ProvidedService implements ServiceFactory {
@@ -68,12 +68,12 @@
      * Factory policy : SERVICE_FACTORY.
      */
     public static final int SERVICE_STRATEGY = 1;
-    
+
     /**
      * Factory policy : STATIC_FACTORY.
      */
     public static final int STATIC_STRATEGY = 2;
-    
+
     /**
      * Factory policy : INSTANCE.
      * Creates one service object per instance consuming the service.
@@ -100,7 +100,7 @@
      * Properties Array.
      */
     private Property[] m_properties;
-    
+
     /**
      * Service Object creation policy.
      */
@@ -108,7 +108,7 @@
 
     /**
      * Creates a provided service object.
-     * 
+     *
      * @param handler the the provided service handler.
      * @param specification the specifications provided by this provided service
      * @param factoryPolicy the service providing policy
@@ -118,14 +118,18 @@
         m_handler = handler;
 
         m_serviceSpecification = specification;
-        
-        // Add instance name & factory name
+
+        // 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("instance.name", 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));
+            }
         } catch (ConfigurationException e) {
             m_handler.error("An exception occurs when adding instance.name and factory.name property : " + e.getMessage());
         }
+
         if (creationStrategyClass != null) {
             try {
                 m_strategy = (CreationStrategy) creationStrategyClass.newInstance();
@@ -187,7 +191,7 @@
 
     /**
      * Add the given property to the property list.
-     * 
+     *
      * @param prop : the element to add
      */
     private synchronized void addProperty(Property prop) {
@@ -209,7 +213,7 @@
 
     /**
      * Remove a property.
-     * 
+     *
      * @param name : the property to remove
      */
     private synchronized void removeProperty(String name) {
@@ -261,7 +265,7 @@
 
     /**
      * The unget method.
-     * 
+     *
      * @see org.osgi.framework.ServiceFactory#ungetService(org.osgi.framework.Bundle,
      * org.osgi.framework.ServiceRegistration, java.lang.Object)
      * @param bundle : bundle
@@ -274,10 +278,10 @@
 
     /**
      * Registers the service. The service object must be able to serve this
-     * service. 
+     * service.
      * This method also notifies the creation strategy of the publication.
      */
-    protected synchronized void registerService() {        
+    protected synchronized void registerService() {
         if (m_serviceRegistration == null) {
             // Build the service properties list
             Properties serviceProperties = getServiceProperties();
@@ -294,9 +298,9 @@
             m_serviceRegistration.unregister();
             m_serviceRegistration = null;
         }
-        
+
         m_strategy.onUnpublication();
-        
+
     }
 
     /**
@@ -318,7 +322,7 @@
     /**
      * Return the list of properties attached to this service. This list
      * contains only property where a value are assigned.
-     * 
+     *
      * @return the properties attached to the provided service.
      */
     private Properties getServiceProperties() {
@@ -399,7 +403,7 @@
     public ServiceRegistration getServiceRegistration() {
         return m_serviceRegistration;
     }
-    
+
     /**
      * Singleton creation strategy.
      * This strategy just creates one service object and
@@ -442,13 +446,13 @@
          * @see org.osgi.framework.ServiceFactory#ungetService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration, java.lang.Object)
          */
         public void ungetService(Bundle arg0, ServiceRegistration arg1,
-                Object arg2) {            
+                Object arg2) {
         }
-        
+
     }
-    
+
     /**
-     * Service object creation policy following the OSGi Service Factory 
+     * Service object creation policy following the OSGi Service Factory
      * policy {@link ServiceFactory}.
      */
     private class FactoryStrategy extends CreationStrategy {
@@ -491,15 +495,15 @@
          * @see org.osgi.framework.ServiceFactory#ungetService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration, java.lang.Object)
          */
         public void ungetService(Bundle arg0, ServiceRegistration arg1,
-                Object arg2) { 
+                Object arg2) {
             m_handler.getInstanceManager().deletePojoObject(arg2);
         }
     }
-    
-    
+
+
     /**
      * Service object creation policy creating a service object per asking iPOJO component
-     * instance. This creation policy follows the iPOJO Service Factory interaction pattern 
+     * instance. This creation policy follows the iPOJO Service Factory interaction pattern
      * and does no support 'direct' invocation.
      */
     private class PerInstanceStrategy extends CreationStrategy implements IPOJOServiceFactory, InvocationHandler {
@@ -510,17 +514,17 @@
 
         /**
          * A method is invoked on the proxy object.
-         * If the method is the {@link IPOJOServiceFactory#getService(ComponentInstance)} 
+         * If the method is the {@link IPOJOServiceFactory#getService(ComponentInstance)}
          * method, this method creates a service object if no already created for the asking
-         * component instance. 
+         * component instance.
          * If the method is {@link IPOJOServiceFactory#ungetService(ComponentInstance, Object)}
          * the service object is unget (i.e. removed from the map and deleted).
          * In all other cases, a {@link UnsupportedOperationException} is thrown as this policy
-         * requires to use  the {@link IPOJOServiceFactory} interaction pattern.  
+         * requires to use  the {@link IPOJOServiceFactory} interaction pattern.
          * @param arg0 the proxy object
          * @param arg1 the called method
          * @param arg2 the arguments
-         * @return the service object attached to the asking instance for 'get', 
+         * @return the service object attached to the asking instance for 'get',
          * <code>null</code> for 'unget',
          * a {@link UnsupportedOperationException} for all other methods.
          * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
@@ -529,12 +533,12 @@
             if (isGetServiceMethod(arg1)) {
                 return getService((ComponentInstance) arg2[0]);
             }
-            
+
             if (isUngetServiceMethod(arg1)) {
                 ungetService((ComponentInstance) arg2[0], arg2[1]);
                 return null;
             }
-            
+
             throw new UnsupportedOperationException("This service requires an advanced creation policy. "
                     + "Before calling the service, call the getService(ComponentInstance) method to get "
                     + "the service object. ");
@@ -600,7 +604,7 @@
          * @see org.osgi.framework.ServiceFactory#getService(org.osgi.framework.Bundle, org.osgi.framework.ServiceRegistration)
          */
         public Object getService(Bundle arg0, ServiceRegistration arg1) {
-            Object proxy = Proxy.newProxyInstance(getInstanceManager().getClazz().getClassLoader(), 
+            Object proxy = Proxy.newProxyInstance(getInstanceManager().getClazz().getClassLoader(),
                     getSpecificationsWithIPOJOServiceFactory(m_serviceSpecification, m_handler.getInstanceManager().getContext()), this);
             return proxy;
         }
@@ -615,7 +619,7 @@
          */
         public void ungetService(Bundle arg0, ServiceRegistration arg1,
                 Object arg2) { }
-        
+
         /**
          * Utility method returning the class array of provided service
          * specification and the {@link IPOJOServiceFactory} interface.
@@ -637,8 +641,8 @@
             classes[i] = IPOJOServiceFactory.class;
             return classes;
         }
-        
-        
+
+
     }
 
 }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java
index 643eaf6..f486c53 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/ManifestMetadataParser.java
@@ -1,4 +1,4 @@
-/* 
+/*
  * 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
@@ -31,7 +31,7 @@
 /**
  * The Manifest Metadata parser reads a manifest file and builds
  * the iPOJO metadata ({@link Element} / {@link Attribute} ) structure.
- * 
+ *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class ManifestMetadataParser {
@@ -79,7 +79,7 @@
     /**
      * Parses an Element to create an instance configuration dictionary.
      * The 'name' attribute of the instance declaration is mapped
-     * to the 'instance.name' property. 
+     * to the 'instance.name' property.
      * @param instance the Element describing an instance.
      * @return the resulting dictionary
      * @throws ParseException if a configuration cannot be parse correctly.
@@ -88,6 +88,8 @@
         Dictionary dict = new Properties();
         String name = instance.getAttribute("name");
         String comp = instance.getAttribute("component");
+        String version = instance.getAttribute("version");
+
         if (name != null) {
             dict.put("instance.name", instance.getAttribute("name"));
         }
@@ -97,6 +99,11 @@
         }
 
         dict.put("component", comp);
+
+        if (version != null) {
+            dict.put("factory.version", version);
+        }
+
         Element[] props = instance.getElements("property");
 
         for (int i = 0; props != null && i < props.length; i++) {
@@ -120,7 +127,7 @@
         if (name == null) {
             throw new ParseException("A property does not have the 'name' attribute: " + prop);
         }
-        
+
         //case : the property element has no 'value' attribute
         if (value == null) {
             // Recursive case
@@ -145,19 +152,19 @@
                     obj = new Object[list.size()];
                 }
                 // Transform the list to array
-                dict.put(name, list.toArray(obj)); 
+                dict.put(name, list.toArray(obj));
             }
         } else {
             dict.put(prop.getAttribute("name"), prop.getAttribute("value"));
         }
     }
-    
+
     /**
-     * Parses a complex property. 
+     * Parses a complex property.
      * This property will be built as a {@link Dictionary}.
      * @param prop the Element to parse.
      * @return the resulting dictionary
-     * @throws ParseException if an internal property is incorrect. 
+     * @throws ParseException if an internal property is incorrect.
      */
     private Dictionary parseDictionary(Element prop) throws ParseException {
      // Check if there is 'property' elements
@@ -173,9 +180,9 @@
             return new Properties();
         }
     }
-    
+
     /**
-     * Parses a complex property. 
+     * Parses a complex property.
      * This property will be built as a {@link Map}.
      * The used {@link Map} implementation is {@link HashMap}.
      * @param prop the property to parse
@@ -195,10 +202,10 @@
             return new HashMap(0);
         }
     }
-    
+
     /**
      * Parses a complex property. This property will be built as a {@link List}.
-     * The used {@link List} implementation is {@link ArrayList}. 
+     * The used {@link List} implementation is {@link ArrayList}.
      * The order of elements is kept.
      * @param prop the property to parse
      * @return the resulting List
@@ -217,7 +224,7 @@
             return new ArrayList(0);
         }
     }
-    
+
     /**
      * Parse a property.
      * This methods handles complex properties.
@@ -266,7 +273,7 @@
     /**
      * Parse an anonymous property.
      * An anonymous property is a property with no name.
-     * An anonymous property can be simple (just a value) or complex (i.e. a map, a dictionary 
+     * An anonymous property can be simple (just a value) or complex (i.e. a map, a dictionary
      * a list or an array).
      * @param prop the property to parse
      * @param list the list to populate with the resulting property
@@ -282,7 +289,7 @@
         //case : the property element has no 'value' attribute
         if (value == null) {
             // Recursive case
-            
+
             // Get the type of the structure to create
             String type = prop.getAttribute("type");
             if (type == null || type.equalsIgnoreCase("dictionary")) {
@@ -314,7 +321,7 @@
                 Element[] subProps = prop.getElements("property");
                 if (subProps != null) {
                     // Create a list to store elements.
-                    List list2 = new ArrayList(subProps.length); 
+                    List list2 = new ArrayList(subProps.length);
                     for (int i = 0; i < subProps.length; i++) {
                         parseAnonymousProperty(subProps[i], list2); // Anonymous properties
                     }
@@ -342,7 +349,7 @@
         } else {
             list.add(prop.getAttribute("value"));
         }
-        
+
     }
 
     /**
@@ -384,7 +391,7 @@
 
     /**
      * Looks for the <code>iPOJO-Components</code> header
-     * in the given dictionary. Then, initializes the 
+     * in the given dictionary. Then, initializes the
      * {@link ManifestMetadataParser#m_elements} list (adds the
      * <code>iPOJO</code> root element) and parses the contained
      * component type declarations and instance configurations.
@@ -399,9 +406,9 @@
     }
 
     /**
-     * Parses the given header, initialized the 
-     * {@link ManifestMetadataParser#m_elements} list 
-     * (adds the <code>iPOJO</code> element) and parses 
+     * Parses the given header, initialized the
+     * {@link ManifestMetadataParser#m_elements} list
+     * (adds the <code>iPOJO</code> element) and parses
      * contained component type declarations and instance configurations.
      * @param header the given header of the manifest file
      * @throws ParseException if any error occurs
@@ -429,12 +436,12 @@
         }
         return parser.m_elements[0];
     }
-    
+
     /**
      * Parses the metadata from the given header string.
      * This method creates a new {@link ManifestMetadataParser} object and then
      * creates the <code>iPOJO</code> root element, parses content elements
-     * (component types and instances declarations), and returns the resulting 
+     * (component types and instances declarations), and returns the resulting
      * {@link Element} / {@link Attribute} structure. The parsed string
      * must be a tree (only one root element).
      * @param header the header to parse
@@ -537,7 +544,7 @@
                         i = i + 1;
                     }
                     i = i + 1; // skip {
-                    
+
                     Element elem = null;
                     if (namespace == null) {
                         elem = new Element(name.toString(), null);
@@ -545,7 +552,7 @@
                         elem = new Element(name.toString(), namespace.toString());
                     }
                     addElement(elem);
-                    
+
                     break;
             }
         }
diff --git a/ipojo/tests/api/src/test/java/org/apache/felix/ipojo/tests/api/PrimitiveComponentTest.java b/ipojo/tests/api/src/test/java/org/apache/felix/ipojo/tests/api/PrimitiveComponentTest.java
index a0a3761..b954a27 100644
--- a/ipojo/tests/api/src/test/java/org/apache/felix/ipojo/tests/api/PrimitiveComponentTest.java
+++ b/ipojo/tests/api/src/test/java/org/apache/felix/ipojo/tests/api/PrimitiveComponentTest.java
@@ -4,7 +4,6 @@
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.CoreMatchers.nullValue;
 import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
 import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
 import static org.ops4j.pax.exam.CoreOptions.options;
 import static org.ops4j.pax.exam.CoreOptions.provision;
@@ -35,28 +34,28 @@
 
 @RunWith( JUnit4TestRunner.class )
 public class PrimitiveComponentTest {
-    
+
     @Inject
     private BundleContext context;
-    
+
     private OSGiHelper osgi;
-    
+
     private IPOJOHelper ipojo;
-    
+
     @Before
     public void init() {
         osgi = new OSGiHelper(context);
         ipojo = new IPOJOHelper(context);
     }
-    
+
     @After
     public void stop() {
         ipojo.dispose();
         osgi.dispose();
     }
-    
+
     @Configuration
-    public static Option[] configure() {    
+    public static Option[] configure() {
         Option[] opt =  options(
                 provision(
                         mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.ipojo").version(asInProject()),
@@ -79,7 +78,7 @@
         assertThat(ref, is(notNullValue()));
 
     }
-    
+
     @Test
     public void killTheFactory() throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
         assertThat( context, is( notNullValue() ) );
@@ -99,7 +98,7 @@
         assertThat(ref, is(nullValue()));
 
     }
-    
+
     @Test
     public void createAServiceCons() throws Exception {
         assertThat( context, is( notNullValue() ) );
@@ -111,45 +110,45 @@
                 is(ComponentInstance.INVALID));
 
     }
-    
+
     @Test
     public void createBoth() throws Exception {
         ComponentInstance cons = createAConsumer().createInstance();
         // cons is invalid
         assertThat("cons is invalid", cons.getState(), is(ComponentInstance.INVALID));
-                
+
         ComponentInstance prov = createAProvider().createInstance();
         assertThat("prov is valid", prov.getState(), is(ComponentInstance.VALID));
         assertThat("cons is valid", cons.getState(), is(ComponentInstance.VALID));
 
     }
-    
+
     @Test
     public void createTwoCons() throws Exception {
         ComponentInstance cons1 = createAConsumer().createInstance();
         // cons is invalid
         assertThat("cons is invalid", cons1.getState(), is(ComponentInstance.INVALID));
-                
+
         ComponentInstance prov = createAProvider().createInstance();
         assertThat("prov is valid", prov.getState(), is(ComponentInstance.VALID));
         assertThat("cons is valid", cons1.getState(), is(ComponentInstance.VALID));
-        
+
         ComponentInstance cons2 = createAnOptionalConsumer().createInstance();
-     
+
         assertThat("cons2 is valid", cons2.getState(), is(ComponentInstance.VALID));
-        
+
         prov.stop();
         assertThat("cons is invalid", cons1.getState(), is(ComponentInstance.INVALID));
         assertThat("cons2 is valid", cons2.getState(), is(ComponentInstance.VALID));
     }
-    
+
     private PrimitiveComponentType createAProvider() {
         return new PrimitiveComponentType()
         .setBundleContext(context)
         .setClassName(FooImpl.class.getName())
         .addService(new Service()); // Provide the FooService
     }
-    
+
     private PrimitiveComponentType createAConsumer() {
         return new SingletonComponentType()
         .setBundleContext(context)
@@ -157,7 +156,7 @@
         .addDependency(new Dependency().setField("myFoo"))
         .setValidateMethod("start");
     }
-    
+
     private PrimitiveComponentType createAnOptionalConsumer() {
         return new SingletonComponentType()
         .setBundleContext(context)
diff --git a/ipojo/tests/composite/composite-runtime/src/main/java/org/apache/felix/ipojo/test/composite/infrastructure/FactoryManagementTest.java b/ipojo/tests/composite/composite-runtime/src/main/java/org/apache/felix/ipojo/test/composite/infrastructure/FactoryManagementTest.java
index c70b643..cf21a25 100644
--- a/ipojo/tests/composite/composite-runtime/src/main/java/org/apache/felix/ipojo/test/composite/infrastructure/FactoryManagementTest.java
+++ b/ipojo/tests/composite/composite-runtime/src/main/java/org/apache/felix/ipojo/test/composite/infrastructure/FactoryManagementTest.java
@@ -1,4 +1,4 @@
-/* 

+/*

  * 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

@@ -37,17 +37,17 @@
 import org.osgi.framework.ServiceRegistration;

 

 public class FactoryManagementTest extends OSGiTestCase {

-	

+

 	private FakeFactory fake1 = new FakeFactory("fake");

 	private FakeFactory fake2 = new FakeFactory("fake2");

-	

+

 	private Factory emptyFactory;

 	private ComponentInstance empty;

-	

+

 	private class FakeFactory implements Factory {

-		

+

 		private String m_name;

-		public FakeFactory(String name) { m_name = name; } 

+		public FakeFactory(String name) { m_name = name; }

 

 		public ComponentInstance createComponentInstance(Dictionary arg0) throws UnacceptableConfiguration { return null; }

 		public ComponentInstance createComponentInstance(Dictionary arg0, ServiceContext arg1) throws UnacceptableConfiguration { return null; }

@@ -63,9 +63,10 @@
         public String getClassName() { return ""; }

         public int getState() { return Factory.VALID; }

         public BundleContext getBundleContext() { return getContext(); }

+        public String getVersion() { return null;  }

 

 	}

-	

+

 	public void setUp() {

 		emptyFactory = Utils.getFactoryByName(getContext(), "composite.empty");

 		Properties props = new Properties();

@@ -74,30 +75,30 @@
 			empty = emptyFactory.createComponentInstance(props);

 		} catch (Exception e) { fail("Cannot create empty instance " + e.getMessage()); }

 	}

-	

+

 	public void tearDown() {

 		empty.dispose();

 		empty = null;

 	}

-	

+

 	public void testOneLevelExposition() {

 		ServiceReference[] parentsFactoryReferences = Utils.getServiceReferences(getContext(), Factory.class.getName(), null);

 		ServiceContext sc = Utils.getServiceContext(empty);

 		ServiceReference[] internalFactoryReferences = Utils.getServiceReferences(sc, Factory.class.getName(), null);

-		

+

 		assertEquals("Check the number of available factories", parentsFactoryReferences.length, internalFactoryReferences.length);

-		

+

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

 			Factory factory = (Factory) getContext().getService(parentsFactoryReferences[i]);

 			assertTrue("Check the avaibility of " + factory.getName(), isExposed(factory, internalFactoryReferences, sc));

 		}

 	}

-	

+

 	public void testTwoLevelExposition() {

 		ServiceReference[] parentsFactoryReferences = Utils.getServiceReferences(getContext(), Factory.class.getName(), null);

 		ServiceContext sc1 = Utils.getServiceContext(empty);

 		ServiceReference[] Level1FactoryReferences = Utils.getServiceReferences(sc1, Factory.class.getName(), null);

-		

+

 		Factory fact = Utils.getFactoryByName(sc1, "composite.empty");

 		Properties p = new Properties();

 		p.put("instance.name","empty2");

@@ -107,27 +108,27 @@
 		} catch (Exception e) {

 			fail("Cannot instantiate empty2 instance : " + e.getMessage());

 		}

-		

+

 		ServiceContext sc2 = Utils.getServiceContext(empty2);

 		ServiceReference[] Level2FactoryReferences = Utils.getServiceReferences(sc2, Factory.class.getName(), null);

-		

+

 		assertEquals("Check the number of available factories - 1", parentsFactoryReferences.length, Level1FactoryReferences.length);

 		assertEquals("Check the number of available factories - 2", parentsFactoryReferences.length, Level2FactoryReferences.length);

 		assertEquals("Check the number of available factories - 3", Level1FactoryReferences.length, Level2FactoryReferences.length);

-		

+

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

 			Factory factory = (Factory) getContext().getService(parentsFactoryReferences[i]);

 			assertTrue("Check the avaibility of " + factory.getName(), isExposed(factory, Level2FactoryReferences, sc2));

 		}

-		

+

 		empty2.dispose();

 	}

-	

+

 	public void testDynamism() {

 		ServiceReference[] parentsFactoryReferences = Utils.getServiceReferences(getContext(), Factory.class.getName(), null);

 		ServiceContext sc1 = Utils.getServiceContext(empty);

 		ServiceReference[] Level1FactoryReferences = Utils.getServiceReferences(sc1, Factory.class.getName(), null);

-		

+

 		Factory fact = Utils.getFactoryByName(sc1, "composite.empty");

 		Properties p = new Properties();

 		p.put("instance.name","empty2");

@@ -137,74 +138,74 @@
 		} catch (Exception e) {

 			fail("Cannot instantiate empty2 instance : " + e.getMessage());

 		}

-		

+

 		ServiceContext sc2 = Utils.getServiceContext(empty2);

 		ServiceReference[] Level2FactoryReferences = Utils.getServiceReferences(sc2, Factory.class.getName(), null);

-		

+

 		assertEquals("Check the number of available factories - 1", parentsFactoryReferences.length, Level1FactoryReferences.length);

 		assertEquals("Check the number of available factories - 2", parentsFactoryReferences.length, Level2FactoryReferences.length);

 		assertEquals("Check the number of available factories - 3", Level1FactoryReferences.length, Level2FactoryReferences.length);

-		

+

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

 			Factory factory = (Factory) getContext().getService(parentsFactoryReferences[i]);

 			assertTrue("Check the avaibility of " + factory.getName(), isExposed(factory, Level2FactoryReferences, sc2));

 		}

-		

+

 		// Publish fake1

 		ServiceRegistration reg1 = getContext().registerService(Factory.class.getName(), fake1, null);

-		

+

 		parentsFactoryReferences = Utils.getServiceReferences(getContext(), Factory.class.getName(), null);

 		sc1 = Utils.getServiceContext(empty);

 		Level1FactoryReferences = Utils.getServiceReferences(sc1, Factory.class.getName(), null);

 		sc2 = Utils.getServiceContext(empty2);

 		Level2FactoryReferences = Utils.getServiceReferences(sc2, Factory.class.getName(), null);

-		

+

 		assertEquals("Check the number of available factories - 1.1", parentsFactoryReferences.length, Level1FactoryReferences.length);

 		assertEquals("Check the number of available factories - 1.2", parentsFactoryReferences.length, Level2FactoryReferences.length);

 		assertEquals("Check the number of available factories - 1.3", Level1FactoryReferences.length, Level2FactoryReferences.length);

-		

+

 		// 	Publish fake2

 		ServiceRegistration reg2 = getContext().registerService(Factory.class.getName(), fake2, null);

-		

+

 		parentsFactoryReferences = Utils.getServiceReferences(getContext(), Factory.class.getName(), null);

 		sc1 = Utils.getServiceContext(empty);

 		Level1FactoryReferences = Utils.getServiceReferences(sc1, Factory.class.getName(), null);

 		sc2 = Utils.getServiceContext(empty2);

 		Level2FactoryReferences = Utils.getServiceReferences(sc2, Factory.class.getName(), null);

-		

+

 		assertEquals("Check the number of available factories - 1.1", parentsFactoryReferences.length, Level1FactoryReferences.length);

 		assertEquals("Check the number of available factories - 1.2", parentsFactoryReferences.length, Level2FactoryReferences.length);

 		assertEquals("Check the number of available factories - 1.3", Level1FactoryReferences.length, Level2FactoryReferences.length);

-		

+

 		reg1.unregister();

-		

+

 		parentsFactoryReferences = Utils.getServiceReferences(getContext(), Factory.class.getName(), null);

 		sc1 = Utils.getServiceContext(empty);

 		Level1FactoryReferences = Utils.getServiceReferences(sc1, Factory.class.getName(), null);

 		sc2 = Utils.getServiceContext(empty2);

 		Level2FactoryReferences = Utils.getServiceReferences(sc2, Factory.class.getName(), null);

-		

+

 		assertEquals("Check the number of available factories - 1.1", parentsFactoryReferences.length, Level1FactoryReferences.length);

 		assertEquals("Check the number of available factories - 1.2", parentsFactoryReferences.length, Level2FactoryReferences.length);

 		assertEquals("Check the number of available factories - 1.3", Level1FactoryReferences.length, Level2FactoryReferences.length);

-		

+

 		reg2.unregister();

-		

+

 		parentsFactoryReferences = Utils.getServiceReferences(getContext(), Factory.class.getName(), null);

 		sc1 = Utils.getServiceContext(empty);

 		Level1FactoryReferences = Utils.getServiceReferences(sc1, Factory.class.getName(), null);

 		sc2 = Utils.getServiceContext(empty2);

 		Level2FactoryReferences = Utils.getServiceReferences(sc2, Factory.class.getName(), null);

-		

+

 		assertEquals("Check the number of available factories - 1.1", parentsFactoryReferences.length, Level1FactoryReferences.length);

 		assertEquals("Check the number of available factories - 1.2", parentsFactoryReferences.length, Level2FactoryReferences.length);

 		assertEquals("Check the number of available factories - 1.3", Level1FactoryReferences.length, Level2FactoryReferences.length);

-		

+

 		empty2.dispose();

 	}

-	

+

 	public void testInvocation() {

-		ServiceContext sc1 = Utils.getServiceContext(empty);		

+		ServiceContext sc1 = Utils.getServiceContext(empty);

 		Factory fact = Utils.getFactoryByName(sc1, "composite.empty");

 		Properties p = new Properties();

 		p.put("instance.name","empty2");

@@ -214,9 +215,9 @@
 		} catch (Exception e) {

 			fail("Cannot instantiate empty2 instance : " + e.getMessage());

 		}

-		

+

 		ServiceContext sc2 = Utils.getServiceContext(empty2);

-		

+

 		Factory fact1 = Utils.getFactoryByName(sc2, "COMPO-SimpleCheckServiceProvider");

 		Properties props = new Properties();

 		props.put("instance.name","client");

@@ -224,7 +225,7 @@
 		try {

 			client = fact1.createComponentInstance(props);

 		} catch (Exception e) { e.printStackTrace(); fail("Cannot instantiate the client : " + e.getMessage()); }

-		

+

 		Factory fact2 = Utils.getFactoryByName(sc2, "COMPO-FooProviderType-1");

 		Properties props2 = new Properties();

 		props2.put("instance.name","provider");

@@ -234,26 +235,26 @@
 		} catch (Exception e) {

 			fail("Cannot instantiate the provider : " + e.getMessage());

 		}

-		

-		ServiceReference ref = sc2.getServiceReference(CheckService.class.getName());		

+

+		ServiceReference ref = sc2.getServiceReference(CheckService.class.getName());

 		assertNotNull("Check ref existency", ref);

 		CheckService check = (CheckService) sc2.getService(ref);

-		

+

 		assertTrue("Check invocation", check.check());

 		client.dispose();

 		provider.dispose();

 		empty2.dispose();

 	}

-	

-	

-	

-	

+

+

+

+

 	private boolean isExposed(Factory fact, ServiceReference[] refs, ServiceContext sc) {

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

 			Factory f = (Factory) sc.getService(refs[i]);

 			if(fact.getName().equals(f.getName())) {

 				sc.ungetService(refs[i]);

-				return true; 

+				return true;

 			}

 			sc.ungetService(refs[i]);

 		}

diff --git a/ipojo/tests/core/factory-version/instances.xml b/ipojo/tests/core/factory-version/instances.xml
new file mode 100644
index 0000000..cda4486
--- /dev/null
+++ b/ipojo/tests/core/factory-version/instances.xml
@@ -0,0 +1,20 @@
+<ipojo>
+
+	<instance component="org.apache.felix.ipojo.tests.core.component.MyComponent"
+		version="1.0"
+		name="instance-v1"
+	/>
+
+	<instance component="org.apache.felix.ipojo.tests.core.component.MyComponent"
+		version="1.1"
+		name="instance-v1.1"
+	/>
+
+	<instance component="org.apache.felix.ipojo.tests.core.component.MyComponent"
+		name="instance-any"
+	/>
+
+	<instance component="MyComponent"
+		name="MyComponentInstance"
+	/>
+</ipojo>
\ No newline at end of file
diff --git a/ipojo/tests/core/factory-version/pom.xml b/ipojo/tests/core/factory-version/pom.xml
new file mode 100644
index 0000000..af28557
--- /dev/null
+++ b/ipojo/tests/core/factory-version/pom.xml
@@ -0,0 +1,122 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>ipojo.tests</groupId>
+  <artifactId>tests.core.factory-version</artifactId>
+  <name>iPOJO Factory Version Test Suite</name>
+  <version>1.3.0-SNAPSHOT</version>
+  <description>Test the factory version attribute</description>
+
+  <build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.5</source>
+					<target>1.5</target>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.servicemix.tooling</groupId>
+				<artifactId>depends-maven-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>generate-depends-file</id>
+						<goals>
+							<goal>generate-depends-file</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+			<!--  <plugin>
+				<groupId>org.ops4j.pax.exam</groupId>
+				<artifactId>maven-paxexam-plugin</artifactId>
+				<executions>
+					<execution>
+					<id>generate-paxexam-config</id>
+					<goals>
+						<goal>generate-paxexam-config</goal>
+					</goals>
+					</execution>
+				</executions>
+				<configuration>
+				<settings>
+					<platform>felix</platform>
+				</settings>
+				</configuration>
+			</plugin> -->
+		</plugins>
+	</build>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.felix</groupId>
+			<artifactId>org.apache.felix.ipojo</artifactId>
+			<version>1.3.0-SNAPSHOT</version>
+		</dependency>
+
+	<!--
+		Pax Exam API:
+	-->
+	<dependency>
+		<groupId>org.ops4j.pax.exam</groupId>
+		<artifactId>pax-exam</artifactId>
+		<version>0.4.0</version>
+	</dependency>
+	<!--
+		During runtime Pax Exam will discover the OSGi container to use by
+		searching metadata available into classpath. Pax Exam comes with a
+		default container that uses [Pax Runner] for implementing the
+		container requirements:
+	-->
+	<dependency>
+		<groupId>org.ops4j.pax.exam</groupId>
+		<artifactId>pax-exam-container-default
+		</artifactId>
+		<version>0.4.0</version>
+	</dependency>
+	<!--
+		If your test code is based on JUnit you will have to have the Junit
+		support artifact:
+	-->
+	<dependency>
+		<groupId>org.ops4j.pax.exam</groupId>
+		<artifactId>pax-exam-junit</artifactId>
+		<version>0.4.0</version>
+	</dependency>
+	<dependency>
+		<groupId>junit</groupId>
+		<artifactId>junit</artifactId>
+		<version>4.5</version>
+		<type>jar</type>
+		<scope>test</scope>
+	</dependency>
+	<!--  Tinybundles -->
+		<dependency>
+		 <groupId>org.ops4j.pax.tinybundles</groupId>
+  		 <artifactId>pax-tinybundles-core</artifactId>
+  		 <version>0.5.0-SNAPSHOT</version>
+  	</dependency>
+  	<dependency>
+  		<groupId>org.apache.felix</groupId>
+  		<artifactId>org.apache.felix.ipojo.pax.exam.target</artifactId>
+  		<version>0.9.0-SNAPSHOT</version>
+ 	 </dependency>
+	</dependencies>
+
+	<repositories>
+		<repository>
+			<id>ops4j.releases</id>
+			<name>OPS4J Release</name>
+			<url> http://repository.ops4j.org/maven2/</url>
+			<releases>
+				<enabled>true</enabled>
+			</releases>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+	</repositories>
+
+</project>
\ No newline at end of file
diff --git a/ipojo/tests/core/factory-version/provider-v1.1.xml b/ipojo/tests/core/factory-version/provider-v1.1.xml
new file mode 100644
index 0000000..77d4fdf
--- /dev/null
+++ b/ipojo/tests/core/factory-version/provider-v1.1.xml
@@ -0,0 +1,5 @@
+<ipojo>
+	<component classname="org.apache.felix.ipojo.tests.core.component.MyComponent" version="BuNdlE">
+		<provides/>
+	</component>
+</ipojo>
\ No newline at end of file
diff --git a/ipojo/tests/core/factory-version/provider-v1.xml b/ipojo/tests/core/factory-version/provider-v1.xml
new file mode 100644
index 0000000..24ce4c8
--- /dev/null
+++ b/ipojo/tests/core/factory-version/provider-v1.xml
@@ -0,0 +1,10 @@
+<ipojo>
+	<component classname="org.apache.felix.ipojo.tests.core.component.MyComponent" version="1.0">
+		<provides/>
+	</component>
+
+
+	<component classname="org.apache.felix.ipojo.tests.core.component.MyComponent" name="MyComponent">
+		<provides/>
+	</component>
+</ipojo>
\ No newline at end of file
diff --git a/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/FactoryVersionTest.java b/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/FactoryVersionTest.java
new file mode 100644
index 0000000..0148684
--- /dev/null
+++ b/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/FactoryVersionTest.java
@@ -0,0 +1,179 @@
+package org.apache.felix.ipojo.tests.core;
+
+import static org.apache.felix.ipojo.pax.exam.target.BundleAsiPOJO.asiPOJOBundle;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.provision;
+import static org.ops4j.pax.exam.MavenUtils.asInProject;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.asURL;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.newBundle;
+import static org.ops4j.pax.tinybundles.core.TinyBundles.with;
+
+import java.io.File;
+
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.tests.core.component.MyComponent;
+import org.apache.felix.ipojo.tests.core.service.MyService;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Inject;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+@RunWith( JUnit4TestRunner.class )
+public class FactoryVersionTest {
+
+    @Inject
+    private BundleContext context;
+
+    private OSGiHelper osgi;
+
+    private IPOJOHelper ipojo;
+
+    @Before
+    public void init() {
+        osgi = new OSGiHelper(context);
+        ipojo = new IPOJOHelper(context);
+    }
+
+    @After
+    public void stop() {
+        ipojo.dispose();
+        osgi.dispose();
+    }
+
+    @Configuration
+    public static Option[] configure() {
+
+        File tmp = new File("target/tmp");
+        tmp.mkdirs();
+
+        Option[] opt =  options(
+                provision(
+                        // Runtime.
+                        mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.ipojo").version(asInProject()),
+                        mavenBundle().groupId( "org.ops4j.pax.tinybundles" ).artifactId( "pax-tinybundles-core" ).version(asInProject())
+                        ),
+                provision(
+                        newBundle()
+                            .addClass( MyService.class )
+                            .prepare()
+                           .set(Constants.BUNDLE_SYMBOLICNAME,"ServiceInterface")
+                           .set(Constants.EXPORT_PACKAGE, "org.apache.felix.ipojo.tests.core.service")
+                            .build( asURL() ).toExternalForm()
+                    ),
+               provision(
+                       // Component V1
+                        newBundle()
+                            .addClass(MyComponent.class)
+                            .prepare(
+                                    with()
+                                        .set(Constants.BUNDLE_SYMBOLICNAME,"ProviderV1")
+                                        .set(Constants.IMPORT_PACKAGE, "org.apache.felix.ipojo.tests.core.service")
+                                    )
+                            .build( asiPOJOBundle(new File(tmp, "provider-v1.jar"), new File("provider-v1.xml"))).toExternalForm(),
+                     // Component V1.1 (Bundle Version)
+                        newBundle()
+                            .addClass(MyComponent.class)
+                            .prepare(
+                                    with()
+                                        .set(Constants.BUNDLE_SYMBOLICNAME,"ProviderV1.1")
+                                        .set(Constants.IMPORT_PACKAGE, "org.apache.felix.ipojo.tests.core.service")
+                                        .set(Constants.BUNDLE_VERSION, "1.1")
+                                    )
+                            .build( asiPOJOBundle(new File(tmp, "provider-v1.1.jar"), new File("provider-v1.1.xml"))).toExternalForm(),
+                // Instance declaration
+                newBundle()
+                    .prepare(
+                            with()
+                                .set(Constants.BUNDLE_SYMBOLICNAME,"Instances")
+                            )
+                    .build( asiPOJOBundle(new File(tmp, "instances.jar"), new File("instances.xml"))).toExternalForm()
+
+                    )
+                );
+        return opt;
+    }
+
+    @Test
+    public void testDeploy() {
+        Bundle[] bundles = context.getBundles();
+        for (int i = 0; i < bundles.length; i++) {
+            Assert.assertEquals(bundles[i].getSymbolicName() + " is not active", Bundle.ACTIVE, bundles[i].getState());
+        }
+    }
+
+    @Test
+    public void testInstanceArchitecture() {
+          // Version 1.0
+          ServiceReference refv1 = ipojo.getServiceReferenceByName(Architecture.class.getName(), "instance-v1");
+          Assert.assertNotNull(refv1);
+          Architecture archv1 = (Architecture) osgi.getServiceObject(refv1);
+
+          String version = archv1.getInstanceDescription().getComponentDescription().getVersion();
+          Assert.assertEquals("1.0", version);
+
+          // Version 1.1
+          ServiceReference refv11 = ipojo.getServiceReferenceByName(Architecture.class.getName(), "instance-v1.1");
+          Assert.assertNotNull(refv11);
+          Architecture archv11 = (Architecture) osgi.getServiceObject(refv11);
+
+          String version11 = archv11.getInstanceDescription().getComponentDescription().getVersion();
+          Assert.assertEquals("1.1", version11);
+
+          // No Version
+          ServiceReference refany = ipojo.getServiceReferenceByName(Architecture.class.getName(), "instance-any");
+          Assert.assertNotNull(refany);
+          Architecture archany = (Architecture) osgi.getServiceObject(refany);
+
+          String any = archany.getInstanceDescription().getComponentDescription().getVersion();
+          Assert.assertNotNull(any);
+
+          // No version set in the factory, so no version.
+          ServiceReference refmci = ipojo.getServiceReferenceByName(Architecture.class.getName(), "MyComponentInstance");
+          Assert.assertNotNull(refmci);
+          Architecture archmcy = (Architecture) osgi.getServiceObject(refmci);
+
+          String mci = archmcy.getInstanceDescription().getComponentDescription().getVersion();
+          Assert.assertNull(mci);
+
+    }
+
+    @Test
+    public void testServiceProperty() {
+          // Version 1.0
+          ServiceReference refv1 = ipojo.getServiceReferenceByName(MyService.class.getName(), "instance-v1");
+          Assert.assertNotNull(refv1);
+          String version = (String) refv1.getProperty("factory.version");
+          Assert.assertEquals("1.0", version);
+
+          // Version 1.1
+          ServiceReference refv11 = ipojo.getServiceReferenceByName(MyService.class.getName(), "instance-v1.1");
+          Assert.assertNotNull(refv11);
+          String version11 = (String) refv11.getProperty("factory.version");
+
+          Assert.assertEquals("1.1", version11);
+
+          // No Version
+          ServiceReference refany = ipojo.getServiceReferenceByName(MyService.class.getName(), "instance-any");
+          Assert.assertNotNull(refany);
+          String any = (String) refany.getProperty("factory.version");
+          Assert.assertNotNull(any);
+
+          // No version set in the factory, so no version.
+          ServiceReference refmci = ipojo.getServiceReferenceByName(MyService.class.getName(), "MyComponentInstance");
+          Assert.assertNotNull(refmci);
+          String mci = (String) refmci.getProperty("factory.version");
+          Assert.assertNull(mci);
+    }
+
+
+}
diff --git a/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/IPOJOHelper.java b/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/IPOJOHelper.java
new file mode 100644
index 0000000..7755c08
--- /dev/null
+++ b/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/IPOJOHelper.java
@@ -0,0 +1,730 @@
+/* 
+ * 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.tests.core;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.Handler;
+import org.apache.felix.ipojo.HandlerFactory;
+import org.apache.felix.ipojo.ServiceContext;
+import org.apache.felix.ipojo.architecture.Architecture;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.ManifestMetadataParser;
+import org.apache.felix.ipojo.parser.ParseException;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+/**
+ * iPOJO Helper.
+ * This helper helps getting {@link Factory}, and managing
+ * {@link ComponentInstance}.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class IPOJOHelper {
+
+    /**
+     * The bundle context.
+     */
+    private BundleContext m_context;
+
+
+    /**
+     * List of instances.
+     */
+    private List<ComponentInstance> m_instances;
+
+    /**
+     * Creates a IPOJOHelper.
+     * @param tc the OSGi Test Case
+     */
+    public IPOJOHelper(BundleContext context) {
+        m_context = context;
+        m_instances = new ArrayList<ComponentInstance>();
+    }
+
+    /**
+     * Disposes created instances.
+     * @see org.apache.felix.ipojo.junit4osgi.Helper#dispose()
+     */
+    public void dispose() {
+        for (int i = 0; i < m_instances.size(); i++) {
+            ((ComponentInstance) m_instances.get(i)).dispose();
+        }
+        m_instances.clear();
+    }
+
+    /**
+     * Gets a created instance from the instance name.
+     * @param name the instance name.
+     * @return the created {@link ComponentInstance} or <code>null</code>
+     * if the instance was not created during the session.
+     */
+    public ComponentInstance getInstanceByName(String name) {
+        for (int i = 0; i < m_instances.size(); i++) {
+            if (((ComponentInstance) m_instances.get(i)).getInstanceName()
+                    .equals(name)) {
+                return (ComponentInstance) m_instances.get(i);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Creates a new component instance with the given name (and empty
+     * configuration), from the factory specified in the given bundle.
+     * 
+     * @param bundle the bundle from which the component factory is defined.
+     * @param factoryName the name of the component factory, defined in the
+     *            specified bundle.
+     * @param instanceName the name of the component instance to create.
+     * @return the newly created component instance.
+     */
+    public static ComponentInstance createComponentInstance(Bundle bundle,
+            String factoryName, String instanceName) {
+
+        // Create the instance configuration
+        Properties configuration = new Properties();
+        configuration.put("instance.name", instanceName);
+
+        return createComponentInstance(bundle, factoryName, configuration);
+    }
+
+    /**
+     * Creates a new component instance with the given configuration, from the
+     * factory specified in the given bundle.
+     * 
+     * @param bundle the bundle from which the component factory is defined.
+     * @param factoryName the name of the component factory, defined in the
+     *            specified bundle.
+     * @param configuration the configuration of the component instance to
+     *            create.
+     * @return the newly created component instance.
+     */
+    public static ComponentInstance createComponentInstance(Bundle bundle,
+            String factoryName, Dictionary configuration) {
+
+        // Retrieve the component factory.
+        Factory fact = getFactory(bundle, factoryName);
+
+        if (fact == null) {
+            // Factory not found...
+            throw new IllegalArgumentException(
+                    "Cannot find the component factory (" + factoryName
+                            + ") in the specified bundle ("
+                            + bundle.getSymbolicName() + ").");
+        }
+
+        try {
+            return fact.createComponentInstance(configuration);
+        } catch (Exception e) {
+            throw new IllegalArgumentException(
+                    "Cannot create the component instance with the given configuration:"
+                            + e.getMessage());
+        }
+    }
+
+    /**
+     * Creates a new component instance with the given name and configuration,
+     * from the factory specified in the given bundle.
+     * 
+     * @param bundle the bundle from which the component factory is defined.
+     * @param factoryName the name of the component factory, defined in the
+     *            specified bundle.
+     * @param instanceName the name of the component instance to create.
+     * @param configuration the configuration of the instance to create.
+     * @return the newly created component instance.
+     */
+    public static ComponentInstance createComponentInstance(Bundle bundle,
+            String factoryName, String instanceName, Dictionary configuration) {
+
+        // Add the instance name to the configuration
+        configuration.put("instance.name", instanceName);
+
+        return createComponentInstance(bundle, factoryName, configuration);
+    }
+
+    /**
+     * Creates a new component instance with the given name (and an empty
+     * configuration), from the factory specified in the given service context.
+     * 
+     * @param serviceContext the service context in which the component factory
+     *            service is registered.
+     * @param factoryName the name of the component factory, defined in the
+     *            specified service context.
+     * @param instanceName the name of the component instance to create.
+     * @return the newly created component instance.
+     */
+    public static ComponentInstance createComponentInstance(
+            ServiceContext serviceContext, String factoryName,
+            String instanceName) {
+
+        // Create the instance configuration
+        Properties configuration = new Properties();
+        configuration.put("instance.name", instanceName);
+
+        return createComponentInstance(serviceContext, factoryName,
+                configuration);
+    }
+
+    /**
+     * Creates a new component instance with the given name and configuration,
+     * from the factory specified in the given service context.
+     * 
+     * @param serviceContext the service context in which the component factory
+     *            service is registered.
+     * @param factoryName the name of the component factory, defined in the
+     *            specified service context.
+     * @param configuration the configuration of the instance to create.
+     * @return the newly created component instance.
+     */
+    public static ComponentInstance createComponentInstance(
+            ServiceContext serviceContext, String factoryName,
+            Dictionary configuration) {
+
+        // Retrieve the component factory.
+        Factory fact = getFactory(serviceContext, factoryName);
+
+        if (fact == null) {
+            // Factory not found...
+            throw new IllegalArgumentException(
+                    "Cannot find the component factory (" + factoryName
+                            + ") in the specified service context.");
+        }
+
+        try {
+            return fact.createComponentInstance(configuration);
+        } catch (Exception e) {
+            throw new IllegalArgumentException(
+                    "Cannot create the component instance with the given configuration: "
+                            + e.getMessage());
+        }
+    }
+
+    /**
+     * Creates a new component instance with the given name and configuration,
+     * from the factory specified in the given service context.
+     * 
+     * @param serviceContext the service context in which the component factory
+     *            service is registered.
+     * @param factoryName the name of the component factory, defined in the
+     *            specified service context.
+     * @param instanceName the name of the component instance to create.
+     * @param configuration the configuration of the instance to create.
+     * @return the newly created component instance.
+     */
+    public static ComponentInstance createComponentInstance(
+            ServiceContext serviceContext, String factoryName,
+            String instanceName, Dictionary configuration) {
+
+        // Add the instance name to the configuration
+        configuration.put("instance.name", instanceName);
+
+        return createComponentInstance(serviceContext, factoryName,
+                configuration);
+    }
+
+    /**
+     * Creates a new component instance with the given name (and empty
+     * configuration), from the factory specified in the local bundle.
+     * 
+     * @param factoryName the name of the component factory, defined in the
+     *            local bundle.
+     * @param instanceName the name of the component instance to create.
+     * @return the newly created component instance.
+     */
+    public ComponentInstance createComponentInstance(String factoryName,
+            String instanceName) {
+        ComponentInstance ci = createComponentInstance(m_context.getBundle(),
+                factoryName, instanceName);
+        m_instances.add(ci);
+        return ci;
+    }
+
+    /**
+     * Creates a new component instance with the given configuration, from the
+     * factory specified in the local bundle.
+     * 
+     * @param factoryName the name of the component factory, in the local
+     *            bundle.
+     * @param configuration the configuration of the component instance to
+     *            create.
+     * @return the newly created component instance.
+     */
+    public ComponentInstance createComponentInstance(String factoryName,
+            Dictionary configuration) {
+        ComponentInstance ci = createComponentInstance(m_context.getBundle(),
+                factoryName, configuration);
+        m_instances.add(ci);
+        return ci;
+    }
+
+    /**
+     * Creates a new component instance with no configuration, from the factory
+     * specified in the local bundle.
+     * 
+     * @param factoryName the name of the component factory, in the local
+     *            bundle.
+     * @return the newly created component instance.
+     */
+    public ComponentInstance createComponentInstance(String factoryName) {
+        ComponentInstance ci = createComponentInstance(m_context.getBundle(),
+                factoryName, (Dictionary) null);
+        m_instances.add(ci);
+        return ci;
+    }
+
+    /**
+     * Creates a new component instance with the given name and configuration,
+     * from the factory specified in the given bundle.
+     * 
+     * @param factoryName the name of the component factory, defined in the
+     *            specified bundle.
+     * @param instanceName the name of the component instance to create.
+     * @param configuration the configuration of the instance to create.
+     * @return the newly created component instance.
+     */
+    public ComponentInstance createComponentInstance(String factoryName,
+            String instanceName, Dictionary configuration) {
+        ComponentInstance ci = createComponentInstance(m_context.getBundle(),
+                factoryName, instanceName, configuration);
+        m_instances.add(ci);
+        return ci;
+    }
+
+    /**
+     * Returns the component factory with the given name in the local bundle.
+     * 
+     * @param factoryName the name of the factory to retrieve.
+     * @return the component factory with the given name in the local bundle, or
+     *         {@code null} if not found.
+     */
+    public Factory getFactory(String factoryName) {
+        return getFactory(m_context.getBundle(), factoryName);
+    }
+
+    /**
+     * Returns the handler factory with the given name in the local bundle.
+     * 
+     * @param factoryName the name of the handler factory to retrieve.
+     * @return the handler factory with the given name in the local bundle, or
+     *         {@code null} if not found.
+     */
+    public HandlerFactory getHandlerFactory(String factoryName) {
+        return getHandlerFactory(m_context.getBundle(), factoryName);
+    }
+
+    /**
+     * Returns the metadata description of the component defined in this bundle.
+     * 
+     * @param component the name of the locally defined component.
+     * @return the metadata description of the component with the given name,
+     *         defined in this given bundle, or {@code null} if not found.
+     */
+    public Element getMetadata(String component) {
+        return getMetadata(m_context.getBundle(), component);
+    }
+
+    /**
+     * Returns the component factory with the given name in the given bundle.
+     * 
+     * @param bundle the bundle from which the component factory is defined.
+     * @param factoryName the name of the defined factory.
+     * @return the component factory with the given name in the given bundle, or
+     *         {@code null} if not found.
+     */
+    public static Factory getFactory(Bundle bundle, String factoryName) {
+        ServiceReference[] refs;
+        try {
+            // Retrieves the component factories services in the bundle.
+            refs = bundle.getBundleContext().getServiceReferences(
+                    Factory.class.getName(),
+                    "(factory.name=" + factoryName + ")");
+            if (refs != null) {
+                return (Factory) bundle.getBundleContext().getService(refs[0]);
+            }
+
+            // Factory not found...
+            return null;
+
+        } catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException(
+                    "Cannot get the component factory services: "
+                            + e.getMessage());
+        }
+    }
+
+    /**
+     * Returns the component factory with the given name, registered in the
+     * given service context.
+     * 
+     * @param serviceContext the service context in which the factory service is
+     *            defined.
+     * @param factoryName the name of the factory.
+     * @return the component factory with the given name, registered in the
+     *         given service context.
+     */
+    public static Factory getFactory(ServiceContext serviceContext,
+            String factoryName) {
+        ServiceReference[] refs;
+        try {
+            // Retrieves the component factories services in the service
+            // context.
+            refs = serviceContext.getServiceReferences(Factory.class.getName(),
+                    "(factory.name=" + factoryName + ")");
+            if (refs != null) {
+                return (Factory) serviceContext.getService(refs[0]);
+            }
+            return null;
+
+        } catch (InvalidSyntaxException e) {
+            System.err.println("Cannot get the factory " + factoryName + " : "
+                    + e.getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * Returns the handler factory with the given name in the given bundle.
+     * 
+     * @param bundle the bundle from which the handler factory is defined.
+     * @param factoryName the name of the handler factory to retrieve.
+     * @return the handler factory with the given name in the given bundle, or
+     *         {@code null} if not found.
+     */
+    public static HandlerFactory getHandlerFactory(Bundle bundle,
+            String factoryName) {
+        ServiceReference[] refs;
+        try {
+            // Retrieves the handler factories services in the bundle.
+            refs = bundle.getBundleContext().getServiceReferences(
+                    HandlerFactory.class.getName(),
+                    "(" + Handler.HANDLER_NAME_PROPERTY + "=" + factoryName
+                            + ")");
+            if (refs != null) {
+                return (HandlerFactory) bundle.getBundleContext().getService(
+                        refs[0]);
+            }
+
+            // Factory not found...
+            return null;
+        } catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException(
+                    "Cannot get the handler factory services: "
+                            + e.getMessage());
+        }
+    }
+
+    /**
+     * Returns the metadata description of the component with the given name,
+     * defined in the given bundle.
+     * 
+     * @param bundle the bundle from which the component is defined.
+     * @param component the name of the defined component.
+     * @return the metadata description of the component with the given name,
+     *         defined in the given bundle, or {@code null} if not found.
+     */
+    public static Element getMetadata(Bundle bundle, String component) {
+
+        // Retrieves the component description from the bundle's manifest.
+        String elem = (String) bundle.getHeaders().get("iPOJO-Components");
+        if (elem == null) {
+            throw new IllegalArgumentException(
+                    "Cannot find iPOJO-Components descriptor in the specified bundle ("
+                            + bundle.getSymbolicName()
+                            + "). Not an iPOJO bundle.");
+        }
+
+        // Parses the retrieved description and find the component with the
+        // given name.
+        try {
+            Element element = ManifestMetadataParser.parseHeaderMetadata(elem);
+            Element[] childs = element.getElements("component");
+            for (int i = 0; i < childs.length; i++) {
+                String name = childs[i].getAttribute("name");
+                String clazz = childs[i].getAttribute("classname");
+                if (name != null && name.equalsIgnoreCase(component)) {
+                    return childs[i];
+                }
+                if (clazz.equalsIgnoreCase(component)) {
+                    return childs[i];
+                }
+            }
+
+            // Component not found...
+            return null;
+
+        } catch (ParseException e) {
+            throw new IllegalStateException(
+                    "Cannot parse the components from specified bundle ("
+                            + bundle.getSymbolicName() + "): " + e.getMessage());
+        }
+    }
+
+    /**
+     * Returns the service object of a service registered in the specified
+     * service context, offering the specified interface and matching the given
+     * filter.
+     * 
+     * @param serviceContext the service context in which the service is
+     *            searched.
+     * @param itf the interface provided by the searched service.
+     * @param filter an additional filter (can be {@code null}).
+     * @return the service object provided by the specified bundle, offering the
+     *         specified interface and matching the given filter.
+     */
+    public static Object getServiceObject(ServiceContext serviceContext,
+            String itf, String filter) {
+        ServiceReference ref = getServiceReference(serviceContext, itf, filter);
+        if (ref != null) {
+            return serviceContext.getService(ref);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the service objects of the services registered in the specified
+     * service context, offering the specified interface and matching the given
+     * filter.
+     * 
+     * @param serviceContext the service context in which services are searched.
+     * @param itf the interface provided by the searched services.
+     * @param filter an additional filter (can be {@code null}).
+     * @return the service objects provided by the specified bundle, offering
+     *         the specified interface and matching the given filter.
+     */
+    public static Object[] getServiceObjects(ServiceContext serviceContext,
+            String itf, String filter) {
+        ServiceReference[] refs = getServiceReferences(serviceContext, itf,
+                filter);
+        if (refs != null) {
+            Object[] list = new Object[refs.length];
+            for (int i = 0; i < refs.length; i++) {
+                list[i] = serviceContext.getService(refs[i]);
+            }
+            return list;
+        } else {
+            return new Object[0];
+        }
+    }
+
+    /**
+     * Returns the service reference of a service registered in the specified
+     * service context, offering the specified interface and matching the given
+     * filter.
+     * 
+     * @param serviceContext the service context in which services are searched.
+     * @param itf the interface provided by the searched service.
+     * @param filter an additional filter (can be {@code null}).
+     * @return a service reference registered in the specified service context,
+     *         offering the specified interface and matching the given filter.
+     *         If no service is found, {@code null} is returned.
+     */
+    public static ServiceReference getServiceReference(
+            ServiceContext serviceContext, String itf, String filter) {
+        ServiceReference[] refs = getServiceReferences(serviceContext, itf,
+                filter);
+        if (refs.length != 0) {
+            return refs[0];
+        } else {
+            // No service found
+            return null;
+        }
+    }
+
+    /**
+     * Returns the service reference of the service registered in the specified
+     * service context, offering the specified interface and having the given
+     * persistent ID.
+     * 
+     * @param serviceContext the service context in which services are searched.
+     * @param itf the interface provided by the searched service.
+     * @param pid the persistent ID of the searched service.
+     * @return a service registered in the specified service context, offering
+     *         the specified interface and having the given persistent ID.
+     */
+    public static ServiceReference getServiceReferenceByPID(
+            ServiceContext serviceContext, String itf, String pid) {
+        String filter = "(" + "service.pid" + "=" + pid + ")";
+        ServiceReference[] refs = getServiceReferences(serviceContext, itf,
+                filter);
+        if (refs == null) {
+            return null;
+        } else if (refs.length == 1) {
+            return refs[0];
+        } else {
+            throw new IllegalStateException(
+                    "A service lookup by PID returned several providers ("
+                            + refs.length + ")" + " for " + itf + " with pid="
+                            + pid);
+        }
+    }
+
+    /**
+     * Returns the service reference of all the services registered in the
+     * specified service context, offering the specified interface and matching
+     * the given filter.
+     * 
+     * @param serviceContext the service context in which services are searched.
+     * @param itf the interface provided by the searched services.
+     * @param filter an additional filter (can be {@code null}).
+     * @return all the service references registered in the specified service
+     *         context, offering the specified interface and matching the given
+     *         filter. If no service matches, an empty array is returned.
+     */
+    public static ServiceReference[] getServiceReferences(
+            ServiceContext serviceContext, String itf, String filter) {
+        ServiceReference[] refs = null;
+        try {
+            // Get all the service references
+            refs = serviceContext.getServiceReferences(itf, filter);
+        } catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException(
+                    "Cannot get service references: " + e.getMessage());
+        }
+        if (refs == null) {
+            return new ServiceReference[0];
+        } else {
+            return refs;
+        }
+    }
+
+    /**
+     * Returns the service reference of a service registered in the specified
+     * service context, offering the specified interface and having the given
+     * name.
+     * 
+     * @param serviceContext the service context in which services are searched.
+     * @param itf the interface provided by the searched service.
+     * @param name the name of the searched service.
+     * @return a service registered in the specified service context, offering
+     *         the specified interface and having the given name.
+     */
+    public static ServiceReference getServiceReferenceByName(
+            ServiceContext serviceContext, String itf, String name) {
+        String filter = null;
+        if (itf.equals(Factory.class.getName())
+                || itf.equals(ManagedServiceFactory.class.getName())) {
+            filter = "(" + "factory.name" + "=" + name + ")";
+        } else if (itf.equals(Architecture.class.getName())) {
+            filter = "(" + "architecture.instance" + "=" + name + ")";
+        } else {
+            filter = "(" + "instance.name" + "=" + name + ")";
+        }
+        return getServiceReference(serviceContext, itf, filter);
+    }
+
+    /**
+     * Checks the availability of a service inside the given service context.
+     * @param sc the service context
+     * @param itf the service interface to found
+     * @return <code>true</code> if the service is available in the service
+     *         context, <code>false</code> otherwise.
+     */
+    public static boolean isServiceAvailable(ServiceContext sc, String itf) {
+        ServiceReference ref = getServiceReference(sc, itf, null);
+        return ref != null;
+    }
+
+    /**
+     * Checks the availability of a service inside the given service context.
+     * @param sc the service context
+     * @param itf the service interface to found
+     * @param name the service provider name
+     * @return <code>true</code> if the service is available in the service
+     *         context, <code>false</code> otherwise.
+     */
+    public static boolean isServiceAvailableByName(ServiceContext sc,
+            String itf, String name) {
+        ServiceReference ref = getServiceReferenceByName(sc, itf, name);
+        return ref != null;
+    }
+
+    /**
+     * Checks the availability of a service inside the given service context.
+     * @param sc the service context
+     * @param itf the service interface to found
+     * @param pid the pid of the service
+     * @return <code>true</code> if the service is available in the service
+     *         context, <code>false</code> otherwise.
+     */
+    public static boolean isServiceAvailableByPID(ServiceContext sc,
+            String itf, String pid) {
+        ServiceReference ref = getServiceReferenceByPID(sc, itf, pid);
+        return ref != null;
+    }
+
+    /**
+     * Returns the service reference of a service provided by the specified
+     * bundle, offering the specified interface and having the given name.
+     * 
+     * @param bundle the bundle from which the service is searched.
+     * @param itf the interface provided by the searched service.
+     * @param name the name of the searched service.
+     * @return a service provided by the specified bundle, offering the
+     *         specified interface and having the given name.
+     */
+    public static ServiceReference getServiceReferenceByName(Bundle bundle,
+            String itf, String name) {
+        String filter = null;
+        if (itf.equals(Factory.class.getName())
+                || itf.equals(ManagedServiceFactory.class.getName())) {
+            filter = "(" + "factory.name" + "=" + name + ")";
+        } else if (itf.equals(Architecture.class.getName())) {
+            filter = "(" + "architecture.instance" + "=" + name + ")";
+        } else {
+            filter = "(" + "instance.name" + "=" + name + ")";
+        }
+        return OSGiHelper.getServiceReference(bundle, itf, filter);
+    }
+
+    /**
+     * Returns the service reference of a service provided by the local bundle,
+     * offering the specified interface and having the given name.
+     * 
+     * @param itf the interface provided by the searched service.
+     * @param name the name of the searched service.
+     * @return a service provided by the specified bundle, offering the
+     *         specified interface and having the given name.
+     */
+    public ServiceReference getServiceReferenceByName(String itf, String name) {
+        return getServiceReferenceByName(m_context.getBundle(), itf, name);
+    }
+
+    /**
+     * Checks if the service is available.
+     * @param itf the service interface
+     * @param name the service provider name
+     * @return <code>true</code> if the service is available, <code>false</code>
+     *         otherwise.
+     */
+    public boolean isServiceAvailableByName(String itf, String name) {
+        ServiceReference ref = getServiceReferenceByName(itf, name);
+        return ref != null;
+    }
+
+}
diff --git a/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/OSGiHelper.java b/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/OSGiHelper.java
new file mode 100644
index 0000000..bf880f1
--- /dev/null
+++ b/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/OSGiHelper.java
@@ -0,0 +1,456 @@
+package org.apache.felix.ipojo.tests.core;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+import static org.junit.Assert.fail;
+
+
+public class OSGiHelper {
+    
+    /**
+     * The bundle context.
+     */
+    private BundleContext context;
+    
+    /**
+     * List of get references.
+     */
+    private List<ServiceReference> m_references = new ArrayList<ServiceReference>();
+    
+    public OSGiHelper(BundleContext context) {
+        this.context = context;
+    }
+    
+    public void dispose() {
+        // Unget services
+        for (int i = 0; i < m_references.size(); i++) {
+            context.ungetService((ServiceReference) m_references.get(i));
+        }
+        m_references.clear();
+    }
+    
+    /**
+     * Gets the Bundle Context.
+     * @return the bundle context.
+     */
+    public BundleContext getContext() {
+        return context;
+    }
+    
+    /**
+     * Returns the service object of a service provided by the specified bundle,
+     * offering the specified interface and matching the given filter.
+     * 
+     * @param bundle the bundle from which the service is searched.
+     * @param itf the interface provided by the searched service.
+     * @param filter an additional filter (can be {@code null}).
+     * @return the service object provided by the specified bundle, offering the
+     *         specified interface and matching the given filter.
+     */
+    public static Object getServiceObject(Bundle bundle, String itf,
+            String filter) {
+        ServiceReference ref = getServiceReference(bundle, itf, filter);
+        if (ref != null) {
+            return bundle.getBundleContext().getService(ref);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the service objects of the services provided by the specified
+     * bundle, offering the specified interface and matching the given filter.
+     * 
+     * @param bundle the bundle from which services are searched.
+     * @param itf the interface provided by the searched services.
+     * @param filter an additional filter (can be {@code null}).
+     * @return the service objects provided by the specified bundle, offering
+     *         the specified interface and matching the given filter.
+     */
+    public static Object[] getServiceObjects(Bundle bundle, String itf,
+            String filter) {
+        ServiceReference[] refs = getServiceReferences(bundle, itf, filter);
+        if (refs != null) {
+            Object[] list = new Object[refs.length];
+            for (int i = 0; i < refs.length; i++) {
+                list[i] = bundle.getBundleContext().getService(refs[i]);
+            }
+            return list;
+        } else {
+            return new Object[0];
+        }
+    }
+
+    /**
+     * Returns the service reference of a service provided by the specified
+     * bundle, offering the specified interface and matching the given filter.
+     * 
+     * @param bundle the bundle from which the service is searched.
+     * @param itf the interface provided by the searched service.
+     * @param filter an additional filter (can be {@code null}).
+     * @return a service reference provided by the specified bundle, offering
+     *         the specified interface and matching the given filter. If no
+     *         service is found, {@code null} is returned.
+     */
+    public static ServiceReference getServiceReference(Bundle bundle,
+            String itf, String filter) {
+        ServiceReference[] refs = getServiceReferences(bundle, itf, filter);
+        if (refs.length != 0) {
+            return refs[0];
+        } else {
+            // No service found
+            return null;
+        }
+    }
+
+    /**
+     * Checks if the service is available.
+     * @param itf the service interface
+     * @return <code>true</code> if the service is available, <code>false</code>
+     *         otherwise.
+     */
+    public boolean isServiceAvailable(String itf) {
+        ServiceReference ref = getServiceReference(itf, null);
+        return ref != null;
+    }
+
+    /**
+     * Checks if the service is available.
+     * @param itf the service interface
+     * @param pid the service pid
+     * @return <code>true</code> if the service is available, <code>false</code>
+     *         otherwise.
+     */
+    public boolean isServiceAvailableByPID(String itf, String pid) {
+        ServiceReference ref = getServiceReferenceByPID(itf, pid);
+        return ref != null;
+    }
+
+    /**
+     * Returns the service reference of the service provided by the specified
+     * bundle, offering the specified interface and having the given persistent
+     * ID.
+     * 
+     * @param bundle the bundle from which the service is searched.
+     * @param itf the interface provided by the searched service.
+     * @param pid the persistent ID of the searched service.
+     * @return a service provided by the specified bundle, offering the
+     *         specified interface and having the given persistent ID.
+     */
+    public static ServiceReference getServiceReferenceByPID(Bundle bundle,
+            String itf, String pid) {
+        String filter = "(" + "service.pid" + "=" + pid + ")";
+        ServiceReference[] refs = getServiceReferences(bundle, itf, filter);
+        if (refs == null) {
+            return null;
+        } else if (refs.length == 1) {
+            return refs[0];
+        } else {
+            throw new IllegalStateException(
+                    "A service lookup by PID returned several providers ("
+                            + refs.length + ")" + " for " + itf + " with pid="
+                            + pid);
+        }
+    }
+
+    /**
+     * Returns the service reference of all the services provided in the
+     * specified bundle, offering the specified interface and matching the given
+     * filter.
+     * 
+     * @param bundle the bundle from which services are searched.
+     * @param itf the interface provided by the searched services.
+     * @param filter an additional filter (can be {@code null}).
+     * @return all the service references provided in the specified bundle,
+     *         offering the specified interface and matching the given filter.
+     *         If no service matches, an empty array is returned.
+     */
+    public static ServiceReference[] getServiceReferences(Bundle bundle,
+            String itf, String filter) {
+        ServiceReference[] refs = null;
+        try {
+            // Get all the service references
+            refs = bundle.getBundleContext().getServiceReferences(itf, filter);
+        } catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException(
+                    "Cannot get service references: " + e.getMessage());
+        }
+        if (refs == null) {
+            return new ServiceReference[0];
+        } else {
+            return refs;
+        }
+    }
+
+    /**
+     * Returns the service object of a service provided by the local bundle,
+     * offering the specified interface and matching the given filter.
+     * 
+     * @param itf the interface provided by the searched service.
+     * @param filter an additional filter (can be {@code null}).
+     * @return the service object provided by the local bundle, offering the
+     *         specified interface and matching the given filter.
+     */
+    public Object getServiceObject(String itf, String filter) {
+        ServiceReference ref = getServiceReference(itf, filter);
+        if (ref != null) {
+            m_references.add(ref);
+            return context.getService(ref);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the service object associated with this service reference.
+     * 
+     * @param ref service reference
+     * @return the service object.
+     */
+    public Object getServiceObject(ServiceReference ref) {
+        if (ref != null) {
+            m_references.add(ref);
+            return context.getService(ref);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the service objects of the services provided by the local bundle,
+     * offering the specified interface and matching the given filter.
+     * 
+     * @param itf the interface provided by the searched services.
+     * @param filter an additional filter (can be {@code null}).
+     * @return the service objects provided by the local bundle, offering the
+     *         specified interface and matching the given filter.
+     */
+    public Object[] getServiceObjects(String itf, String filter) {
+        ServiceReference[] refs = getServiceReferences(itf, filter);
+        if (refs != null) {
+            Object[] list = new Object[refs.length];
+            for (int i = 0; i < refs.length; i++) {
+                m_references.add(refs[i]);
+                list[i] = context.getService(refs[i]);
+            }
+            return list;
+        } else {
+            return new Object[0];
+        }
+    }
+
+    /**
+     * Returns the service reference of a service provided by the local bundle,
+     * offering the specified interface and matching the given filter.
+     * 
+     * @param itf the interface provided by the searched service.
+     * @param filter an additional filter (can be {@code null}).
+     * @return a service reference provided by the local bundle, offering the
+     *         specified interface and matching the given filter. If no service
+     *         is found, {@code null} is returned.
+     */
+    public ServiceReference getServiceReference(String itf, String filter) {
+        return getServiceReference(context.getBundle(), itf, filter);
+    }
+
+    /**
+     * Returns the service reference of a service provided offering the
+     * specified interface.
+     * 
+     * @param itf the interface provided by the searched service.
+     * @return a service reference provided by the local bundle, offering the
+     *         specified interface and matching the given filter. If no service
+     *         is found, {@code null} is returned.
+     */
+    public ServiceReference getServiceReference(String itf) {
+        return getServiceReference(context.getBundle(), itf, null);
+    }
+
+    /**
+     * Returns the service reference of the service provided by the local
+     * bundle, offering the specified interface and having the given persistent
+     * ID.
+     * 
+     * @param itf the interface provided by the searched service.
+     * @param pid the persistent ID of the searched service.
+     * @return a service provided by the local bundle, offering the specified
+     *         interface and having the given persistent ID.
+     */
+    public ServiceReference getServiceReferenceByPID(String itf, String pid) {
+        return getServiceReferenceByPID(context.getBundle(), itf, pid);
+    }
+
+    /**
+     * Returns the service reference of all the services provided in the local
+     * bundle, offering the specified interface and matching the given filter.
+     * 
+     * @param itf the interface provided by the searched services.
+     * @param filter an additional filter (can be {@code null}).
+     * @return all the service references provided in the local bundle, offering
+     *         the specified interface and matching the given filter. If no
+     *         service matches, an empty array is returned.
+     */
+    public ServiceReference[] getServiceReferences(String itf, String filter) {
+        return getServiceReferences(context.getBundle(), itf, filter);
+    }
+    
+    /**
+     * Gets the package admin exposed by the framework.
+     * Fails if the package admin is not available. 
+     * @return the package admin service.
+     */
+    public PackageAdmin getPackageAdmin() {
+        PackageAdmin pa = (PackageAdmin) getServiceObject(PackageAdmin.class.getName(), null);
+        if (pa == null) {
+            fail("No package admin available");
+        }
+        return pa;
+    }
+    
+    /**
+     * Refresh the packages.
+     * Fails if the package admin service is not available.
+     */
+    public void refresh() {
+        getPackageAdmin().refreshPackages(null);
+    }
+    
+    /**
+     * Waits for a service. Fails on timeout.
+     * If timeout is set to 0, it sets the timeout to 10s.
+     * @param itf the service interface
+     * @param filter  the filter
+     * @param timeout the timeout
+     */
+    public void waitForService(String itf, String filter, long timeout) {
+        if (timeout == 0) {
+            timeout = 10000; // Default 10 secondes.
+        }
+        ServiceReference[] refs = getServiceReferences(itf, filter);
+        long begin = System.currentTimeMillis();
+        if (refs.length != 0) {
+            return;
+        } else {
+            while(refs.length == 0) {
+                try {
+                    Thread.sleep(5);
+                } catch (InterruptedException e) {
+                    // Interrupted
+                }
+                long now = System.currentTimeMillis();
+                
+                if ((now - begin) > timeout) {
+                    fail("Timeout ... no services matching with the request after " + timeout + "ms");
+                }
+                refs = getServiceReferences(itf, filter);
+            }
+        }
+    }
+    
+    
+    /**
+     * Installs a bundle.
+     * Fails if the bundle cannot be installed.
+     * Be aware that you have to uninstall the bundle yourself.
+     * @param url bundle url
+     * @return the installed bundle
+     */
+    public Bundle installBundle(String url) {
+        try {
+            return context.installBundle(url);
+        } catch (BundleException e) {
+            fail("Cannot install the bundle " + url + " : " + e.getMessage());
+        }
+        return null; // Can not happen
+    }
+    
+    /**
+     * Installs a bundle.
+     * Fails if the bundle cannot be installed.
+     * Be aware that you have to uninstall the bundle yourself.
+     * @param url bundle url
+     * @param stream input stream containing the bundle
+     * @return the installed bundle
+     */
+    public Bundle installBundle(String url, InputStream stream) {
+        try {
+            return context.installBundle(url, stream);
+        } catch (BundleException e) {
+            fail("Cannot install the bundle " + url + " : " + e.getMessage());
+        }
+        return null; // Can not happen
+    }
+    
+    /**
+     * Installs and starts a bundle.
+     * Fails if the bundle cannot be installed or an error occurs
+     * during startup. Be aware that you have to uninstall the bundle
+     * yourself.
+     * @param url the bundle url
+     * @return the Bundle object.
+     */
+    public Bundle installAndStart(String url) {
+        Bundle bundle = installBundle(url);
+        try {
+            bundle.start();
+        } catch (BundleException e) {
+           fail("Cannot start the bundle " + url + " : " + e.getMessage());
+        }
+        return bundle;
+    }
+    
+    /**
+     * Installs and starts a bundle.
+     * Fails if the bundle cannot be installed or an error occurs
+     * during startup. Be aware that you have to uninstall the bundle
+     * yourself.
+     * @param url the bundle url
+     * @param stream input stream containing the bundle
+     * @return the Bundle object.
+     */
+    public Bundle installAndStart(String url, InputStream stream) {
+        Bundle bundle = installBundle(url, stream);
+        try {
+            bundle.start();
+        } catch (BundleException e) {
+           fail("Cannot start the bundle " + url + " : " + e.getMessage());
+        }
+        return bundle;
+    }
+    
+    /**
+     * Get the bundle by its id.
+     * @param bundleId the bundle id.
+     * @return the bundle with the given id.
+     */
+    public Bundle getBundle(long bundleId) {
+        return context.getBundle(bundleId);
+    }
+    
+    /**
+     * Gets a bundle by its symbolic name.
+     * Fails if no bundle matches.
+     * @param name the symbolic name of the bundle
+     * @return the bundle object.
+     */
+    public Bundle getBundle(String name) {
+        Bundle[] bundles = context.getBundles();
+        for (int i = 0; i < bundles.length; i++) {
+            if (name.equals(bundles[i].getSymbolicName())) {
+                return bundles[i];
+            }
+        }
+        fail("No bundles with the given symbolic name " + name);
+        return null; // should not happen
+    }
+
+}
diff --git a/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/component/MyComponent.java b/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/component/MyComponent.java
new file mode 100644
index 0000000..71fcc94
--- /dev/null
+++ b/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/component/MyComponent.java
@@ -0,0 +1,11 @@
+package org.apache.felix.ipojo.tests.core.component;
+
+import org.apache.felix.ipojo.tests.core.service.MyService;
+
+public class MyComponent implements MyService {
+
+    public void foo() {
+        // Nothing to do.
+    }
+
+}
diff --git a/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/service/MyService.java b/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/service/MyService.java
new file mode 100644
index 0000000..9ffaa52
--- /dev/null
+++ b/ipojo/tests/core/factory-version/src/test/java/org/apache/felix/ipojo/tests/core/service/MyService.java
@@ -0,0 +1,7 @@
+package org.apache.felix.ipojo.tests.core.service;
+
+public interface MyService {
+
+    public void foo();
+
+}