You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2013/10/01 18:16:51 UTC

svn commit: r1528135 [2/2] - in /felix/trunk/ipojo: manipulator/bnd-ipojo-plugin/src/test/java/org/apache/felix/ipojo/bnd/ manipulator/manipulator-it/ipojo-manipulator-manipulation-test/src/main/java/org/apache/felix/ipojo/runtime/core/components/ mani...

Modified: felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/InnerClassAdapterTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/InnerClassAdapterTest.java?rev=1528135&r1=1528134&r2=1528135&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/InnerClassAdapterTest.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/InnerClassAdapterTest.java Tue Oct  1 16:16:51 2013
@@ -43,36 +43,136 @@ public class InnerClassAdapterTest {
 
     public static String baseClassDirectory = "target/test-classes/";
 
-    private static ManipulatedClassLoader manipulate(String className, Manipulator manipulator) throws IOException {
+    public static ManipulatedClassLoader manipulate(String className, Manipulator manipulator) throws IOException {
+        byte[] bytecode = ManipulatorTest.getBytesFromFile(
+                new File(baseClassDirectory + className.replace(".", "/") + ".class"));
+
+        // Preparation.
+        try {
+            manipulator.prepare(bytecode);
+        } catch (IOException e) {
+            Assert.fail("Cannot read " + className);
+        }
+
+        // Inner class preparation
+        for (String inner : manipulator.getInnerClasses()) {
+            // Get the bytecode and start manipulation
+            String resourcePath = inner + ".class";
+            byte[] innerClassBytecode;
+            try {
+                innerClassBytecode = ManipulatorTest.getBytesFromFile(new File(baseClassDirectory + resourcePath));
+                manipulator.prepareInnerClass(inner, innerClassBytecode);
+            } catch (IOException e) {
+                Assert.fail("Cannot find or analyze inner class '" + resourcePath + "'");
+            }
+        }
+
+        // Now manipulate the classes.
+        byte[] out = new byte[0];
+        try {
+            out = manipulator.manipulate(bytecode);
+        } catch (IOException e) {
+            Assert.fail("Cannot manipulate the class " + className + " : " + e.getMessage());
+        }
+
+        ManipulatedClassLoader classloader = new ManipulatedClassLoader(className, out);
+
+        // Visit inner classes
+        for (String inner : manipulator.getInnerClasses()) {
+            // Get the bytecode and start manipulation
+            String resourcePath = inner + ".class";
+            byte[] innerClassBytecode;
+            try {
+                innerClassBytecode = ManipulatorTest.getBytesFromFile(new File(baseClassDirectory + resourcePath));
+                byte[] manipulated = manipulator.manipulateInnerClass(inner, innerClassBytecode);
+                classloader.addInnerClass(inner.replace("/", "."), manipulated);
+            } catch (IOException e) {
+                Assert.fail("Cannot find inner class '" + resourcePath + "'");
+            }
+        }
+        return classloader;
+    }
+
+    public static ManipulatedClassLoader manipulate(String className, Manipulator manipulator,
+                                                    ManipulatedClassLoader initial) throws IOException {
+        byte[] bytecode = initial.get(className);
+
+        // Preparation.
+        try {
+            manipulator.prepare(bytecode);
+        } catch (IOException e) {
+            Assert.fail("Cannot read " + className);
+        }
+
+        // Inner class preparation
+        for (String inner : manipulator.getInnerClasses()) {
+            // Get the bytecode and start manipulation
+            String resourcePath = inner + ".class";
+            byte[] innerClassBytecode;
+            try {
+                innerClassBytecode = initial.get(inner.replace("/", "."));
+                manipulator.prepareInnerClass(inner, innerClassBytecode);
+            } catch (IOException e) {
+                Assert.fail("Cannot find or analyze inner class '" + resourcePath + "'");
+            }
+        }
 
-        byte[] clazz = manipulator.manipulate(ManipulatorTest.getBytesFromFile(new File
-                (baseClassDirectory + className.replace(".", "/") + ".class")));
-        ManipulatedClassLoader classloader = new ManipulatedClassLoader(className, clazz);
-
-        // Manipulate all inner classes
-        for (String s : manipulator.getInnerClasses()) {
-            String outerClassInternalName = className.replace(".", "/");
-            byte[] innerClassBytecode = ManipulatorTest.getBytesFromFile(new File(baseClassDirectory + s + "" +
-                    ".class"));
-            String innerClassName = s.replace("/", ".");
-            InnerClassManipulator innerManipulator = new InnerClassManipulator(s, outerClassInternalName,
-                    manipulator);
-            byte[] manipulated = innerManipulator.manipulate(innerClassBytecode, manipulator.getClassVersion());
-            classloader.addInnerClass(innerClassName, manipulated);
+        // Now manipulate the classes.
+        byte[] out = new byte[0];
+        try {
+            out = manipulator.manipulate(bytecode);
+        } catch (IOException e) {
+            Assert.fail("Cannot manipulate the class " + className + " : " + e.getMessage());
         }
 
+        ManipulatedClassLoader classloader = new ManipulatedClassLoader(className, out);
+
+        // Visit inner classes
+        for (String inner : manipulator.getInnerClasses()) {
+            // Get the bytecode and start manipulation
+            String resourcePath = inner + ".class";
+            byte[] innerClassBytecode;
+            try {
+                innerClassBytecode = initial.get(inner.replace("/", "."));
+                byte[] manipulated = manipulator.manipulateInnerClass(inner, innerClassBytecode);
+                classloader.addInnerClass(inner.replace("/", "."), manipulated);
+            } catch (IOException e) {
+                Assert.fail("Cannot find inner class '" + resourcePath + "'");
+            }
+        }
         return classloader;
     }
 
+    private static Element getInnerClassMetadataByName(Element[] inners, String name) {
+        for (Element element : inners) {
+            if (name.equals(element.getAttribute("name"))) {
+                return element;
+            }
+        }
+        return null;
+    }
+
+    private static Element getMethodByName(Element[] methods, String name) {
+        for (Element element : methods) {
+            if (name.equals(element.getAttribute("name"))) {
+                return element;
+            }
+        }
+        return null;
+    }
+
     @Test
     public void testManipulatingTheInner() throws Exception {
         Manipulator manipulator = new Manipulator();
         String className = "test.PojoWithInner";
-        byte[] origin =  ManipulatorTest.getBytesFromFile(new File(baseClassDirectory + className.replace(".",
+        byte[] origin = ManipulatorTest.getBytesFromFile(new File(baseClassDirectory + className.replace(".",
                 "/") + ".class"));
 
         ManipulatedClassLoader classloader = manipulate(className, manipulator);
 
+
+
+
         Class cl = classloader.findClass(className);
         Assert.assertNotNull(cl);
         Assert.assertNotNull(manipulator.getManipulationMetadata());
@@ -89,7 +189,7 @@ public class InnerClassAdapterTest {
         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  &&
+            if (csts[i].getParameterTypes().length == 1 &&
                     csts[i].getParameterTypes()[0].equals(InstanceManager.class)) {
                 found = true;
                 cst = csts[i];
@@ -113,7 +213,7 @@ public class InnerClassAdapterTest {
 
         InstanceManager im = Mockito.mock(InstanceManager.class);
         cst.setAccessible(true);
-        Object pojo = cst.newInstance(new Object[] {im});
+        Object pojo = cst.newInstance(new Object[]{im});
         Assert.assertNotNull(pojo);
         Assert.assertTrue(pojo instanceof Pojo);
         Method method = cl.getMethod("doSomething", new Class[0]);
@@ -121,13 +221,13 @@ public class InnerClassAdapterTest {
 
     }
 
-
     @Test
     public void testInnerClasses() throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
         Manipulator manipulator = new Manipulator();
         String className = "test.inner.ComponentWithInnerClasses";
         ManipulatedClassLoader classloader = manipulate(className, manipulator);
 
+
         Class clazz = classloader.findClass(className);
         Assert.assertNotNull(clazz);
         Assert.assertNotNull(manipulator.getManipulationMetadata());
@@ -139,7 +239,7 @@ public class InnerClassAdapterTest {
         InstanceManager im = Mockito.mock(InstanceManager.class);
         Constructor constructor = clazz.getDeclaredConstructor(InstanceManager.class);
         constructor.setAccessible(true);
-        Object pojo = constructor.newInstance(new Object[] {im});
+        Object pojo = constructor.newInstance(new Object[]{im});
         Assert.assertNotNull(pojo);
         Assert.assertTrue(pojo instanceof Pojo);
         Method method = clazz.getMethod("doSomething", new Class[0]);
@@ -148,31 +248,14 @@ public class InnerClassAdapterTest {
     }
 
     @Test
-    public void testRemanipulationOfInnerClasses() throws IOException, ClassNotFoundException, NoSuchMethodException,
+    public void testDoubleManipulation() throws IOException, ClassNotFoundException, NoSuchMethodException,
             IllegalAccessException, InvocationTargetException, InstantiationException {
         Manipulator manipulator = new Manipulator();
         String className = "test.inner.ComponentWithInnerClasses";
+        ManipulatedClassLoader classloader = manipulate(className, manipulator);
 
-        // Two manipulation of the outer class.
-        byte[] bytecode = manipulator.manipulate(ManipulatorTest.getBytesFromFile(new File
-                (baseClassDirectory + className.replace(".", "/") + ".class")));
-        bytecode = manipulator.manipulate(bytecode);
-
-        ManipulatedClassLoader classloader = new ManipulatedClassLoader(className, bytecode);
-
-        // Manipulate all inner classes
-        for (String s : manipulator.getInnerClasses()) {
-            String outerClassInternalName = className.replace(".", "/");
-            byte[] innerClassBytecode = ManipulatorTest.getBytesFromFile(new File(baseClassDirectory + s + "" +
-                    ".class"));
-            String innerClassName = s.replace("/", ".");
-            InnerClassManipulator innerManipulator = new InnerClassManipulator(s, outerClassInternalName,
-                    manipulator);
-            // Two manipulation of all inner classes.
-            byte[] manipulated = innerManipulator.manipulate(innerClassBytecode, manipulator.getClassVersion());
-            manipulated = innerManipulator.manipulate(manipulated, manipulator.getClassVersion());
-            classloader.addInnerClass(innerClassName, manipulated);
-        }
+        manipulator = new Manipulator();
+        classloader = manipulate(className, manipulator, classloader);
 
         Class clazz = classloader.findClass(className);
         Assert.assertNotNull(clazz);
@@ -185,7 +268,7 @@ public class InnerClassAdapterTest {
         InstanceManager im = Mockito.mock(InstanceManager.class);
         Constructor constructor = clazz.getDeclaredConstructor(InstanceManager.class);
         constructor.setAccessible(true);
-        Object pojo = constructor.newInstance(new Object[] {im});
+        Object pojo = constructor.newInstance(new Object[]{im});
         Assert.assertNotNull(pojo);
         Assert.assertTrue(pojo instanceof Pojo);
         Method method = clazz.getMethod("doSomething", new Class[0]);
@@ -218,25 +301,25 @@ public class InnerClassAdapterTest {
         inner = getInnerClassMetadataByName(inners, "1");
         assertThat(inner).isNotNull();
         assertThat(getMethodByName(inner.getElements("method"), "compute")).isNotNull();
-
     }
 
-    private static Element getInnerClassMetadataByName(Element[] inners, String name) {
-        for (Element element : inners) {
-            if (name.equals(element.getAttribute("name"))) {
-                return element;
-            }
-        }
-        return null;
-    }
+    @Test
+    public void testThatTheClassContainsTheFlagsForTheInnerMethods() throws IOException, ClassNotFoundException,
+            NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
+        Manipulator manipulator = new Manipulator();
+        String className = "test.inner.ComponentWithInnerClasses";
+        ManipulatedClassLoader classLoader = manipulate(className, manipulator);
 
-    private static Element getMethodByName(Element[] methods, String name) {
-        for (Element element : methods) {
-            if (name.equals(element.getAttribute("name"))) {
-                return element;
-            }
-        }
-        return null;
+        Class clazz = classLoader.findClass(className);
+
+        String flag = "__M" + "MyInnerWithANativeMethod" + "___" + "foo";
+        assertThat(clazz.getDeclaredField(flag)).isNotNull();
+
+        flag = "__M" + "MyInnerClass" + "___" + "foo";
+        assertThat(clazz.getDeclaredField(flag)).isNotNull();
+
+        flag = "__M" + "1" + "___" + "compute" + "$java_lang_String";
+        assertThat(clazz.getDeclaredField(flag)).isNotNull();
     }
 
 }

Modified: felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatedClassLoader.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatedClassLoader.java?rev=1528135&r1=1528134&r2=1528135&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatedClassLoader.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatedClassLoader.java Tue Oct  1 16:16:51 2013
@@ -19,6 +19,10 @@
 
 package org.apache.felix.ipojo.manipulation;
 
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
@@ -69,4 +73,19 @@ public class ManipulatedClassLoader exte
         }
         return super.loadClass(classname);
     }
+
+    public static final File DUMP_BASEDIR = new File("target/dump");
+
+    public void dump() throws IOException {
+        File outer = new File(DUMP_BASEDIR, name.replace(".", "/") + ".class");
+        FileUtils.writeByteArrayToFile(outer, clazz);
+        for (String name : inner.keySet()) {
+            File file = new File(DUMP_BASEDIR, name.replace(".", "/") + ".class");
+            FileUtils.writeByteArrayToFile(file, inner.get(name));
+        }
+    }
+
+    public Map<String, byte[]> getAllInnerClasses() {
+        return inner;
+    }
 }

Modified: felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java?rev=1528135&r1=1528134&r2=1528135&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/ManipulatorTest.java Tue Oct  1 16:16:51 2013
@@ -39,7 +39,10 @@ public class ManipulatorTest extends Tes
 
     public void testClusterDaemon() throws Exception {
         Manipulator manipulator = new Manipulator();
-        byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/ClusterDaemon.class")));
+        byte[] origin = getBytesFromFile(new File("target/test-classes/test/ClusterDaemon.class"));
+        manipulator.prepare(origin);
+        byte[] clazz = manipulator.manipulate(origin);
+
         ManipulatedClassLoader classloader = new ManipulatedClassLoader("test.ClusterDaemon", clazz);
 
         //Assert.assertNotNull(manipulator.getManipulationMetadata());
@@ -62,7 +65,9 @@ public class ManipulatorTest extends Tes
 
     public void testManipulatingTheSimplePojo() throws Exception {
         Manipulator manipulator = new Manipulator();
-        byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/SimplePojo.class")));
+        byte[] origin = getBytesFromFile(new File("target/test-classes/test/SimplePojo.class"));
+        manipulator.prepare(origin);
+        byte[] clazz = manipulator.manipulate(origin);
         ManipulatedClassLoader classloader = new ManipulatedClassLoader("test.SimplePojo", clazz);
         Class cl = classloader.findClass("test.SimplePojo");
         Assert.assertNotNull(cl);
@@ -113,7 +118,10 @@ public class ManipulatorTest extends Tes
 
     public void testManipulatingTheNonSunPOJO() throws Exception {
         Manipulator manipulator = new Manipulator();
-        byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/NonSunClass.class")));
+        byte[] origin = getBytesFromFile(new File("target/test-classes/test/NonSunClass.class"));
+        manipulator.prepare(origin);
+        byte[] clazz = manipulator.manipulate(origin);
+
         ManipulatedClassLoader classloader = new ManipulatedClassLoader("test.NonSunClass", clazz);
         Class cl = classloader.findClass("test.NonSunClass");
         Assert.assertNotNull(cl);
@@ -153,7 +161,10 @@ public class ManipulatorTest extends Tes
 
     public void testManipulatingChild() throws Exception {
         Manipulator manipulator = new Manipulator();
-        byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/Child.class")));
+        byte[] origin = getBytesFromFile(new File("target/test-classes/test/Child.class"));
+        manipulator.prepare(origin);
+        byte[] clazz = manipulator.manipulate(origin);
+
         ManipulatedClassLoader classloader = new ManipulatedClassLoader("test.Child", clazz);
         Class cl = classloader.findClass("test.Child");
         Assert.assertNotNull(cl);
@@ -199,7 +210,9 @@ public class ManipulatorTest extends Tes
 
     public void testManipulatingWithConstructorModification() throws Exception {
         Manipulator manipulator = new Manipulator();
-        byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/Child.class")));
+        byte[] origin = getBytesFromFile(new File("target/test-classes/test/Child.class"));
+        manipulator.prepare(origin);
+        byte[] clazz = manipulator.manipulate(origin);
         ManipulatedClassLoader classloader = new ManipulatedClassLoader("test.Child", clazz);
         Class cl = classloader.findClass("test.Child");
         Assert.assertNotNull(cl);
@@ -264,7 +277,9 @@ public class ManipulatorTest extends Tes
 
     public void testManipulatingWithNoValidConstructor() throws Exception {
         Manipulator manipulator = new Manipulator();
-        byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/NoValidConstructor.class")));
+        byte[] origin = getBytesFromFile(new File("target/test-classes/test/NoValidConstructor.class"));
+        manipulator.prepare(origin);
+        byte[] clazz = manipulator.manipulate(origin);
         ManipulatedClassLoader classloader = new ManipulatedClassLoader("test.NoValidConstructor", clazz);
         Class cl = classloader.findClass("test.NoValidConstructor");
         Assert.assertNotNull(cl);
@@ -273,7 +288,7 @@ public class ManipulatorTest extends Tes
         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);
+        Assert.assertTrue(clazz.length > origin.length);
 
 
         boolean found = false;
@@ -301,7 +316,9 @@ public class ManipulatorTest extends Tes
 
      public void testConstructor() throws Exception {
         Manipulator manipulator = new Manipulator();
-        byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/ConstructorCheck.class")));
+         byte[] origin = getBytesFromFile(new File("target/test-classes/test/ConstructorCheck.class"));
+         manipulator.prepare(origin);
+         byte[] clazz = manipulator.manipulate(origin);
 
 //        File out = new File("target/ManipulatedConstructorCheck.class");
 //        FileOutputStream fos = new FileOutputStream(out);
@@ -328,8 +345,9 @@ public class ManipulatorTest extends Tes
      */
     public void testManipulatingDoubleArray() throws Exception {
         Manipulator manipulator = new Manipulator();
-        byte[] clazz = manipulator.manipulate(getBytesFromFile(new File("target/test-classes/test/DoubleArray.class")
-        ));
+        byte[] origin = getBytesFromFile(new File("target/test-classes/test/DoubleArray.class"));
+        manipulator.prepare(origin);
+        byte[] clazz = manipulator.manipulate(origin);
         ManipulatedClassLoader classloader = new ManipulatedClassLoader("test.DoubleArray", clazz);
         Class cl = classloader.findClass("test.DoubleArray");
         Assert.assertNotNull(cl);
@@ -339,7 +357,7 @@ public class ManipulatorTest extends Tes
         Assert.assertTrue(manipulator.getManipulationMetadata().toString().contains("arguments=\"{int[][]}\""));
 
         // The manipulation add stuff to the class.
-        Assert.assertTrue(clazz.length > getBytesFromFile(new File("target/test-classes/test/DoubleArray.class")).length);
+        Assert.assertTrue(clazz.length > origin.length);
 
 
         boolean found = false;

Modified: felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java?rev=1528135&r1=1528134&r2=1528135&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/org/apache/felix/ipojo/manipulation/RemanipulationTest.java Tue Oct  1 16:16:51 2013
@@ -53,15 +53,16 @@ public class RemanipulationTest extends 
         Reporter reporter = mock(Reporter.class);
         // Step 1 - First collection and manipulation
         //1.1 Metadata collection
+        byte[] origin = ManipulatorTest.getBytesFromFile(new File("target/test-classes/test/PlentyOfAnnotations.class"));
         MiniStore store = new MiniStore()
                 .addClassToStore("test.PlentyOfAnnotations",
-                        ManipulatorTest.getBytesFromFile(new File("target/test-classes/test/PlentyOfAnnotations.class")));
+                        origin);
         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")));
+        manipulator.prepare(origin);
+        byte[] clazz = manipulator.manipulate(origin);
         Element originalManipulationMetadata = manipulator.getManipulationMetadata();
         // 1.3 Check that the class is valid
         ManipulatedClassLoader classloader = new ManipulatedClassLoader("test.PlentyOfAnnotations", clazz);
@@ -78,6 +79,7 @@ public class RemanipulationTest extends 
         List<Element> metadataAfterOneManipulation = provider.getMetadatas();
         // 2.2 Manipulation
         manipulator = new Manipulator();
+        manipulator.prepare(clazz);
         byte[] clazz2 = manipulator.manipulate(clazz);
         Element manipulationMetadataAfterSecondManipulation = manipulator.getManipulationMetadata();
         // 2.3 Check that the class is valid
@@ -95,6 +97,7 @@ public class RemanipulationTest extends 
         List<Element> metadataAfterTwoManipulation = provider.getMetadatas();
         // 3.2 Manipulation
         manipulator = new Manipulator();
+        manipulator.prepare(clazz2);
         byte[] clazz3 = manipulator.manipulate(clazz2);
         Element manipulationMetadataAfterThirdManipulation = manipulator.getManipulationMetadata();
         // 3.3 Check that the class is valid

Modified: felix/trunk/ipojo/manipulator/manipulator/src/test/java/test/inner/ComponentWithInnerClasses.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/test/inner/ComponentWithInnerClasses.java?rev=1528135&r1=1528134&r2=1528135&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/test/java/test/inner/ComponentWithInnerClasses.java (original)
+++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/test/inner/ComponentWithInnerClasses.java Tue Oct  1 16:16:51 2013
@@ -39,6 +39,17 @@ public class ComponentWithInnerClasses{
         return nat.foo() + MyStaticInnerClass.foo() + inn.foo() + compute.compute("");
     }
 
+    private void doSomethingPrivately() {
+
+    }
+    private boolean flag;
+
+    boolean getFlag() {
+        return flag;
+    }
+
+    private String test = "";
+
     private String foo = "foo";
 
     private class MyInnerWithANativeMethod {
@@ -47,6 +58,12 @@ public class ComponentWithInnerClasses{
             return ComponentWithInnerClasses.this.foo;
         }
 
+        public void bar() {
+            if (! getFlag()) {
+                test.charAt(0);
+            }
+        }
+
         public native void baz();
 
     }

Added: felix/trunk/ipojo/manipulator/manipulator/src/test/java/test/inner/Example.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/manipulator/src/test/java/test/inner/Example.java?rev=1528135&view=auto
==============================================================================
--- felix/trunk/ipojo/manipulator/manipulator/src/test/java/test/inner/Example.java (added)
+++ felix/trunk/ipojo/manipulator/manipulator/src/test/java/test/inner/Example.java Tue Oct  1 16:16:51 2013
@@ -0,0 +1,80 @@
+/*
+ * 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 test.inner;
+
+/**
+ * Created with IntelliJ IDEA.
+ * User: clement
+ * Date: 01/10/13
+ * Time: 14:57
+ * To change this template use File | Settings | File Templates.
+ */
+public class Example {
+
+    private String myString;
+
+    org.apache.felix.ipojo.InstanceManager __IM;
+    boolean __M1___run;
+    boolean __MFoo___run;
+
+    public void doSomething() {
+        Runnable runnable = new Runnable() {
+            public void run() {
+                if (! __M1___run) {
+                    __run();
+                } else {
+                    try {
+                        __IM.onEntry(Example.this, "__M1___run", new Object[0]);
+                        __run();
+                        __IM.onExit(Example.this, "__M1___run", new Object[0]);
+                    } catch (Throwable e) {
+                        __IM.onError(Example.this, "__M1___run", e);
+                    }
+                }
+            }
+
+            private void __run() {
+                System.out.println(myString);
+            }
+        };
+        runnable.run();
+    }
+
+    private class Foo {
+        public void run() {
+            if (! __MFoo___run) {
+                __run();
+            } else {
+                try {
+                    __IM.onEntry(Example.this, "__MFoo___run", new Object[0]);
+                    __run();
+                    __IM.onExit(Example.this, "__MFoo___run", new Object[0]);
+                } catch (Throwable e) {
+                    __IM.onError(Example.this, "__MFoo___run", e);
+                }
+            }
+        }
+
+        private void __run() {
+            System.out.println(myString);
+        }
+    }
+
+}

Modified: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java?rev=1528135&r1=1528134&r2=1528135&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java (original)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/InstanceManager.java Tue Oct  1 16:16:51 2013
@@ -148,7 +148,7 @@ public class InstanceManager implements 
      * The Map storing the Method objects by ids.
      * [id=>{@link Method}].
      */
-    private Map m_methods = new Hashtable();
+    private Map m_methods = new HashMap();
 
 
     /**
@@ -1068,6 +1068,38 @@ public class InstanceManager implements 
     }
 
     /**
+     * Registers a method interceptor on a methods from an inner class.
+     * A method interceptor will be notified of method entries, exits
+     * and errors. Note that handlers are method interceptors.
+     * @param method the field to monitor
+     * @param innerClass the inner class name
+     * @param interceptor the field interceptor object
+     */
+    public void register(MethodMetadata method, String innerClass, MethodInterceptor interceptor) {
+        if (m_methodRegistration == null) {
+            m_methodRegistration = new HashMap();
+            m_methodRegistration.put(innerClass + "___" + method.getMethodIdentifier(),
+                    new MethodInterceptor[] { interceptor });
+        } else {
+            MethodInterceptor[] list = (MethodInterceptor[]) m_methodRegistration.get(method.getMethodIdentifier());
+            if (list == null) {
+                m_methodRegistration.put(innerClass + "___" + method.getMethodIdentifier(),
+                        new MethodInterceptor[] { interceptor });
+            } else {
+                for (int j = 0; j < list.length; j++) {
+                    if (list[j] == interceptor) {
+                        return;
+                    }
+                }
+                MethodInterceptor[] newList = new MethodInterceptor[list.length + 1];
+                System.arraycopy(list, 0, newList, 0, list.length);
+                newList[list.length] = interceptor;
+                m_methodRegistration.put(innerClass + "___" + method.getMethodIdentifier(), newList);
+            }
+        }
+    }
+
+    /**
      * Registers a constructor injector.
      * The constructor injector will be called when a pojo object is going to be
      * created.
@@ -1154,8 +1186,11 @@ public class InstanceManager implements 
         if (m_methodRegistration == null) { // Immutable field.
             return;
         }
+
         MethodInterceptor[] list = (MethodInterceptor[]) m_methodRegistration.get(methodId);
         Member method = getMethodById(methodId);
+        // We can't find the member object of anonymous methods.
+
         // In case of a constructor, the method is null, and the list is null too.
         for (int i = 0; list != null && i < list.length; i++) {
             list[i].onEntry(pojo, method, args); // Outside a synchronized block.
@@ -1222,7 +1257,42 @@ public class InstanceManager implements 
     private Member getMethodById(String methodId) {
         // Used a synchronized map.
         Member member = (Member) m_methods.get(methodId);
-        if (member == null  && m_clazz != null) {
+        if (! m_methods.containsKey(methodId) && m_clazz != null) {
+            // Is it a inner class method
+            if (methodId.contains("___")) { // Mark to detect a inner class method.
+                String[] split = methodId.split("___");
+                if (split.length != 2) {
+                    m_logger.log(Logger.INFO, "A methodID cannot be associated with a method from the POJO class: " + methodId);
+                    return null;
+                } else {
+                    String innerClassName = split[0];
+                    methodId = split[1];
+
+                    // We can't find the member objects from anonymous methods, identified by their numeric name
+                    // Just escaping in this case.
+                    if (innerClassName.matches("-?\\d+")) {
+                        m_methods.put(methodId, null);
+                        return null;
+                    }
+
+                    for (Class c : m_clazz.getDeclaredClasses()) {
+                        if (innerClassName.equals(c.getSimpleName())) {
+                            Method[] mets = c.getDeclaredMethods();
+                            for (Method met : mets) {
+                                if (MethodMetadata.computeMethodId(met).equals(methodId)) {
+                                    // Store the new methodId
+                                    m_methods.put(methodId, met);
+                                    return met;
+                                }
+                            }
+                        }
+                        m_logger.log(Logger.INFO, "Cannot find the member associated to " + methodId + " - reason: " +
+                                "cannot find the class " + innerClassName + " declared in " + m_clazz.getName());
+                    }
+                }
+            }
+
+
             // First try on methods.
             Method[] mets = m_clazz.getDeclaredMethods();
             for (int i = 0; i < mets.length; i++) {

Modified: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java?rev=1528135&r1=1528134&r2=1528135&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java (original)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/handlers/dependency/DependencyHandler.java Tue Oct  1 16:16:51 2013
@@ -19,23 +19,21 @@
 
 package org.apache.felix.ipojo.handlers.dependency;
 
-import java.util.*;
-
 import org.apache.felix.ipojo.*;
 import org.apache.felix.ipojo.architecture.HandlerDescription;
 import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.parser.FieldMetadata;
 import org.apache.felix.ipojo.parser.MethodMetadata;
 import org.apache.felix.ipojo.parser.PojoMetadata;
 import org.apache.felix.ipojo.util.*;
-import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
+
+import java.util.*;
 
 /**
  * The dependency handler manages a list of service dependencies.
+ *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class DependencyHandler extends PrimitiveHandler implements DependencyStateListener {
@@ -44,54 +42,81 @@ public class DependencyHandler extends P
      * Proxy settings property.
      */
     public static final String PROXY_SETTINGS_PROPERTY = "ipojo.proxy";
-
     /**
      * Proxy type property.
      */
     public static final String PROXY_TYPE_PROPERTY = "ipojo.proxy.type";
-
     /**
      * Proxy type value: smart.
      */
     public static final String SMART_PROXY = "smart";
-
     /**
      * Proxy type value: dynamic-proxy.
      */
     public static final String DYNAMIC_PROXY = "dynamic-proxy";
-
     /**
      * Proxy settings value: enabled.
      */
     public static final String PROXY_ENABLED = "enabled";
-
     /**
      * Proxy settings value: disabled.
      */
     public static final String PROXY_DISABLED = "disabled";
-
     /**
      * List of dependencies of the component.
      */
     private final List<Dependency> m_dependencies = new ArrayList<Dependency>();
-
     /**
      * Is the handler started.
      */
     private boolean m_started;
-
     /**
      * The handler description.
      */
     private DependencyHandlerDescription m_description;
-
     /**
      * The instance configuration context source, updated once reconfiguration.
      */
     private InstanceConfigurationSource m_instanceConfigurationSource;
 
     /**
+     * Builds a description of this dependency to help the user to identify it. IT's not related to the Dependency
+     * Description, it's just a string containing dependency information to spot it easily in the code.
+     *
+     * @param dep the dependency
+     * @return the identifier containing (if defined) the id, the specification, the field and the callback.
+     * @since 1.10.1
+     */
+    public static String getDependencyIdentifier(Dependency dep) {
+        StringBuilder identifier = new StringBuilder("{");
+        if (dep.getId() != null) {
+            identifier.append("id=").append(dep.getId());
+        }
+        if (dep.getField() != null) {
+            if (identifier.length() > 1) {
+                identifier.append(", ");
+            }
+            identifier.append("field=").append(dep.getField());
+        }
+        if (dep.getCallbacks() != null && dep.getCallbacks().length > 0) {
+            if (identifier.length() > 1) {
+                identifier.append(", ");
+            }
+            identifier.append("method=").append(dep.getCallbacks()[0].getMethodName());
+        }
+        if (dep.getSpecification() != null) {
+            if (identifier.length() > 1) {
+                identifier.append(", ");
+            }
+            identifier.append("specification=").append(dep.getSpecification().getName());
+        }
+        identifier.append("}");
+        return identifier.toString();
+    }
+
+    /**
      * Get the list of managed dependency.
+     *
      * @return the dependency list
      */
     public Dependency[] getDependencies() {
@@ -100,6 +125,7 @@ public class DependencyHandler extends P
 
     /**
      * Validate method. This method is invoked by an AbstractServiceDependency when this dependency becomes RESOLVED.
+     *
      * @param dep : the dependency becoming RESOLVED.
      * @see org.apache.felix.ipojo.util.DependencyStateListener#validate(org.apache.felix.ipojo.util.DependencyModel)
      */
@@ -109,6 +135,7 @@ public class DependencyHandler extends P
 
     /**
      * Invalidate method. This method is invoked by an AbstractServiceDependency when this dependency becomes UNRESOLVED or BROKEN.
+     *
      * @param dep : the dependency becoming UNRESOLVED or BROKEN.
      * @see org.apache.felix.ipojo.util.DependencyStateListener#invalidate(org.apache.felix.ipojo.util.DependencyModel)
      */
@@ -156,43 +183,10 @@ public class DependencyHandler extends P
     }
 
     /**
-     * Builds a description of this dependency to help the user to identify it. IT's not related to the Dependency
-     * Description, it's just a string containing dependency information to spot it easily in the code.
-     * @param dep the dependency
-     * @return the identifier containing (if defined) the id, the specification, the field and the callback.
-     * @since 1.10.1
-     */
-    public static String getDependencyIdentifier(Dependency dep) {
-        StringBuilder identifier = new StringBuilder("{");
-        if (dep.getId() != null) {
-            identifier.append("id=").append(dep.getId());
-        }
-        if (dep.getField() != null) {
-            if (identifier.length() > 1) {
-                identifier.append(", ");
-            }
-            identifier.append("field=").append(dep.getField());
-        }
-        if (dep.getCallbacks() != null  && dep.getCallbacks().length > 0) {
-            if (identifier.length() > 1) {
-                identifier.append(", ");
-            }
-            identifier.append("method=").append(dep.getCallbacks()[0].getMethodName());
-        }
-        if (dep.getSpecification() != null) {
-            if (identifier.length() > 1) {
-                identifier.append(", ");
-            }
-            identifier.append("specification=").append(dep.getSpecification().getName());
-        }
-        identifier.append("}");
-        return identifier.toString();
-    }
-
-    /**
      * Configure the handler.
+     *
      * @param componentMetadata : the component type metadata
-     * @param configuration : the instance configuration
+     * @param configuration     : the instance configuration
      * @throws ConfigurationException : one dependency metadata is not correct.
      * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
      */
@@ -256,8 +250,8 @@ public class DependencyHandler extends P
             // Add the constructor parameter if needed
             String paramIndex = dependencyElement.getAttribute("constructor-parameter");
             if (paramIndex != null) {
-            	int index = Integer.parseInt(paramIndex);
-            	dep.addConstructorInjection(index);
+                int index = Integer.parseInt(paramIndex);
+                dep.addConstructorInjection(index);
             }
 
             // Check the dependency, throws an exception on error.
@@ -277,6 +271,19 @@ public class DependencyHandler extends P
                     getInstanceManager().register(method, dep);
                 }
             }
+
+            // Also track the inner class methods
+            for (String inner : manipulation.getInnerClasses()) {
+                MethodMetadata[] meths = manipulation.getMethodsFromInnerClass(inner);
+                if (meths != null) {
+                    for (MethodMetadata method : meths) {
+                        for (Dependency dep : m_dependencies) {
+                            System.out.println("Registering " + method.getMethodName());
+                            getInstanceManager().register(method, inner, dep);
+                        }
+                    }
+                }
+            }
         }
 
         m_description = new DependencyHandlerDescription(this, getDependencies()); // Initialize the description.
@@ -286,6 +293,7 @@ public class DependencyHandler extends P
 
     /**
      * Add internal context source to all dependencies.
+     *
      * @param configuration the instance configuration to creates the instance configuration source
      */
     private void manageContextSources(Dictionary<String, Object> configuration) {
@@ -353,7 +361,7 @@ public class DependencyHandler extends P
             if (proxy.equals("false")) {
                 isProxy = false;
             } else if (proxy.equals("true")) {
-                if (! isProxy) { // The configuration overrides the system setting
+                if (!isProxy) { // The configuration overrides the system setting
                     warn("The configuration of a service dependency overrides the proxy mode");
                 }
                 isProxy = true;
@@ -446,39 +454,41 @@ public class DependencyHandler extends P
     }
 
     /**
-	 * Gets the requires filter configuration from the given object.
-	 * The given object must come from the instance configuration.
-	 * This method was made to fix FELIX-2688. It supports filter configuration using
-	 * an array:
-	 * <code>{"myFirstDep", "(property1=value1)", "mySecondDep", "(property2=value2)"});</code>
-	 * @param requiresFiltersValue the value contained in the instance
-	 * configuration.
-	 * @return the dictionary. If the object in already a dictionary, just returns it,
-	 * if it's an array, builds the dictionary.
-	 * @throws ConfigurationException the dictionary cannot be built
-	 */
-	private Dictionary getRequiresFilters(Object requiresFiltersValue)
-			throws ConfigurationException {
-		if (requiresFiltersValue != null
-				&& requiresFiltersValue.getClass().isArray()) {
-			String[] filtersArray = (String[]) requiresFiltersValue;
-			if (filtersArray.length % 2 != 0) {
-				throw new ConfigurationException(
-						"A requirement filter is invalid : "
-								+ requiresFiltersValue);
-			}
-			Dictionary<String, Object> requiresFilters = new Hashtable<String, Object>();
-			for (int i = 0; i < filtersArray.length; i += 2) {
-				requiresFilters.put(filtersArray[i], filtersArray[i + 1]);
-			}
-			return requiresFilters;
-		}
+     * Gets the requires filter configuration from the given object.
+     * The given object must come from the instance configuration.
+     * This method was made to fix FELIX-2688. It supports filter configuration using
+     * an array:
+     * <code>{"myFirstDep", "(property1=value1)", "mySecondDep", "(property2=value2)"});</code>
+     *
+     * @param requiresFiltersValue the value contained in the instance
+     *                             configuration.
+     * @return the dictionary. If the object in already a dictionary, just returns it,
+     *         if it's an array, builds the dictionary.
+     * @throws ConfigurationException the dictionary cannot be built
+     */
+    private Dictionary getRequiresFilters(Object requiresFiltersValue)
+            throws ConfigurationException {
+        if (requiresFiltersValue != null
+                && requiresFiltersValue.getClass().isArray()) {
+            String[] filtersArray = (String[]) requiresFiltersValue;
+            if (filtersArray.length % 2 != 0) {
+                throw new ConfigurationException(
+                        "A requirement filter is invalid : "
+                                + requiresFiltersValue);
+            }
+            Dictionary<String, Object> requiresFilters = new Hashtable<String, Object>();
+            for (int i = 0; i < filtersArray.length; i += 2) {
+                requiresFilters.put(filtersArray[i], filtersArray[i + 1]);
+            }
+            return requiresFilters;
+        }
 
-		return (Dictionary) requiresFiltersValue;
-	}
+        return (Dictionary) requiresFiltersValue;
+    }
 
     /**
      * Handler start method.
+     *
      * @see org.apache.felix.ipojo.Handler#start()
      */
     public void start() {
@@ -494,6 +504,7 @@ public class DependencyHandler extends P
 
     /**
      * Handler stop method.
+     *
      * @see org.apache.felix.ipojo.Handler#stop()
      */
     public void stop() {
@@ -505,6 +516,7 @@ public class DependencyHandler extends P
 
     /**
      * Handler createInstance method. This method is override to allow delayed callback invocation.
+     *
      * @param instance : the created object
      * @see org.apache.felix.ipojo.PrimitiveHandler#onCreation(Object)
      */
@@ -516,6 +528,7 @@ public class DependencyHandler extends P
 
     /**
      * Get the dependency handler description.
+     *
      * @return the dependency handler description.
      * @see org.apache.felix.ipojo.Handler#getDescription()
      */
@@ -525,6 +538,7 @@ public class DependencyHandler extends P
 
     /**
      * The instance is reconfigured.
+     *
      * @param configuration the new instance configuration.
      */
     @Override