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);
}