summaryrefslogtreecommitdiffstats
path: root/java/sca/modules
diff options
context:
space:
mode:
authorrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2008-07-21 22:29:57 +0000
committerrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2008-07-21 22:29:57 +0000
commitfea70a868259d29d62d7cfba7a331149fd3109b2 (patch)
tree2a802e781935b8e0749d3240ff161f576d6d57ba /java/sca/modules
parentf1d04ae9c2fa7e3f55dab43187b5015e17533e51 (diff)
Fix the a set of classloading related issues such as ClassNotFoundException, ClassCastException and VerifyError
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@678589 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/sca/modules')
-rw-r--r--java/sca/modules/extensibility-osgi/src/main/java/org/apache/tuscany/sca/extensibility/osgi/OSGiServiceDiscoverer.java78
-rw-r--r--java/sca/modules/implementation-node-osgi-runtime/pom.xml2
-rw-r--r--java/sca/modules/implementation-node-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/osgi/launcher/LauncherBundleActivator.java122
-rw-r--r--java/sca/modules/implementation-node-osgi-runtime/src/test/java/org/apache/tuscany/sca/implementation/node/osgi/LauncherBundleActivatorTestCase.java50
4 files changed, 209 insertions, 43 deletions
diff --git a/java/sca/modules/extensibility-osgi/src/main/java/org/apache/tuscany/sca/extensibility/osgi/OSGiServiceDiscoverer.java b/java/sca/modules/extensibility-osgi/src/main/java/org/apache/tuscany/sca/extensibility/osgi/OSGiServiceDiscoverer.java
index 1d26d2891a..e90ded0901 100644
--- a/java/sca/modules/extensibility-osgi/src/main/java/org/apache/tuscany/sca/extensibility/osgi/OSGiServiceDiscoverer.java
+++ b/java/sca/modules/extensibility-osgi/src/main/java/org/apache/tuscany/sca/extensibility/osgi/OSGiServiceDiscoverer.java
@@ -28,6 +28,8 @@ 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;
import java.util.HashSet;
@@ -48,9 +50,77 @@ import org.osgi.framework.BundleContext;
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 @@ public class OSGiServiceDiscoverer implements ServiceDiscoverer {
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);
diff --git a/java/sca/modules/implementation-node-osgi-runtime/pom.xml b/java/sca/modules/implementation-node-osgi-runtime/pom.xml
index e301bf3a34..23836bb141 100644
--- a/java/sca/modules/implementation-node-osgi-runtime/pom.xml
+++ b/java/sca/modules/implementation-node-osgi-runtime/pom.xml
@@ -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>
diff --git a/java/sca/modules/implementation-node-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/osgi/launcher/LauncherBundleActivator.java b/java/sca/modules/implementation-node-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/osgi/launcher/LauncherBundleActivator.java
index 8296da93b5..015ef5741d 100644
--- a/java/sca/modules/implementation-node-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/osgi/launcher/LauncherBundleActivator.java
+++ b/java/sca/modules/implementation-node-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/node/osgi/launcher/LauncherBundleActivator.java
@@ -27,20 +27,54 @@ import java.util.zip.ZipEntry;
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 @@ public class LauncherBundleActivator implements BundleActivator, Constants {
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 @@ public class LauncherBundleActivator implements BundleActivator, Constants {
}
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 class LauncherBundleActivator implements BundleActivator, Constants {
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 @@ public class LauncherBundleActivator implements BundleActivator, Constants {
}
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 @@ public class LauncherBundleActivator implements BundleActivator, Constants {
}
+ 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 @@ public class LauncherBundleActivator implements BundleActivator, Constants {
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 @@ public class LauncherBundleActivator implements BundleActivator, Constants {
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 @@ public class LauncherBundleActivator implements BundleActivator, Constants {
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 @@ public class LauncherBundleActivator implements BundleActivator, Constants {
return version;
}
+ public BundleContext getBundleContext() {
+ return bundleContext;
+ }
+
+ public void bundleChanged(BundleEvent event) {
+ }
+
}
diff --git a/java/sca/modules/implementation-node-osgi-runtime/src/test/java/org/apache/tuscany/sca/implementation/node/osgi/LauncherBundleActivatorTestCase.java b/java/sca/modules/implementation-node-osgi-runtime/src/test/java/org/apache/tuscany/sca/implementation/node/osgi/LauncherBundleActivatorTestCase.java
index eb6eac78dd..50d1363887 100644
--- a/java/sca/modules/implementation-node-osgi-runtime/src/test/java/org/apache/tuscany/sca/implementation/node/osgi/LauncherBundleActivatorTestCase.java
+++ b/java/sca/modules/implementation-node-osgi-runtime/src/test/java/org/apache/tuscany/sca/implementation/node/osgi/LauncherBundleActivatorTestCase.java
@@ -64,7 +64,9 @@ public class LauncherBundleActivatorTestCase {
+ "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 @@ public class LauncherBundleActivatorTestCase {
// 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 @@ public class LauncherBundleActivatorTestCase {
}
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);
+ }
}