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 2011/09/23 14:24:42 UTC

svn commit: r1174696 - in /aries/trunk/spi-fly: spi-fly-dynamic-bundle/src/test/java/org/apache/aries/spifly/dynamic/ClientWeavingHookTest.java spi-fly-weaver/src/main/java/org/apache/aries/spifly/weaver/TCCLSetterVisitor.java

Author: davidb
Date: Fri Sep 23 12:24:41 2011
New Revision: 1174696

URL: http://svn.apache.org/viewvc?rev=1174696&view=rev
Log:
Use bytecode generation to generate try/finally around TCCL setting

Initial implementation, open to feedback.
Some unit tests include, more unit tests to come.


Modified:
    aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/test/java/org/apache/aries/spifly/dynamic/ClientWeavingHookTest.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/test/java/org/apache/aries/spifly/dynamic/ClientWeavingHookTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/test/java/org/apache/aries/spifly/dynamic/ClientWeavingHookTest.java?rev=1174696&r1=1174695&r2=1174696&view=diff
==============================================================================
--- aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/test/java/org/apache/aries/spifly/dynamic/ClientWeavingHookTest.java (original)
+++ aries/trunk/spi-fly/spi-fly-dynamic-bundle/src/test/java/org/apache/aries/spifly/dynamic/ClientWeavingHookTest.java Fri Sep 23 12:24:41 2011
@@ -71,7 +71,7 @@ public class ClientWeavingHookTest {
     }
 
     @Test
-    public void testClientWeavingHookBasicServiveLoaderUsage() throws Exception {
+    public void testBasicServiveLoaderUsage() throws Exception {
         Dictionary<String, String> consumerHeaders = new Hashtable<String, String>();
         consumerHeaders.put(SpiFlyConstants.SPI_CONSUMER_HEADER, "*");
 
@@ -99,7 +99,7 @@ public class ClientWeavingHookTest {
         String di = wc.getDynamicImports().get(0);
         Assert.assertTrue("Weaving should have added a dynamic import", di1.equals(di) || di2.equals(di));
 
-        // Invoke the woven class and check that it propertly sets the TCCL so that the
+        // Invoke the woven class and check that it properly sets the TCCL so that the
         // META-INF/services/org.apache.aries.mytest.MySPI file from impl1 is visible.
         Class<?> cls = wc.getDefinedClass();
         Method method = cls.getMethod("test", new Class [] {String.class});
@@ -108,7 +108,54 @@ public class ClientWeavingHookTest {
     }
 
     @Test
-    public void testClientWeavingHookAltServiceLoaderLoadUnprocessed() throws Exception {
+    public void testTCCLResetting() throws Exception {
+        ClassLoader cl = new URLClassLoader(new URL [] {});
+        Thread.currentThread().setContextClassLoader(cl);
+        Assert.assertSame("Precondition", cl, Thread.currentThread().getContextClassLoader());
+
+        Dictionary<String, String> consumerHeaders = new Hashtable<String, String>();
+        consumerHeaders.put(SpiFlyConstants.SPI_CONSUMER_HEADER, "*");
+
+        // Register the bundle that provides the SPI implementation.
+        Bundle providerBundle = mockProviderBundle("impl1", 1);
+        activator.registerProviderBundle("org.apache.aries.mytest.MySPI", providerBundle);
+
+        Bundle consumerBundle = mockConsumerBundle(consumerHeaders, providerBundle);
+        activator.addConsumerWeavingData(consumerBundle, SpiFlyConstants.SPI_CONSUMER_HEADER);
+
+        Bundle spiFlyBundle = mockSpiFlyBundle("spifly", Version.parseVersion("1.9.4"), consumerBundle, providerBundle);
+        WeavingHook wh = new ClientWeavingHook(spiFlyBundle.getBundleContext(), activator);
+
+        // Weave the TestClient class.
+        URL clsUrl = getClass().getResource("TestClient.class");
+        Assert.assertNotNull("Precondition", clsUrl);
+
+        String clientClassName = "org.apache.aries.spifly.dynamic.TestClient";
+        WovenClass wc = new MyWovenClass(clsUrl, clientClassName, consumerBundle);
+        Assert.assertEquals("Precondition", 0, wc.getDynamicImports().size());
+        wh.weave(wc);
+        Assert.assertEquals(1, wc.getDynamicImports().size());
+        String di1 = "org.apache.aries.spifly;bundle-symbolic-name=spifly;bundle-version=1.9.4";
+        String di2 = "org.apache.aries.spifly;bundle-version=1.9.4;bundle-symbolic-name=spifly";
+        String di = wc.getDynamicImports().get(0);
+        Assert.assertTrue("Weaving should have added a dynamic import", di1.equals(di) || di2.equals(di));
+
+        // Invoke the woven class and check that it properly sets the TCCL so that the
+        // META-INF/services/org.apache.aries.mytest.MySPI file from impl1 is visible.
+        Class<?> cls = wc.getDefinedClass();
+        Method method = cls.getMethod("test", new Class [] {String.class});
+        method.invoke(cls.newInstance(), "hi there");
+
+        Assert.assertSame(cl, Thread.currentThread().getContextClassLoader());
+    }
+
+    @Test
+    public void testTCCLResettingOnException() {
+        // TODO
+    }
+
+    @Test
+    public void testAltServiceLoaderLoadUnprocessed() throws Exception {
         Bundle spiFlyBundle = mockSpiFlyBundle();
 
         Dictionary<String, String> headers = new Hashtable<String, String>();
@@ -140,7 +187,7 @@ public class ClientWeavingHookTest {
     }
 
     @Test
-    public void testClientWeavingHookMultipleProviders() throws Exception {
+    public void testMultipleProviders() throws Exception {
         Bundle spiFlyBundle = mockSpiFlyBundle();
 
         Dictionary<String, String> headers = new Hashtable<String, String>();

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=1174696&r1=1174695&r2=1174696&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 Fri Sep 23 12:24:41 2011
@@ -27,6 +27,7 @@ import org.apache.aries.spifly.Util;
 import org.apache.aries.spifly.WeavingData;
 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;
@@ -155,6 +156,12 @@ public class TCCLSetterVisitor extends C
 
                 additionalImportRequired = true;
 
+                // try/finally setup
+                // Add: try {
+                Label l0 = new Label();
+                Label l1 = new Label();
+                mv.visitTryCatchBlock(l0, l1, l1, null);
+                mv.visitLabel(l0);
                 // Add: Util.storeContextClassloader();
                 mv.visitMethodInsn(INVOKESTATIC, UTIL_CLASS,
                         "storeContextClassloader", VOID_RETURN_TYPE);
@@ -179,9 +186,25 @@ public class TCCLSetterVisitor extends C
 
                 super.visitMethodInsn(opcode, owner, name, desc);
 
-                // Add: Util.restoreContextClassloader();
+                // 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);
             } else {
                 super.visitMethodInsn(opcode, owner, name, desc);
             }