Integrate the constructor-injection branch into the trunk.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1052264 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Property.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Property.java
index 691de4f..2c80de5 100644
--- a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Property.java
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Property.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

@@ -26,25 +26,25 @@
  * It can target both fields and methods.

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

  */

-@Target({ ElementType.FIELD, ElementType.METHOD })

+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })

 public @interface Property {

-    

+

     /**

      * Set property name.

      * Default : empty

      */

     String name() default "";

-    

+

     /**

      * Set property value.

      * Default : empty

      */

     String value() default "";

-    

+

     /**

      * Is the property mandatory?

      * Default: false

      */

     boolean mandatory() default false;

-    

+

 }

diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Requires.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Requires.java
index f7ea606..4ea2408 100644
--- a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Requires.java
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/annotations/Requires.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

@@ -27,34 +27,34 @@
  * This annotation declares a service requirement.

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

  */

-@Target(ElementType.FIELD)

+@Target({ ElementType.FIELD, ElementType.PARAMETER })

 @Inherited

 public @interface Requires {

-    

+

     /**

      * Set the LDAP filter of the dependency.

      * Default : no filter

      */

     String filter() default "";

-    

+

     /**

      * Set if the dependency is optional.

      * Default : false

      */

     boolean optional() default false;

-    

+

     /**

      * Set the dependency id.

      * Default : empty

      */

     String id() default "";

-    

+

     /**

      * Enable / Disable nullable pattern.

      * Default : true

      */

     boolean nullable() default true;

-    

+

     /**

      * Set the default-implementation to use if the dependency is optional,

      * and no providers are available.

@@ -62,31 +62,31 @@
      * Default : no default-implementation

      */

     Class defaultimplementation() default Class.class;

-    

+

     /**

      * Set the binding policy.

      * Acceptable policy are dynamic, static and dynamic-priority.

      * Default: dynamic.

      */

     String policy() default "dynamic";

-    

+

     /**

      * Set the comparator.

      * The indicated class must implement {@link Comparator}

      */

     Class comparator() default Comparator.class;

-    

+

     /**

      * Set the from attribute.

      */

     String from() default "";

-    

+

     /**

      * Set the required service specification.

      * This attribute is required for Collection field.

      */

     String specification() default "";

-    

+

     /**

      * Set to true if the service dependency is injected

      * as a proxy.

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 a91362f..3e28ee1 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
@@ -35,6 +35,7 @@
 import org.apache.felix.ipojo.util.Logger;
 import org.apache.felix.ipojo.util.Tracker;
 import org.apache.felix.ipojo.util.TrackerCustomizer;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
@@ -291,7 +292,7 @@
         Element[] elems = m_componentMetadata.getElements();
         for (int i = 0; i < elems.length; i++) {
             Element current = elems[i];
-            if (!"manipulation".equals(current.getName())) {
+            if (!"manipulation".equals(current.getName())) { // Remove the manipulation element
                 RequiredHandler req = new RequiredHandler(current.getName(), current.getNameSpace());
                 if (!list.contains(req)) {
                     list.add(req);
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/ConstructorInjector.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/ConstructorInjector.java
new file mode 100644
index 0000000..dffd3bc
--- /dev/null
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/ConstructorInjector.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo;
+
+/**
+ * Interface implemented to support constructor parameter injection.
+ * When a new POJO object has to be created, all constructor injectors are
+ * called to gets the objects to injects as well as the type (to discover
+ * the constructor).
+ * Handlers willing to inject constructor parameters must register themselves
+ * using {@link InstanceManager#register(int, ConstructorInjector)} where
+ * the integer is the parameter index. Only one injector can inject a value
+ * for a specific index. If several injectors are registered for the same index,
+ * the component type is declared as invalid.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface ConstructorInjector {
+
+   /**
+    * Gets the type of the object to inject in the constructor parameter.
+    * This is the type looked into the Pojo class, so it must match.
+    * Returning <code>null</code> will try to get the class from the
+    * injected object, however this can be wrong (implementation instead of interface,
+    * boxed objects...) and error-prone.
+    * @param index the parameter index
+    * @return the Class object (must fit for primitive type)
+    */
+	Object getConstructorParameter(int index);
+
+	/**
+	 * Gets the type of the object to
+	 * @param index
+	 * @return
+	 */
+	Class getConstructorParameterType(int index);
+
+}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java
index 2e1e740..4472200 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManager.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

@@ -82,7 +82,7 @@
         if (m_handler != null) { return; }

         m_handler = (Handler) createPojoObject();

     }

-    

+

     /**

      * Creates an instance of the content.

      * This method needs to be called once only for singleton provided service.

@@ -103,9 +103,9 @@
             }

             m_pojoObjects.add(instance);

         }

-        

+

         //Do not call onCreation, this will be done in the start method.

-        

+

         return instance;

     }

 

@@ -114,9 +114,9 @@
      */

     public void start() {

         synchronized (this) {

-            if (m_state != STOPPED) { 

+            if (m_state != STOPPED) {

                 return; // Instance already started

-            } else { 

+            } else {

                 m_state = -2; // Temporary starting state, avoiding concurrent starts.

             }

         }

@@ -126,16 +126,16 @@
             m_handlers[i].addInstanceStateListener(this);

             m_handlers[i].start();

         }

-        

+

         // Call the onCreation method.

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

             ((PrimitiveHandler) m_handlers[i].getHandler()).onCreation(m_handler);

         }

 

-        

+

         m_handler.start(); // Call the handler start method, the instance might be invalid.

-        

-        

+

+

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

             if (!m_handlers[i].getHandler().isValid()) {

                 setState(INVALID);

@@ -147,7 +147,7 @@
         } else {

             setState(INVALID);

         }

-        

+

         // Now, the state is necessary different from the temporary state.

     }

 

@@ -156,10 +156,10 @@
      */

     public void stop() {

         synchronized (this) {

-            if (m_state == STOPPED) { 

+            if (m_state == STOPPED) {

                 return; // Instance already stopped

             } else {

-                m_state = -2; // Temporary state avoiding concurrent stopping. 

+                m_state = -2; // Temporary state avoiding concurrent stopping.

             }

         }

 

@@ -182,7 +182,7 @@
                 listeners = new ArrayList(m_listeners); // Stack confinement.

             }

         }

-        

+

         if (listeners != null) {

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

                 ((InstanceStateListener) listeners.get(i)).stateChanged(this, STOPPED);

@@ -190,7 +190,7 @@
         }

     }

 

-    /** 

+    /**

      * Disposes the instance.

      * @see org.apache.felix.ipojo.ComponentInstance#dispose()

      */

@@ -211,14 +211,14 @@
     /**

      * State Change listener callback.

      * This method is notified at each time a plugged handler becomes invalid.

-     * @param instance the changing instance 

+     * @param instance the changing instance

      * @param newState the new state

      * @see org.apache.felix.ipojo.InstanceStateListener#stateChanged(org.apache.felix.ipojo.ComponentInstance, int)

      */

     public void stateChanged(ComponentInstance instance, int newState) {

         int state;

         synchronized (this) {

-            if (m_state <= STOPPED) { 

+            if (m_state <= STOPPED) {

                 return;

             } else {

                 state = m_state; // Stack confinement

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManagerFactory.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManagerFactory.java
index 44b7d0c..e237d6f 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManagerFactory.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/HandlerManagerFactory.java
@@ -152,7 +152,7 @@
         Element[] elems = m_componentMetadata.getElements();

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

             Element current = elems[i];

-            if (!"manipulation".equals(current.getName())) {

+            if (!"manipulation".equals(current.getName())) { // Remove the manipulation element

                 RequiredHandler req = new RequiredHandler(current.getName(),

                         current.getNameSpace());

                 if (!list.contains(req)) {

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
index 4910516..dbebc19 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
@@ -105,12 +105,20 @@
     private Map m_fieldRegistration;
 
     /**
-     * the map [method identifier, {@link MethodInterceptor} list] storing handlers interested by the method.
-     * Once configure this map can't change.
+     * the map [method identifier, {@link MethodInterceptor} list] interested
+     * by the method.
+     * Once configured, this map can't change.
      */
     private Map m_methodRegistration;
 
     /**
+     * the map (sorted by parameter index) or {@link ConstructorInjector} interested by
+     * injecting constructor parameter.
+     * Once configured, this list can't change.
+     */
+    private Map m_constructorRegistration;
+
+    /**
      * The manipulated class.
      * Once set, this field doesn't change.
      */
@@ -197,6 +205,15 @@
         for (int i = 0; i < m_handlers.length; i++) {
             m_handlers[i].init(this, metadata, configuration);
         }
+
+        // Check that the constructor parameter are continuous.
+        if (m_constructorRegistration != null) {
+        	for (int i = 0; i < m_constructorRegistration.size(); i++) {
+        		if (! m_constructorRegistration.containsKey(new Integer(i))) {
+        			throw new ConfigurationException("The constructor parameter " + i + " is not managed");
+        		}
+        	}
+        }
     }
 
     /**
@@ -416,6 +433,7 @@
             m_fields.clear();
             m_fieldRegistration = new HashMap();
             m_methodRegistration = new HashMap();
+            m_constructorRegistration = new HashMap();
             m_clazz = null;
         }
     }
@@ -595,29 +613,65 @@
         if (m_factoryMethod == null) {
             // No factory-method, we use the constructor.
             try {
-                // Try to find if there is a constructor with a bundle context as parameter :
-                try {
-                    Constructor cst = m_clazz.getDeclaredConstructor(new Class[] { InstanceManager.class, BundleContext.class });
-                    if (! cst.isAccessible()) {
+            	// Try to find the correct constructor.
+            	if (m_constructorRegistration != null) {
+            		// Initialize the injected values and types
+            		// We have the IM first.
+            		Object[] values = new Object[m_constructorRegistration.size() + 1];
+            		Class[] types = new Class[m_constructorRegistration.size() + 1];
+            		values[0] = this;
+            		types[0] = InstanceManager.class;
+
+            		// Iterate over the constructor injector
+            		for (int i = 0; i < m_constructorRegistration.size(); i++) {
+        				ConstructorInjector injector = (ConstructorInjector)
+        					m_constructorRegistration.get(new Integer(i));
+        				Object v = injector.getConstructorParameter(i);
+        				if (v != null) {
+        					values[i + 1] = v;
+        					Class t = injector.getConstructorParameterType(i);
+        					if (t == null) {
+        						t = v.getClass();
+        					}
+        					types[i + 1] = t;
+        				}
+            		}
+            		// Find the constructor.
+            		Constructor cst = m_clazz.getDeclaredConstructor(types);
+            		if (! cst.isAccessible()) {
                         cst.setAccessible(true);
                     }
-                    Object[] args = new Object[] { this, m_context };
-                    onEntry(null, MethodMetadata.BC_CONSTRUCTOR_ID,  new Object[] {m_context});
-                    instance = cst.newInstance(args);
-                    onExit(instance, MethodMetadata.BC_CONSTRUCTOR_ID, instance);
-                } catch (NoSuchMethodException e) {
-                    // Create an instance if no instance are already created with <init>()BundleContext
-                    if (instance == null) {
-                        Constructor cst = m_clazz.getDeclaredConstructor(new Class[] { InstanceManager.class });
+            		String methodId = MethodMetadata.computeMethodId(cst);
+                    onEntry(null, methodId,  values);
+            		instance = cst.newInstance(values);
+            		onExit(instance, methodId, instance);
+            	} else {
+            		// Old semantic
+            		// Try to find if there is a constructor with a bundle context as parameter :
+                    try {
+                        Constructor cst = m_clazz.getDeclaredConstructor(new Class[] { InstanceManager.class, BundleContext.class });
                         if (! cst.isAccessible()) {
                             cst.setAccessible(true);
                         }
-                        Object[] args = new Object[] {this};
-                        onEntry(null, MethodMetadata.EMPTY_CONSTRUCTOR_ID, new Object[0]);
+                        Object[] args = new Object[] { this, m_context };
+                        onEntry(null, MethodMetadata.BC_CONSTRUCTOR_ID,  new Object[] {m_context});
                         instance = cst.newInstance(args);
-                        onExit(instance, MethodMetadata.EMPTY_CONSTRUCTOR_ID, instance);
+                        onExit(instance, MethodMetadata.BC_CONSTRUCTOR_ID, instance);
+                    } catch (NoSuchMethodException e) {
+                        // Create an instance if no instance are already created with <init>()BundleContext
+                        if (instance == null) {
+                            Constructor cst = m_clazz.getDeclaredConstructor(new Class[] { InstanceManager.class });
+                            if (! cst.isAccessible()) {
+                                cst.setAccessible(true);
+                            }
+                            Object[] args = new Object[] {this};
+                            onEntry(null, MethodMetadata.EMPTY_CONSTRUCTOR_ID, new Object[0]);
+                            instance = cst.newInstance(args);
+                            onExit(instance, MethodMetadata.EMPTY_CONSTRUCTOR_ID, instance);
+                        }
                     }
-                }
+            	}
+
             } catch (IllegalAccessException e) {
                 m_logger.log(Logger.ERROR,
                                           "[" + m_name + "] createInstance -> The POJO constructor is not accessible : " + e.getMessage(), e);
@@ -937,6 +991,29 @@
     }
 
     /**
+     * Registers a constructor injector.
+     * The constructor injector will be called when a pojo object is going to be
+     * created.
+     * @param index the index of the parameter. Only one injector per index can
+     * be registered.
+     * @param injector the injector object.
+     * @throws ConfigurationException if the given index is already injected by another
+     * injector
+     */
+    public void register(int index, ConstructorInjector injector) throws ConfigurationException {
+    	Integer key = new Integer(index);
+    	if (m_constructorRegistration == null) {
+    		m_constructorRegistration = new HashMap();
+    	}
+    	if (! m_constructorRegistration.containsKey(key)) {
+    		m_constructorRegistration.put(key, injector);
+    	} else {
+    		throw new ConfigurationException("Another constructor injector " +
+    				"manages the parameter " + index);
+    	}
+    }
+
+    /**
      * This method is called by the manipulated class each time that a GETFIELD instruction is executed.
      * The method asks to each attached handler monitoring this field which value need
      * to be injected (i.e. returned) by invoking the {@link PrimitiveHandler#onGet(Object, String, Object)}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
index 94a7544..1e5069c 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/PrimitiveHandler.java
@@ -33,7 +33,8 @@
 * Classes overriding this class can change the behavior of those methods.

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

 */

-public abstract class PrimitiveHandler extends Handler implements FieldInterceptor, MethodInterceptor {

+public abstract class PrimitiveHandler extends Handler implements FieldInterceptor, MethodInterceptor,

+	ConstructorInjector {

 

     /**

      * The "Primitive" Handler type (value).

@@ -159,6 +160,32 @@
     }

 

     /**

+     * Gets the object to inject as a constructor parameter

+     * @param index the index of the parameter

+     * @return the object to inject, or <code>null</code> if no

+     * objects are injected. This implementation returns <code>null</code>

+     * @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameter(int)

+     */

+    public Object getConstructorParameter(int index) {

+    	return null;

+    }

+

+    /**

+     * Gets the type of the object to inject in the constructor parameter.

+     * This is the type looked into the Pojo class, so it must match.

+     * Returning <code>null</code> will try to get the class from the

+     * injected object, however this can be wrong (implementation instead of interface,

+     * boxed objects...) and error-prone.

+     * @param index the parameter index

+     * @return the Class object (must fit for primitive type), this implementation

+     * just returns <code>null</code>

+     * @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameterType(int)

+     */

+    public Class getConstructorParameterType(int index) {

+    	return null;

+    }

+

+    /**

      * Callback method called when a method will be invoked.

      * This default implementation does nothing.

      * @param pojo the pojo on which the method is called.

diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
index 3d0e7f8..612b3c5 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
@@ -123,17 +123,21 @@
         for (int i = 0; configurables != null && i < configurables.length; i++) {
             String fieldName = configurables[i].getAttribute("field");
             String methodName = configurables[i].getAttribute("method");
+            String paramIndex = configurables[i].getAttribute("constructor-parameter");
 
-            if (fieldName == null && methodName == null) {
-                throw new ConfigurationException("Malformed property : The property needs to contain at least a field or a method");
+            if (fieldName == null && methodName == null  && paramIndex == null) {
+                throw new ConfigurationException("Malformed property : The property needs to contain" +
+                		" at least a field, a method or a constructor-parameter");
             }
 
             String name = configurables[i].getAttribute("name");
             if (name == null) {
-                if (fieldName == null) {
+                if (fieldName == null  && methodName != null) {
                     name = methodName;
+                } else if (fieldName == null  && paramIndex != null) {
+                	name = paramIndex;
                 } else {
-                    name = fieldName;
+                	name = fieldName;
                 }
                 configurables[i].addAttribute(new Attribute("name", name)); // Add the type to avoid configure checking
             }
@@ -143,7 +147,7 @@
             // Detect the type of the property
             PojoMetadata manipulation = getFactory().getPojoMetadata();
             String type = null;
-            if (fieldName == null) {
+            if (methodName != null) {
                 MethodMetadata[] method = manipulation.getMethods(methodName);
                 if (method.length == 0) {
                     type = configurables[i].getAttribute("type");
@@ -157,11 +161,24 @@
                     type = method[0].getMethodArguments()[0];
                     configurables[i].addAttribute(new Attribute("type", type)); // Add the type to avoid configure checking
                 }
-            } else {
+            } else if (fieldName != null) {
                 FieldMetadata field = manipulation.getField(fieldName);
                 if (field == null) { throw new ConfigurationException("Malformed property : The field " + fieldName + " does not exist in the implementation class"); }
                 type = field.getFieldType();
                 configurables[i].addAttribute(new Attribute("type", type)); // Add the type to avoid configure checking
+            } else if (paramIndex != null) {
+            	int index = Integer.parseInt(paramIndex);
+            	type = configurables[i].getAttribute("type");
+        		MethodMetadata[] cts = manipulation.getConstructors();
+        		// If we don't have a type, try to get the first constructor and get the type of the parameter
+        		// we the index 'index'.
+        		if (type == null && cts.length > 0  && cts[0].getMethodArguments().length > index) {
+            		type = cts[0].getMethodArguments()[index];
+            	} else if (type == null) { // Applied only if type was not determined.
+            		throw new ConfigurationException("Cannot determine the type of the property " + index +
+            				", please use the type attribute");
+            	}
+            	configurables[i].addAttribute(new Attribute("type", type));
             }
 
             // Is the property set to immutable
@@ -240,13 +257,22 @@
         for (int i = 0; configurables != null && i < configurables.length; i++) {
             String fieldName = configurables[i].getAttribute("field");
             String methodName = configurables[i].getAttribute("method");
+            String paramIndex = configurables[i].getAttribute("constructor-parameter");
+            int index = -1;
 
             String name = configurables[i].getAttribute("name"); // The initialize method has fixed the property name.
             String value = configurables[i].getAttribute("value");
 
             String type = configurables[i].getAttribute("type"); // The initialize method has fixed the property name.
 
-            Property prop = new Property(name, fieldName, methodName, value, type, getInstanceManager(), this);
+            Property prop = null;
+            if (paramIndex == null) {
+            	prop = new Property(name, fieldName, methodName, value, type, getInstanceManager(), this);
+            } else {
+            	index = Integer.parseInt(paramIndex);
+            	prop = new Property(name, fieldName, methodName, index,
+            			value, type, getInstanceManager(), this);
+            }
             addProperty(prop);
 
             // Check if the instance configuration contains value for the current property :
@@ -262,6 +288,10 @@
                 FieldMetadata field = new FieldMetadata(fieldName, type);
                 getInstanceManager().register(field, prop);
             }
+
+            if (index != -1) {
+            	getInstanceManager().register(index, prop);
+            }
         }
 
         m_description = new ConfigurationHandlerDescription(this, m_configurableProperties, m_managedServicePID);
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
index 724e94b..c6419ba 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/Dependency.java
@@ -32,6 +32,8 @@
 import java.util.Set;
 import java.util.Vector;
 
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.ConstructorInjector;
 import org.apache.felix.ipojo.FieldInterceptor;
 import org.apache.felix.ipojo.InstanceManager;
 import org.apache.felix.ipojo.MethodInterceptor;
@@ -47,7 +49,8 @@
  * Represent a service dependency of the component instance.
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class Dependency extends DependencyModel implements FieldInterceptor, MethodInterceptor {
+public class Dependency extends DependencyModel implements FieldInterceptor, MethodInterceptor,
+	ConstructorInjector {
 
     /**
      * Reference on the Dependency Handler.
@@ -84,7 +87,7 @@
     /**
      * Thread Local.
      */
-    private final ServiceUsage m_usage;
+    private ServiceUsage m_usage;
 
     /**
      * Type of the object to inject.
@@ -125,6 +128,12 @@
     private Object m_proxyObject;
 
     /**
+     * Constructor paramter index.
+     * -1 if not used.
+     */
+    private int m_index = -1;
+
+    /**
      * Dependency constructor. After the creation the dependency is not started.
      *
      * @param handler : the dependency handler managing this dependency
@@ -163,6 +172,7 @@
         } else {
             m_id = identity;
         }
+
         // Else wait the setSpecification call.
     }
 
@@ -201,6 +211,13 @@
         }
     }
 
+
+    protected void addConstructorInjection(int index) throws ConfigurationException {
+    	m_index = index;
+    	m_usage = new ServiceUsage();
+    	m_handler.getInstanceManager().register(index, this);
+    }
+
     /**
      * Stop the current dependency.
      * @see org.apache.felix.ipojo.util.DependencyModel#stop()
@@ -998,6 +1015,53 @@
 
     }
 
+	/**
+	 * Gets the constructor parameter.
+	 * @return the index of the constructor parameter,
+	 * or <code>-1</code> if not set.
+	 */
+	public int getConstructorParameterIndex() {
+		return m_index;
+	}
+
+	/**
+	 * Gets the object to inject in the constructor parameter.
+	 * @param index the index of the parameter
+	 * @return the created proxy object
+	 * @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameter(int)
+	 */
+	public Object getConstructorParameter(int index) {
+		if (m_index == index  && m_proxyObject != null) {
+			return m_proxyObject;
+		}
+		return null;
+	}
+
+	/**
+	 * Gets the type of the constructor parameter.
+	 * @param index the parameter index
+	 * @return the class of the object. For scalar dependency, it's the
+	 * specification, for aggregate it depends of the container object:
+	 * {@link List} or {@link Set}.
+	 * @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameterType(int)
+	 */
+	public Class getConstructorParameterType(int index) {
+		if (m_index == index  && m_proxyObject != null) {
+			if (isAggregate()) {
+				switch (m_type) {
+				case DependencyHandler.LIST: return List.class;
+				case DependencyHandler.SET : return Set.class;
+				//TODO We should also manage the Collection type.
+				default: return null; // Should never happen, it was checked before.
+				}
+			} else {
+				return getSpecification();
+			}
+		} else {
+			return null;
+		}
+	}
+
 
 
 }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
index b676324..84993b0 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
@@ -209,9 +209,11 @@
         // Check the internal type of dependency
         String field = dep.getField();
         DependencyCallback[] callbacks = dep.getCallbacks();
+        int index = dep.getConstructorParameterIndex();
 
-        if (callbacks == null && field == null) {
-            throw new ConfigurationException("A service requirement requires at least binding methods or a field");
+        if (callbacks == null && field == null  && index == -1) {
+            throw new ConfigurationException("A service requirement requires at least binding methods, " +
+            		"a field or a constructor parameter");
         }
 
         for (int i = 0; callbacks != null && i < callbacks.length; i++) {
@@ -286,6 +288,41 @@
             setSpecification(dep, type, true); // Throws an exception if the field type mismatch.
         }
 
+        // Constructor parameter
+        if (index != -1) {
+        	if (! dep.isProxy()) {
+        		throw new ConfigurationException("Services injected into constructor must be proxied");
+        	}
+
+    		MethodMetadata[] cts = manipulation.getConstructors();
+    		// If we don't have a type, try to get the first constructor and get the type of the parameter
+    		// we the index 'index'.
+    		if (cts.length > 0  && cts[0].getMethodArguments().length > index) {
+        		String type = cts[0].getMethodArguments()[index];
+        		if (type.endsWith("[]")) {
+                    throw new ConfigurationException("Services injected into constructor cannot be arrays");
+                } else if (type.equals(List.class.getName()) || type.equals(Collection.class.getName())) {
+                    dep.setType(LIST);
+                    type = null;
+                } else if (type.equals(Vector.class.getName())) {
+                	throw new ConfigurationException("Services injected into constructor cannot be Vectors");
+                } else if (type.equals(Set.class.getName())) {
+                    dep.setType(SET);
+                    type = null;
+                } else {
+                    if (dep.isAggregate()) {
+                        throw new ConfigurationException("A required service is not correct : the constructor parameter "
+                                + index
+                                + " must be an aggregate type to support aggregate injections");
+                    }
+                }
+                setSpecification(dep, type, true); // Throws an exception if the field type mismatch.
+        	} else {
+        		throw new ConfigurationException("Cannot determine the specification of the dependency " + index +
+        				", please use the specification attribute");
+        	}
+        }
+
         // Disable proxy on scalar dependency targeting non-interface specification
         if (! dep.isAggregate()  && dep.isProxy()) {
         	if (! dep.getSpecification().isInterface()) {
@@ -317,7 +354,14 @@
             // No found type (list and vector)
             if (dep.getSpecification() == null) {
                 if (error) {
-                    throw new ConfigurationException("Cannot discover the required specification for " + dep.getField());
+                	String id = dep.getId();
+                	if (id == null) {
+                		id = dep.getField();
+                		if (id == null) {
+                			id = Integer.toString(dep.getConstructorParameterIndex());
+                		}
+                	}
+                    throw new ConfigurationException("Cannot discover the required specification for " + id);
                 } else {
                     // If the specification is different, warn that we will override it.
                     info("Cannot discover the required specification for " + dep.getField());
@@ -502,6 +546,13 @@
                 dep.addDependencyCallback(callback);
             }
 
+            // Add the constructor parameter if needed
+            String paramIndex = deps[i].getAttribute("constructor-parameter");
+            if (paramIndex != null) {
+            	int index = Integer.parseInt(paramIndex);
+            	dep.addConstructorInjection(index);
+            }
+
             // Check the dependency :
             if (checkDependency(dep, manipulation)) {
                 addDependency(dep);
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java
index ab8eb76..1de846a 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.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
@@ -18,6 +18,7 @@
  */
 package org.apache.felix.ipojo.parser;
 
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 
 import org.apache.felix.ipojo.metadata.Element;
@@ -28,7 +29,7 @@
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class MethodMetadata {
-    
+
     /**
      * Empty Constructor Method Id.
      */
@@ -38,7 +39,7 @@
      * Bundle Context Constructor Method Id.
      */
     public static final String BC_CONSTRUCTOR_ID = "$init$org_osgi_framework_BundleContext";
-    
+
     /**
      * Constructor Prefix.
      */
@@ -50,12 +51,12 @@
     private String m_name;
 
     /**
-     * The argument type array. 
+     * The argument type array.
      */
     private String[] m_arguments = new String[0];
 
     /**
-     * The returned type. 
+     * The returned type.
      */
     private String m_return = "void";
 
@@ -110,7 +111,7 @@
     }
 
     /**
-     * Computes the method id for the given Method object. 
+     * Computes the method id for the given Method object.
      * @param method the Method object.
      * @return the method id.
      */
@@ -140,4 +141,36 @@
         }
         return identifier.toString();
     }
+
+    /**
+     * Computes the method id for the given Constructor object.
+     * @param method the Method object.
+     * @return the method id.
+     */
+    public static String computeMethodId(Constructor method) {
+        StringBuffer identifier = new StringBuffer("$init");
+        Class[] args = method.getParameterTypes();
+        for (int i = 0; i < args.length; i++) {
+            identifier.append('$'); // Argument separator.
+            if (args[i].isArray()) {
+                if (args[i].getComponentType().isPrimitive()) {
+                    // Primitive array
+                    identifier.append(FieldMetadata.getPrimitiveTypeByClass(args[i].getComponentType()));
+                } else {
+                    // Object array
+                    identifier.append(args[i].getComponentType().getName().replace('.', '_')); // Replace '.' by '_'
+                }
+                identifier.append("__"); // Add __ (array)
+            } else {
+                if (args[i].isPrimitive()) {
+                    // Primitive type
+                    identifier.append(FieldMetadata.getPrimitiveTypeByClass(args[i]));
+                } else {
+                    // Object type
+                    identifier.append(args[i].getName().replace('.', '_')); // Replace '.' by '_'
+                }
+            }
+        }
+        return identifier.toString();
+    }
 }
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/PojoMetadata.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/PojoMetadata.java
index d716ca7..8b06832 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/PojoMetadata.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/parser/PojoMetadata.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
@@ -24,25 +24,25 @@
 /**
  * Manipulation Metadata allows getting information about the implementation class
  * without using reflection such as implemented interfaces, super class,
- * methods and fields. 
+ * methods and fields.
  * This method allows getting object to register {@link org.apache.felix.ipojo.FieldInterceptor} and
  * {@link org.apache.felix.ipojo.MethodInterceptor}.
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class PojoMetadata {
-    
+
     /**
      * The list of implemented interfaces.
      */
     private String[] m_interfaces = new String[0];
-    
+
     /**
      * The list of fields.
      */
     private FieldMetadata[] m_fields = new FieldMetadata[0];
-    
+
     /**
-     * The list of methods. 
+     * The list of methods.
      */
     private MethodMetadata[] m_methods = new MethodMetadata[0];
 
@@ -50,8 +50,8 @@
      * The Super class (if <code>null</code> for {@link Object}).
      */
     private String m_super;
-    
-    
+
+
     /**
      * Creates Pojo metadata.
      * Manipulation Metadata object are created from component type metadata by
@@ -62,7 +62,7 @@
     public PojoMetadata(Element metadata) throws ConfigurationException {
         Element[] elems = metadata.getElements("manipulation", "");
         if (elems == null) {
-            throw new ConfigurationException("The component " + metadata.getAttribute("classname") + " has no manipulation metadata"); 
+            throw new ConfigurationException("The component " + metadata.getAttribute("classname") + " has no manipulation metadata");
         }
         Element manip = elems[0];
         m_super = manip.getAttribute("super");
@@ -81,38 +81,38 @@
             addInterface(itfs[i].getAttribute("name"));
         }
     }
-    
+
     public MethodMetadata[] getMethods() { return m_methods; }
-    
+
     public FieldMetadata[] getFields() { return m_fields; }
-    
+
     public String[] getInterfaces() { return m_interfaces; }
-    
+
     /**
-     * Gets the field metadata for the given name. 
+     * Gets the field metadata for the given name.
      * @param name : the name of the field
      * @return the corresponding field metadata or <code>null</code> if not found
      */
-    public FieldMetadata getField(String name) { 
+    public FieldMetadata getField(String name) {
         for (int i = 0; i < m_fields.length; i++) {
             if (m_fields[i].getFieldName().equalsIgnoreCase(name)) { return m_fields[i]; }
         }
         return null;
     }
-    
+
     /**
-     * Gets the field metadata for the given name and type. 
+     * Gets the field metadata for the given name and type.
      * @param name : the name of the field
      * @param type : the type of the field
      * @return the corresponding field metadata or <code>null</code> if not found
      */
-    public FieldMetadata getField(String name, String type) { 
+    public FieldMetadata getField(String name, String type) {
         for (int i = 0; i < m_fields.length; i++) {
             if (m_fields[i].getFieldName().equalsIgnoreCase(name) && m_fields[i].getFieldType().equalsIgnoreCase(type)) { return m_fields[i]; }
         }
         return null;
     }
-    
+
     /**
      * Checks if the given interface name is implemented.
      * This methods checks on interface directly implemented
@@ -127,7 +127,7 @@
         }
         return false;
     }
-    
+
     /**
      * Gets the MethodMetadata corresponding to the method
      * (contained in the implementation class) with
@@ -142,11 +142,11 @@
         }
         return null;
     }
-    
+
     /**
      * Gets the MethodMetadata list corresponding to the method
      * (contained in the implementation class) to given name.
-     * All methods contained in the implementation class matching 
+     * All methods contained in the implementation class matching
      * with the name are in the returned list.
      * @param name the name of the method to look for.
      * @return the Method Metadata array or an empty array if not found
@@ -154,7 +154,7 @@
     public MethodMetadata[] getMethods(String name) {
         MethodMetadata[] mms = new MethodMetadata[0];
         for (int i = 0; i < m_methods.length; i++) {
-            if (m_methods[i].getMethodName().equalsIgnoreCase(name)) { 
+            if (m_methods[i].getMethodName().equalsIgnoreCase(name)) {
                 if (mms.length > 0) {
                     MethodMetadata[] newInstances = new MethodMetadata[mms.length + 1];
                     System.arraycopy(mms, 0, newInstances, 0, mms.length);
@@ -167,13 +167,22 @@
         }
         return mms;
     }
-    
+
+    /**
+     * Gets the MethodMetadata list corresponding to the constructors
+     * (contained in the implementation class).
+     * @return the Method Metadata array or an empty array if not found
+     */
+    public MethodMetadata[] getConstructors() {
+        return getMethods("$init");
+    }
+
     /**
      * Gets the MethodMetadata corresponding to the method
-     * (contained in the implementation class) to given name 
+     * (contained in the implementation class) to given name
      * and argument types.
      * @param name the name of the method to look for.
-     * @param types the array of the argument types of the method 
+     * @param types the array of the argument types of the method
      * @return the Method Metadata or <code>null</code> if not found
      */
     public MethodMetadata getMethod(String name, String[] types) {
@@ -190,7 +199,16 @@
         }
         return null;
     }
-        
+
+    /**
+     * Gets the constructor corresponding to the given argument types.
+     * @param types the argument types
+     * @return the matching constructor or <code>null</code> if not found.
+     */
+    public MethodMetadata getConstructor(String[] types) {
+    	return getMethod("$init", types); // Constructors are named $init in the manipulation metadata
+    }
+
      /**
      * Adds a method to the list.
      * This method is used during the creation of the {@link PojoMetadata}
@@ -207,7 +225,7 @@
             m_methods = new MethodMetadata[] { method };
         }
     }
-        
+
      /**
      * Adds a field to the list.
      * This method is used during the creation of the {@link PojoMetadata}
@@ -224,7 +242,7 @@
             m_fields = new FieldMetadata[] { field };
         }
     }
-        
+
     /**
      * Adds the interface to the list.
      * This method is used during the creation of the {@link PojoMetadata}
diff --git a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
index a2d3534..63395cd 100644
--- a/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
+++ b/ipojo/core/src/main/java/org/apache/felix/ipojo/util/Property.java
@@ -25,6 +25,7 @@
 

 import org.apache.felix.ipojo.ComponentInstance;

 import org.apache.felix.ipojo.ConfigurationException;

+import org.apache.felix.ipojo.ConstructorInjector;

 import org.apache.felix.ipojo.FieldInterceptor;

 import org.apache.felix.ipojo.Handler;

 import org.apache.felix.ipojo.InstanceManager;

@@ -33,10 +34,11 @@
 

 /**

  * Property class managing a managed value.

- * This class managed the method invocation as well as field injection.

+ * This class managed the method invocation, field injection

+ * and constructor injection.

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

  */

-public class Property implements FieldInterceptor {

+public class Property implements FieldInterceptor, ConstructorInjector {

 

     /**

      * Object used for an unvalued property.

@@ -62,6 +64,12 @@
     private final Callback m_method;

 

     /**

+     * The index of the parameter in case of

+     * constructor injection.

+     */

+    private int m_index = -1;

+

+    /**

      * The value of the property.

      */

     private Object m_value = NO_VALUE;

@@ -125,7 +133,12 @@
         } else {

             m_method = null;

         }

+    }

 

+    public Property(String name, String field, String method, int index,

+    		String value, String type, InstanceManager manager, Handler handler) throws ConfigurationException {

+    	this(name, field, method, value, type, manager, handler);

+    	m_index = index;

     }

 

     /**

@@ -258,6 +271,16 @@
     }

 

     /**

+     * Gets the parameter index.

+     * @return the parameter index or <code>-1</code>

+     * if this property is not injected using constructor

+     * parameter.

+     */

+    public int getParameterIndex() {

+    	return m_index;

+    }

+

+    /**

      * Checks if the property has a field.

      * @return <code>true</code> if the property has a field.

      */

@@ -567,6 +590,36 @@
     }

 

     /**

+     * Gets the object to inject as constructor parameter.

+     * @param index the constructor parameter index

+     * @return the object to inject, so the property value.

+     * @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameter(int)

+     */

+    public Object getConstructorParameter(int index) {

+    	if (m_index != index) {

+    		return null;

+    	}

+

+    	if (m_value  == NO_VALUE) {

+           return getNoValue(m_type);

+        }

+        return m_value;

+	}

+

+	/**

+	 * Gets the type of the constructor parameter to inject.

+	 * @param index the parameter index

+	 * @return the Class of the property.

+	 * @see org.apache.felix.ipojo.ConstructorInjector#getConstructorParameterType(int)

+	 */

+	public Class getConstructorParameterType(int index) {

+		if (m_index != index) {

+    		return null;

+    	}

+		return m_type;

+	}

+

+	/**

      * Gets the handler managing the property.

      * @return the configuration handler.

      */

diff --git a/ipojo/core/src/test/java/org/apache/felix/ipojo/parser/ManipulationMetadataTest.java b/ipojo/core/src/test/java/org/apache/felix/ipojo/parser/ManipulationMetadataTest.java
new file mode 100644
index 0000000..7658320
--- /dev/null
+++ b/ipojo/core/src/test/java/org/apache/felix/ipojo/parser/ManipulationMetadataTest.java
@@ -0,0 +1,257 @@
+/*

+ * 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.parser;

+

+import java.io.File;

+import java.io.FileInputStream;

+import java.io.FileNotFoundException;

+import java.io.IOException;

+import java.util.jar.Manifest;

+

+import junit.framework.TestCase;

+

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

+

+/**

+ * Check manipulation metadata written in the manifest.

+ */

+public class ManipulationMetadataTest extends TestCase {

+

+	private String header;

+

+	public void setUp() {

+		File manFile = new File("src/test/resources/manipulation/MANIFEST.MF");

+		Manifest manifest;

+		try {

+			manifest = new Manifest(new FileInputStream(manFile));

+			header = manifest.getMainAttributes().getValue("iPOJO-Components");

+		} catch (FileNotFoundException e) {

+			fail(e.getMessage());

+		} catch (IOException e) {

+			fail(e.getMessage());

+		}

+	}

+

+	public void testGetMetadata() {

+		Element elem = null;

+		try {

+			elem = ManifestMetadataParser.parseHeaderMetadata(header);

+		} catch (ParseException e) {

+			fail("Parse Exception when parsing iPOJO-Component");

+		}

+

+		assertNotNull("Check elem not null", elem);

+

+		Element manip = getManipulationForComponent(elem, "ManipulationMetadata-FooProviderType-1");

+		assertNotNull("Check manipulation metadata not null for " + "FooProviderType-1", manip);

+	}

+

+	public void testInterface() {

+		String comp_name = "ManipulationMetadata-FooProviderType-1";

+		Element manip = getManipulationForComponent(comp_name);

+		Element[] itf = manip.getElements("Interface");

+		assertEquals("Check interfaces number", itf.length, 1);

+		assertEquals("Check itf name", itf[0].getAttribute("name"),

+				"org.apache.felix.ipojo.test.scenarios.manipulation.service.FooService");

+	}

+

+	public void testInterfaces() {

+		String comp_name = "ManipulationMetadata-FooBarProviderType-1";

+		Element manip = getManipulationForComponent(comp_name);

+		Element[] itf = manip.getElements("Interface");

+		assertEquals("Check interfaces number", itf.length, 2);

+		assertEquals("Check itf name", itf[0].getAttribute("name"),

+				"org.apache.felix.ipojo.test.scenarios.manipulation.service.FooService");

+		assertEquals("Check itf name", itf[1].getAttribute("name"),

+				"org.apache.felix.ipojo.test.scenarios.manipulation.service.BarService");

+	}

+

+	public void testFields() {

+		String comp_name = "ManipulationMetadata-FooProviderType-Dyn";

+		Element manip = getManipulationForComponent(comp_name);

+		Element[] fields = manip.getElements("field");

+		assertEquals("Check field count " + fields.length, fields.length, 5);

+		/*

+		private int intProp;

+		private String strProp;

+		private String[] strAProp;

+		private int[] intAProp;

+		private boolean boolProp;

+		 */

+

+		Element field;

+

+		field = getFieldFromName(manip, "intProp");

+		assertEquals("Check field name : " + field.getAttribute("name"), field.getAttribute("name"), "intProp");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "int");

+

+		field = getFieldFromName(manip, "strProp");

+		assertEquals("Check field name : " + field.getAttribute("name"), field.getAttribute("name"), "strProp");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "java.lang.String");

+

+		field = getFieldFromName(manip, "strAProp");

+		assertEquals("Check field name : " + field.getAttribute("name"), field.getAttribute("name"), "strAProp");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "java.lang.String[]");

+

+		field = getFieldFromName(manip, "intAProp");

+		assertEquals("Check field name : " + field.getAttribute("name"), field.getAttribute("name"), "intAProp");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "int[]");

+

+		field = getFieldFromName(manip, "boolProp");

+		assertEquals("Check field name : " + field.getAttribute("name"), field.getAttribute("name"), "boolProp");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "boolean");

+	}

+

+	public void testPrimitivesFields() {

+		String comp_name = "ManipulationMetadata-PrimitiveManipulationTester";

+		Element manip = getManipulationForComponent(comp_name);

+		Element[] fields = manip.getElements("Field");

+		assertEquals("Check field count", fields.length, 16);

+		/*

+		byte b = 1;

+		short s = 1;

+		int i = 1;

+		long l = 1;

+		double d = 1.1;

+		float f = 1.1f;

+		char c = 'a';

+		boolean bool = false;

+		byte[] bs = new byte[] {0,1,2};

+		short[] ss = new short[] {0,1,2};

+		int[] is = new int[] {0,1,2};

+		long[] ls = new long[] {0,1,2};

+		double[] ds = new double[] {0.0, 1.1, 2.2};

+		float[] fs = new float[] {0.0f, 1.1f, 2.2f};

+		char[] cs = new char[] {'a', 'b', 'c'};

+		boolean[] bools = new boolean[] {false, true, false};

+		 */

+		Element field;

+

+		field = getFieldFromName(manip, "b");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "byte");

+		field = getFieldFromName(manip, "s");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "short");

+		field = getFieldFromName(manip, "i");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "int");

+		field = getFieldFromName(manip, "l");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "long");

+		field = getFieldFromName(manip, "d");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "double");

+		field = getFieldFromName(manip, "f");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "float");

+		field = getFieldFromName(manip, "c");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "char");

+		field = getFieldFromName(manip, "bool");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "boolean");

+

+		field = getFieldFromName(manip, "bs");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "byte[]");

+		field = getFieldFromName(manip, "ss");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "short[]");

+		field = getFieldFromName(manip, "is");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "int[]");

+		field = getFieldFromName(manip, "ls");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "long[]");

+		field = getFieldFromName(manip, "ds");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "double[]");

+		field = getFieldFromName(manip, "fs");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "float[]");

+		field = getFieldFromName(manip, "cs");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "char[]");

+		field = getFieldFromName(manip, "bools");

+		assertEquals("Check field type : " + field.getAttribute("name"), field.getAttribute("type"), "boolean[]");

+	}

+

+	public void testNoArgMethod() {

+		String comp_name = "ManipulationMetadata-SimpleMultipleCheckServiceProvider";

+		Element manip = getManipulationForComponent(comp_name);

+		Element method = getMethodFromName(manip, "check");

+		assertFalse("Check no args", method.containsAttribute("arguments"));

+		assertEquals("Check return", method.getAttribute("return"), "boolean");

+	}

+

+	public void testOneArgsMethod() {

+		String comp_name = "ManipulationMetadata-SimpleMultipleCheckServiceProvider";

+		Element manip = getManipulationForComponent(comp_name);

+		Element method = getMethodFromName(manip, "refBind");

+		assertEquals("Check args", method.getAttribute("arguments"), "{org.osgi.framework.ServiceReference}");

+		assertEquals("Check args count", 1, ParseUtils.parseArrays("{org.osgi.framework.ServiceReference}").length);

+		assertFalse("Check return", method.containsAttribute("return"));

+	}

+

+	public void testTwoArgsMethod() {

+		String comp_name = "ManipulationMetadata-SimpleMultipleCheckServiceProvider";

+		Element manip = getManipulationForComponent(comp_name);

+		Element method = getMethodFromName(manip, "doNothing");

+		assertEquals("Check args", method.getAttribute("arguments"), "{java.lang.Object,java.lang.String}");

+		assertEquals("Check args count", 2, ParseUtils.parseArrays("{java.lang.Object,java.lang.String}").length);

+		assertEquals("Check return", method.getAttribute("return"), "java.lang.Object");

+	}

+

+	private Element getManipulationForComponent(Element metadata, String comp_name) {

+		Element[] comps = metadata.getElements("component");

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

+			if(comps[i].containsAttribute("factory") && comps[i].getAttribute("factory").equals(comp_name)) {

+				return comps[i].getElements("manipulation")[0];

+			}

+            if(comps[i].containsAttribute("name") && comps[i].getAttribute("name").equals(comp_name)) {

+                return comps[i].getElements("manipulation")[0];

+            }

+		}

+		return null;

+	}

+

+	private Element getManipulationForComponent(String comp_name) {

+		Element elem = null;

+		try {

+			elem = ManifestMetadataParser.parseHeaderMetadata(header);

+		} catch (ParseException e) {

+			fail("Parse Exception when parsing iPOJO-Component");

+		}

+

+		assertNotNull("Check elem not null", elem);

+		Element manip = getManipulationForComponent(elem, comp_name);

+		assertNotNull("Check manipulation metadata not null for " + comp_name, manip);

+		return manip;

+	}

+

+	private Element getMethodFromName(Element manip, String name) {

+		Element methods[] = manip.getElements("Method");

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

+			if(methods[i].containsAttribute("name") && methods[i].getAttribute("name").equals(name)) {

+				return methods[i];

+			}

+		}

+		fail("Method " + name + " not found");

+		return null;

+	}

+

+	private Element getFieldFromName(Element manip, String name) {

+		Element fields[] = manip.getElements("Field");

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

+			if(fields[i].containsAttribute("name") && fields[i].getAttribute("name").equals(name)) {

+				return fields[i];

+			}

+		}

+		fail("Field " + name + " not found");

+		return null;

+	}

+

+

+}

diff --git a/ipojo/core/src/test/java/org/apache/felix/ipojo/parser/PojoMetadataTest.java b/ipojo/core/src/test/java/org/apache/felix/ipojo/parser/PojoMetadataTest.java
new file mode 100644
index 0000000..050590f
--- /dev/null
+++ b/ipojo/core/src/test/java/org/apache/felix/ipojo/parser/PojoMetadataTest.java
@@ -0,0 +1,322 @@
+/*

+ * 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.parser;

+

+import java.io.File;

+import java.io.FileInputStream;

+import java.io.FileNotFoundException;

+import java.io.IOException;

+import java.util.jar.Manifest;

+

+import junit.framework.TestCase;

+

+import org.apache.felix.ipojo.ConfigurationException;

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

+

+public class PojoMetadataTest extends TestCase {

+

+    PojoMetadata FooProviderType1, FooBarProviderType1, FooProviderTypeDyn, PrimitiveManipulationTester, SimpleMultipleCheckServiceProvider;

+

+    private String header;

+

+	public void setUp() {

+		File manFile = new File("src/test/resources/manipulation/MANIFEST.MF");

+		Manifest manifest;

+		try {

+			manifest = new Manifest(new FileInputStream(manFile));

+			header = manifest.getMainAttributes().getValue("iPOJO-Components");

+		} catch (FileNotFoundException e) {

+			fail(e.getMessage());

+		} catch (IOException e) {

+			fail(e.getMessage());

+		}

+

+        String comp_name = "ManipulationMetadata-FooProviderType-1";

+        FooProviderType1 = getManipulationMetadataForComponent(comp_name);

+

+        comp_name = "ManipulationMetadata-FooBarProviderType-1";

+        FooBarProviderType1 = getManipulationMetadataForComponent(comp_name);

+

+        comp_name = "ManipulationMetadata-FooProviderType-Dyn";

+        FooProviderTypeDyn = getManipulationMetadataForComponent(comp_name);

+

+        comp_name = "ManipulationMetadata-PrimitiveManipulationTester";

+        PrimitiveManipulationTester = getManipulationMetadataForComponent(comp_name);

+

+        comp_name = "ManipulationMetadata-SimpleMultipleCheckServiceProvider";

+        SimpleMultipleCheckServiceProvider = getManipulationMetadataForComponent(comp_name);

+	}

+

+	public void testGetMetadata() {

+		Element elem = null;

+		try {

+			elem = ManifestMetadataParser.parseHeaderMetadata(header);

+		} catch (ParseException e) {

+			fail("Parse Exception when parsing iPOJO-Component");

+		}

+

+		assertNotNull("Check elem not null", elem);

+

+		Element manip = getMetadataForComponent(elem, "ManipulationMetadata-FooProviderType-1");

+        assertNotNull("Check manipulation metadata not null for " + "Manipulation-FooProviderType-1", manip);

+        PojoMetadata mm;

+        try {

+            mm = new PojoMetadata(manip);

+            assertNotNull("Check mm not null", mm);

+        } catch (ConfigurationException e) {

+            fail("The creation of pojo metadata has failed");

+        }

+	}

+

+	public void testInterface() {

+	    PojoMetadata manip = FooProviderType1;

+

+        String[] itf = manip.getInterfaces();

+		assertEquals("Check interfaces number", itf.length, 1);

+		assertEquals("Check itf name", itf[0], "org.apache.felix.ipojo.test.scenarios.manipulation.service.FooService");

+

+        assertTrue("Check Foo Service implementation", manip.isInterfaceImplemented("org.apache.felix.ipojo.test.scenarios.manipulation.service.FooService"));

+        assertFalse("Check Bar Service implementation", manip.isInterfaceImplemented("org.apache.felix.ipojo.test.scenarios.manipulation.service.BarService"));

+	}

+

+	public void testInterfaces() {

+	    PojoMetadata manip = FooBarProviderType1;

+        String[] itf = manip.getInterfaces();

+		assertEquals("Check interfaces number", itf.length, 2);

+		assertEquals("Check itf name", itf[0], "org.apache.felix.ipojo.test.scenarios.manipulation.service.FooService");

+		assertEquals("Check itf name", itf[1], "org.apache.felix.ipojo.test.scenarios.manipulation.service.BarService");

+

+        assertTrue("Check Foo Service implementation", manip.isInterfaceImplemented("org.apache.felix.ipojo.test.scenarios.manipulation.service.FooService"));

+        assertTrue("Check Bar Service implementation", manip.isInterfaceImplemented("org.apache.felix.ipojo.test.scenarios.manipulation.service.BarService"));

+	}

+

+	public void testFields() {

+	    PojoMetadata manip = FooProviderTypeDyn;

+

+		FieldMetadata[] fields = manip.getFields();

+		assertEquals("Check field count + " + fields.length, fields.length, 5);

+		/*

+		private int intProp;

+		private String strProp;

+		private String[] strAProp;

+		private int[] intAProp;

+		private boolean boolProp;

+		 */

+

+		FieldMetadata field;

+

+		field = manip.getField("intProp");

+		assertEquals("Check field name : " + field.getFieldName(), field.getFieldName(), "intProp");

+		assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "int");

+        assertEquals("Check field reflective type : " + field.getFieldName(), FieldMetadata.getReflectionType(field.getFieldType()), "int");

+

+        field = manip.getField("intProp", "int");

+        assertEquals("Check field name : " + field.getFieldName(), field.getFieldName(), "intProp");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "int");

+

+        field = manip.getField("intProp", "long");

+        assertNull("Check bad field", field);

+

+		field = manip.getField("strProp");

+		assertEquals("Check field name : " + field.getFieldName(), field.getFieldName(), "strProp");

+		assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "java.lang.String");

+        assertEquals("Check field reflective type : " + field.getFieldName(), FieldMetadata.getReflectionType(field.getFieldType()), "java.lang.String");

+

+        field = manip.getField("strProp", "String");

+        assertNull("Check bad field", field);

+

+        field = manip.getField("strProp", "java.lang.String");

+        assertEquals("Check field name : " + field.getFieldName(), field.getFieldName(), "strProp");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "java.lang.String");

+

+		field = manip.getField("strAProp");

+		assertEquals("Check field name : " + field.getFieldName(), field.getFieldName(), "strAProp");

+		assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "java.lang.String[]");

+        assertEquals("Check field reflective type : " + field.getFieldName() + " -> " + FieldMetadata.getReflectionType(field.getFieldType()), FieldMetadata.getReflectionType(field.getFieldType()), "[Ljava.lang.String;");

+

+        field = manip.getField("strAProp", "java.lang.String[]");

+        assertEquals("Check field name : " + field.getFieldName(), field.getFieldName(), "strAProp");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "java.lang.String[]");

+

+        field = manip.getField("strAProp", "String[]");

+        assertNull("Check bad field", field);

+

+		field = manip.getField("intAProp");

+		assertEquals("Check field name : " + field.getFieldName(), field.getFieldName(), "intAProp");

+		assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "int[]");

+        assertEquals("Check field reflective type : " + field.getFieldName() + " -> " + FieldMetadata.getReflectionType(field.getFieldType()), FieldMetadata.getReflectionType(field.getFieldType()), "[I");

+

+        field = manip.getField("intAProp", "int[]");

+        assertEquals("Check field name : " + field.getFieldName(), field.getFieldName(), "intAProp");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "int[]");

+

+        field = manip.getField("intAProp", "String[]");

+        assertNull("Check bad field", field);

+

+		field = manip.getField("boolProp");

+		assertEquals("Check field name : " + field.getFieldName(), field.getFieldName(), "boolProp");

+		assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "boolean");

+        assertEquals("Check field reflective type : " + field.getFieldName(), FieldMetadata.getReflectionType(field.getFieldType()), "boolean");

+

+        field = manip.getField("boolProp", "boolean");

+        assertEquals("Check field name : " + field.getFieldName(), field.getFieldName(), "boolProp");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "boolean");

+

+        field = manip.getField("boolProp", "bool");

+        assertNull("Check bad field", field);

+	}

+

+	public void testPrimitivesFields() {

+	    PojoMetadata manip = PrimitiveManipulationTester;

+		FieldMetadata[] fields = manip.getFields();

+		assertEquals("Check field count", fields.length, 16);

+

+		FieldMetadata field;

+

+		field = manip.getField("b");

+		assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "byte");

+		field = manip.getField("s");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "short");

+		field = manip.getField("i");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "int");

+		field = manip.getField("l");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "long");

+		field = manip.getField("d");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "double");

+		field = manip.getField("f");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "float");

+		field = manip.getField("c");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "char");

+		field = manip.getField("bool");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "boolean");

+

+		field = manip.getField("bs");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "byte[]");

+		field = manip.getField("ss");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "short[]");

+		field = manip.getField("is");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "int[]");

+		field = manip.getField("ls");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "long[]");

+		field = manip.getField("ds");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "double[]");

+		field = manip.getField("fs");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "float[]");

+		field = manip.getField("cs");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "char[]");

+		field = manip.getField("bools");

+        assertEquals("Check field type : " + field.getFieldName(), field.getFieldType(), "boolean[]");

+	}

+

+	public void testNoArgMethod() {

+	    PojoMetadata manip = SimpleMultipleCheckServiceProvider;

+		MethodMetadata method = manip.getMethod("check");

+		assertEquals("Check no args", method.getMethodArguments().length, 0);

+		assertEquals("Check return", method.getMethodReturn(), "boolean");

+

+        method = manip.getMethod("check", new String[0]);

+        assertEquals("Check no args", method.getMethodArguments().length, 0);

+        assertEquals("Check return", method.getMethodReturn(), "boolean");

+	}

+

+	public void testOneArgsMethod() {

+	    PojoMetadata manip = SimpleMultipleCheckServiceProvider;

+        MethodMetadata method = manip.getMethods("refBind")[0];

+		assertEquals("Check args count", method.getMethodArguments().length, 1);

+        assertEquals("Check args", method.getMethodArguments()[0], "org.osgi.framework.ServiceReference");

+		assertEquals("Check return", method.getMethodReturn(), "void");

+

+        method = manip.getMethod("refBind", new String[] {"org.osgi.framework.ServiceReference"});

+        assertEquals("Check args count", method.getMethodArguments().length, 1);

+        assertEquals("Check args", method.getMethodArguments()[0], "org.osgi.framework.ServiceReference");

+        assertEquals("Check return", method.getMethodReturn(), "void");

+	}

+

+	public void testTwoArgsMethod() {

+	    PojoMetadata manip = SimpleMultipleCheckServiceProvider;

+        MethodMetadata method = manip.getMethods("doNothing")[0];

+        assertEquals("Check args count", 2, method.getMethodArguments().length);

+		assertEquals("Check args - 1", method.getMethodArguments()[0], "java.lang.Object");

+        assertEquals("Check args - 2", method.getMethodArguments()[1], "java.lang.String");

+		assertEquals("Check return", method.getMethodReturn(), "java.lang.Object");

+

+        method = manip.getMethod("doNothing", new String[] {"java.lang.Object", "java.lang.String"});

+        assertEquals("Check args count", 2, method.getMethodArguments().length);

+        assertEquals("Check args - 1", method.getMethodArguments()[0], "java.lang.Object");

+        assertEquals("Check args - 2", method.getMethodArguments()[1], "java.lang.String");

+        assertEquals("Check return", method.getMethodReturn(), "java.lang.Object");

+	}

+

+	public void testSuper() {

+		String comp_name = "org.apache.felix.ipojo.test.scenarios.component.Child";

+		PojoMetadata manip = getManipulationMetadataForComponent(comp_name);

+		assertEquals("org.apache.felix.ipojo.test.scenarios.component.Parent", manip.getSuperClass());

+		assertEquals(1, manip.getConstructors().length);

+	}

+

+	public void testConstructors() {

+		String comp_name = "org.apache.felix.ipojo.test.scenarios.component.Multiconstructor";

+		PojoMetadata manip = getManipulationMetadataForComponent(comp_name);

+		assertEquals(3, manip.getConstructors().length);

+		assertNotNull(manip.getConstructor(new String[] {String.class.getName(), String.class.getName()}));

+		assertNotNull(manip.getConstructor(new String[] {String.class.getName(), String.class.getName(), Integer.TYPE.getName()}));

+		assertNotNull(manip.getConstructor(new String[] {String.class.getName(), Integer.TYPE.getName()}));

+		assertNull(manip.getConstructor(new String[] {String.class.getName()}));

+	}

+

+

+	private Element getMetadataForComponent(Element metadata, String comp_name) {

+		Element[] comps = metadata.getElements("component");

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

+			if(comps[i].containsAttribute("factory") && comps[i].getAttribute("factory").equals(comp_name)) {

+				return comps[i];

+			}

+            if(comps[i].containsAttribute("name") && comps[i].getAttribute("name").equals(comp_name)) {

+                return comps[i];

+            }

+            if(comps[i].containsAttribute("classname") && comps[i].getAttribute("classname").equals(comp_name)) {

+                return comps[i];

+            }

+		}

+		return null;

+	}

+

+

+    private PojoMetadata getManipulationMetadataForComponent(String comp_name) {

+        Element elem = null;

+        try {

+            elem = ManifestMetadataParser.parseHeaderMetadata(header);

+        } catch (ParseException e) {

+            e.printStackTrace();

+            fail("Parse Exception when parsing iPOJO-Component " + e);

+        }

+

+        assertNotNull("Check elem not null", elem);

+

+        Element manip = getMetadataForComponent(elem, comp_name);

+        assertNotNull("Check manipulation metadata not null for " + comp_name, manip);

+        try {

+            return new PojoMetadata(manip);

+        } catch (ConfigurationException e) {

+            fail("The creation of pojo metadata for " + comp_name + " has failed");

+            return null;

+        }

+    }

+

+}

diff --git a/ipojo/core/src/test/resources/manipulation/MANIFEST.MF b/ipojo/core/src/test/resources/manipulation/MANIFEST.MF
new file mode 100644
index 0000000..4becd87
--- /dev/null
+++ b/ipojo/core/src/test/resources/manipulation/MANIFEST.MF
@@ -0,0 +1,142 @@
+Manifest-Version: 1.0

+Export-Package: org.apache.felix.ipojo.test.scenarios.manipulation.ser

+ vice

+iPOJO-Components: component { $name="ManipulationMetadata-FooProviderT

+ ype-1" $classname="org.apache.felix.ipojo.test.scenarios.component.Fo

+ oProviderType1" $architecture="true" provides { }manipulation { field

+  { $name="m_context" $type="org.osgi.framework.BundleContext" }field 

+ { $name="m_foo" $type="java.lang.String" }field { $name="m_bar" $type

+ ="int" }method { $arguments="{org.osgi.framework.BundleContext}" $nam

+ e="singleton" $return="org.apache.felix.ipojo.test.scenarios.componen

+ t.FooProviderType1" }method { $arguments="{org.osgi.framework.BundleC

+ ontext}" $name="several" $return="org.apache.felix.ipojo.test.scenari

+ os.component.FooProviderType1" }method { $arguments="{org.osgi.framew

+ ork.BundleContext}" $name="$init" }method { $name="foo" $return="bool

+ ean" }method { $name="fooProps" $return="java.util.Properties" }metho

+ d { $name="testException" }method { $name="testTry" }method { $argume

+ nts="{java.lang.String}" $name="testTry2" }method { $arguments="{java

+ .lang.String}" $name="nexttry" }method { $name="getBoolean" $return="

+ boolean" }method { $name="getDouble" $return="double" }method { $name

+ ="getInt" $return="int" }method { $name="getLong" $return="long" }met

+ hod { $name="getObject" $return="java.lang.Boolean" }method { $argume

+ nts="{int,java.lang.String,org.osgi.framework.BundleContext}" $name="

+ $init" }interface { $name="org.apache.felix.ipojo.test.scenarios.mani

+ pulation.service.FooService" }}}component { $name="ManipulationMetada

+ ta-FooBarProviderType-1" $classname="org.apache.felix.ipojo.test.scen

+ arios.component.FooBarProviderType1" $architecture="true" provides { 

+ }manipulation { method { $name="$init" }method { $name="foo" $return=

+ "boolean" }method { $name="fooProps" $return="java.util.Properties" }

+ method { $name="bar" $return="boolean" }method { $name="getProps" $re

+ turn="java.util.Properties" }method { $name="getBoolean" $return="boo

+ lean" }method { $name="getDouble" $return="double" }method { $name="g

+ etInt" $return="int" }method { $name="getLong" $return="long" }method

+  { $name="getObject" $return="java.lang.Boolean" }interface { $name="

+ org.apache.felix.ipojo.test.scenarios.manipulation.service.FooService

+ " }interface { $name="org.apache.felix.ipojo.test.scenarios.manipulat

+ ion.service.BarService" }}}component { $name="ManipulationMetadata-Fo

+ oProviderType-Dyn" $classname="org.apache.felix.ipojo.test.scenarios.

+ component.FooProviderTypeDyn" $architecture="true" provides { propert

+ y { $field="intProp" $mandatory="false" $name="int" $value="2" }prope

+ rty { $field="boolProp" $mandatory="false" $name="boolean" $value="fa

+ lse" }property { $field="strProp" $mandatory="false" $name="string" $

+ value="foo" }property { $field="strAProp" $mandatory="false" $name="s

+ trAProp" $value="[foo, bar]" }property { $field="intAProp" $mandatory

+ ="false" $name="intAProp" $value="[ 1,2,3]" }}manipulation { field { 

+ $name="boolProp" $type="boolean" }field { $name="strProp" $type="java

+ .lang.String" }field { $name="strAProp" $type="java.lang.String[]" }f

+ ield { $name="intProp" $type="int" }field { $name="intAProp" $type="i

+ nt[]" }method { $name="$init" }method { $name="foo" $return="boolean"

+  }method { $name="fooProps" $return="java.util.Properties" }method { 

+ $name="getBoolean" $return="boolean" }method { $name="getDouble" $ret

+ urn="double" }method { $name="getInt" $return="int" }method { $name="

+ getLong" $return="long" }method { $name="getObject" $return="java.lan

+ g.Boolean" }interface { $name="org.apache.felix.ipojo.test.scenarios.

+ manipulation.service.FooService" }}}component { $name="ManipulationMe

+ tadata-PrimitiveManipulationTester" $classname="org.apache.felix.ipoj

+ o.test.scenarios.component.Manipulation23Tester" $architecture="true"

+  provides { }manipulation { field { $name="f" $type="float" }field { 

+ $name="d" $type="double" }field { $name="is" $type="int[]" }field { $

+ name="bools" $type="boolean[]" }field { $name="b" $type="byte" }field

+  { $name="ls" $type="long[]" }field { $name="c" $type="char" }field {

+  $name="l" $type="long" }field { $name="bs" $type="byte[]" }field { $

+ name="cs" $type="char[]" }field { $name="i" $type="int" }field { $nam

+ e="s" $type="short" }field { $name="fs" $type="float[]" }field { $nam

+ e="ss" $type="short[]" }field { $name="bool" $type="boolean" }field {

+  $name="ds" $type="double[]" }method { $name="$init" }method { $name=

+ "getBoolean" $return="boolean" }method { $name="getBooleans" $return=

+ "boolean[]" }method { $name="getByte" $return="byte" }method { $name=

+ "getBytes" $return="byte[]" }method { $name="getChar" $return="char" 

+ }method { $name="getChars" $return="char[]" }method { $name="getDoubl

+ e" $return="double" }method { $name="getDoubles" $return="double[]" }

+ method { $name="getFloat" $return="float" }method { $name="getFloats"

+  $return="float[]" }method { $name="getInt" $return="int" }method { $

+ name="getInts" $return="int[]" }method { $name="getLong" $return="lon

+ g" }method { $name="getLongs" $return="long[]" }method { $name="getSh

+ ort" $return="short" }method { $name="getShorts" $return="short[]" }m

+ ethod { $arguments="{boolean}" $name="setBoolean" }method { $argument

+ s="{boolean[]}" $name="setBooleans" }method { $arguments="{byte}" $na

+ me="setByte" }method { $arguments="{byte[]}" $name="setBytes" }method

+  { $arguments="{char}" $name="setChar" }method { $arguments="{char[]}

+ " $name="setChars" }method { $arguments="{double}" $name="setDouble" 

+ }method { $arguments="{double[]}" $name="setDoubles" }method { $argum

+ ents="{float}" $name="setFloat" }method { $arguments="{float[]}" $nam

+ e="setFloats" }method { $arguments="{int}" $name="setInt" }method { $

+ arguments="{int[]}" $name="setInts" }method { $arguments="{long}" $na

+ me="setLong" }method { $arguments="{long[]}" $name="setLongs" }method

+  { $arguments="{short}" $name="setShort" }method { $arguments="{short

+ []}" $name="setShorts" }method { $arguments="{long,java.lang.String}"

+  $name="setLong" }interface { $name="org.apache.felix.ipojo.test.scen

+ arios.manipulation.service.PrimitiveManipulationTestService" }}}compo

+ nent { $name="ManipulationMetadata-SimpleMultipleCheckServiceProvider

+ " $classname="org.apache.felix.ipojo.test.scenarios.component.Multipl

+ eCheckService" $architecture="true" provides { }manipulation { field 

+ { $name="refU" $type="int" }field { $name="objectU" $type="int" }fiel

+ d { $name="bothB" $type="int" }field { $name="objectB" $type="int" }f

+ ield { $name="bothU" $type="int" }field { $name="fs" $type="org.apach

+ e.felix.ipojo.test.scenarios.manipulation.service.FooService[]" }fiel

+ d { $name="simpleU" $type="int" }field { $name="simpleB" $type="int" 

+ }field { $name="refB" $type="int" }method { $name="$init" }method { $

+ name="check" $return="boolean" }method { $name="getBoolean" $return="

+ boolean" }method { $name="getInt" $return="int" }method { $name="getL

+ ong" $return="long" }method { $name="getDouble" $return="double" }met

+ hod { $arguments="{java.lang.Object,java.lang.String}" $name="doNothi

+ ng" $return="java.lang.Object" }method { $name="getProps" $return="ja

+ va.util.Properties" }method { $name="voidBind" }method { $name="voidU

+ nbind" }method { $arguments="{org.apache.felix.ipojo.test.scenarios.m

+ anipulation.service.FooService}" $name="objectBind" }method { $argume

+ nts="{org.apache.felix.ipojo.test.scenarios.manipulation.service.FooS

+ ervice}" $name="objectUnbind" }method { $arguments="{org.osgi.framewo

+ rk.ServiceReference}" $name="refBind" }method { $arguments="{org.osgi

+ .framework.ServiceReference}" $name="refUnbind" }method { $arguments=

+ "{org.apache.felix.ipojo.test.scenarios.manipulation.service.FooServi

+ ce,org.osgi.framework.ServiceReference}" $name="bothBind" }method { $

+ arguments="{org.apache.felix.ipojo.test.scenarios.manipulation.servic

+ e.FooService,org.osgi.framework.ServiceReference}" $name="bothUnbind"

+  }interface { $name="org.apache.felix.ipojo.test.scenarios.manipulati

+ on.service.CheckService" }}requires { $field="fs" }}component { $clas

+ sname="org.apache.felix.ipojo.test.scenarios.component.Child" manipul

+ ation { $super="org.apache.felix.ipojo.test.scenarios.component.Paren

+ t" method { $arguments="{java.lang.String}" $name="$init" }}}componen

+ t { $classname="org.apache.felix.ipojo.test.scenarios.component.Multi

+ constructor" manipulation { method { $arguments="{java.lang.String,ja

+ va.lang.String}" $name="$init" }method { $arguments="{java.lang.Strin

+ g,int}" $name="$init" }method { $arguments="{java.lang.String,java.la

+ ng.String,int}" $name="$init" }}}

+Test-Suite: org.apache.felix.ipojo.test.scenarios.manipulation.Manipul

+ ationTestSuite

+Built-By: clement

+Tool: Bnd-0.0.357

+Bundle-Name: iPOJO Manipulation Metadata Test Suite

+Created-By: Apache Maven Bundle Plugin & iPOJO  1.6.0

+Build-Jdk: 1.6.0_22

+Bundle-Version: 1.5.0.SNAPSHOT

+Bnd-LastModified: 1292762858403

+Bundle-ManifestVersion: 2

+Import-Package: org.osgi.service.log;version=1.3, org.apache.felix.ipo

+ jo.test.scenarios.manipulation.service, org.apache.felix.ipojo.junit4

+ osgi, junit.framework, org.apache.felix.ipojo.architecture;version=1.

+ 6, org.apache.felix.ipojo;version=1.6, org.osgi.framework;version=1.5

+ , org.osgi.service.cm;version=1.2, org.apache.felix.ipojo.metadata, o

+ rg.apache.felix.ipojo.parser;version=1.6

+Bundle-SymbolicName: tests.manipulation.metadata

+

diff --git a/ipojo/manipulator/pom.xml b/ipojo/manipulator/pom.xml
index 5b0e68b..ea42af2 100644
--- a/ipojo/manipulator/pom.xml
+++ b/ipojo/manipulator/pom.xml
@@ -51,6 +51,11 @@
       <artifactId>org.apache.felix.ipojo.metadata</artifactId>
       <version>1.4.0</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.ipojo.annotations</artifactId>
+      <version>1.7.0-SNAPSHOT</version>
+    </dependency>
   </dependencies>
   <build>
     <plugins>
@@ -109,6 +114,16 @@
           <configLocation>http://felix.apache.org/ipojo/dev/checkstyle_ipojo.xml</configLocation>
         </configuration>
       </plugin>
+
+	<plugin>
+		<groupId>org.apache.maven.plugins</groupId>
+		<artifactId>maven-compiler-plugin</artifactId>
+		<configuration>
+			<source>1.5</source>
+			<target>1.5</target>
+		</configuration>
+	</plugin>
+
     </plugins>
 
     <resources>
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodCreator.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodCreator.java
index 41cca2f..7847464 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodCreator.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/MethodCreator.java
@@ -191,15 +191,14 @@
             newDesc = "(Lorg/apache/felix/ipojo/InstanceManager;" + newDesc;

 

             Type[] args = Type.getArgumentTypes(desc);

+

+            // TODO HERE ! => All constructor matches, no distinction between the different constructors.

+            generateConstructor(access, desc, signature, exceptions, md.getAnnotations(), md.getParameterAnnotations());

+

             if (args.length == 0) {

-                generateEmptyConstructor(access, signature, exceptions, md.getAnnotations()); // No parameters, so no annotations parameters

                 m_foundSuitableConstructor = true;

             } else if (args.length == 1 && args[0].getClassName().equals("org.osgi.framework.BundleContext")) {

-                generateBCConstructor(access, signature, exceptions, md.getAnnotations()); // One parameter, so no annotations parameters

                 m_foundSuitableConstructor = true;

-            } else {

-                // Do nothing, the constructor does not match.

-                return cv.visitMethod(access, name, desc, signature, exceptions);

             }

 

             // Insert the new constructor

@@ -297,64 +296,56 @@
     }

 

     /**

-     * Create a constructor to call the manipulated constructor.

-     * This constructor does not have any argument. It will call the manipulated

-     * constructor with a null instance manager.

+     * Modify the given constructor to be something like:

+     * <code>

+     * this(null, params...);

+     * return;

+     * </code>

+     * The actual constructor is modified to support the instance manager argument.

      * @param access : access flag

+     * @param descriptor : the original constructor descriptor

      * @param signature : method signature

      * @param exceptions : declared exception

      * @param annotations : the annotations to move to this constructor.

      */

-    private void generateEmptyConstructor(int access, String signature, String[] exceptions, List annotations) {

-        MethodVisitor mv = cv.visitMethod(access, "<init>", "()V", signature, exceptions);

-        mv.visitCode();

-        mv.visitVarInsn(ALOAD, 0);

-        mv.visitInsn(ACONST_NULL);

-        mv.visitMethodInsn(INVOKESPECIAL, m_owner, "<init>", "(Lorg/apache/felix/ipojo/InstanceManager;)V");

-        mv.visitInsn(RETURN);

+    private void generateConstructor(int access, String descriptor, String signature, String[] exceptions, List annotations, Map paramAnnotations) {

+         GeneratorAdapter mv = new GeneratorAdapter(

+        		 cv.visitMethod(access, "<init>", descriptor, signature, exceptions),

+        		 access, "<init>", descriptor);

+    	 // Compute the new signature

+    	 String newDesc = descriptor.substring(1); // Remove the first (

+         newDesc = "(Lorg/apache/felix/ipojo/InstanceManager;" + newDesc;

 

-        // Move annotations

-        if (annotations != null) {

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

-                AnnotationDescriptor ad = (AnnotationDescriptor) annotations.get(i);

-                ad.visitAnnotation(mv);

-            }

-        }

+         mv.visitCode();

+         mv.visitVarInsn(ALOAD, 0);

+         mv.visitInsn(ACONST_NULL);

+         mv.loadArgs();

+         mv.visitMethodInsn(INVOKESPECIAL, m_owner, "<init>", newDesc);

+         mv.visitInsn(RETURN);

 

-        mv.visitMaxs(0, 0);

-        mv.visitEnd();

-    }

+         // Move annotations

+         if (annotations != null) {

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

+                 AnnotationDescriptor ad = (AnnotationDescriptor) annotations.get(i);

+                 ad.visitAnnotation(mv);

+             }

+         }

 

-    /**

-     * Create a constructor to call the manipulated constructor.

-     * This constructor has one argument (the bundle context). It will call the manipulated

-     * constructor with a null instance manager.

-     * @param access : access flag

-     * @param signature : method signature

-     * @param exceptions : declared exception

-     * @param annotations : the annotations to move to this constructor.

-     */

-    private void generateBCConstructor(int access, String signature, String[] exceptions, List annotations) {

-        MethodVisitor mv = cv.visitMethod(access, "<init>", "(Lorg/osgi/framework/BundleContext;)V", signature, exceptions);

-        mv.visitCode();

-        Label l0 = new Label();

-        mv.visitLabel(l0);

-        mv.visitVarInsn(ALOAD, 0);

-        mv.visitInsn(ACONST_NULL);

-        mv.visitVarInsn(ALOAD, 1);

-        mv.visitMethodInsn(INVOKESPECIAL, m_owner, "<init>", "(Lorg/apache/felix/ipojo/InstanceManager;Lorg/osgi/framework/BundleContext;)V");

-        mv.visitInsn(RETURN);

+         // Move parameter annotations if any

+         if (paramAnnotations != null  && ! paramAnnotations.isEmpty()) {

+             Iterator ids = paramAnnotations.keySet().iterator();

+             while(ids.hasNext()) {

+                 Integer id = (Integer) ids.next();

+                 List ads = (List) paramAnnotations.get(id);

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

+                     AnnotationDescriptor ad = (AnnotationDescriptor) ads.get(i);

+                     ad.visitParameterAnnotation(id.intValue(), mv);

+                 }

+             }

+         }

 

-        // Move annotations

-        if (annotations != null) {

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

-                AnnotationDescriptor ad = (AnnotationDescriptor) annotations.get(i);

-                ad.visitAnnotation(mv);

-            }

-        }

-

-        mv.visitMaxs(0, 0);

-        mv.visitEnd();

+         mv.visitMaxs(0, 0);

+         mv.visitEnd();

     }

 

     /**

diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/CustomAnnotationVisitor.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/CustomAnnotationVisitor.java
index fdd3ba2..a5e9f45 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/CustomAnnotationVisitor.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/CustomAnnotationVisitor.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

@@ -23,6 +23,7 @@
 import org.apache.felix.ipojo.metadata.Attribute;

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

 import org.objectweb.asm.AnnotationVisitor;

+import org.objectweb.asm.Type;

 import org.objectweb.asm.commons.EmptyVisitor;

 

 /**

@@ -31,8 +32,6 @@
  */

 public class CustomAnnotationVisitor extends EmptyVisitor implements AnnotationVisitor {

 

-    //TODO manage enum annotations.

-    

     /**

      * Parent element.

      */

@@ -54,7 +53,7 @@
      * Is the custom annotation a first-order annotation.

      */

     private boolean m_root;

-    

+

     /**

      * Is the visit annotation a class annotation?

      */

@@ -64,7 +63,22 @@
      * Metadata collector.

      */

     private MetadataCollector m_collector;

-    

+

+    /**

+     * Flag sets to true for parameter annotation.

+     */

+    private boolean m_isParameterAnnotation = false;

+

+    /**

+     * For parameter annotations, the index of the parameter.

+     */

+    private int m_index = -1;

+

+    /**

+     * For parameter annotation, the descriptor of the method.

+     */

+    private String m_desc;

+

     /**

      * Constructor.

      * @param elem the parent element

@@ -78,7 +92,26 @@
         m_collector = collector;

         m_classAnnotation = clazz;

     }

-    

+

+    /**

+     * Constructor used for parameter annotations

+     * @param elem the parent element

+     * @param collector the metadata collector

+     * @param root is the annotation a root

+     * @param clazz the annotation is a class annotation.

+     * @param index the index of the argument

+     * @param the descriptor of the method

+     */

+    public CustomAnnotationVisitor(Element elem, MetadataCollector collector, boolean root, boolean clazz, int index, String descriptor) {

+        m_elem = elem;

+        m_root = root;

+        m_collector = collector;

+        m_classAnnotation = clazz;

+        m_isParameterAnnotation = true;

+        m_index = index;

+        m_desc = descriptor;

+    }

+

     /**

      * Check if the given annotation descriptor is an iPOJO custom annotation.

      * A valid iPOJO custom annotation must contains 'ipojo' or 'handler' in its qualified name.

@@ -92,7 +125,7 @@
         }

         return false;

     }

-    

+

     /**

      * Build the element object from the given descriptor.

      * @param desc : annotation descriptor

@@ -109,7 +142,7 @@
 

     /**

      * Visit a 'simple' annotation attribute.

-     * This method is used for primitive arrays too. 

+     * This method is used for primitive arrays too.

      * @param arg0 : attribute name

      * @param arg1 : attribute value

      * @see org.objectweb.asm.commons.EmptyVisitor#visit(java.lang.String, java.lang.Object)

@@ -164,7 +197,7 @@
     public AnnotationVisitor visitArray(String arg0) {

         return new SubArrayVisitor(m_elem, arg0);

     }

-    

+

     /**

      * Visits an enumeration attribute.

      * @param arg0 the attribute name

@@ -186,6 +219,7 @@
             if (m_id != null) {

                 m_collector.getIds().put(m_id, m_elem);

             } else {

+            	m_id = m_elem.getNameSpace();

                 if (! m_collector.getIds().containsKey(m_elem.getNameSpace()) && m_classAnnotation) {

                     // If the namespace is not already used, add the annotation as the

                     // root element of this namespace.

@@ -197,8 +231,15 @@
                     }

                 }

             }

-            

+

             m_collector.getElements().put(m_elem, m_parent);

+

+            if (m_isParameterAnnotation) {

+            	String t = Type.getArgumentTypes(m_desc)[m_index].getClassName();

+            	m_elem.addAttribute(new Attribute("type", t));

+            	m_elem.addAttribute(

+            			new Attribute("constructor-parameter", Integer.toString(m_index)));

+            }

         }

     }

 

diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java
index f3a4836..7c54269 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MetadataCollector.java
@@ -210,7 +210,7 @@
      * @see org.objectweb.asm.ClassAdapter#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
      */
     public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
-        return new MethodCollector(name, this);
+        return new MethodCollector(name, desc, this);
     }
 
     /**
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java
index 770316a..13ced4c 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/annotations/MethodCollector.java
@@ -18,6 +18,8 @@
  */
 package org.apache.felix.ipojo.manipulation.annotations;
 
+import java.awt.image.renderable.ParameterBlock;
+
 import org.apache.felix.ipojo.metadata.Attribute;
 import org.apache.felix.ipojo.metadata.Element;
 import org.objectweb.asm.AnnotationVisitor;
@@ -41,16 +43,47 @@
     private String m_name;
 
     /**
+     * Method Descriptor.
+     */
+    private String m_descriptor;
+
+    /**
      * Constructor.
      * @param name : name of the method.
      * @param collector : parent collector.
      */
-    public MethodCollector(String name, MetadataCollector collector) {
+    public MethodCollector(String name, String descriptor, MetadataCollector collector) {
         m_collector = collector;
         m_name = name;
+        m_descriptor = descriptor;
     }
 
     /**
+     * Visit a parameter annotation.
+     * @see org.objectweb.asm.commons.EmptyVisitor#visitParameterAnnotation(int, java.lang.String, boolean)
+     */
+    public AnnotationVisitor visitParameterAnnotation(int index, String annotation,
+			boolean visible) {
+    	if (m_name.equals("<init>")) {
+    		if (annotation.equals("Lorg/apache/felix/ipojo/annotations/Property;")) {
+                return processProperty(true, index);
+            }
+            if (annotation.equals("Lorg/apache/felix/ipojo/annotations/Requires;")) {
+                return new BindAnnotationParser(index);
+            }
+
+            if (CustomAnnotationVisitor.isCustomAnnotation(annotation)) {
+                Element elem = CustomAnnotationVisitor.buildElement(annotation);
+                elem.addAttribute(new Attribute("index", "" + index));
+                return new CustomAnnotationVisitor(elem, m_collector, true, false, index, m_descriptor);
+            }
+    	}
+    	return super.visitParameterAnnotation(index, annotation, visible);
+	}
+
+
+
+	/**
      * Visit method annotations.
      * @param arg0 : annotation name.
      * @param arg1 : is the annotation visible at runtime.
@@ -59,7 +92,7 @@
      */
     public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) {
         if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Property;")) {
-            return processProperty();
+            return processProperty(false, -1);
         }
         if (arg0.equals("Lorg/apache/felix/ipojo/annotations/Validate;")) {
             return processValidate();
@@ -181,9 +214,11 @@
 
     /**
      * Process @property annotation.
+     * @param parameter true if we're processing a parameter
+     * @param index the index, meaningful only if parameter is true
      * @return the visitor parsing the visited annotation.
      */
-    private AnnotationVisitor processProperty() {
+    private AnnotationVisitor processProperty(boolean parameter, int index) {
         Element prop = null;
         if (! m_collector.getIds().containsKey("properties")) {
             prop = new Element("Properties", "");
@@ -192,7 +227,7 @@
         } else {
             prop = (Element) m_collector.getIds().get("properties");
         }
-        return new PropertyAnnotationParser(prop, m_name);
+        return new PropertyAnnotationParser(prop, m_name, parameter, index);
     }
 
     /**
@@ -251,6 +286,12 @@
         private String m_from;
 
         /**
+         * For annotation parameter,
+         * the parameter index.
+         */
+        private int m_index = -1;
+
+        /**
          * Constructor.
          * @param bind : method name.
          * @param type : is the callback a bind or an unbind method.
@@ -260,6 +301,10 @@
             m_type = type;
         }
 
+        private BindAnnotationParser(int index) {
+        	m_index = index;
+        }
+
         /**
          * Visit annotation attribute.
          * @param arg0 : annotation name
@@ -310,17 +355,20 @@
          */
         public void visitEnd() {
             if (m_id == null) {
-                if (m_name.startsWith("bind")) {
+                if (m_name != null  && m_name.startsWith("bind")) {
                     m_id = m_name.substring("bind".length());
-                } else if (m_name.startsWith("unbind")) {
+                } else if (m_name != null  && m_name.startsWith("unbind")) {
                     m_id = m_name.substring("unbind".length());
-                } else if (m_name.startsWith("modified")) {
+                } else if (m_name != null  && m_name.startsWith("modified")) {
                 	m_id = m_name.substring("modified".length());
-                } else {
+                } else if (m_index != -1) {
+                	m_id = "" + m_index;
+            	} else {
                     System.err.println("Cannot determine the id of the " + m_type + " method : " + m_name);
                     return;
                 }
             }
+
             // Check if it is a full-determined requirement
             Element req = (Element) m_collector.getIds().get(m_id);
             if (req == null) {
@@ -422,17 +470,22 @@
                 }
 
             }
-            Element method = new Element("callback", "");
-            method.addAttribute(new Attribute("method", m_name));
-            method.addAttribute(new Attribute("type", m_type));
-            req.addElement(method);
+            if (m_name != null) {
+	            Element method = new Element("callback", "");
+	            method.addAttribute(new Attribute("method", m_name));
+	            method.addAttribute(new Attribute("type", m_type));
+	            req.addElement(method);
+            } else {
+            	req.addAttribute(new Attribute("constructor-parameter", Integer.toString(m_index)));
+            }
+
             m_collector.getIds().put(m_id, req);
             m_collector.getElements().put(req, null);
             return;
         }
     }
 
-    private static final class PropertyAnnotationParser extends EmptyVisitor implements AnnotationVisitor {
+    private final class PropertyAnnotationParser extends EmptyVisitor implements AnnotationVisitor {
 
         /**
          * Parent element.
@@ -450,6 +503,11 @@
         private String m_name;
 
         /**
+         * Property id.
+         */
+        private String m_id;
+
+        /**
          * Property value.
          */
         private String m_value;
@@ -460,13 +518,27 @@
         private String m_mandatory;
 
         /**
+         * Flag set to true if we're processing an annotation parameter.
+         */
+        private boolean m_isParameterAnnotation = false;
+
+        /**
+         * If this is a parameter annotation, the index of the parameter.
+         */
+        private int m_index = -1;
+
+        /**
          * Constructor.
          * @param parent : parent element.
          * @param method : attached method.
+         * @param param : we're processing a parameter
+         * @param index : the parameter index
          */
-        private PropertyAnnotationParser(Element parent, String method) {
+        private PropertyAnnotationParser(Element parent, String method, boolean param, int index) {
             m_parent = parent;
             m_method = method;
+            m_isParameterAnnotation = param;
+            m_index = index;
         }
 
         /**
@@ -488,6 +560,10 @@
                 m_mandatory = arg1.toString();
                 return;
             }
+            if (arg0.equals("id")) {
+                m_id = arg1.toString();
+                return;
+            }
         }
 
         /**
@@ -496,9 +572,17 @@
          * @see org.objectweb.asm.commons.EmptyVisitor#visitEnd()
          */
         public void visitEnd() {
-            if (m_name == null && m_method.startsWith("set")) {
+        	// If neither name not id, try to extract the name
+            if (m_name == null && m_id == null  && m_method.startsWith("set")) {
                 m_name = m_method.substring("set".length());
+                m_id = m_name;
+            // Else align the two values
+            } else if (m_name != null  && m_id == null) {
+            	m_id = m_name;
+            } else if (m_id != null  && m_name == null) {
+            	m_name = m_id;
             }
+
             Element[] props = m_parent.getElements("Property");
             Element prop = null;
             for (int i = 0; props != null && prop == null && i < props.length; i++) {
@@ -516,7 +600,6 @@
                 }
             }
 
-            prop.addAttribute(new Attribute("method", m_method));
             if (m_value != null) {
                 prop.addAttribute(new Attribute("value", m_value));
             }
@@ -524,6 +607,14 @@
                 prop.addAttribute(new Attribute("mandatory", m_mandatory));
             }
 
+            if (m_isParameterAnnotation) {
+            	String t = Type.getArgumentTypes(m_descriptor)[m_index].getClassName();
+            	prop.addAttribute(new Attribute("type", t));
+                prop.addAttribute(new Attribute("constructor-parameter", Integer.toString(m_index)));
+            } else {
+                prop.addAttribute(new Attribute("method", m_method));
+            }
+
         }
     }
 }
diff --git a/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/ComponentInstance.java b/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/ComponentInstance.java
new file mode 100644
index 0000000..a81dea8
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/ComponentInstance.java
@@ -0,0 +1,12 @@
+package org.apache.felix.ipojo;
+
+
+/**
+ * Component Instance Fake.
+ * We're using a fake to avoid the cyclic build dependency:
+ * manipulator -> ipojo -> maven-ipojo-plugin -> manipulator
+ */
+public interface ComponentInstance {
+
+
+}
diff --git a/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/InstanceManager.java b/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/InstanceManager.java
new file mode 100644
index 0000000..04281df
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/InstanceManager.java
@@ -0,0 +1,20 @@
+package org.apache.felix.ipojo;
+
+import java.util.Set;
+
+/**
+ * Instance Manager Fake.
+ * We're using a fake to avoid the cyclic build dependency:
+ * manipulator -> ipojo -> maven-ipojo-plugin -> manipulator
+ */
+public class InstanceManager {
+
+    public Set getRegistredFields() {
+        return null;
+    }
+
+    public Set getRegistredMethods() {
+        return null;
+    }
+
+}
diff --git a/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/Pojo.java b/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/Pojo.java
new file mode 100644
index 0000000..c7bcb59
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/Pojo.java
@@ -0,0 +1,10 @@
+package org.apache.felix.ipojo;
+
+/**
+ * POJO Interface fake.
+ * We're using a fake to avoid the cyclic build dependency:
+ * manipulator -> ipojo -> maven-ipojo-plugin -> manipulator
+ */
+public interface Pojo {
+
+}
diff --git a/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java b/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java
new file mode 100644
index 0000000..03576b1
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java
@@ -0,0 +1,335 @@
+package org.apache.felix.ipojo.manipulation;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.Pojo;
+import org.apache.felix.ipojo.manipulation.annotations.MetadataCollector;
+import org.mockito.Mockito;
+import org.objectweb.asm.ClassReader;
+
+public class ManipulatorTest extends TestCase {
+
+	public void testManipulatingTheSimplePojo() throws Exception {
+		Manipulator manipulator = new Manipulator();
+		byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/SimplePojo.class")));
+		TestClassLoader classloader = new TestClassLoader("test.SimplePojo", clazz);
+		Class cl = classloader.findClass("test.SimplePojo");
+		Assert.assertNotNull(cl);
+		Assert.assertNotNull(manipulator.getManipulationMetadata());
+
+		System.out.println(manipulator.getManipulationMetadata());
+
+		// The manipulation add stuff to the class.
+		Assert.assertTrue(clazz.length > getBytesFromFile(new File("target/test-classes/test/SimplePojo.class")).length);
+
+
+		boolean found = false;
+		Constructor cst = null;
+		Constructor[] csts = cl.getDeclaredConstructors();
+		for (int i = 0; i < csts.length; i++) {
+			System.out.println(Arrays.asList(csts[i].getParameterTypes()));
+			if (csts[i].getParameterTypes().length == 1  &&
+					csts[i].getParameterTypes()[0].equals(InstanceManager.class)) {
+				found = true;
+				cst = csts[i];
+			}
+		}
+		Assert.assertTrue(found);
+
+		// We still have the empty constructor
+		found = false;
+		csts = cl.getDeclaredConstructors();
+		for (int i = 0; i < csts.length; i++) {
+			System.out.println(Arrays.asList(csts[i].getParameterTypes()));
+			if (csts[i].getParameterTypes().length == 0) {
+				found = true;
+			}
+		}
+		Assert.assertTrue(found);
+
+		// Check the POJO interface
+		Assert.assertTrue(Arrays.asList(cl.getInterfaces()).contains(Pojo.class));
+
+		cst.setAccessible(true);
+		Object pojo = cst.newInstance(new Object[] {new InstanceManager()});
+		Assert.assertNotNull(pojo);
+		Assert.assertTrue(pojo instanceof Pojo);
+
+		Method method = cl.getMethod("doSomething", new Class[0]);
+		Assert.assertTrue(((Boolean) method.invoke(pojo, new Object[0])).booleanValue());
+
+	}
+
+	public void testManipulatingChild() throws Exception {
+		Manipulator manipulator = new Manipulator();
+		byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/Child.class")));
+		TestClassLoader classloader = new TestClassLoader("test.Child", clazz);
+		Class cl = classloader.findClass("test.Child");
+		Assert.assertNotNull(cl);
+		Assert.assertNotNull(manipulator.getManipulationMetadata());
+
+		boolean found = false;
+		Constructor cst = null;
+		Constructor[] csts = cl.getDeclaredConstructors();
+		for (int i = 0; i < csts.length; i++) {
+			System.out.println(Arrays.asList(csts[i].getParameterTypes()));
+			if (csts[i].getParameterTypes().length == 1  &&
+					csts[i].getParameterTypes()[0].equals(InstanceManager.class)) {
+				found = true;
+				cst = csts[i];
+			}
+		}
+		Assert.assertTrue(found);
+
+		// We still have the regular constructor
+		found = false;
+		csts = cl.getDeclaredConstructors();
+		for (int i = 0; i < csts.length; i++) {
+			System.out.println(Arrays.asList(csts[i].getParameterTypes()));
+			if (csts[i].getParameterTypes().length == 2) {
+				found = true;
+			}
+		}
+		Assert.assertTrue(found);
+
+		// Check the POJO interface
+		Assert.assertTrue(Arrays.asList(cl.getInterfaces()).contains(Pojo.class));
+
+		InstanceManager im = (InstanceManager) Mockito.mock(InstanceManager.class);
+		cst.setAccessible(true);
+		Object pojo = cst.newInstance(new Object[] {im});
+		Assert.assertNotNull(pojo);
+		Assert.assertTrue(pojo instanceof Pojo);
+
+		Method method = cl.getMethod("doSomething", new Class[0]);
+		Assert.assertEquals(9, ((Integer) method.invoke(pojo, new Object[0])).intValue());
+
+	}
+
+	public void testManipulatingTheInner() throws Exception {
+		Manipulator manipulator = new Manipulator();
+		byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/PojoWithInner.class")));
+		TestClassLoader classloader = new TestClassLoader("test.PojoWithInner", clazz);
+		Class cl = classloader.findClass("test.PojoWithInner");
+		Assert.assertNotNull(cl);
+		Assert.assertNotNull(manipulator.getManipulationMetadata());
+		Assert.assertFalse(manipulator.getInnerClasses().isEmpty());
+
+
+		System.out.println(manipulator.getManipulationMetadata());
+
+		// The manipulation add stuff to the class.
+		Assert.assertTrue(clazz.length > getBytesFromFile(new File("target/test-classes/test/PojoWithInner.class")).length);
+
+
+		boolean found = false;
+		Constructor cst = null;
+		Constructor[] csts = cl.getDeclaredConstructors();
+		for (int i = 0; i < csts.length; i++) {
+			System.out.println(Arrays.asList(csts[i].getParameterTypes()));
+			if (csts[i].getParameterTypes().length == 1  &&
+					csts[i].getParameterTypes()[0].equals(InstanceManager.class)) {
+				found = true;
+				cst = csts[i];
+			}
+		}
+		Assert.assertTrue(found);
+
+		// We still have the empty constructor
+		found = false;
+		csts = cl.getDeclaredConstructors();
+		for (int i = 0; i < csts.length; i++) {
+			System.out.println(Arrays.asList(csts[i].getParameterTypes()));
+			if (csts[i].getParameterTypes().length == 0) {
+				found = true;
+			}
+		}
+		Assert.assertTrue(found);
+
+		// Check the POJO interface
+		Assert.assertTrue(Arrays.asList(cl.getInterfaces()).contains(Pojo.class));
+
+		InstanceManager im = (InstanceManager) Mockito.mock(InstanceManager.class);
+		cst.setAccessible(true);
+		Object pojo = cst.newInstance(new Object[] {im});
+		Assert.assertNotNull(pojo);
+		Assert.assertTrue(pojo instanceof Pojo);
+
+		Method method = cl.getMethod("doSomething", new Class[0]);
+		Assert.assertTrue(((Boolean) method.invoke(pojo, new Object[0])).booleanValue());
+
+	}
+
+	public void testManipulatingWithConstructorModification() throws Exception {
+		Manipulator manipulator = new Manipulator();
+		byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/Child.class")));
+		TestClassLoader classloader = new TestClassLoader("test.Child", clazz);
+		Class cl = classloader.findClass("test.Child");
+		Assert.assertNotNull(cl);
+		Assert.assertNotNull(manipulator.getManipulationMetadata());
+
+		boolean found = false;
+		Constructor cst = null;
+		Constructor[] csts = cl.getDeclaredConstructors();
+		for (int i = 0; i < csts.length; i++) {
+			System.out.println(Arrays.asList(csts[i].getParameterTypes()));
+			if (csts[i].getParameterTypes().length == 1  &&
+					csts[i].getParameterTypes()[0].equals(InstanceManager.class)) {
+				found = true;
+				cst = csts[i];
+			}
+		}
+		Assert.assertTrue(found);
+
+		// We still have the regular constructor
+		found = false;
+		csts = cl.getDeclaredConstructors();
+		for (int i = 0; i < csts.length; i++) {
+			System.out.println(Arrays.asList(csts[i].getParameterTypes()));
+			if (csts[i].getParameterTypes().length == 2) {
+				found = true;
+			}
+		}
+		Assert.assertTrue(found);
+
+		// Check that we have the IM, Integer, String constructor too
+		Constructor cst2 = cl.getDeclaredConstructor(new Class[] { InstanceManager.class, Integer.TYPE, String.class });
+		Assert.assertNotNull(cst2);
+
+		// Check the POJO interface
+		Assert.assertTrue(Arrays.asList(cl.getInterfaces()).contains(Pojo.class));
+
+
+		// Creation using cst
+		InstanceManager im = (InstanceManager) Mockito.mock(InstanceManager.class);
+		cst.setAccessible(true);
+		Object pojo = cst.newInstance(new Object[] {im});
+		Assert.assertNotNull(pojo);
+		Assert.assertTrue(pojo instanceof Pojo);
+
+		Method method = cl.getMethod("doSomething", new Class[0]);
+		Assert.assertEquals(9, ((Integer) method.invoke(pojo, new Object[0])).intValue());
+
+		// Try to create using cst2
+		im = (InstanceManager) Mockito.mock(InstanceManager.class);
+		cst2.setAccessible(true);
+		pojo = cst2.newInstance(new Object[] {im, new Integer(2), "bariton"});
+		Assert.assertNotNull(pojo);
+		Assert.assertTrue(pojo instanceof Pojo);
+
+		method = cl.getMethod("doSomething", new Class[0]);
+		Assert.assertEquals(10, ((Integer) method.invoke(pojo, new Object[0])).intValue());
+
+
+
+	}
+
+
+	public void testManipulatingWithNoValidConstructor() throws Exception {
+		Manipulator manipulator = new Manipulator();
+		byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/NoValidConstructor.class")));
+		TestClassLoader classloader = new TestClassLoader("test.NoValidConstructor", clazz);
+		Class cl = classloader.findClass("test.NoValidConstructor");
+		Assert.assertNotNull(cl);
+		Assert.assertNotNull(manipulator.getManipulationMetadata());
+
+		System.out.println(manipulator.getManipulationMetadata());
+
+		// The manipulation add stuff to the class.
+		Assert.assertTrue(clazz.length > getBytesFromFile(new File("target/test-classes/test/NoValidConstructor.class")).length);
+
+
+		boolean found = false;
+		Constructor cst = null;
+		Constructor[] csts = cl.getDeclaredConstructors();
+		for (int i = 0; i < csts.length; i++) {
+			System.out.println(Arrays.asList(csts[i].getParameterTypes()));
+			if (csts[i].getParameterTypes().length == 1  &&
+					csts[i].getParameterTypes()[0].equals(InstanceManager.class)) {
+				found = true;
+				cst = csts[i];
+			}
+		}
+		Assert.assertTrue(found);
+
+		// Check the POJO interface
+		Assert.assertTrue(Arrays.asList(cl.getInterfaces()).contains(Pojo.class));
+
+		cst.setAccessible(true);
+		Object pojo = cst.newInstance(new Object[] {new InstanceManager()});
+		Assert.assertNotNull(pojo);
+		Assert.assertTrue(pojo instanceof Pojo);
+
+	}
+
+	public void test() throws Exception {
+
+
+		byte[] clazz = getBytesFromFile(new File("target/test-classes/test/Constructor.class"));
+		ClassReader cr = new ClassReader(clazz);
+        MetadataCollector collector = new MetadataCollector();
+        cr.accept(collector, 0);
+
+        System.out.println(collector.getComponentTypeDeclaration());
+
+	}
+
+	public static byte[] getBytesFromFile(File file) throws IOException {
+	    InputStream is = new FileInputStream(file);
+	    long length = file.length();
+	    byte[] bytes = new byte[(int)length];
+
+	    // Read in the bytes
+	    int offset = 0;
+	    int numRead = 0;
+	    while (offset < bytes.length
+	           && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
+	        offset += numRead;
+	    }
+
+	    // Ensure all the bytes have been read in
+	    if (offset < bytes.length) {
+	        throw new IOException("Could not completely read file "+file.getName());
+	    }
+
+	    // Close the input stream and return bytes
+	    is.close();
+	    return bytes;
+	}
+
+	class TestClassLoader extends ClassLoader {
+
+		private String name;
+		private byte[] clazz;
+
+		public TestClassLoader(String name, byte[] clazz) {
+			this.name = name;
+			this.clazz = clazz;
+		}
+
+        public Class findClass(String name) throws ClassNotFoundException {
+        	if (name.equals(this.name)) {
+	            return defineClass(name, clazz, 0, clazz.length);
+        	}
+        	return super.findClass(name);
+        }
+
+		public Class loadClass(String arg0) throws ClassNotFoundException {
+			return super.loadClass(arg0);
+		}
+
+
+
+    }
+
+}
diff --git a/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/PojoizationTest.java b/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/PojoizationTest.java
new file mode 100644
index 0000000..68d4b5e
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/PojoizationTest.java
@@ -0,0 +1,43 @@
+package org.apache.felix.ipojo.manipulation;
+
+import java.io.File;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.felix.ipojo.manipulator.Pojoization;
+
+public class PojoizationTest extends TestCase {
+
+	public void testJarManipulation() {
+		Pojoization pojoization = new Pojoization();
+		File in = new File("target/test-classes/tests.manipulation-no-annotations.jar");
+		File out = new File("target/test-classes/tests.manipulation-no-annotations-manipulated.jar");
+		out.delete();
+		File metadata = new File("target/test-classes/metadata.xml");
+		pojoization.pojoization(in, out, metadata);
+
+		Assert.assertTrue(out.exists());
+	}
+
+	public void testManipulationWithAnnotations() {
+		Pojoization pojoization = new Pojoization();
+		File in = new File("target/test-classes/tests.manipulator-annotations.jar");
+		File out = new File("target/test-classes/tests.manipulation-annotations-manipulated.jar");
+		out.delete();
+		pojoization.pojoization(in, out, (File) null);
+
+		Assert.assertTrue(out.exists());
+	}
+
+	public void testJarManipulationJava5() {
+		Pojoization pojoization = new Pojoization();
+		File in = new File("target/test-classes/tests.manipulation.java5.jar");
+		File out = new File("target/test-classes/tests.manipulation.java5-manipulated.jar");
+		out.delete();
+		pojoization.pojoization(in, out, (File) null);
+
+		Assert.assertTrue(out.exists());
+	}
+
+}
diff --git a/ipojo/manipulator/src/test/java/test/Child.java b/ipojo/manipulator/src/test/java/test/Child.java
new file mode 100644
index 0000000..1eda305
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/test/Child.java
@@ -0,0 +1,17 @@
+package test;
+
+public class Child extends Parent {
+
+	Child(int i, String f) {
+		super(i, f);
+	}
+
+	Child() {
+		super(5, "foo");
+	}
+
+	public int doSomething() {
+		return getIndex() + 1; // 9
+	}
+
+}
diff --git a/ipojo/manipulator/src/test/java/test/Constructor.java b/ipojo/manipulator/src/test/java/test/Constructor.java
new file mode 100644
index 0000000..ccbaebe
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/test/Constructor.java
@@ -0,0 +1,15 @@
+package test;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Property;
+import org.apache.felix.ipojo.annotations.Requires;
+
+@Component
+public class Constructor {
+
+	public Constructor(@Property(name="foo") String s, @Requires(id="t") Thread t) {
+		// plop
+
+	}
+
+}
diff --git a/ipojo/manipulator/src/test/java/test/NoValidConstructor.java b/ipojo/manipulator/src/test/java/test/NoValidConstructor.java
new file mode 100644
index 0000000..45d52cb
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/test/NoValidConstructor.java
@@ -0,0 +1,15 @@
+package test;
+
+public class NoValidConstructor {
+
+	String m_s;
+
+	public NoValidConstructor(String s) {
+		m_s = s;
+	}
+
+	public String getS() {
+		return m_s;
+	}
+
+}
diff --git a/ipojo/manipulator/src/test/java/test/Parent.java b/ipojo/manipulator/src/test/java/test/Parent.java
new file mode 100644
index 0000000..51ac622
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/test/Parent.java
@@ -0,0 +1,15 @@
+package test;
+
+public class Parent {
+
+	private int m_index = 0;
+
+	public Parent(int i, String s) {
+		m_index = i + s.length();
+	}
+
+	public int getIndex() {
+		return m_index;
+	}
+
+}
diff --git a/ipojo/manipulator/src/test/java/test/PojoWithInner.java b/ipojo/manipulator/src/test/java/test/PojoWithInner.java
new file mode 100644
index 0000000..ac5a052
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/test/PojoWithInner.java
@@ -0,0 +1,21 @@
+package test;
+
+public class PojoWithInner {
+
+	private MyInner m_result = new MyInner();
+
+	// This is a simple POJO
+
+	public boolean doSomething() {
+		return m_result.getInner();
+	}
+
+	public class MyInner {
+
+		public boolean getInner() {
+			return true;
+		}
+
+	}
+
+}
diff --git a/ipojo/manipulator/src/test/java/test/SimplePojo.java b/ipojo/manipulator/src/test/java/test/SimplePojo.java
new file mode 100644
index 0000000..3c1d6fa
--- /dev/null
+++ b/ipojo/manipulator/src/test/java/test/SimplePojo.java
@@ -0,0 +1,13 @@
+package test;
+
+public class SimplePojo {
+
+	private boolean m_result = true;
+
+	// This is a simple POJO
+
+	public boolean doSomething() {
+		return m_result;
+	}
+
+}
diff --git a/ipojo/manipulator/src/test/resources/metadata.xml b/ipojo/manipulator/src/test/resources/metadata.xml
new file mode 100644
index 0000000..b3e0262
--- /dev/null
+++ b/ipojo/manipulator/src/test/resources/metadata.xml
@@ -0,0 +1,37 @@
+<ipojo

+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

+    xsi:schemaLocation="org.apache.felix.ipojo http://felix.apache.org/ipojo/schemas/SNAPSHOT/core.xsd"

+    xmlns="org.apache.felix.ipojo"

+>

+	<!-- Simple provider  used for manipulation analysis -->

+	<component

+		classname="org.apache.felix.ipojo.test.scenarios.component.FooProviderType1"

+		name="Manipulation-FooProviderType-1" architecture="true">

+		<provides />

+	</component>

+	

+	<!-- Non lazzy service provider, to check instantiation -->

+	<component

+		classname="org.apache.felix.ipojo.test.scenarios.component.FooProviderType1"

+		name="Manipulation-ImmediateFooProviderType" immediate="true"

+		architecture="true">

+		<provides />

+	</component>

+	

+	<!-- Nested & Inner classes -->

+	<component name="inners" classname="org.apache.felix.ipojo.test.scenarios.component.InnerClasses">

+		<provides>

+			<property field="privateObject"/>

+			<property field="privateInt"/>

+			

+			<property field="protectedObject"/>

+			<property field="protectedInt"/>

+			

+			<property field="packageObject"/>

+			<property field="packageInt"/>

+			

+			<property field="publicObject"/>

+			<property field="publicInt"/>

+		</provides>

+	</component>

+</ipojo>

diff --git a/ipojo/manipulator/src/test/resources/tests.manipulation-no-annotations.jar b/ipojo/manipulator/src/test/resources/tests.manipulation-no-annotations.jar
new file mode 100644
index 0000000..a701fc0
--- /dev/null
+++ b/ipojo/manipulator/src/test/resources/tests.manipulation-no-annotations.jar
Binary files differ
diff --git a/ipojo/manipulator/src/test/resources/tests.manipulation.java5.jar b/ipojo/manipulator/src/test/resources/tests.manipulation.java5.jar
new file mode 100644
index 0000000..456e356
--- /dev/null
+++ b/ipojo/manipulator/src/test/resources/tests.manipulation.java5.jar
Binary files differ
diff --git a/ipojo/manipulator/src/test/resources/tests.manipulator-annotations.jar b/ipojo/manipulator/src/test/resources/tests.manipulator-annotations.jar
new file mode 100644
index 0000000..45322aa
--- /dev/null
+++ b/ipojo/manipulator/src/test/resources/tests.manipulator-annotations.jar
Binary files differ
diff --git a/ipojo/tests/manipulator/metadata/src/main/java/org/apache/felix/ipojo/test/scenarios/component/Child.java b/ipojo/tests/manipulator/metadata/src/main/java/org/apache/felix/ipojo/test/scenarios/component/Child.java
new file mode 100644
index 0000000..bc1e310
--- /dev/null
+++ b/ipojo/tests/manipulator/metadata/src/main/java/org/apache/felix/ipojo/test/scenarios/component/Child.java
@@ -0,0 +1,9 @@
+package org.apache.felix.ipojo.test.scenarios.component;
+
+public class Child extends Parent {
+
+	public Child(String s) {
+		super(s);
+	}
+
+}
diff --git a/ipojo/tests/manipulator/metadata/src/main/java/org/apache/felix/ipojo/test/scenarios/component/Multiconstructor.java b/ipojo/tests/manipulator/metadata/src/main/java/org/apache/felix/ipojo/test/scenarios/component/Multiconstructor.java
new file mode 100644
index 0000000..e9a51af
--- /dev/null
+++ b/ipojo/tests/manipulator/metadata/src/main/java/org/apache/felix/ipojo/test/scenarios/component/Multiconstructor.java
@@ -0,0 +1,17 @@
+package org.apache.felix.ipojo.test.scenarios.component;
+
+public class Multiconstructor {
+
+	public Multiconstructor(String s1, String s2) {
+		this(s1, s2, -1);
+	}
+
+	public Multiconstructor(String s1, int s2) {
+		this(s1, "" + s2, s2);
+	}
+
+	public Multiconstructor(String s1, String s2, int i) {
+		//...
+	}
+
+}
diff --git a/ipojo/tests/manipulator/metadata/src/main/java/org/apache/felix/ipojo/test/scenarios/component/Parent.java b/ipojo/tests/manipulator/metadata/src/main/java/org/apache/felix/ipojo/test/scenarios/component/Parent.java
new file mode 100644
index 0000000..feaaff1
--- /dev/null
+++ b/ipojo/tests/manipulator/metadata/src/main/java/org/apache/felix/ipojo/test/scenarios/component/Parent.java
@@ -0,0 +1,15 @@
+package org.apache.felix.ipojo.test.scenarios.component;
+
+public class Parent {
+
+	private String s;
+
+	public Parent(String s) {
+		this.s = s;
+	}
+
+	public String getS() {
+		return s;
+	}
+
+}
diff --git a/ipojo/tests/manipulator/metadata/src/main/resources/metadata.xml b/ipojo/tests/manipulator/metadata/src/main/resources/metadata.xml
index 6641a4b..3e0d95e 100644
--- a/ipojo/tests/manipulator/metadata/src/main/resources/metadata.xml
+++ b/ipojo/tests/manipulator/metadata/src/main/resources/metadata.xml
@@ -9,14 +9,14 @@
 		name="ManipulationMetadata-FooProviderType-1" architecture="true">

 		<provides />

 	</component>

-	

+

 	<!-- Provider providing 2 services -->

 	<component

 		classname="org.apache.felix.ipojo.test.scenarios.component.FooBarProviderType1"

 		name="ManipulationMetadata-FooBarProviderType-1" architecture="true">

 		<provides />

 	</component>

-	

+

 	<!-- Provider with dynamic property -->

 	<component

 		classname="org.apache.felix.ipojo.test.scenarios.component.FooProviderTypeDyn"

@@ -30,7 +30,7 @@
 			<property name="intAProp" field="intAProp" value="[ 1,2,3]" />

 		</provides>

 	</component>

-	

+

 	<!-- Manipulation -->

 	<component

 		classname="org.apache.felix.ipojo.test.scenarios.component.Manipulation23Tester"

@@ -38,11 +38,20 @@
 		<provides />

 	</component>

 

-	

+

 	<component

 		classname="org.apache.felix.ipojo.test.scenarios.component.MultipleCheckService"

 		name="ManipulationMetadata-SimpleMultipleCheckServiceProvider" architecture="true">

 		<requires field="fs" />

 		<provides />

 	</component>

+

+

+	<component

+		classname="org.apache.felix.ipojo.test.scenarios.component.Child">

+	</component>

+

+	<component

+		classname="org.apache.felix.ipojo.test.scenarios.component.Multiconstructor">

+    </component>

 </ipojo>