Author: davidb
Date: Wed Sep 28 13:06:56 2011
New Revision: 1176865

URL: http://svn.apache.org/viewvc?rev=1176865&view=rev
Log:
Improved weaving code thanks to Tim Ward!


Modified:
    
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java
    
aries/trunk/spi-fly/spi-fly-weaver/src/main/java/org/apache/aries/spifly/weaver/TCCLSetterVisitor.java

Modified: 
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java?rev=1176865&r1=1176864&r2=1176865&view=diff
==============================================================================
--- 
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java
 (original)
+++ 
aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/main/java/org/apache/aries/spifly/dynamic/ClientWeavingHook.java
 Wed Sep 28 13:06:56 2011
@@ -57,7 +57,7 @@ public class ClientWeavingHook implement
                ClassReader cr = new ClassReader(wovenClass.getBytes());
                ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | 
ClassWriter.COMPUTE_FRAMES);
                TCCLSetterVisitor tsv = new TCCLSetterVisitor(cw, 
wovenClass.getClassName(), wd);
-               cr.accept(tsv, 0);
+               cr.accept(tsv, ClassReader.SKIP_FRAMES);
                wovenClass.setBytes(cw.toByteArray());
                if (tsv.additionalImportRequired())
                    wovenClass.getDynamicImports().add(addedImport);

Modified: 
aries/trunk/spi-fly/spi-fly-weaver/src/main/java/org/apache/aries/spifly/weaver/TCCLSetterVisitor.java
URL: 
http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-weaver/src/main/java/org/apache/aries/spifly/weaver/TCCLSetterVisitor.java?rev=1176865&r1=1176864&r2=1176865&view=diff
==============================================================================
--- 
aries/trunk/spi-fly/spi-fly-weaver/src/main/java/org/apache/aries/spifly/weaver/TCCLSetterVisitor.java
 (original)
+++ 
aries/trunk/spi-fly/spi-fly-weaver/src/main/java/org/apache/aries/spifly/weaver/TCCLSetterVisitor.java
 Wed Sep 28 13:06:56 2011
@@ -28,22 +28,28 @@ import org.apache.aries.spifly.WeavingDa
 import org.objectweb.asm.ClassAdapter;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodAdapter;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.GeneratorAdapter;
+import org.objectweb.asm.commons.Method;
 
 /**
  * This class implements an ASM ClassVisitor which puts the appropriate 
ThreadContextClassloader
  * calls around applicable method invocations. It does the actual bytecode 
weaving.
  */
 public class TCCLSetterVisitor extends ClassAdapter implements ClassVisitor, 
Opcodes {
+    private static final Type CLASSLOADER_TYPE = 
Type.getType(ClassLoader.class);
+
     private static final String GENERATED_METHOD_NAME = "$$FCCL$$";
 
-    private static final String UTIL_CLASS = Util.class.getName().replace('.', 
'/');
-    private static final String VOID_RETURN_TYPE = "()V";
+    private static final Type UTIL_CLASS = Type.getType(Util.class);
+
+    private static final Type CLASS_TYPE = Type.getType(Class.class);
+    
+    private static final Type String_TYPE = Type.getType(String.class);
 
-    private final String targetClass;
+    private final Type targetClass;
     private final Set<WeavingData> weavingData;
 
     // Set to true when the weaving code has changed the client such that an 
additional import
@@ -52,7 +58,7 @@ public class TCCLSetterVisitor extends C
 
     public TCCLSetterVisitor(ClassVisitor cv, String className, 
Set<WeavingData> weavingData) {
         super(cv);
-        this.targetClass = className.replace('.', '/');
+        this.targetClass = Type.getType("L" + className.replace('.', '/') + 
";");
         this.weavingData = weavingData;
     }
 
@@ -62,7 +68,7 @@ public class TCCLSetterVisitor extends C
         System.out.println("@@@ " + access + ": " + name + "#" + desc + "#" + 
signature + "~" + Arrays.toString(exceptions));
 
         MethodVisitor mv = super.visitMethod(access, name, desc, signature, 
exceptions);
-        return new TCCLSetterMethodVisitor(mv);
+        return new TCCLSetterMethodVisitor(mv, access, name, desc);
     }
 
     @Override
@@ -81,24 +87,28 @@ public class TCCLSetterVisitor extends C
                  continue;
 
              methodNames.add(methodName);
-             MethodVisitor mv = cv.visitMethod(ACC_PRIVATE + ACC_STATIC, 
methodName,
-                     "(Ljava/lang/Class;)V", "(Ljava/lang/Class<*>;)V", null);
-             mv.visitCode();
+             Method method = new Method(methodName, Type.VOID_TYPE, new Type[] 
{CLASS_TYPE});
+             
+             GeneratorAdapter mv = new 
GeneratorAdapter(cv.visitMethod(ACC_PRIVATE + ACC_STATIC, methodName,
+                     method.getDescriptor(), null, null), ACC_PRIVATE + 
ACC_STATIC, methodName,
+                     method.getDescriptor());
+             
+             //Load the strings, method parameter and target
              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();
+             mv.loadArg(0);
+             mv.visitLdcInsn(targetClass);
+             
+             //Change the class on the stack into a classloader
+             mv.invokeVirtual(CLASS_TYPE, new Method("getClassLoader", 
+                 CLASSLOADER_TYPE, new Type[0]));
+             
+             //Call our util method
+             mv.invokeStatic(UTIL_CLASS, new Method("fixContextClassloader", 
Type.VOID_TYPE, 
+                 new Type[] {String_TYPE, String_TYPE, CLASS_TYPE, 
CLASSLOADER_TYPE}));
+             
+             mv.returnValue();
+             mv.endMethod();
         }
 
         super.visitEnd();
@@ -118,12 +128,12 @@ public class TCCLSetterVisitor extends C
         return name.toString();
     }
 
-    private class TCCLSetterMethodVisitor extends MethodAdapter implements 
MethodVisitor
+    private class TCCLSetterMethodVisitor extends GeneratorAdapter implements 
MethodVisitor
     {
         Type lastLDCType;
 
-        public TCCLSetterMethodVisitor(MethodVisitor mv) {
-            super(mv);
+        public TCCLSetterMethodVisitor(MethodVisitor mv, int access, String 
name, String descriptor) {
+            super(mv, access, name, descriptor);
         }
 
         /**
@@ -155,17 +165,18 @@ public class TCCLSetterVisitor extends C
                 System.out.println("+++ Gotcha!");
 
                 additionalImportRequired = true;
-
-                // try/finally setup
-                // Add: try {
-                Label l0 = new Label();
-                Label l1 = new Label();
-                mv.visitTryCatchBlock(l0, l1, l1, null);
-                mv.visitLabel(l0);
+                
+                Label startTry = newLabel();
+                Label endTry = newLabel();
+                
+                //start try block
+                visitTryCatchBlock(startTry, endTry, endTry, null);
+                mark(startTry);
+                
                 // Add: Util.storeContextClassloader();
-                mv.visitMethodInsn(INVOKESTATIC, UTIL_CLASS,
-                        "storeContextClassloader", VOID_RETURN_TYPE);
-
+                invokeStatic(UTIL_CLASS, new Method("storeContextClassloader", 
Type.VOID_TYPE, new Type[0]));
+                
+                
                 // Add: MyClass.$$FCCL$$<classname>$<methodname>(<class>);
                 if (ServiceLoader.class.getName().equals(wd.getClassName()) &&
                     "load".equals(wd.getMethodName()) &&
@@ -173,6 +184,7 @@ public class TCCLSetterVisitor extends C
                     // 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.
+                    
                     mv.visitLdcInsn(lastLDCType);
                 } else {
                     // In any other case, we're not dealing with a 
general-purpose service loader, but rather
@@ -181,30 +193,27 @@ public class TCCLSetterVisitor extends C
                     Type type = Type.getObjectType(owner);
                     mv.visitLdcInsn(type);
                 }
-                mv.visitMethodInsn(INVOKESTATIC, targetClass,
-                        getGeneratedMethodName(wd), "(Ljava/lang/Class;)V");
+                invokeStatic(targetClass, new 
Method(getGeneratedMethodName(wd),
+                    Type.VOID_TYPE, new Type[] {CLASS_TYPE}));
 
+                //Call the original instruction
                 super.visitMethodInsn(opcode, owner, name, desc);
 
-                // end the try part and do the finally part
-                // Add: } finally { Util.restoreContextClassLoader(); }
-                Label l2 = new Label();
-                mv.visitJumpInsn(GOTO, l2);
-                mv.visitLabel(l1);
-                mv.visitFrame(F_FULL, 2, new Object[] {"[Ljava/lang/String;", 
"java/lang/ClassLoader"}, 1, new Object[] {"java/lang/Throwable"});
-                mv.visitVarInsn(ASTORE, 2);
-                mv.visitMethodInsn(INVOKESTATIC, UTIL_CLASS,
-                        "restoreContextClassloader", VOID_RETURN_TYPE);
-//                mv.visitMethodInsn(INVOKESTATIC, UTIL_CLASS,
-//                        "storeContextClassloader", VOID_RETURN_TYPE);
-                mv.visitVarInsn(ALOAD, 2);
-                mv.visitInsn(ATHROW);
-                mv.visitLabel(l2);
-                mv.visitFrame(F_SAME, 0, null, 0, null);
-                mv.visitMethodInsn(INVOKESTATIC, UTIL_CLASS,
-                        "restoreContextClassloader", VOID_RETURN_TYPE);
-//                mv.visitMethodInsn(INVOKESTATIC, UTIL_CLASS,
-//                        "storeContextClassloader", VOID_RETURN_TYPE);
+                //If no exception then go to the finally (finally blocks are a 
catch block with a jump)
+                Label afterCatch = newLabel();
+                goTo(afterCatch);
+                
+                
+                //start the catch 
+                mark(endTry);
+                //Run the restore method then throw on the exception
+                invokeStatic(UTIL_CLASS, new 
Method("restoreContextClassloader", Type.VOID_TYPE, new Type[0]));
+                throwException();
+                
+                //start the finally
+                mark(afterCatch);
+                //Run the restore and continue
+                invokeStatic(UTIL_CLASS, new 
Method("restoreContextClassloader", Type.VOID_TYPE, new Type[0]));
             } else {
                 super.visitMethodInsn(opcode, owner, name, desc);
             }


Reply via email to