Fix FELIX-3461 - Issue with collected metadata and manipulation metadata on re-manipulation

* Fix the constructor argument shift by not moving the annotations
* Fix the method name when it is a manipulated method
* Cleanup the manipulation metadata

(forgot to add files in my first commit)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1327154 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatedClassLoader.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatedClassLoader.java
new file mode 100644
index 0000000..f0f5c15
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatedClassLoader.java
@@ -0,0 +1,26 @@
+package org.apache.felix.ipojo.manipulation;
+
+/**
+ * A classloader used to load manipulated classes.
+ */
+class ManipulatedClassLoader extends ClassLoader {
+
+    private String name;
+    private byte[] clazz;
+
+    public ManipulatedClassLoader(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/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java
new file mode 100644
index 0000000..1b8945c
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java
@@ -0,0 +1,136 @@
+package org.apache.felix.ipojo.manipulation;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+import org.apache.felix.ipojo.manipulator.Reporter;
+import org.apache.felix.ipojo.manipulator.ResourceStore;
+import org.apache.felix.ipojo.manipulator.ResourceVisitor;
+import org.apache.felix.ipojo.manipulator.metadata.AnnotationMetadataProvider;
+import org.apache.felix.ipojo.manipulator.util.Strings;
+import org.apache.felix.ipojo.metadata.Element;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.Mockito.mock;
+
+/**
+ * Test Case for FELIX-3461.
+ * Checks the consistency of multiple manipulation.
+ */
+public class RemanipulationTest extends TestCase {
+
+    /**
+     * Tests checking that the consecutive manipulation does still returns valid metadata (from annotations),
+     * and valid manipulation metadata.
+     *
+     * @throws IOException
+     * @throws ClassNotFoundException
+     */
+    public void testDoubleManipulationWithAnnotations() throws IOException, ClassNotFoundException {
+        Reporter reporter = mock(Reporter.class);
+        // Step 1 - First collection and manipulation
+        //1.1 Metadata collection
+        MiniStore store = new MiniStore()
+                .addClassToStore("test.PlentyOfAnnotations",
+                        ManipulatorTest.getBytesFromFile(new File("target/test-classes/test/PlentyOfAnnotations.class")));
+        AnnotationMetadataProvider provider = new AnnotationMetadataProvider(store, reporter);
+        List<Element> originalMetadata = provider.getMetadatas();
+        // 1.2 Manipulation
+        Manipulator manipulator = new Manipulator();
+        byte[] clazz = manipulator.manipulate(
+                ManipulatorTest.getBytesFromFile(new File("target/test-classes/test/PlentyOfAnnotations.class")));
+        Element originalManipulationMetadata = manipulator.getManipulationMetadata();
+        // 1.3 Check that the class is valid
+        ManipulatedClassLoader classloader = new ManipulatedClassLoader("test.PlentyOfAnnotations", clazz);
+        Class cl = classloader.findClass("test.PlentyOfAnnotations");
+        Assert.assertNotNull(cl);
+
+        // ---------------
+
+        // Step 2 - Second collection and manipulation
+        // We use the output class as entry.
+        // 2.1 Metadata collection
+        store = new MiniStore().addClassToStore("test.PlentyOfAnnotations", clazz);
+        provider = new AnnotationMetadataProvider(store, reporter);
+        List<Element> metadataAfterOneManipulation = provider.getMetadatas();
+        // 2.2 Manipulation
+        manipulator = new Manipulator();
+        byte[] clazz2 = manipulator.manipulate(clazz);
+        Element manipulationMetadataAfterSecondManipulation = manipulator.getManipulationMetadata();
+        // 2.3 Check that the class is valid
+        classloader = new ManipulatedClassLoader("test.PlentyOfAnnotations", clazz);
+        cl = classloader.findClass("test.PlentyOfAnnotations");
+        Assert.assertNotNull(cl);
+
+        // ---------------
+
+        // Step 3 - Third collection and manipulation
+        // We use the output class of 2 as entry.
+        // 3.1 Metadata collection
+        store = new MiniStore().addClassToStore("test.PlentyOfAnnotations", clazz2);
+        provider = new AnnotationMetadataProvider(store, reporter);
+        List<Element> metadataAfterTwoManipulation = provider.getMetadatas();
+        // 3.2 Manipulation
+        manipulator = new Manipulator();
+        byte[] clazz3 = manipulator.manipulate(clazz2);
+        Element manipulationMetadataAfterThirdManipulation = manipulator.getManipulationMetadata();
+        // 3.3 Check that the class is valid
+        classloader = new ManipulatedClassLoader("test.PlentyOfAnnotations", clazz);
+        cl = classloader.findClass("test.PlentyOfAnnotations");
+        Assert.assertNotNull(cl);
+
+        // ---------------
+        // Verification
+
+        // Unchanged metadata
+        Assert.assertEquals(originalMetadata.toString(), metadataAfterOneManipulation.toString());
+        Assert.assertEquals(originalMetadata.toString(), metadataAfterTwoManipulation.toString());
+
+        // Unchanged manipulation metadata
+        Assert.assertEquals(originalManipulationMetadata.toString(),
+                manipulationMetadataAfterSecondManipulation.toString());
+        Assert.assertEquals(originalManipulationMetadata.toString(),
+                manipulationMetadataAfterThirdManipulation.toString());
+
+    }
+
+    private class MiniStore implements ResourceStore {
+
+        private Map<String, byte[]> resources;
+
+        public MiniStore addClassToStore(String qualifiedName, byte[] bytes) {
+            if (this.resources == null) {
+                this.resources = new HashMap<String, byte[]>();
+            }
+            this.resources.put(Strings.asResourcePath(qualifiedName), bytes);
+            return this;
+        }
+
+        public byte[] read(String path) throws IOException {
+            return resources.get(path);
+        }
+
+        public void accept(ResourceVisitor visitor) {
+            for (Map.Entry<String, byte[]> entry : resources.entrySet()) {
+                visitor.visit(entry.getKey());
+            }
+        }
+
+        public void open() throws IOException {
+        }
+
+        public void writeMetadata(Element metadata) {
+        }
+
+        public void write(String resourcePath, byte[] resource) throws IOException {
+        }
+
+        public void close() throws IOException {
+        }
+    }
+
+}
diff --git a/ipojo/manipulator/manipulator/src/test/java/test/PlentyOfAnnotations.java b/ipojo/manipulator/manipulator/src/test/java/test/PlentyOfAnnotations.java
new file mode 100644
index 0000000..3697920
--- /dev/null
+++ b/ipojo/manipulator/manipulator/src/test/java/test/PlentyOfAnnotations.java
@@ -0,0 +1,40 @@
+package test;
+
+import org.apache.felix.ipojo.annotations.*;
+import test.ipojo.ExternalHandler;
+
+import java.util.List;
+
+@Component
+@Instantiate
+public class PlentyOfAnnotations {
+
+    @Requires
+    List list;
+    private String m_prop;
+    private Runnable m_runnable;
+    private String m_stuff;
+
+    @ExternalHandler
+    private String stuff2;
+
+
+    PlentyOfAnnotations(@Property String prop, @Requires Runnable runnable, @ExternalHandler String stuff) {
+
+        m_prop = prop;
+        m_runnable = runnable;
+        m_stuff = stuff;
+
+    }
+
+    @Validate
+    public void start() {
+        //...
+    }
+
+    @ExternalHandler
+    public void stuff() {
+        // ...
+    }
+
+}