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;