You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by da...@apache.org on 2010/12/23 11:37:09 UTC
svn commit: r1052217 - in
/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook:
SpiFly/src/org/apache/aries/spifly/ SpiFlyTests/src/org/apache/aries/spifly/
Author: davidb
Date: Thu Dec 23 10:37:08 2010
New Revision: 1052217
URL: http://svn.apache.org/viewvc?rev=1052217&view=rev
Log:
Support multiple WeavingData instances per client.
Modified:
incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/ClientWeavingHook.java
incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/TCCLSetterVisitor.java
incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/WeavingData.java
incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/ClientWeavingHookTest.java
Modified: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/ClientWeavingHook.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/ClientWeavingHook.java?rev=1052217&r1=1052216&r2=1052217&view=diff
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/ClientWeavingHook.java (original)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/ClientWeavingHook.java Thu Dec 23 10:37:08 2010
@@ -54,7 +54,7 @@ public class ClientWeavingHook implement
if (consumerHeader != null) {
Activator.activator.log(LogService.LOG_DEBUG, "Weaving class " + wovenClass.getClassName());
- WeavingData wd = processHeader(consumerBundle, consumerHeader);
+ WeavingData[] wd = processHeader(consumerBundle, consumerHeader);
ClassReader cr = new ClassReader(wovenClass.getBytes());
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
@@ -91,10 +91,11 @@ public class ClientWeavingHook implement
* @param consumerHeader the <tt>SPI-Consumer</tt> header.
* @return an instance of the {@link WeavingData} class.
*/
- private WeavingData processHeader(Bundle consumerBundle, String consumerHeader) {
- List<BundleDescriptor> allowedBundles = new ArrayList<BundleDescriptor>();
-
+ private WeavingData[] processHeader(Bundle consumerBundle, String consumerHeader) {
+ Set<WeavingData> weavingData = new HashSet<WeavingData>();
+
for (PathElement element : HeaderParser.parseHeader(consumerHeader)) {
+ List<BundleDescriptor> allowedBundles = new ArrayList<BundleDescriptor>();
String name = element.getName().trim();
String className;
@@ -179,9 +180,8 @@ public class ClientWeavingHook implement
allowedBundles.size() == 0 ? null : allowedBundles);
String[] argClasses = restriction.getMethodRestriction(methodName).getArgClasses();
- // TODO support more than one definition
- return new WeavingData(className, methodName, argClasses);
+ weavingData.add(new WeavingData(className, methodName, argClasses));
}
- return null;
+ return weavingData.toArray(new WeavingData [weavingData.size()]);
}
}
Modified: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/TCCLSetterVisitor.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/TCCLSetterVisitor.java?rev=1052217&r1=1052216&r2=1052217&view=diff
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/TCCLSetterVisitor.java (original)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/TCCLSetterVisitor.java Thu Dec 23 10:37:08 2010
@@ -39,13 +39,13 @@ public class TCCLSetterVisitor extends C
private static final String VOID_RETURN_TYPE = "()V";
private final String targetClass;
- private final WeavingData weavingData;
+ private final WeavingData [] weavingData;
// Set to true when the weaving code has changed the client such that an additional import
// (to the Util.class.getPackage()) is needed.
private boolean additionalImportRequired = false;
- public TCCLSetterVisitor(ClassVisitor cv, String className, WeavingData weavingData) {
+ public TCCLSetterVisitor(ClassVisitor cv, String className, WeavingData [] weavingData) {
super(cv);
this.targetClass = className.replace('.', '/');
this.weavingData = weavingData;
@@ -64,32 +64,48 @@ public class TCCLSetterVisitor extends C
public void visitEnd() {
// Add generated static method
- /* Equivalent to:
- * private static void $$FCCL$$(Class<?> cls) {
- * Util.fixContextClassLoader("java.util.ServiceLoader", "load", cls, WovenClass.class.getClassLoader());
- * }
- */
- MethodVisitor mv = cv.visitMethod(ACC_PRIVATE + ACC_STATIC, GENERATED_METHOD_NAME,
- "(Ljava/lang/Class;)V", "(Ljava/lang/Class<*>;)V", null);
- mv.visitCode();
- mv.visitLdcInsn(weavingData.getClassName());
- mv.visitLdcInsn(weavingData.getMethodName());
- mv.visitVarInsn(ALOAD, 0);
- String typeIdentifier = "L" + targetClass + ";";
- mv.visitLdcInsn(Type.getType(typeIdentifier));
- mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class",
- "getClassLoader", "()Ljava/lang/ClassLoader;");
- mv.visitMethodInsn(
- INVOKESTATIC,
- "org/apache/aries/spifly/Util",
- "fixContextClassloader",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/ClassLoader;)V");
- mv.visitInsn(RETURN);
- mv.visitMaxs(4, 1);
- mv.visitEnd();
+ for (WeavingData wd : weavingData) {
+ /* Equivalent to:
+ * private static void $$FCCL$$<className>$<methodName>(Class<?> cls) {
+ * Util.fixContextClassLoader("java.util.ServiceLoader", "load", cls, WovenClass.class.getClassLoader());
+ * }
+ */
+ MethodVisitor mv = cv.visitMethod(ACC_PRIVATE + ACC_STATIC, getGeneratedMethodName(wd),
+ "(Ljava/lang/Class;)V", "(Ljava/lang/Class<*>;)V", null);
+ mv.visitCode();
+ mv.visitLdcInsn(wd.getClassName());
+ mv.visitLdcInsn(wd.getMethodName());
+ mv.visitVarInsn(ALOAD, 0);
+ String typeIdentifier = "L" + targetClass + ";";
+ mv.visitLdcInsn(Type.getType(typeIdentifier));
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class",
+ "getClassLoader", "()Ljava/lang/ClassLoader;");
+ mv.visitMethodInsn(
+ INVOKESTATIC,
+ "org/apache/aries/spifly/Util",
+ "fixContextClassloader",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/ClassLoader;)V");
+ mv.visitInsn(RETURN);
+ mv.visitMaxs(4, 1);
+ mv.visitEnd();
+ }
super.visitEnd();
}
+
+ private String getGeneratedMethodName(WeavingData wd) {
+ StringBuilder name = new StringBuilder(GENERATED_METHOD_NAME);
+ name.append(wd.getClassName().replace('.', '#'));
+ name.append("$");
+ name.append(wd.getMethodName());
+ if (wd.getArgClasses() != null) {
+ for (String cls : wd.getArgClasses()) {
+ name.append("$");
+ name.append(cls.replace('.', '#'));
+ }
+ }
+ return name.toString();
+ }
private class TCCLSetterMethodVisitor extends MethodAdapter implements MethodVisitor
{
@@ -122,17 +138,9 @@ public class TCCLSetterVisitor extends C
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
System.out.println("### " + opcode + ": " + owner + "#" + name + "#" + desc);
-
- Type[] argTypes = Type.getArgumentTypes(desc);
- String [] argClassNames = new String[argTypes.length];
- for (int i = 0; i < argTypes.length; i++) {
- argClassNames[i] = argTypes[i].getClassName();
- }
-
- if (opcode == INVOKESTATIC &&
- weavingData.getClassName().replace('.', '/').equals(owner) &&
- weavingData.getMethodName().equals(name) &&
- (weavingData.getArgClasses() != null ? Arrays.equals(argClassNames, weavingData.getArgClasses()) : true)) {
+
+ WeavingData wd = findWeavingData(owner, name, desc);
+ if (opcode == INVOKESTATIC && wd != null) {
System.out.println("+++ Gotcha!");
additionalImportRequired = true;
@@ -141,10 +149,10 @@ public class TCCLSetterVisitor extends C
mv.visitMethodInsn(INVOKESTATIC, UTIL_CLASS,
"storeContextClassloader", VOID_RETURN_TYPE);
- // Add: MyClass.$$FCCL$$(<class>);
- if (ServiceLoader.class.getName().equals(weavingData.getClassName()) &&
- "load".equals(weavingData.getMethodName()) &&
- Arrays.equals(new String [] {Class.class.getName()}, weavingData.getArgClasses())) {
+ // Add: MyClass.$$FCCL$$<classname>$<methodname>(<class>);
+ if (ServiceLoader.class.getName().equals(wd.getClassName()) &&
+ "load".equals(wd.getMethodName()) &&
+ Arrays.equals(new String [] {Class.class.getName()}, wd.getArgClasses())) {
// ServiceLoader.load() is a special case because it's a general-purpose service loader,
// therefore, the target class it the class being passed in to the ServiceLoader.load()
// call itself.
@@ -157,7 +165,7 @@ public class TCCLSetterVisitor extends C
mv.visitLdcInsn(type);
}
mv.visitMethodInsn(INVOKESTATIC, targetClass,
- GENERATED_METHOD_NAME, "(Ljava/lang/Class;)V");
+ getGeneratedMethodName(wd), "(Ljava/lang/Class;)V");
super.visitMethodInsn(opcode, owner, name, desc);
@@ -168,6 +176,25 @@ public class TCCLSetterVisitor extends C
super.visitMethodInsn(opcode, owner, name, desc);
}
}
+
+ private WeavingData findWeavingData(String owner, String methodName, String methodDesc) {
+ owner = owner.replace('/', '.');
+
+ Type[] argTypes = Type.getArgumentTypes(methodDesc);
+ String [] argClassNames = new String[argTypes.length];
+ for (int i = 0; i < argTypes.length; i++) {
+ argClassNames[i] = argTypes[i].getClassName();
+ }
+
+ for (WeavingData wd : weavingData) {
+ if (wd.getClassName().equals(owner) &&
+ wd.getMethodName().equals(methodName) &&
+ (wd.getArgClasses() != null ? Arrays.equals(argClassNames, wd.getArgClasses()) : true)) {
+ return wd;
+ }
+ }
+ return null;
+ }
}
public boolean additionalImportRequired() {
Modified: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/WeavingData.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/WeavingData.java?rev=1052217&r1=1052216&r2=1052217&view=diff
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/WeavingData.java (original)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/WeavingData.java Thu Dec 23 10:37:08 2010
@@ -18,7 +18,8 @@
*/
package org.apache.aries.spifly;
-import java.util.Map;
+import java.util.Arrays;
+
public class WeavingData {
private final String className;
@@ -41,5 +42,44 @@ public class WeavingData {
public String[] getArgClasses() {
return argClasses;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(argClasses);
+ result = prime * result + ((className == null) ? 0 : className.hashCode());
+ result = prime * result + ((methodName == null) ? 0 : methodName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+
+ if (obj == null)
+ return false;
+
+ if (getClass() != obj.getClass())
+ return false;
+
+ WeavingData other = (WeavingData) obj;
+ if (!Arrays.equals(argClasses, other.argClasses))
+ return false;
+ if (className == null) {
+ if (other.className != null)
+ return false;
+ } else if (!className.equals(other.className))
+ return false;
+ if (methodName == null) {
+ if (other.methodName != null)
+ return false;
+ } else if (!methodName.equals(other.methodName))
+ return false;
+ return true;
}
+
+
}
Modified: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/ClientWeavingHookTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/ClientWeavingHookTest.java?rev=1052217&r1=1052216&r2=1052217&view=diff
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/ClientWeavingHookTest.java (original)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/ClientWeavingHookTest.java Thu Dec 23 10:37:08 2010
@@ -238,7 +238,7 @@ public class ClientWeavingHookTest {
Class<?> cls = wc.getDefinedClass();
Method method = cls.getMethod("test", new Class [] {String.class});
Object result = method.invoke(cls.newInstance(), "hello");
- Assert.assertEquals("All providers should be selected for this one", "ollehHELLO5", result);
+ Assert.assertEquals("All providers should be selected for this one", "ollehHELLO5impl4", result);
// Weave the AltTestClient class.
URL cls2Url = getClass().getResource("AltTestClient.class");
@@ -249,7 +249,7 @@ public class ClientWeavingHookTest {
Class<?> cls2 = wc2.getDefinedClass();
Method method2 = cls2.getMethod("test", new Class [] {long.class});
Object result2 = method2.invoke(cls2.newInstance(), 4096);
- Assert.assertEquals("Only the services from bundle impl4 should be selected", 8192, result2);
+ Assert.assertEquals("Only the services from bundle impl4 should be selected", -4096L*4096L, result2);
}
@Test
@@ -385,11 +385,11 @@ public class ClientWeavingHookTest {
// The BundleWiring API is used on the bundle by the generated code to obtain its classloader
BundleWiring bw = EasyMock.createMock(BundleWiring.class);
- EasyMock.expect(bw.getClassLoader()).andReturn(cl);
+ EasyMock.expect(bw.getClassLoader()).andReturn(cl).anyTimes();
EasyMock.replay(bw);
Bundle providerBundle = EasyMock.createMock(Bundle.class);
- EasyMock.expect(providerBundle.adapt(BundleWiring.class)).andReturn(bw);
+ EasyMock.expect(providerBundle.adapt(BundleWiring.class)).andReturn(bw).anyTimes();
EasyMock.expect(providerBundle.getSymbolicName()).andReturn(subdir).anyTimes();
EasyMock.expect(providerBundle.getBundleId()).andReturn(id).anyTimes();
EasyMock.expect(providerBundle.getVersion()).andReturn(version).anyTimes();
@@ -404,14 +404,14 @@ public class ClientWeavingHookTest {
Bundle consumerBundle = EasyMock.createMock(Bundle.class);
EasyMock.expect(consumerBundle.getSymbolicName()).andReturn("testConsumer").anyTimes();
- EasyMock.expect(consumerBundle.getHeaders()).andReturn(headers);
- EasyMock.expect(consumerBundle.getBundleContext()).andReturn(bc);
+ EasyMock.expect(consumerBundle.getHeaders()).andReturn(headers).anyTimes();
+ EasyMock.expect(consumerBundle.getBundleContext()).andReturn(bc).anyTimes();
EasyMock.expect(consumerBundle.getBundleId()).andReturn(Long.MAX_VALUE).anyTimes();
EasyMock.replay(consumerBundle);
List<Bundle> allBundles = new ArrayList<Bundle>(Arrays.asList(otherBundles));
allBundles.add(consumerBundle);
- EasyMock.expect(bc.getBundles()).andReturn(allBundles.toArray(new Bundle [] {}));
+ EasyMock.expect(bc.getBundles()).andReturn(allBundles.toArray(new Bundle [] {})).anyTimes();
EasyMock.replay(bc);
return consumerBundle;