Added patch (FELIX-103) that checks to see if the component class was
already instrumented.


git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@426410 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java b/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
new file mode 100644
index 0000000..e8880f9
--- /dev/null
+++ b/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/ClassChecker.java
@@ -0,0 +1,116 @@
+package org.apache.felix.ipojo.manipulation;
+
+import java.util.HashMap;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+public class ClassChecker implements ClassVisitor, Opcodes {
+	
+	/**
+	 * True if the class is already manipulated.
+	 */
+	private boolean isAlreadyManipulated = false;
+	
+    /**
+     * Interfaces implemented by the component.
+     */
+    private String[] m_itfs = new String[0];
+
+	/**
+	 * Field hashmap [field name, type] discovered in the component class.
+	 */
+	private HashMap m_fields = new HashMap();
+
+	/** Check if the _cm field already exists.
+	 * @see org.objectweb.asm.ClassVisitor#visitField(int, java.lang.String, java.lang.String, java.lang.String, java.lang.Object)
+	 */
+	public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
+		
+		if (access == ACC_PRIVATE && name.equals("_cm") && desc.equals("Lorg/apache/felix/ipojo/ComponentManager;")) {
+			isAlreadyManipulated = true;
+		}
+		
+		Type type = Type.getType(desc);
+		if (type.getSort() == Type.ARRAY) {
+        	if (type.getInternalName().startsWith("L")) {
+        		String internalType = type.getInternalName().substring(1);
+        		String nameType = internalType.replace('/', '.');
+                m_fields.put(name, nameType + "[]");
+        	}
+        	else {
+        		String nameType = type.getClassName().substring(0, type.getClassName().length() - 2);
+        		m_fields.put(name, nameType);
+        	}
+		} else {
+			m_fields.put(name, type.getClassName());
+		}
+		
+		return null;
+	}
+	
+	public boolean isalreadyManipulated() { return isAlreadyManipulated; }
+	
+	/**
+     * @see org.objectweb.asm.ClassVisitor#visit(int, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
+     */
+    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)  {
+    	//Store the interfaces :
+        m_itfs = interfaces;
+    }
+
+    /**
+     * @see org.objectweb.asm.ClassVisitor#visitSource(java.lang.String, java.lang.String)
+     */
+    public void visitSource(String arg0, String arg1) { }
+
+    /**
+     * @see org.objectweb.asm.ClassVisitor#visitOuterClass(java.lang.String, java.lang.String, java.lang.String)
+     */
+    public void visitOuterClass(String arg0, String arg1, String arg2) { }
+
+    /**
+     * @see org.objectweb.asm.ClassVisitor#visitAnnotation(java.lang.String, boolean)
+     */
+    public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) { return null; }
+
+    /**
+     * @see org.objectweb.asm.ClassVisitor#visitAttribute(org.objectweb.asm.Attribute)
+     */
+    public void visitAttribute(Attribute arg0) { }
+
+    /**
+     * @see org.objectweb.asm.ClassVisitor#visitInnerClass(java.lang.String, java.lang.String, java.lang.String, int)
+     */
+    public void visitInnerClass(String arg0, String arg1, String arg2, int arg3) { }
+    
+    /**
+     * @see org.objectweb.asm.ClassVisitor#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 null; }
+
+    /**
+     * @see org.objectweb.asm.ClassVisitor#visitEnd()
+     */
+    public void visitEnd() { }
+    
+    /**
+     * @return the interfaces implemented by the component class.
+     */
+    public String[] getInterfaces() {
+        return m_itfs;
+    }
+
+	/**
+	 * @return the field hashmap [field_name, type]
+	 */
+	public HashMap getFields() {
+		return m_fields;
+	}
+
+}
diff --git a/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java b/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java
index e001d4d..34f55cc 100644
--- a/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java
+++ b/org.apache.felix.ipojo.plugin/src/main/java/org/apache/felix/ipojo/manipulation/Manipulator.java
@@ -79,23 +79,38 @@
         //if (url == null) { throw new ClassNotFoundException(name); }
         IPojoPluginConfiguration.getLogger().log(Level.INFO, "Manipulate the class file : " + clazz.getAbsolutePath());
 
-        InputStream is = url.openStream();
+        InputStream is1 = url.openStream();
+        
+        
+        // First check if the class is already manipulated : 
+        ClassReader ckReader = new ClassReader(is1);
+        ClassChecker ck = new ClassChecker();
+        ckReader.accept(ck, true);
+        is1.close();
+        
+        m_fields = ck.getFields();
+        m_interfaces = new String[ck.getInterfaces().length];
+        for (int i = 0; i < m_interfaces.length; i++) {
+        	m_interfaces[i] = ck.getInterfaces()[i].replace('/', '.');
+        }
+        
+        if(!ck.isalreadyManipulated()) {
 
-        //Manipulation  ->
-        // Add the _setComponentManager method
-        // Instrument all fields
-        ClassReader cr0 = new ClassReader(is);
-        ClassWriter cw0 = new ClassWriter(true);
-        PreprocessClassAdapter preprocess = new PreprocessClassAdapter(cw0);
-        cr0.accept(preprocess, false);
-        is.close();
+        	//Manipulation  ->
+        	// Add the _setComponentManager method
+        	// Instrument all fields
+        	InputStream is2 = url.openStream();
+        	ClassReader cr0 = new ClassReader(is2);
+        	ClassWriter cw0 = new ClassWriter(true);
+        	PreprocessClassAdapter preprocess = new PreprocessClassAdapter(cw0);
+        	cr0.accept(preprocess, false);
+        	is2.close();
 
-        File file = null;
-        try {
-                file = new File(url.getFile());
+        	File file = null;
+        	try {
+        		file = new File(url.getFile());
 
-                
-                //file.createNewFile();
+        		//file.createNewFile();
                 FileOutputStream fos = new FileOutputStream(file);
                 
                 fos.write(cw0.toByteArray());
@@ -104,10 +119,6 @@
                 IPojoPluginConfiguration.getLogger().log(Level.INFO, "Put the file " + file.getAbsolutePath() + " in the jar file");
             } catch (Exception e) { System.err.println("Problem to write the adapted class on the file system " + " [ "+ file.getAbsolutePath() +" ] " + e.getMessage()); }
 
-        m_fields = preprocess.getFields();
-        m_interfaces = new String[preprocess.getInterfaces().length];
-        for (int i = 0; i < m_interfaces.length; i++) {
-        	m_interfaces[i] = preprocess.getInterfaces()[i].replace('/', '.');
         }
     }
 
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 454d618..bb569e1 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
@@ -48,17 +48,6 @@
         private String  m_owner;
 
         /**
-         * Interfaces implemented by the component.
-         */
-        private String[] m_itfs = new String[0];
-
-		/**
-		 * Field hashmap [field name, type] discovered in the component class.
-		 */
-		private HashMap m_fields = new HashMap();
-
-
-        /**
          * Constructor.
          * @param cv : Class visitor
          */
@@ -95,9 +84,6 @@
             // Create the _cmSetter(ComponentManager cm) method
             createComponentManagerSetter();
 
-            //Store the interfaces :
-            m_itfs = interfaces;
-
             super.visit(version, access, name, signature, superName, interfaces);
         }
         
@@ -177,15 +163,6 @@
                     FieldVisitor fv =  cv.visitField(access, name, desc, signature, value);
 
                     if (type.getSort() == Type.ARRAY) {
-                    	if (type.getInternalName().startsWith("L")) {
-                    		String internalType = type.getInternalName().substring(1);
-                    		String nameType = internalType.replace('/', '.');
-                            m_fields.put(name, nameType + "[]");
-                    	}
-                    	else {
-                    		String nameType = type.getClassName().substring(0, type.getClassName().length() - 2);
-                    		m_fields.put(name, nameType);
-                    	}
 
                         String gDesc = "()" + desc;
                     	createArrayGetter(name, gDesc, type);
@@ -196,8 +173,6 @@
 
                     }
                     else {
-                    	// Store information on the fields
-                    	m_fields.put(name, type.getClassName());
 
                     	// Generate the getter method
                     	String gDesc = "()" + desc;
@@ -485,19 +460,5 @@
             mv.visitMaxs(0, 0);
             mv.visitEnd();
         }
-
-        /**
-         * @return the interfaces implemented by the component class.
-         */
-        public String[] getInterfaces() {
-            return m_itfs;
-        }
-
-		/**
-		 * @return the field hashmap [field_name, type]
-		 */
-		public HashMap getFields() {
-			return m_fields;
-		}
 }