From 9eadabfbf44beef2a1825f6a9c877449c374f420 Mon Sep 17 00:00:00 2001 From: rfeng Date: Sat, 6 Sep 2008 01:46:45 +0000 Subject: Starting to add support Classloading for 3rd party jars git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@692604 13f79535-47bb-0310-9956-ffa450edef68 --- java/sca/modules/extensibility-equinox/pom.xml | 11 ++- .../equinox/EquinoxServiceDiscoverer.java | 21 ++++- .../extensibility/equinox/URLClassLoadingHook.java | 99 ++++++++++++++++++++++ java/sca/modules/node-launcher-equinox/pom.xml | 4 +- .../sca/node/equinox/launcher/EquinoxOSGiHost.java | 66 ++++++++++++++- .../equinox/launcher/LauncherBundleActivator.java | 13 ++- .../sca/node/equinox/launcher/NodeLauncher.java | 15 ++-- .../equinox/launcher/NodeLauncherTestCase.java | 11 +-- 8 files changed, 216 insertions(+), 24 deletions(-) create mode 100644 java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/URLClassLoadingHook.java (limited to 'java/sca/modules') diff --git a/java/sca/modules/extensibility-equinox/pom.xml b/java/sca/modules/extensibility-equinox/pom.xml index 25f78760b2..66966b2106 100644 --- a/java/sca/modules/extensibility-equinox/pom.xml +++ b/java/sca/modules/extensibility-equinox/pom.xml @@ -73,15 +73,22 @@ ${tuscany.version} org.apache.tuscany.sca.extensibility.equinox + ${pom.name} org.apache.tuscany.sca.extensibility.equinox.EquinoxServiceDiscoveryActivator + + * + global,app + global,app + true - \ No newline at end of file + diff --git a/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java b/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java index f662f44a24..dd3b3c56e9 100644 --- a/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java +++ b/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java @@ -28,7 +28,6 @@ import java.security.AccessController; 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; @@ -54,6 +53,7 @@ public class EquinoxServiceDiscoverer implements ServiceDiscoverer { public EquinoxServiceDiscoverer(BundleContext context) { this.context = context; + // http://wiki.eclipse.org/index.php/Context_Class_Loader_Enhancements this.classLoader = new ClassLoaderImpl(); } @@ -116,12 +116,27 @@ public class EquinoxServiceDiscoverer implements ServiceDiscoverer { } - public class ClassLoaderImpl extends SecureClassLoader { - + private final static ClassLoader getTCCL() { + return AccessController.doPrivileged(new PrivilegedAction() { + public ClassLoader run() { + return Thread.currentThread().getContextClassLoader(); + } + }); + } + + public class ClassLoaderImpl extends ClassLoader { + private ClassLoader delegate; + public ClassLoaderImpl() { super(EquinoxServiceDiscoverer.class.getClassLoader()); + this.delegate = getTCCL(); } + @Override + protected Class findClass(String name) throws ClassNotFoundException { + return delegate.loadClass(name); + } + /** * Open a back-door to expose the META-INF/services resources */ diff --git a/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/URLClassLoadingHook.java b/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/URLClassLoadingHook.java new file mode 100644 index 0000000000..51c42350b2 --- /dev/null +++ b/java/sca/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/URLClassLoadingHook.java @@ -0,0 +1,99 @@ +/* + * 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.tuscany.sca.extensibility.equinox; + +import java.security.ProtectionDomain; +import java.util.ArrayList; + +import org.eclipse.osgi.baseadaptor.BaseData; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry; +import org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook; +import org.eclipse.osgi.baseadaptor.loader.BaseClassLoader; +import org.eclipse.osgi.baseadaptor.loader.ClasspathEntry; +import org.eclipse.osgi.baseadaptor.loader.ClasspathManager; +import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain; +import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate; + +/** + * + */ +public class URLClassLoadingHook implements ClassLoadingHook { + + /* (non-Javadoc) + * @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#addClassPathEntry(java.util.ArrayList, java.lang.String, org.eclipse.osgi.baseadaptor.loader.ClasspathManager, org.eclipse.osgi.baseadaptor.BaseData, java.security.ProtectionDomain) + */ + public boolean addClassPathEntry(ArrayList cpEntries, + String cp, + ClasspathManager hostmanager, + BaseData sourcedata, + ProtectionDomain sourcedomain) { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#createClassLoader(java.lang.ClassLoader, org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate, org.eclipse.osgi.framework.adaptor.BundleProtectionDomain, org.eclipse.osgi.baseadaptor.BaseData, java.lang.String[]) + */ + public BaseClassLoader createClassLoader(ClassLoader parent, + ClassLoaderDelegate delegate, + BundleProtectionDomain domain, + BaseData data, + String[] bundleclasspath) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#findLibrary(org.eclipse.osgi.baseadaptor.BaseData, java.lang.String) + */ + public String findLibrary(BaseData data, String libName) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#getBundleClassLoaderParent() + */ + public ClassLoader getBundleClassLoaderParent() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#initializedClassLoader(org.eclipse.osgi.baseadaptor.loader.BaseClassLoader, org.eclipse.osgi.baseadaptor.BaseData) + */ + public void initializedClassLoader(BaseClassLoader baseClassLoader, BaseData data) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.eclipse.osgi.baseadaptor.hooks.ClassLoadingHook#processClass(java.lang.String, byte[], org.eclipse.osgi.baseadaptor.loader.ClasspathEntry, org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry, org.eclipse.osgi.baseadaptor.loader.ClasspathManager) + */ + public byte[] processClass(String name, + byte[] classbytes, + ClasspathEntry classpathEntry, + BundleEntry entry, + ClasspathManager manager) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/java/sca/modules/node-launcher-equinox/pom.xml b/java/sca/modules/node-launcher-equinox/pom.xml index 0356d142d6..9a6e350ba1 100644 --- a/java/sca/modules/node-launcher-equinox/pom.xml +++ b/java/sca/modules/node-launcher-equinox/pom.xml @@ -87,6 +87,7 @@ + org.apache.maven.plugins maven-jar-plugin diff --git a/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxOSGiHost.java b/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxOSGiHost.java index 0a7cf67cc2..bacfc4df87 100644 --- a/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxOSGiHost.java +++ b/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxOSGiHost.java @@ -20,12 +20,15 @@ package org.apache.tuscany.sca.node.equinox.launcher; import java.io.File; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.eclipse.core.runtime.adaptor.EclipseStarter; import org.eclipse.core.runtime.adaptor.LocationManager; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; /** * Wraps the Equinox runtime. @@ -33,7 +36,8 @@ import org.osgi.framework.BundleContext; public class EquinoxOSGiHost { private LauncherBundleActivator activator = new LauncherBundleActivator(); private BundleContext context; - + private ClassLoader tccl; + private final static String systemPackages = "org.osgi.framework; version=1.3.0," + "org.osgi.service.packageadmin; version=1.2.0, " + "org.osgi.service.startlevel; version=1.0.0, " @@ -81,6 +85,26 @@ public class EquinoxOSGiHost { throw new IllegalStateException(e); } } + + public Bundle findBundle(String symbolicName, String version) { + if (context == null) { + return null; + } + Bundle[] bundles = context.getBundles(); + if (version == null) { + version = "0.0.0"; + } + for (Bundle b : bundles) { + String v = (String)b.getHeaders().get(Constants.BUNDLE_VERSION); + if (v == null) { + v = "0.0.0"; + } + if (b.getSymbolicName().equals(symbolicName) && (version.equals("0.0.0") || v.equals(version))) { + return b; + } + } + return null; + } public void stop() { try { @@ -90,6 +114,10 @@ public class EquinoxOSGiHost { } } + public BundleContext getBundleContext() { + return context; + } + private BundleContext startup() throws Exception { String args[] = {}; Map props = new HashMap(); @@ -101,16 +129,50 @@ public class EquinoxOSGiHost { props.put(LocationManager.PROP_INSTALL_AREA, new File("target/eclipse/install").toURI().toString()); props.put(LocationManager.PROP_CONFIG_AREA, new File("target/eclipse/config").toURI().toString()); props.put(LocationManager.PROP_USER_AREA, new File("target/eclipse/user").toURI().toString()); - + EclipseStarter.setInitialProperties(props); context = EclipseStarter.startup(args, null); activator.start(context); + +// [rfeng] This is useful to report bundle resolving issues +// for (Bundle b : context.getBundles()) { +// System.out.println("Starting: " + b); +// try { +// b.start(); +// } catch (BundleException e) { +// e.printStackTrace(); +// } +// } + tccl = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(getContextClassLoader()); return context; } + private ClassLoader getContextClassLoader() { + Bundle b = findBundle("org.apache.tuscany.sca.extensibility.equinox", null); + if (b != null) { + try { + b.start(); + Class discovererClass = b.loadClass("org.apache.tuscany.sca.extensibility.ServiceDiscovery"); + Method getInstance = discovererClass.getMethod("getInstance"); + Object instance = getInstance.invoke(null); + Method getter = discovererClass.getMethod("getServiceDiscoverer"); + Object discoverer = getter.invoke(instance); + + Method getCL = discoverer.getClass().getMethod("getContextClassLoader"); + ClassLoader cl = (ClassLoader)getCL.invoke(discoverer); + return cl; + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + throw new IllegalStateException("Bundle org.apache.tuscany.sca.extensibility.equinox is not installed"); + } + private void shutdown() throws Exception { activator.stop(context); EclipseStarter.shutdown(); + Thread.currentThread().setContextClassLoader(tccl); } } diff --git a/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/LauncherBundleActivator.java b/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/LauncherBundleActivator.java index d5358726df..3f259c33a7 100644 --- a/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/LauncherBundleActivator.java +++ b/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/LauncherBundleActivator.java @@ -88,10 +88,12 @@ public class LauncherBundleActivator implements BundleActivator, Constants, Bund for (Bundle b : bundleContext.getBundles()) { try { - if ("org.apache.tuscany.sca.contribution.osgi".equals(b.getSymbolicName())) { - b.start(); - logger.info(toString(b, false) + " " + b.getState()); - break; + if ("org.apache.tuscany.sca.contribution.osgi".equals(b.getSymbolicName()) || "org.apache.tuscany.sca.extensibility.equinox" + .equals(b.getSymbolicName())) { + if (b.getHeaders().get("Fragment-Host") == null) { + b.start(); + logger.info(toString(b, false) + " " + b.getState()); + } } } catch (Exception e) { logger.log(Level.SEVERE, e.getMessage(), e); @@ -223,11 +225,14 @@ public class LauncherBundleActivator implements BundleActivator, Constants, Bund } else { return null; } + } else if (file != null && !file.exists()) { + return null; } Manifest manifest = readManifest(bundleFile); boolean isOSGiBundle = manifest != null && manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME) != null; if (!isOSGiBundle) { + // return null; manifest = updateBundleManifest(bundleFile, manifest); } diff --git a/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncher.java b/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncher.java index bc9e3f24f2..e3313e7bdf 100644 --- a/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncher.java +++ b/java/sca/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncher.java @@ -33,11 +33,14 @@ import java.util.logging.Logger; public class NodeLauncher { static final Logger logger = Logger.getLogger(NodeLauncher.class.getName()); + private EquinoxOSGiHost host; /** * Constructs a new node launcher. */ private NodeLauncher() { + host = new EquinoxOSGiHost(); + host.start(); } /** @@ -115,15 +118,11 @@ public class NodeLauncher { // Create a node launcher NodeLauncher launcher = newInstance(); - EquinoxOSGiHost equinox = null; + EquinoxOSGiHost equinox = launcher.host; Object node = null; ShutdownThread shutdown = null; try { - // Start the OSGi host - equinox = new EquinoxOSGiHost(); - equinox.start(); - if (args.length ==1) { // Create a node from a configuration URI @@ -180,6 +179,12 @@ public class NodeLauncher { } } } + + public void destroy() { + if (host != null) { + host.stop(); + } + } /** * Stop the given node. diff --git a/java/sca/modules/node-launcher-equinox/src/test/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherTestCase.java b/java/sca/modules/node-launcher-equinox/src/test/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherTestCase.java index 9e30c1695e..d393637848 100644 --- a/java/sca/modules/node-launcher-equinox/src/test/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherTestCase.java +++ b/java/sca/modules/node-launcher-equinox/src/test/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherTestCase.java @@ -32,26 +32,23 @@ import org.junit.Test; * */ public class NodeLauncherTestCase { - private static EquinoxOSGiHost equinox; + private static NodeLauncher launcher; @BeforeClass public static void setUp() { - // System.setProperty("TUSCANY_HOME", "target/tuscany"); - equinox = new EquinoxOSGiHost(); - equinox.start(); + launcher = NodeLauncher.newInstance(); } @AfterClass public static void tearDown() { - if (equinox != null) { - equinox.stop(); + if (launcher != null) { + launcher.destroy(); } } @Test public void testLaunch() throws Exception { - NodeLauncher launcher = NodeLauncher.newInstance(); SCANode node = launcher.createNodeFromClassLoader("HelloWorld.composite", getClass().getClassLoader()); node.start(); -- cgit v1.2.3