Patched code to remove use of a static component manager to support
component factories (FELIX-99).


git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@425681 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/PreprocessClassAdapter.java b/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/PreprocessClassAdapter.java
index 42955e2..454d618 100644
--- a/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/PreprocessClassAdapter.java
+++ b/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/PreprocessClassAdapter.java
@@ -31,10 +31,10 @@
 
 /**
  * Manipulate the class.
- * - Add a static component manager field (_cm) ok
- * - Create getter and setter for each fields ok
- * - Store information about field ok
- * - Store information about implemented interfaces ok
+ * - Add a component manager field (_cm) 
+ * - Create getter and setter for each fields 
+ * - Store information about field
+ * - Store information about implemented interfaces
  * - Change GETFIELD and PUTFIELD to called the getter and setter method
  * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
  *
@@ -89,8 +89,9 @@
             m_owner = name;
 
             // Insert _cm field
-            super.visitField(ACC_PRIVATE + ACC_STATIC, "_cm", ManipulationProperty.IPOJO_INTERNAL_DESCRIPTOR + "ComponentManager;", null, null);
-
+            FieldVisitor fv = super.visitField(ACC_PRIVATE, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;", null, null);
+            fv.visitEnd();
+            
             // Create the _cmSetter(ComponentManager cm) method
             createComponentManagerSetter();
 
@@ -99,6 +100,7 @@
 
             super.visit(version, access, name, signature, superName, interfaces);
         }
+        
 
         /** visit method method :-).
          * @see org.objectweb.asm.ClassVisitor#visitMethod(int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
@@ -115,28 +117,39 @@
                 final String desc,
                 final String signature,
                 final String[] exceptions) {
-            MethodVisitor mv = cv.visitMethod(access,
-                    name,
-                    desc,
-                    signature,
-                    exceptions);
+        	// The method is a constructor, adapt the constructor to add a ComponentManager argument
+        	if(name.equals("<init>")) {
+        		// 1) change the constructor descriptor (add a component manager arg as first argument)
+        		String new_desc = desc.substring(1);
+        		new_desc = "(Lorg/apache/felix/ipojo/ComponentManager;"+new_desc;
+        		
+        		// Insert the new constructor
+        		MethodVisitor mv = super.visitMethod(ACC_PUBLIC, "<init>", new_desc, null, null);
 
-            if (mv == null) { return null; }
-            else { return new PreprocessCodeAdapter(mv, m_owner); }
+        		if (mv == null) { return null; }
+        		else {return new ConstructorCodeAdapter(mv, m_owner); } 
+
+            }     
+            else {
+            	 MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
+            	 if (mv == null) { return null; }
+            	 else {return new PreprocessCodeAdapter(mv, m_owner); }
+            	}
 
         }
 
         /**
          * Create the setter method for the _cm field.
-         * The generated method must be called only one time.
          */
-        private void createComponentManagerSetter() {
-            MethodVisitor mv = super.visitMethod(ACC_PRIVATE + ACC_STATIC, "setComponentManager", "(" + ManipulationProperty.IPOJO_INTERNAL_DESCRIPTOR + "ComponentManager;)V", null, null);
-
+        private void createComponentManagerSetter() {            
+            MethodVisitor mv = cv.visitMethod(ACC_PRIVATE, "_setComponentManager", "(Lorg/apache/felix/ipojo/ComponentManager;)V", null, null);
+            
             mv.visitVarInsn(ALOAD, 0);
-            mv.visitFieldInsn(PUTSTATIC, m_owner, "_cm", ManipulationProperty.IPOJO_INTERNAL_DESCRIPTOR + "ComponentManager;");
+            mv.visitVarInsn(ALOAD, 1);
+            mv.visitFieldInsn(PUTFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
+            
             mv.visitInsn(RETURN);
-
+           
             mv.visitMaxs(0, 0);
             mv.visitEnd();
         }
@@ -174,7 +187,6 @@
                     		m_fields.put(name, nameType);
                     	}
 
-                    	// TODO : Getter & SETTER on array :
                         String gDesc = "()" + desc;
                     	createArrayGetter(name, gDesc, type);
 
@@ -212,7 +224,8 @@
         	mv.visitVarInsn(ALOAD, 1);
         	mv.visitFieldInsn(PUTFIELD, m_owner, name, internalType);
 
-        	mv.visitFieldInsn(GETSTATIC, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
+        	mv.visitVarInsn(ALOAD, 0);
+        	mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
         	mv.visitLdcInsn(name);
         	mv.visitVarInsn(ALOAD, 1);
         	mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/ComponentManager", "setterCallback", "(Ljava/lang/String;Ljava/lang/Object;)V");
@@ -244,8 +257,9 @@
             	//mv.visitFieldInsn(GETFIELD, m_owner, name, "["+type.getInternalName()+";");
             	mv.visitFieldInsn(GETFIELD, m_owner, name, internalType);
             	mv.visitVarInsn(ASTORE, 1);
-
-            	mv.visitFieldInsn(GETSTATIC, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
+            	
+            	mv.visitVarInsn(ALOAD, 0);
+            	mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
             	mv.visitLdcInsn(name);
             	mv.visitVarInsn(ALOAD, 1);
             	mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/ComponentManager", "getterCallback", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;");
@@ -318,7 +332,8 @@
             		mv.visitMethodInsn(INVOKESPECIAL, boxingType, "<init>", "(" + internalName + ")V");
             		mv.visitVarInsn(ASTORE, 2);
 
-            		mv.visitFieldInsn(GETSTATIC, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
+            		mv.visitVarInsn(ALOAD, 0);
+            		mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
             		mv.visitLdcInsn(name);
             		mv.visitVarInsn(ALOAD, 2);
             		mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/ComponentManager", "getterCallback", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;");
@@ -357,7 +372,8 @@
             		mv.visitFieldInsn(GETFIELD, m_owner, name, "L" + type.getInternalName() + ";");
             		mv.visitVarInsn(ASTORE, 1);
 
-            		mv.visitFieldInsn(GETSTATIC, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
+            		mv.visitVarInsn(ALOAD, 0);
+            		mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
             		mv.visitLdcInsn(name);
             		mv.visitVarInsn(ALOAD, 1);
             		mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/ComponentManager", "getterCallback", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;");
@@ -437,7 +453,8 @@
 
                 	Label l2 = new Label();
                 	mv.visitLabel(l2);
-                	mv.visitFieldInsn(GETSTATIC, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
+                	mv.visitVarInsn(ALOAD, 0);
+                	mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
                 	mv.visitLdcInsn(name);
                 	mv.visitVarInsn(ALOAD, 2);
                 	mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/ComponentManager", "setterCallback", "(Ljava/lang/String;Ljava/lang/Object;)V");
@@ -452,7 +469,8 @@
                 	mv.visitVarInsn(ALOAD, 1);
                 	mv.visitFieldInsn(PUTFIELD, m_owner, name, "L" + type.getInternalName() + ";");
 
-                	mv.visitFieldInsn(GETSTATIC, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
+                	mv.visitVarInsn(ALOAD, 0);
+                	mv.visitFieldInsn(GETFIELD, m_owner, "_cm", "Lorg/apache/felix/ipojo/ComponentManager;");
                 	mv.visitLdcInsn(name);
                 	mv.visitVarInsn(ALOAD, 1);
                 	mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/ComponentManager", "setterCallback", "(Ljava/lang/String;Ljava/lang/Object;)V");
diff --git a/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/PreprocessCodeAdapter.java b/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/PreprocessCodeAdapter.java
index c547242..bea6444 100644
--- a/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/PreprocessCodeAdapter.java
+++ b/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/PreprocessCodeAdapter.java
@@ -65,7 +65,6 @@
                     return;
             } else
             	if (opcode == PUTFIELD) {
-            		// replaces PUTFIELD f by INVOKESPECIAL _setf
             		IPojoPluginConfiguration.getLogger().log(Level.INFO, "Manipulate a PUTFIELD on : " + name);
             		String sDesc = "(" + desc + ")V";
             		visitMethodInsn(INVOKESPECIAL, owner, "_set" + name, sDesc);
@@ -74,5 +73,6 @@
         }
         super.visitFieldInsn(opcode, owner, name, desc);
     }
+    
 }
 
diff --git a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManager.java b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManager.java
index f513b47..8a0c4d8 100644
--- a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManager.java
+++ b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/ComponentManager.java
@@ -18,7 +18,6 @@
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.logging.Level;
 
 import org.apache.felix.ipojo.metadata.Element;
@@ -305,23 +304,17 @@
 	 * @return a new instance
 	 */
 	public Object createInstance() {
+
 		if (!isLoaded()) { load(); }
 		Object instance = null;
 		try {
-
-			Activator.getLogger().log(Level.INFO, "[" + m_metadata.getClassName() + "] createInstance -> call setComponentManager");
-			// Invoke the static method setComponentManager on the manipulated class
-			Method method = m_clazz.getDeclaredMethod("setComponentManager", new Class[] {this.getClass()});
-			method.setAccessible(true);
-			method.invoke(null, new Object[] {this});
-
 			Activator.getLogger().log(Level.INFO, "[" + m_metadata.getClassName() + "] createInstance -> Try to find the constructor");
 
 			// Try to find if there is a constructor with a bundle context as parameter :
 			try {
-				Constructor constructor = m_clazz.getConstructor(new Class[] {BundleContext.class});
+				Constructor constructor = m_clazz.getConstructor(new Class[] {ComponentManager.class, BundleContext.class});
 				constructor.setAccessible(true);
-				instance = constructor.newInstance(new Object[] {m_factory.getBundleContext()});
+				instance = constructor.newInstance(new Object[] {this, m_factory.getBundleContext()});
 			}
 			catch (NoSuchMethodException e) {
 				Activator.getLogger().log(Level.INFO, "[" + m_metadata.getClassName() + "] createInstance -> No constructor with a bundle context");
@@ -329,7 +322,11 @@
 
 			// Create an instance if no instance are already created with <init>()BundleContext
 			Activator.getLogger().log(Level.INFO, "[" + m_metadata.getClassName() + "] createInstance -> Try to create the object with an empty constructor");
-			if (instance == null) { instance = m_clazz.newInstance(); }
+			if (instance == null) {
+				Constructor constructor = m_clazz.getConstructor(new Class[] {ComponentManager.class});
+				constructor.setAccessible(true);
+				instance = constructor.newInstance(new Object[] {this});
+				}
 
 		} catch (InstantiationException e) {
 			Activator.getLogger().log(Level.SEVERE, "[" + m_metadata.getClassName() + "] createInstance -> The Component Instance cannot be instancied : " + e.getMessage());
@@ -340,14 +337,11 @@
 		} catch (SecurityException e) {
 			Activator.getLogger().log(Level.SEVERE, "[" + m_metadata.getClassName() + "] createInstance -> The Component Instance is not accessible (security reason) : " + e.getMessage());
 			e.printStackTrace();
-		} catch (IllegalArgumentException e) {
-			Activator.getLogger().log(Level.SEVERE, "[" + m_metadata.getClassName() + "] createInstance -> Cannot invoke the setComponentManager method (illegal argument) : " + e.getMessage());
-			e.printStackTrace();
 		} catch (InvocationTargetException e) {
-			Activator.getLogger().log(Level.SEVERE, "[" + m_metadata.getClassName() + "] createInstance -> Cannot invoke the setComponentManager method (illegal target) : " + e.getMessage());
+			Activator.getLogger().log(Level.SEVERE, "[" + m_metadata.getClassName() + "] createInstance -> Cannot invoke the constructor method (illegal target) : " + e.getMessage());
 			e.printStackTrace();
 		} catch (NoSuchMethodException e) {
-			Activator.getLogger().log(Level.SEVERE, "[" + m_metadata.getClassName() + "] createInstance -> Cannot invoke the setComponentManager method (method not found) : " + e.getMessage());
+			Activator.getLogger().log(Level.SEVERE, "[" + m_metadata.getClassName() + "] createInstance -> Cannot invoke the constructor (method not found) : " + e.getMessage());
 			e.printStackTrace();
 		}
 
@@ -499,4 +493,4 @@
 
 	// ======================= end Handlers Management =====================
 
-}
+}
\ No newline at end of file
diff --git a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
index eb8c332..62b6cff 100644
--- a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
+++ b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/handlers/configuration/ConfigurationHandler.java
@@ -24,6 +24,8 @@
 import org.apache.felix.ipojo.ComponentManager;
 import org.apache.felix.ipojo.Handler;
 import org.apache.felix.ipojo.Activator;
+import org.apache.felix.ipojo.handlers.providedservice.Property;
+import org.apache.felix.ipojo.handlers.providedservice.ProvidedService;
 import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandler;
 import org.apache.felix.ipojo.metadata.Element;
 import org.osgi.framework.BundleContext;
@@ -140,7 +142,17 @@
 	 * @see org.apache.felix.ipojo.Handler#setterCallback(java.lang.String, java.lang.Object)
 	 */
 	public void setterCallback(String fieldName, Object value) {
-		// Nothing to do
+		//	Verify that the field name correspond to a configurable property
+		for (int i = 0; i < m_configurableProperties.length; i++) {
+			ConfigurableProperty cp = m_configurableProperties[i];
+			if (cp.getName().equals(fieldName)) {
+				// Check if the value has change
+				if (cp.getValue() == null || !cp.getValue().equals(value)) {
+					cp.setValue(value); // Change the value
+			}
+		}
+		}
+		//Else do nothing
 	}
 
 	/**
@@ -193,7 +205,7 @@
 					if (m_configurableProperties[i].getName().equals(name)) {
 						// Check if the value has change
 						if (m_configurableProperties[i].getValue() == null || !m_configurableProperties[i].getValue().equals(value)) {
-							m_configurableProperties[i].setValue(value); // Change the value
+							//m_configurableProperties[i].setValue(value); // Useless, the setterCallback will call the setValue
 							m_manager.setterCallback(m_configurableProperties[i].getField(), value); // says that the value has change
 						}
 						find = true;
diff --git a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
index 1546a3d..6361bd7 100644
--- a/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
+++ b/org.apache.felix.ipojo/src/main/java/org/apache/felix/ipojo/handlers/providedservice/ProvidedServiceHandler.java
@@ -195,11 +195,10 @@
 				}
 
 				if (type != null) {
-					if (type.endsWith("[]")) {
-						// TODO array property
-						Activator.getLogger().log(Level.SEVERE, "[" + m_componentManager.getComponentMetatada().getClassName() + "] An array property was found in the class [Not implemented yet] : " + prop.getMetadata().getField());
-						return false;
-					}
+//					if (type.endsWith("[]")) {
+//						Activator.getLogger().log(Level.SEVERE, "[" + m_componentManager.getComponentMetatada().getClassName() + "] An array property was found in the class [Not implemented yet] : " + prop.getMetadata().getField());
+//						return false;
+//					}
 
 					if (prop.getMetadata().getType() == null) { prop.getMetadata().setType(type); }