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/21 09:05:16 UTC
svn commit: r1051409 - in
/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook:
SpiFly/src/org/apache/aries/spifly/ SpiFlyTests/src/org/apache/aries/spifly/
SpiFlyTests/src/org/apache/aries/spifly/impl4/
SpiFlyTests/src/org/apache/aries/spifl...
Author: davidb
Date: Tue Dec 21 08:05:15 2010
New Revision: 1051409
URL: http://svn.apache.org/viewvc?rev=1051409&view=rev
Log:
Ability to deal with distinguishing overloads, e.g. ServiceLoader.load(Class) != ServiceLoader.load(Class, ClassLoader)
Added:
incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/UnaffectedTestClient.java
incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/
incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/META-INF/
incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/META-INF/services/
incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/META-INF/services/org.apache.aries.mytest.MySPI
incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/MySPIImpl4.java
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=1051409&r1=1051408&r2=1051409&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 Tue Dec 21 08:05:15 2010
@@ -19,7 +19,6 @@
package org.apache.aries.spifly;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import java.util.ServiceLoader;
@@ -58,12 +57,21 @@ 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, 0);
wovenClass.setBytes(cw.toByteArray());
- wovenClass.getDynamicImports().add(addedImport);
+ if (tsv.additionalImportRequired())
+ wovenClass.getDynamicImports().add(addedImport);
}
}
+ /**
+ * Parses headers of the following syntax:
+ * <ul>
+ * </ul>
+ * @param consumerBundle
+ * @param consumerHeader
+ * @return
+ */
private WeavingData parseHeader(Bundle consumerBundle, String consumerHeader) {
List<Bundle> selectedBundles = new ArrayList<Bundle>();
@@ -71,22 +79,37 @@ public class ClientWeavingHook implement
String name = element.getName().trim();
String className;
String methodName;
+ String[] argClasses;
int hashIdx = name.indexOf('#');
if (hashIdx > 0) {
className = name.substring(0, hashIdx);
int braceIdx = name.substring(hashIdx).indexOf('(');
if (braceIdx > 0) {
methodName = name.substring(hashIdx + 1, hashIdx + braceIdx);
+ int closeIdx = name.substring(hashIdx).indexOf(')');
+ if (closeIdx > 0) {
+ String classes = name.substring(hashIdx + braceIdx + 1, hashIdx + closeIdx).trim();
+ if (classes.length() > 0) {
+ argClasses = classes.split(",");
+ } else {
+ argClasses = null;
+ }
+ } else {
+ argClasses = null;
+ }
} else {
- methodName = name.substring(hashIdx + 1);
+ methodName = name.substring(hashIdx + 1);
+ argClasses = null;
}
} else {
if ("true".equalsIgnoreCase(name)) {
className = ServiceLoader.class.getName();
methodName = "load";
+ argClasses = new String [] { Class.class.getName() };
} else {
className = name;
methodName = null;
+ argClasses = null;
}
}
@@ -118,7 +141,7 @@ public class ClientWeavingHook implement
Activator.activator.registerConsumerBundle(consumerBundle, selectedBundles);
// TODO support more than one definition
- return new WeavingData(className, methodName, 1);
+ return new WeavingData(className, methodName, argClasses);
}
return null;
}
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=1051409&r1=1051408&r2=1051409&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 Tue Dec 21 08:05:15 2010
@@ -41,6 +41,10 @@ public class TCCLSetterVisitor extends C
private final String targetClass;
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) {
super(cv);
this.targetClass = className.replace('.', '/');
@@ -119,22 +123,37 @@ public class TCCLSetterVisitor extends C
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.getMethodName().equals(name) &&
+ (weavingData.getArgClasses() != null ? Arrays.equals(argClassNames, weavingData.getArgClasses()) : true)) {
System.out.println("+++ Gotcha!");
+ additionalImportRequired = true;
+
// Add: Util.storeContextClassloader();
mv.visitMethodInsn(INVOKESTATIC, UTIL_CLASS,
"storeContextClassloader", VOID_RETURN_TYPE);
- // Add: MyClass.$$FCCL$$(<class>);
-
- // The class is the same class as the one passed into the ServiceLoader.load() api.
+
+ // Add: MyClass.$$FCCL$$(<class>);
if (ServiceLoader.class.getName().equals(weavingData.getClassName()) &&
- "load".equals(weavingData.getMethodName())) {
+ "load".equals(weavingData.getMethodName()) &&
+ Arrays.equals(new String [] {Class.class.getName()}, weavingData.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.
mv.visitLdcInsn(lastLDCType);
} else {
- Type type = Type.getType("L" + owner + ";");
+ // In any other case, we're not dealing with a general-purpose service loader, but rather
+ // with a specific one, such as DocumentBuilderFactory.newInstance(). In that case the
+ // target class is the class that is being invoked on (i.e. DocumentBuilderFactory).
+ Type type = Type.getObjectType(owner);
mv.visitLdcInsn(type);
}
mv.visitMethodInsn(INVOKESTATIC, targetClass,
@@ -150,4 +169,8 @@ public class TCCLSetterVisitor extends C
}
}
}
+
+ public boolean additionalImportRequired() {
+ return 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=1051409&r1=1051408&r2=1051409&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 Tue Dec 21 08:05:15 2010
@@ -1,18 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
package org.apache.aries.spifly;
-import java.util.List;
-
-import org.osgi.framework.Bundle;
-
public class WeavingData {
private final String className;
private final String methodName;
- private final int argCount;
+ private final String[] argClasses;
- public WeavingData(String className, String methodName, int argCount) {
+ public WeavingData(String className, String methodName, String[] argClasses2) {
this.className = className;
this.methodName = methodName;
- this.argCount = argCount;
+ this.argClasses = argClasses2;
}
public String getClassName() {
@@ -23,7 +37,7 @@ public class WeavingData {
return methodName;
}
- public int getArgCount() {
- return argCount;
+ public String[] getArgClasses() {
+ return argClasses;
}
}
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=1051409&r1=1051408&r2=1051409&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 Tue Dec 21 08:05:15 2010
@@ -43,7 +43,7 @@ public class ClientWeavingHookTest {
// Weave the TestClient class.
URL clsUrl = getClass().getResource("TestClient.class");
- Assert.assertNotNull("precondition", clsUrl);
+ Assert.assertNotNull("Precondition", clsUrl);
WovenClass wc = new MyWovenClass(clsUrl, "org.apache.aries.spifly.TestClient", consumerBundle);
Assert.assertEquals("Precondition", 0, wc.getDynamicImports().size());
wh.weave(wc);
@@ -66,6 +66,38 @@ public class ClientWeavingHookTest {
}
@Test
+ public void testClientWeavingHookAltServiceLoaderLoadUnprocessed() throws Exception {
+ Bundle spiFlyBundle = mockSpiFlyBundle();
+
+ Dictionary<String, String> headers = new Hashtable<String, String>();
+ headers.put(SpiFlyConstants.SPI_CONSUMER_HEADER, "true");
+ Bundle consumerBundle = mockConsumerBundle(headers, spiFlyBundle);
+
+ WeavingHook wh = new ClientWeavingHook(spiFlyBundle.getBundleContext());
+
+ // Weave the TestClient class.
+ URL clsUrl = getClass().getResource("UnaffectedTestClient.class");
+ Assert.assertNotNull("Precondition", clsUrl);
+ WovenClass wc = new MyWovenClass(clsUrl, "org.apache.aries.spifly.UnaffectedTestClient", consumerBundle);
+ Assert.assertEquals("Precondition", 0, wc.getDynamicImports().size());
+ wh.weave(wc);
+
+ Assert.assertEquals("The client is not affected so no additional imports should have been added",
+ 0, wc.getDynamicImports().size());
+
+ // ok the weaving is done, now prepare the registry for the call
+ Bundle providerBundle = mockProviderBundle("impl1", 1, "META-INF/services/org.apache.aries.mytest.MySPI");
+ Activator.activator.registerProviderBundle("org.apache.aries.mytest.MySPI", providerBundle);
+
+ // Invoke the woven class and check that it propertly 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});
+ Object result = method.invoke(cls.newInstance(), "hello");
+ Assert.assertEquals("impl4", result);
+ }
+
+ @Test
public void testClientWeavingHookMultipleProviders() throws Exception {
Bundle spiFlyBundle = mockSpiFlyBundle();
@@ -121,12 +153,7 @@ public class ClientWeavingHookTest {
Object result = method.invoke(cls.newInstance(), "hello");
Assert.assertEquals("Only the services from bundle impl2 should be selected", "HELLO5", result);
}
-
- @Test
- public void testServiceProviderOverloadUnprocessed() {
- Assert.fail("Test that ServiceLoader.load(2) doesn't get affected");
- }
-
+
@Test
public void testJAXPClientWantsJREImplementation1() throws Exception {
Bundle systembundle = mockSystemBundle();
@@ -285,7 +312,7 @@ public class ClientWeavingHookTest {
return systemBundle;
}
- private class TestImplClassLoader extends URLClassLoader {
+ public static class TestImplClassLoader extends URLClassLoader {
private final List<String> resources;
private final String prefix;
Added: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/UnaffectedTestClient.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/UnaffectedTestClient.java?rev=1051409&view=auto
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/UnaffectedTestClient.java (added)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/UnaffectedTestClient.java Tue Dec 21 08:05:15 2010
@@ -0,0 +1,18 @@
+package org.apache.aries.spifly;
+
+import java.util.ServiceLoader;
+
+import org.apache.aries.mytest.MySPI;
+
+public class UnaffectedTestClient {
+ public String test(String input) {
+ StringBuilder sb = new StringBuilder();
+
+ ServiceLoader<MySPI> loader = ServiceLoader.load(MySPI.class,
+ new ClientWeavingHookTest.TestImplClassLoader("impl4", "META-INF/services/org.apache.aries.mytest.MySPI"));
+ for (MySPI mySPI : loader) {
+ sb.append(mySPI.someMethod(input));
+ }
+ return sb.toString();
+ }
+}
Added: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/META-INF/services/org.apache.aries.mytest.MySPI
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/META-INF/services/org.apache.aries.mytest.MySPI?rev=1051409&view=auto
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/META-INF/services/org.apache.aries.mytest.MySPI (added)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/META-INF/services/org.apache.aries.mytest.MySPI Tue Dec 21 08:05:15 2010
@@ -0,0 +1,2 @@
+org.apache.aries.spifly.impl4.MySPIImpl4
+
Added: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/MySPIImpl4.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/MySPIImpl4.java?rev=1051409&view=auto
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/MySPIImpl4.java (added)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl4/MySPIImpl4.java Tue Dec 21 08:05:15 2010
@@ -0,0 +1,10 @@
+package org.apache.aries.spifly.impl4;
+
+import org.apache.aries.mytest.MySPI;
+
+public class MySPIImpl4 implements MySPI {
+ @Override
+ public String someMethod(String s) {
+ return "impl4";
+ }
+}