Author: rfeng
Date: Mon Jul 21 15:29:57 2008
New Revision: 678589

URL: http://svn.apache.org/viewvc?rev=678589&view=rev
Log:
Fix the a set of classloading related issues such as ClassNotFoundException, 
ClassCastException and VerifyError

Modified:
    
tuscany/java/sca/modules/extensibility-osgi/src/main/java/org/apache/tuscany/sca/extensibility/osgi/OSGiServiceDiscoverer.java
    tuscany/java/sca/modules/implementation-node-osgi-runtime/pom.xml
    
tuscany/java/sca/modules/implementation-node-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/osgi/launcher/LauncherBundleActivator.java
    
tuscany/java/sca/modules/implementation-node-osgi-runtime/src/test/java/org/apache/tuscany/sca/implementation/node/osgi/LauncherBundleActivatorTestCase.java

Modified: 
tuscany/java/sca/modules/extensibility-osgi/src/main/java/org/apache/tuscany/sca/extensibility/osgi/OSGiServiceDiscoverer.java
URL: 
http://svn.apache.org/viewvc/tuscany/java/sca/modules/extensibility-osgi/src/main/java/org/apache/tuscany/sca/extensibility/osgi/OSGiServiceDiscoverer.java?rev=678589&r1=678588&r2=678589&view=diff
==============================================================================
--- 
tuscany/java/sca/modules/extensibility-osgi/src/main/java/org/apache/tuscany/sca/extensibility/osgi/OSGiServiceDiscoverer.java
 (original)
+++ 
tuscany/java/sca/modules/extensibility-osgi/src/main/java/org/apache/tuscany/sca/extensibility/osgi/OSGiServiceDiscoverer.java
 Mon Jul 21 15:29:57 2008
@@ -28,6 +28,8 @@
 import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
+import java.security.SecureClassLoader;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -48,9 +50,77 @@
 public class OSGiServiceDiscoverer implements ServiceDiscoverer {
     private static final Logger logger = 
Logger.getLogger(OSGiServiceDiscoverer.class.getName());
     private BundleContext context;
+    private ClassLoader classLoader;
 
     public OSGiServiceDiscoverer(BundleContext context) {
         this.context = context;
+        this.classLoader = new ClassLoaderImpl();
+    }
+
+    public class ClassLoaderImpl extends SecureClassLoader {
+
+        public ClassLoaderImpl() {
+            super(OSGiServiceDiscoverer.class.getClassLoader());
+        }
+
+        /**
+         * Open a back-door to expose the META-INF/services resources
+         */
+        @Override
+        protected URL findResource(String name) {
+            int index = name.lastIndexOf('/');
+            if (index == -1) {
+                return null;
+            }
+            String path = name.substring(0, index);
+            if (path.startsWith("/")) {
+                path = path.substring(1);
+            }
+
+            if (!path.startsWith("META-INF/services")) {
+                return null;
+            }
+
+            for (Bundle bundle : context.getBundles()) {
+                URL url = bundle.getEntry(name);
+                if (url != null) {
+                    return url;
+                }
+            }
+
+            return null;
+        }
+
+        /**
+         * Open a back-door to expose the META-INF/services resources
+         */
+        @Override
+        protected Enumeration<URL> findResources(String name) throws 
IOException {
+            int index = name.lastIndexOf('/');
+            if (index == -1) {
+                return null;
+            }
+            String path = name.substring(0, index);
+            String file = name.substring(index + 1);
+            if (path.startsWith("/")) {
+                path = path.substring(1);
+            }
+
+            if (!path.startsWith("META-INF/services")) {
+                return null;
+            }
+
+            Set<URL> urlSet = new HashSet<URL>();
+
+            for (Bundle bundle : context.getBundles()) {
+                Enumeration<URL> urls = bundle.findEntries(path, file, false);
+                if (urls != null) {
+                    urlSet.addAll(Collections.list(urls));
+                }
+            }
+            return Collections.enumeration(urlSet);
+        }
+
     }
 
     public static class ServiceDeclarationImpl implements ServiceDeclaration {
@@ -173,6 +243,14 @@
         return attributes;
     }
 
+    /**
+     * This class loader can be set as the thread context class loader for 
non-OSGi code
+     * @return
+     */
+    public ClassLoader getClassLoader() {
+        return classLoader;
+    }
+
     @SuppressWarnings("unchecked")
     public Set<ServiceDeclaration> discover(String serviceName, boolean 
firstOnly) {
         boolean debug = logger.isLoggable(Level.FINE);

Modified: tuscany/java/sca/modules/implementation-node-osgi-runtime/pom.xml
URL: 
http://svn.apache.org/viewvc/tuscany/java/sca/modules/implementation-node-osgi-runtime/pom.xml?rev=678589&r1=678588&r2=678589&view=diff
==============================================================================
--- tuscany/java/sca/modules/implementation-node-osgi-runtime/pom.xml (original)
+++ tuscany/java/sca/modules/implementation-node-osgi-runtime/pom.xml Mon Jul 
21 15:29:57 2008
@@ -99,7 +99,7 @@
                             <goal>copy-dependencies</goal>
                         </goals>
                         <configuration>
-                            
<outputDirectory>${project.build.directory}/modules</outputDirectory>
+                            
<outputDirectory>${project.build.directory}/tuscany/modules</outputDirectory>
                             <excludeArtifactIds></excludeArtifactIds>
                         </configuration>
                     </execution>

Modified: 
tuscany/java/sca/modules/implementation-node-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/osgi/launcher/LauncherBundleActivator.java
URL: 
http://svn.apache.org/viewvc/tuscany/java/sca/modules/implementation-node-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/osgi/launcher/LauncherBundleActivator.java?rev=678589&r1=678588&r2=678589&view=diff
==============================================================================
--- 
tuscany/java/sca/modules/implementation-node-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/osgi/launcher/LauncherBundleActivator.java
 (original)
+++ 
tuscany/java/sca/modules/implementation-node-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/osgi/launcher/LauncherBundleActivator.java
 Mon Jul 21 15:29:57 2008
@@ -27,20 +27,54 @@
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
 import org.osgi.framework.Constants;
 
 /**
  * Bundle activator which installs Tuscany modules and 3rd party jars into an 
OSGi runtime.
  *
  */
-public class LauncherBundleActivator implements BundleActivator, Constants {
-
+public class LauncherBundleActivator implements BundleActivator, Constants, 
BundleListener {
     private static Logger logger = 
Logger.getLogger(LauncherBundleActivator.class.getName());
-    private ArrayList<Bundle> tuscanyBundles = new ArrayList<Bundle>();
-
     private static final String[] immutableJars = {"bcprov"};
 
+    private BundleContext bundleContext;
+    private List<Bundle> tuscanyBundles = new ArrayList<Bundle>();
+
+    public static String toString(Bundle b, boolean verbose) {
+        StringBuffer sb = new StringBuffer();
+        sb.append(b.getBundleId()).append(" ").append(b.getSymbolicName());
+        int s = b.getState();
+        if ((s & Bundle.UNINSTALLED) != 0) {
+            sb.append(" UNINSTALLED");
+        }
+        if ((s & Bundle.INSTALLED) != 0) {
+            sb.append(" INSTALLED");
+        }
+        if ((s & Bundle.RESOLVED) != 0) {
+            sb.append(" RESOLVED");
+        }
+        if ((s & Bundle.STARTING) != 0) {
+            sb.append(" STARTING");
+        }
+        if ((s & Bundle.STOPPING) != 0) {
+            sb.append(" STOPPING");
+        }
+        if ((s & Bundle.ACTIVE) != 0) {
+            sb.append(" ACTIVE");
+        }
+
+        if (verbose) {
+            sb.append(" ").append(b.getLocation());
+            sb.append(" ").append(b.getHeaders());
+        }
+        return sb.toString();
+    }
+
     public void start(BundleContext bundleContext) throws Exception {
+        this.bundleContext = bundleContext;
+        this.bundleContext.addBundleListener(this);
         installTuscany(bundleContext);
     }
 
@@ -49,18 +83,20 @@
             try {
                 bundle.stop();
             } catch (Exception e) {
-                // Ignore error
+                logger.severe(e.toString());
             }
         }
 
         for (Bundle bundle : tuscanyBundles) {
             try {
+                logger.info("Uninstalling bundle: " + toString(bundle, false));
                 bundle.uninstall();
             } catch (Exception e) {
-                // Ignore error
+                logger.severe(e.toString());
             }
         }
-
+        this.bundleContext.removeBundleListener(this);
+        this.bundleContext = null;
     }
 
     public void installTuscany(BundleContext bundleContext) {
@@ -82,12 +118,14 @@
                 }
                 try {
                     Bundle bundle = createAndInstallBundle(bundleContext, 
file);
-                    tuscanyBundles.add(bundle);
+                    if (bundle != null) {
+                        tuscanyBundles.add(bundle);
+                    }
                 } catch (Exception e) {
                     logger.log(Level.SEVERE, e.getMessage(), e);
                 }
             }
-            
+
             long end = System.currentTimeMillis();
             logger.info("Tuscany bundles are installed in " + (end - start) + 
" ms.");
 
@@ -130,11 +168,25 @@
     public Bundle createAndInstallBundle(BundleContext bundleContext, File 
bundleFile) throws Exception {
         logger.info("Installing bundle: " + bundleFile);
         long start = System.currentTimeMillis();
-        String bundleLocation = bundleFile.toURI().toString();
-        Manifest manifest = createBundleManifest(bundleFile);
 
+        Manifest manifest = readManifest(bundleFile);
+        boolean isOSGiBundle = manifest != null && 
manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME) != null;
+
+        if (!isOSGiBundle) {
+            manifest = updateBundleManifest(bundleFile, manifest);
+        }
+
+        String symbolicName = 
manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
+        String version = manifest.getMainAttributes().getValue(BUNDLE_VERSION);
+        Bundle bundle = findBundle(bundleContext, symbolicName, version);
+        if (bundle != null) {
+            logger.info("Bundle is already installed: " + symbolicName);
+            return null;
+        }
+
+        String bundleLocation = bundleFile.toURI().toString();
         InputStream inStream = null;
-        if (manifest != null) {
+        if (!isOSGiBundle) {
             // We need to repackage the bundle
             ByteArrayOutputStream out = new ByteArrayOutputStream();
             JarOutputStream jarOut = new JarOutputStream(out, manifest);
@@ -155,7 +207,7 @@
         }
 
         try {
-            Bundle bundle = bundleContext.installBundle(bundleLocation, 
inStream);
+            bundle = bundleContext.installBundle(bundleLocation, inStream);
             logger.info("Bundle installed in " + (System.currentTimeMillis() - 
start) + " ms: " + bundleLocation);
             return bundle;
         } finally {
@@ -164,6 +216,23 @@
 
     }
 
+    private Bundle findBundle(BundleContext bundleContext, String 
symbolicName, String version) {
+        Bundle[] bundles = bundleContext.getBundles();
+        if (version == null) {
+            version = "0.0.0";
+        }
+        for (Bundle b : bundles) {
+            String v = (String)b.getHeaders().get(BUNDLE_VERSION);
+            if (v == null) {
+                v = "0.0.0";
+            }
+            if (b.getSymbolicName().equals(symbolicName) && v.equals(version)) 
{
+                return b;
+            }
+        }
+        return null;
+    }
+
     private void addFileToJar(File file, JarOutputStream jarOut) throws 
IOException {
         JarEntry ze = new JarEntry(file.getName());
         jarOut.putNextEntry(ze);
@@ -192,8 +261,7 @@
         jarIn.close();
     }
 
-    private Manifest createBundleManifest(File jarFile) throws Exception {
-
+    private Manifest readManifest(File jarFile) throws IOException {
         if (!jarFile.exists()) {
             return null;
         }
@@ -205,11 +273,14 @@
         if (manifest == null) {
             // Create a new one if no Manifest is found
             manifest = new Manifest();
-        } else {
-            Attributes attributes = manifest.getMainAttributes();
-            if (attributes.getValue(BUNDLE_SYMBOLICNAME) != null) {
-                return null;
-            }
+        }
+        return manifest;
+    }
+
+    private Manifest updateBundleManifest(File jarFile, Manifest manifest) 
throws Exception {
+
+        if (!jarFile.exists()) {
+            return null;
         }
 
         // Check if we have an associated .mf file
@@ -252,12 +323,12 @@
         if (attributes.getValue(BUNDLE_MANIFESTVERSION) == null) {
             attributes.putValue(BUNDLE_MANIFESTVERSION, "2");
         }
-        
+
         if (isImmutableJar && attributes.getValue(BUNDLE_CLASSPATH) == null) {
             attributes.putValue(BUNDLE_CLASSPATH, ".," + jarFileName);
         }
 
-        jar = new JarInputStream(new FileInputStream(jarFile));
+        JarInputStream jar = new JarInputStream(new FileInputStream(jarFile));
         HashSet<String> packages = getPackagesInJar(jarFileName, jar);
         jar.close();
         String version = getJarVersion(jarFileName);
@@ -341,4 +412,11 @@
         return version;
     }
 
+    public BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    public void bundleChanged(BundleEvent event) {
+    }
+
 }

Modified: 
tuscany/java/sca/modules/implementation-node-osgi-runtime/src/test/java/org/apache/tuscany/sca/implementation/node/osgi/LauncherBundleActivatorTestCase.java
URL: 
http://svn.apache.org/viewvc/tuscany/java/sca/modules/implementation-node-osgi-runtime/src/test/java/org/apache/tuscany/sca/implementation/node/osgi/LauncherBundleActivatorTestCase.java?rev=678589&r1=678588&r2=678589&view=diff
==============================================================================
--- 
tuscany/java/sca/modules/implementation-node-osgi-runtime/src/test/java/org/apache/tuscany/sca/implementation/node/osgi/LauncherBundleActivatorTestCase.java
 (original)
+++ 
tuscany/java/sca/modules/implementation-node-osgi-runtime/src/test/java/org/apache/tuscany/sca/implementation/node/osgi/LauncherBundleActivatorTestCase.java
 Mon Jul 21 15:29:57 2008
@@ -64,7 +64,9 @@
             + "javax.xml.transform.stream, "
             + "javax.xml.validation, "
             + "javax.xml.xpath, "
+            // Force the classes to be imported from the system bundle
             + "javax.xml.stream, "
+            + "javax.xml.stream.util, "
             + "javax.sql,"
             + "org.w3c.dom, "
             + "org.xml.sax, "
@@ -108,10 +110,10 @@
         // Now start Felix instance.
         felix.start();
         BundleContext context = felix.getBundleContext();
-//        discoverer = new OSGiServiceDiscoverer(context);
-//        ServiceDiscovery.setServiceDiscoverer(discoverer);
+        //        discoverer = new OSGiServiceDiscoverer(context);
+        //        ServiceDiscovery.setServiceDiscoverer(discoverer);
 
-        System.setProperty("TUSCANY_HOME", "target");
+        System.setProperty("TUSCANY_HOME", "target/tuscany");
         activator = new LauncherBundleActivator();
         activator.start(context);
     }
@@ -140,26 +142,34 @@
         }
         Bundle b1 = bundles.get("org.apache.tuscany.sca.extensibility.osgi");
         Class<?> discovererClass = 
b1.loadClass(OSGiServiceDiscoverer.class.getName());
-        
Thread.currentThread().setContextClassLoader(discovererClass.getClassLoader());
-        
         Constructor<?> ctor = 
discovererClass.getConstructor(BundleContext.class);
         Object discoverer = ctor.newInstance(felix.getBundleContext());
 
-        Class<?> serviceDiscoveryClass = 
b1.loadClass(ServiceDiscovery.class.getName());
-        Method set = serviceDiscoveryClass.getMethod("setServiceDiscoverer", 
discovererClass.getInterfaces()[0]);
-        set.invoke(null, discoverer);
-
-        Bundle b2 = bundles.get("org.apache.tuscany.sca.node2.api");
-        // b2.start();
-        Class<?> factory = b2.loadClass(className);
-        Method newInstance = factory.getMethod("newInstance");
-        Object instance = newInstance.invoke(null);
-        Method create = 
instance.getClass().getMethod("createSCANodeFromClassLoader", String.class, 
ClassLoader.class);
-        Object node = create.invoke(instance, "HelloWorld.composite", 
getClass().getClassLoader());
-        Method start = node.getClass().getMethod("start");
-        start.invoke(node);
-        Method stop = node.getClass().getMethod("stop");
-        stop.invoke(node);
+        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+        Method getCL = discovererClass.getMethod("getClassLoader");
+        ClassLoader cl = (ClassLoader)getCL.invoke(discoverer);
+        Thread.currentThread().setContextClassLoader(cl);
+
+        try {
+            Class<?> serviceDiscoveryClass = 
b1.loadClass(ServiceDiscovery.class.getName());
+            Method set = 
serviceDiscoveryClass.getMethod("setServiceDiscoverer", 
discovererClass.getInterfaces()[0]);
+            set.invoke(null, discoverer);
+
+            Bundle b2 = bundles.get("org.apache.tuscany.sca.node2.api");
+            // b2.start();
+            Class<?> factory = b2.loadClass(className);
+            Method newInstance = factory.getMethod("newInstance");
+            Object instance = newInstance.invoke(null);
+            Method create =
+                instance.getClass().getMethod("createSCANodeFromClassLoader", 
String.class, ClassLoader.class);
+            Object node = create.invoke(instance, "HelloWorld.composite", 
getClass().getClassLoader());
+            Method start = node.getClass().getMethod("start");
+            start.invoke(node);
+            Method stop = node.getClass().getMethod("stop");
+            stop.invoke(node);
+        } finally {
+            Thread.currentThread().setContextClassLoader(tccl);
+        }
 
     }
 


Reply via email to