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/20 11:35:45 UTC

svn commit: r1051042 - 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/impl3/ SpiFlyTests/src/org/apache/aries/spifl...

Author: davidb
Date: Mon Dec 20 10:35:45 2010
New Revision: 1051042

URL: http://svn.apache.org/viewvc?rev=1051042&view=rev
Log:
Support for treating methods other than ServiceLoader.load()

Added:
    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/JaxpClient.java
    incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/
    incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/META-INF/
    incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/META-INF/services/
    incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/META-INF/services/javax.xml.parsers.DocumentBuilderFactory
    incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/MyAltDocumentBuilderFactory.java
Modified:
    incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/Activator.java
    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/SpiFlyTests/src/org/apache/aries/spifly/ClientWeavingHookTest.java

Modified: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/Activator.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/Activator.java?rev=1051042&r1=1051041&r2=1051042&view=diff
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/Activator.java (original)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/Activator.java Mon Dec 20 10:35:45 2010
@@ -18,7 +18,6 @@
  */
 package org.apache.aries.spifly;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -120,14 +119,16 @@ public class Activator implements Bundle
     }
     
     // TODO unRegisterProviderBundle();
-    
     public void registerConsumerBundle(Bundle consumer, Collection<Bundle> spiProviders) {
+        if (spiProviders == null)
+            return;
+        
         registeredConsumers.put(consumer, spiProviders);
     }
     
     public Collection<Bundle> findConsumerRestrictions(Bundle consumer) {
         return registeredConsumers.get(consumer);
     }
-    
+
     // TODO unRegisterConsumerBundle();
 }

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=1051042&r1=1051041&r2=1051042&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 Mon Dec 20 10:35:45 2010
@@ -21,6 +21,7 @@ package org.apache.aries.spifly;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.ServiceLoader;
 
 import org.apache.aries.spifly.HeaderParser.PathElement;
 import org.apache.aries.spifly.api.SpiFlyConstants;
@@ -53,26 +54,45 @@ public class ClientWeavingHook implement
 	    Bundle consumerBundle = wovenClass.getBundleWiring().getBundle();
         String consumerHeader = consumerBundle.getHeaders().get(SpiFlyConstants.SPI_CONSUMER_HEADER);
         if (consumerHeader != null) {
-	        Activator activator = Activator.activator;
-            activator.log(LogService.LOG_DEBUG, "Weaving class " + wovenClass.getClassName());            
+	        Activator.activator.log(LogService.LOG_DEBUG, "Weaving class " + wovenClass.getClassName());            
             
-	        if (!"true".equalsIgnoreCase(consumerHeader)) {
-	             activator.registerConsumerBundle(consumerBundle, parseHeader(consumerHeader));	            
-	        }
+            WeavingData wd = parseHeader(consumerBundle, consumerHeader);
 	        
 	        ClassReader cr = new ClassReader(wovenClass.getBytes());
 	        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
-	        TCCLSetterVisitor tsv = new TCCLSetterVisitor(cw, wovenClass.getClassName());
+	        TCCLSetterVisitor tsv = new TCCLSetterVisitor(cw, wovenClass.getClassName(), wd);
 	        cr.accept(tsv, 0);
 	        wovenClass.setBytes(cw.toByteArray());
 	        wovenClass.getDynamicImports().add(addedImport);
 	    }			
 	}
 
-    private Collection<Bundle> parseHeader(String consumerHeader) {
+    private WeavingData parseHeader(Bundle consumerBundle, String consumerHeader) {
         List<Bundle> selectedBundles = new ArrayList<Bundle>();
 
         for (PathElement element : HeaderParser.parseHeader(consumerHeader)) {
+            String name = element.getName().trim();
+            String className;
+            String methodName;
+            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);
+                } else {
+                    methodName = name.substring(hashIdx + 1);                    
+                }
+            } else {
+                if ("true".equalsIgnoreCase(name)) {
+                    className = ServiceLoader.class.getName();
+                    methodName = "load";
+                } else {
+                    className = name;
+                    methodName = null;
+                }
+            }            
+                
             String bsn = element.getAttribute("bundle");
             if (bsn != null) {
                 for (Bundle b : bundleContext.getBundles()) {
@@ -82,8 +102,16 @@ public class ClientWeavingHook implement
                     }
                 }
             }
+            
+            Activator.activator.log(LogService.LOG_INFO, "Weaving " + className + "#" + methodName + " from bundle " + 
+                consumerBundle.getSymbolicName() + " to " + (selectedBundles.size() == 0 ? " any provider" : selectedBundles));
+            
+            if (selectedBundles.size() > 0)
+                Activator.activator.registerConsumerBundle(consumerBundle, selectedBundles);
+           
+            // TODO support more than one definition
+            return new WeavingData(className, methodName, 1);
         }
-        
-        return selectedBundles;
+        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=1051042&r1=1051041&r2=1051042&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 Mon Dec 20 10:35:45 2010
@@ -19,6 +19,7 @@
 package org.apache.aries.spifly;
 
 import java.util.Arrays;
+import java.util.ServiceLoader;
 
 import org.objectweb.asm.ClassAdapter;
 import org.objectweb.asm.ClassVisitor;
@@ -38,10 +39,12 @@ public class TCCLSetterVisitor extends C
     private static final String VOID_RETURN_TYPE = "()V";
     
     private final String targetClass;
+    private final WeavingData weavingData;
 
-    public TCCLSetterVisitor(ClassVisitor cv, String className) {
+    public TCCLSetterVisitor(ClassVisitor cv, String className, WeavingData weavingData) {
         super(cv);
         this.targetClass = className.replace('.', '/');
+        this.weavingData = weavingData;
     }
 
     @Override
@@ -58,15 +61,15 @@ public class TCCLSetterVisitor extends C
         // Add generated static method
 
         /* Equivalent to:
-         * private static void SomeMethodName(Class<?> cls) {
+         * 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("java.util.ServiceLoader");
-        mv.visitLdcInsn("load");
+        mv.visitLdcInsn(weavingData.getClassName());
+        mv.visitLdcInsn(weavingData.getMethodName());
         mv.visitVarInsn(ALOAD, 0);
         String typeIdentifier = "L" + targetClass + ";";
         mv.visitLdcInsn(Type.getType(typeIdentifier));
@@ -91,7 +94,6 @@ public class TCCLSetterVisitor extends C
         public TCCLSetterMethodVisitor(MethodVisitor mv) {
             super(mv);
         }
-
         
         /**
          * Store the last LDC call. When ServiceLoader.load(Class cls) is called
@@ -118,16 +120,23 @@ public class TCCLSetterVisitor extends C
             System.out.println("### " + opcode + ": " + owner + "#" + name + "#" + desc);
             
             if (opcode == INVOKESTATIC &&
-                "java/util/ServiceLoader".equals(owner) &&
-                "load".equals(name)) {
+                weavingData.getClassName().replace('.', '/').equals(owner) &&
+                weavingData.getMethodName().equals(name)) {
                 System.out.println("+++ Gotcha!");
           
                 // 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.
-                mv.visitLdcInsn(lastLDCType);
+                if (ServiceLoader.class.getName().equals(weavingData.getClassName()) &&
+                    "load".equals(weavingData.getMethodName())) {
+                    mv.visitLdcInsn(lastLDCType);
+                } else {
+                    Type type = Type.getType("L" + owner + ";");
+                    mv.visitLdcInsn(type);
+                }
                 mv.visitMethodInsn(INVOKESTATIC, targetClass,
                         GENERATED_METHOD_NAME, "(Ljava/lang/Class;)V");
 

Added: 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=1051042&view=auto
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/WeavingData.java (added)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFly/src/org/apache/aries/spifly/WeavingData.java Mon Dec 20 10:35:45 2010
@@ -0,0 +1,29 @@
+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;
+    
+    public WeavingData(String className, String methodName, int argCount) {
+        this.className = className;
+        this.methodName = methodName;
+        this.argCount = argCount;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public String getMethodName() {
+        return methodName;
+    }
+
+    public int getArgCount() {
+        return argCount;
+    }
+}

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=1051042&r1=1051041&r2=1051042&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 Mon Dec 20 10:35:45 2010
@@ -119,6 +119,50 @@ public class ClientWeavingHookTest {
         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 testJAXPClientWantsJREImplementation() throws Exception {
+        Dictionary<String, String> headers = new Hashtable<String, String>();
+        headers.put(SpiFlyConstants.SPI_CONSUMER_HEADER, "todo");
+        Bundle consumerBundle = mockConsumerBundle(headers);
+
+        WeavingHook wh = new ClientWeavingHook(mockSpiFlyBundle(consumerBundle));
+
+        URL clsUrl = getClass().getResource("JaxpClient.class");
+        WovenClass wc = new MyWovenClass(clsUrl, "org.apache.aries.spifly.JaxpClient", consumerBundle);
+        wh.weave(wc);
+        
+        Class<?> cls = wc.getDefinedClass();
+        Method method = cls.getMethod("test", new Class [] {});
+        Class<?> result = (Class<?>) method.invoke(cls.newInstance());
+        Assert.assertEquals("JAXP implementation from JRE", "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl", result.getName());                
+    }
+    
+    @Test
+    public void testJAXPClientWantsAltImplementation() throws Exception {
+        Dictionary<String, String> headers = new Hashtable<String, String>();
+        headers.put(SpiFlyConstants.SPI_CONSUMER_HEADER, "javax.xml.parsers.DocumentBuilderFactory#newInstance();bundle=impl3");
+        Bundle consumerBundle = mockConsumerBundle(headers);
+        
+        Bundle providerBundle = mockProviderBundle("impl3", 1, "META-INF/services/javax.xml.parsers.DocumentBuilderFactory");
+        Activator.activator.registerProviderBundle("javax.xml.parsers.DocumentBuilderFactory", providerBundle);
+
+        WeavingHook wh = new ClientWeavingHook(mockSpiFlyBundle(consumerBundle));
+
+        URL clsUrl = getClass().getResource("JaxpClient.class");
+        WovenClass wc = new MyWovenClass(clsUrl, "org.apache.aries.spifly.JaxpClient", consumerBundle);
+        wh.weave(wc);
+        
+        Class<?> cls = wc.getDefinedClass();
+        Method method = cls.getMethod("test", new Class [] {});
+        Class<?> result = (Class<?>) method.invoke(cls.newInstance());
+        Assert.assertEquals("JAXP implementation from alternative bundle", "org.apache.aries.spifly.impl3.MyAltDocumentBuilderFactory", result.getName());                        
+    }
+    
     private BundleContext mockSpiFlyBundle(Bundle ... bundles) {
         return mockSpiFlyBundle("spifly", new Version(1, 0, 0), bundles);
     }

Added: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/JaxpClient.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/JaxpClient.java?rev=1051042&view=auto
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/JaxpClient.java (added)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/JaxpClient.java Mon Dec 20 10:35:45 2010
@@ -0,0 +1,9 @@
+package org.apache.aries.spifly;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+public class JaxpClient {
+    public Class<?> test() {
+        return DocumentBuilderFactory.newInstance().getClass();
+    }
+}

Added: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/META-INF/services/javax.xml.parsers.DocumentBuilderFactory
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/META-INF/services/javax.xml.parsers.DocumentBuilderFactory?rev=1051042&view=auto
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/META-INF/services/javax.xml.parsers.DocumentBuilderFactory (added)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/META-INF/services/javax.xml.parsers.DocumentBuilderFactory Mon Dec 20 10:35:45 2010
@@ -0,0 +1 @@
+org.apache.aries.spifly.impl3.MyAltDocumentBuilderFactory

Added: incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/MyAltDocumentBuilderFactory.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/MyAltDocumentBuilderFactory.java?rev=1051042&view=auto
==============================================================================
--- incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/MyAltDocumentBuilderFactory.java (added)
+++ incubator/aries/trunk/spi-fly/contrib/pilot_using_weavinghook/SpiFlyTests/src/org/apache/aries/spifly/impl3/MyAltDocumentBuilderFactory.java Mon Dec 20 10:35:45 2010
@@ -0,0 +1,52 @@
+/**
+ * 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.impl3;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+public class MyAltDocumentBuilderFactory extends DocumentBuilderFactory {
+
+    @Override
+    public DocumentBuilder newDocumentBuilder()
+            throws ParserConfigurationException {
+        return null;
+    }
+
+    @Override
+    public void setAttribute(String name, Object value)
+            throws IllegalArgumentException {
+    }
+
+    @Override
+    public Object getAttribute(String name) throws IllegalArgumentException {
+        return null;
+    }
+
+    @Override
+    public void setFeature(String name, boolean value)
+            throws ParserConfigurationException {
+    }
+
+    @Override
+    public boolean getFeature(String name) throws ParserConfigurationException {
+        return false;
+    }
+}