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