summaryrefslogtreecommitdiffstats
path: root/branches/sca-equinox/modules
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2008-09-22 01:03:53 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2008-09-22 01:03:53 +0000
commita770a0cd29a37998e805287dca090cae44109bdb (patch)
tree9923aa6eee1c62cdde6111c947031f41611733e7 /branches/sca-equinox/modules
parent5b2c0562e87008db1d69ddb3b8e3769d561aa37d (diff)
Added support for several bundle packaging and distribution schemes (jars and class folders, distribution and development workspace). Changed the RCP sample to use the node-launcher.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@697650 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r--branches/sca-equinox/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java4
-rw-r--r--branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxHost.java340
-rw-r--r--branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxLauncherBundleHelper.java119
-rw-r--r--branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/JarFileFinder.java373
-rw-r--r--branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncher.java12
-rw-r--r--branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherUtil.java598
-rw-r--r--branches/sca-equinox/modules/node-launcher-equinox/src/test/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxOSGiHostTestCase.java24
7 files changed, 780 insertions, 690 deletions
diff --git a/branches/sca-equinox/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java b/branches/sca-equinox/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java
index c918ad735d..cdf47230e4 100644
--- a/branches/sca-equinox/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java
+++ b/branches/sca-equinox/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java
@@ -119,8 +119,10 @@ public class EquinoxServiceDiscoverer implements ServiceDiscoverer {
}
+ /**
+ * Empty static method to trigger the activation of this bundle.
+ */
public static void init() {
- // Empty static method to trigger the activation of this bundle
}
private static String toString(Bundle b) {
diff --git a/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxHost.java b/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxHost.java
index aabfd4bcfe..7cbcdab693 100644
--- a/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxHost.java
+++ b/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxHost.java
@@ -19,20 +19,24 @@
package org.apache.tuscany.sca.node.equinox.launcher;
-import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.bundleLocation;
-import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.installBundle;
+import static java.lang.System.currentTimeMillis;
+import static java.lang.System.setProperty;
+import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.bundleName;
+import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.file;
+import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.fixupBundle;
+import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.runtimeClasspathEntries;
import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.string;
-import static org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME;
+import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.thirdPartyLibraryBundle;
+import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.thisBundleLocation;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
+import java.io.InputStream;
import java.net.URL;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
+import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -49,10 +53,16 @@ public class EquinoxHost {
private BundleContext bundleContext;
private Bundle launcherBundle;
- private EquinoxLauncherBundleHelper launcherActivator;
+ private boolean startedEclipse;
+ private List<String> bundleFiles = new ArrayList<String>();
+ private List<String> bundleNames = new ArrayList<String>();
+ private List<String> jarFiles = new ArrayList<String>();
+ private Map<String, Bundle> allBundles = new HashMap<String, Bundle>();
+ private List<Bundle> installedBundles = new ArrayList<Bundle>();
private final static String systemPackages =
- "org.osgi.framework; version=1.3.0," + "org.osgi.service.packageadmin; version=1.2.0, "
+ "org.osgi.framework; version=1.3.0,"
+ + "org.osgi.service.packageadmin; version=1.2.0, "
+ "org.osgi.service.startlevel; version=1.0.0, "
+ "org.osgi.service.url; version=1.0.0, "
+ "org.osgi.util.tracker; version=1.3.2, "
@@ -67,8 +77,8 @@ public class EquinoxHost {
+ "javax.xml.validation, "
+ "javax.xml.xpath, "
// Force the classes to be imported from the system bundle
- // + "javax.xml.stream, "
- // + "javax.xml.stream.util, "
+ + "javax.xml.stream, "
+ + "javax.xml.stream.util, "
+ "javax.sql,"
+ "org.w3c.dom, "
+ "org.xml.sax, "
@@ -88,91 +98,187 @@ public class EquinoxHost {
+ "javax.net.ssl, "
+ "javax.crypto, "
+ "javax.rmi, "
- + "javax.transaction, "
- + "javax.transaction.xa";
-
+ //+ "javax.transaction, "
+ //+ "javax.transaction.xa, "
+ + "org.omg.CosNaming, "
+ + "org.omg.CORBA, "
+ + "org.omg.CORBA.portable, "
+ + "org.omg.PortableServer, "
+ + "org.omg.CosNaming, "
+ + "org.omg.CosNaming.NamingContextExtPackage, "
+ + "org.omg.CosNaming.NamingContextPackage, "
+ + "org.omg.CORBA_2_3.portable, "
+ + "org.omg.IOP, "
+ + "org.omg.PortableInterceptor, "
+ + "org.omg.stub.java.rmi, "
+ + "javax.rmi.CORBA";
+
+ /**
+ * Start the Equinox host.
+ *
+ * @return
+ */
public BundleContext start() {
try {
- // Configure Eclipse properties
- Map<Object, Object> props = new HashMap<Object, Object>();
-
- // Set system packages
- props.put("org.osgi.framework.system.packages", systemPackages);
+ if (!EclipseStarter.isRunning()) {
- // Use the boot classloader as the parent classloader
- props.put("osgi.contextClassLoaderParent", "boot");
-
- // Set startup properties
- props.put(EclipseStarter.PROP_CLEAN, "true");
-
- if (logger.isLoggable(Level.FINE)) {
- props.put("osgi.console", "8085");
- }
-
- // Set location properties
- // FIXME Use proper locations
- props.put(LocationManager.PROP_INSTANCE_AREA, new File("target/workspace").toURI().toString());
- 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());
-
- // Find the Tuscany JARs
- File tuscanyInstallDir = findTuscanyInstallDir();
- List<URL> urls;
- if (tuscanyInstallDir != null) {
- urls = JarFileFinder.findJarFiles(tuscanyInstallDir, new JarFileFinder.StandAloneJARFileNameFilter());
+ // Configure Eclipse properties
+ Map<Object, Object> props = new HashMap<Object, Object>();
+
+ // Set system packages
+ props.put("org.osgi.framework.system.packages", systemPackages);
+
+ // Use the boot classloader as the parent classloader
+ props.put("osgi.contextClassLoaderParent", "boot");
+
+ // Set startup properties
+ props.put(EclipseStarter.PROP_CLEAN, "true");
+
+ if (logger.isLoggable(Level.FINE)) {
+ props.put("osgi.console", "8085");
+ }
+
+ // Set location properties
+ // FIXME Use proper locations
+ props.put(LocationManager.PROP_INSTANCE_AREA, new File("target/workspace").toURI().toString());
+ 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);
+
+ // Start Eclipse
+ bundleContext = EclipseStarter.startup(new String[]{}, null);
+ startedEclipse = true;
+
} else {
- urls = JarFileFinder.getClassPathEntries(JarFileFinder.class.getClassLoader(), false);
+
+ // Get bundle context from the running Eclipse instance
+ bundleContext = EclipseStarter.getSystemBundleContext();
}
+
+ // Determine the runtime classpath entries
+ Set<URL> urls = runtimeClasspathEntries();
// Sort out which are bundles (and not already installed) and which are just
// regular JARs
- StringBuffer bundleFiles = new StringBuffer();
- StringBuffer bundleNames = new StringBuffer();
- StringBuffer jarFiles = new StringBuffer();
for (URL url : urls) {
- File file = NodeLauncherUtil.file(url);
- String bundleName = getBundleName(file);
+ File file = file(url);
+ String bundleName = bundleName(file);
if (bundleName != null) {
- bundleFiles.append(url.toString() + ";");
- bundleNames.append(bundleName + ";");
+ bundleFiles.add(url.toString());
+ bundleNames.add(bundleName);
} else {
if (file.isFile()) {
- jarFiles.append(url.toString() + ";");
+ jarFiles.add(url.toString());
}
}
}
- props.put("org.apache.tuscany.sca.node.launcher.equinox.bundleFiles", bundleFiles.toString());
- props.put("org.apache.tuscany.sca.node.launcher.equinox.bundleNames", bundleNames.toString());
- props.put("org.apache.tuscany.sca.node.launcher.equinox.jarFiles", jarFiles.toString());
-
- EclipseStarter.setInitialProperties(props);
-
- // Start Eclipse
- bundleContext = EclipseStarter.startup(new String[]{}, null);
+
+ // Get the already installed bundles
+ for (Bundle bundle: bundleContext.getBundles()) {
+ allBundles.put(bundle.getSymbolicName(), bundle);
+ }
+
+ // Install the launcher bundle if necessary
+ String launcherBundleName = "org.apache.tuscany.sca.node.launcher.equinox";
+ String launcherBundleLocation;
+ launcherBundle = allBundles.get(launcherBundleName);
+ if (launcherBundle == null) {
+ launcherBundleLocation = thisBundleLocation();
+ logger.info("Installing launcher bundle: " + launcherBundleLocation);
+ fixupBundle(launcherBundleLocation);
+ launcherBundle = bundleContext.installBundle(launcherBundleLocation);
+ allBundles.put(launcherBundleName, launcherBundle);
+ installedBundles.add(launcherBundle);
+ } else {
+ logger.info("Launcher bundle is already installed: " + string(launcherBundle, false));
+ launcherBundleLocation = thisBundleLocation(launcherBundle);
+ }
- // Install the launcher bundle
- String bundleLocation = bundleLocation();
- logger.info("Installing launcher bundle: " + bundleLocation);
- launcherBundle = installBundle(bundleContext, bundleLocation);
- logger.info("Starting bundle: " + string(launcherBundle, false));
- launcherBundle.start();
+ // Install the Tuscany bundles
+ long start = currentTimeMillis();
+
+ // FIXME: SDO bundles dont have the correct dependencies
+ setProperty("commonj.sdo.impl.HelperProvider", "org.apache.tuscany.sdo.helper.HelperProviderImpl");
+
+ // Install a single 'library' bundle for the third-party JAR files
+ String libraryBundleName = "org.apache.tuscany.sca.node.launcher.equinox.libraries";
+ Bundle libraryBundle = allBundles.get(libraryBundleName);
+ if (libraryBundle == null) {
+ logger.info("Generating third-party library bundle.");
+ for (String jarFile: jarFiles) {
+ logger.info("Adding third-party jar: " + jarFile);
+ }
+ long libraryStart = currentTimeMillis();
+ InputStream library = thirdPartyLibraryBundle(jarFiles);
+ logger.info("Third-party library bundle generated in " + (currentTimeMillis() - libraryStart) + " ms.");
+ libraryStart = currentTimeMillis();
+ libraryBundle = bundleContext.installBundle("org.apache.tuscany.sca.node.launcher.equinox.libraries", library);
+ allBundles.put(libraryBundleName, libraryBundle);
+ installedBundles.add(libraryBundle);
+ logger.info("Third-party library bundle installed in " + (currentTimeMillis() - libraryStart) + " ms: " + string(libraryBundle, false));
+ } else {
+ logger.info("Third-party library bundle is already installed: " + string(libraryBundle, false));
+ }
- // Manually call the LauncherBundleActivator for now
- launcherActivator = new EquinoxLauncherBundleHelper();
- launcherActivator.start(launcherBundle.getBundleContext());
+ // Install all the other bundles that are not already installed
+ for (int i =0, n = bundleFiles.size(); i < n; i++) {
+ String bundleFile = bundleFiles.get(i);
+ fixupBundle(bundleFile);
+ }
+ for (int i =0, n = bundleFiles.size(); i < n; i++) {
+ String bundleFile = bundleFiles.get(i);
+ String bundleName = bundleNames.get(i);
+ if (bundleName.contains("org.eclipse.jdt.junit")) {
+ continue;
+ }
+ if (bundleName.contains("host.openejb")) {
+ continue;
+ }
+ Bundle bundle = allBundles.get(bundleName);
+ if (bundle == null) {
+ long installStart = currentTimeMillis();
+ bundle = bundleContext.installBundle(bundleFile);
+ logger.info("Bundle installed in " + (currentTimeMillis() - installStart) + " ms: " + string(bundle, false));
+ allBundles.put(bundleName, bundle);
+ installedBundles.add(bundle);
+ }
+ }
+
+ long end = currentTimeMillis();
+ logger.info("Tuscany bundles are installed in " + (end - start) + " ms.");
- // Start all bundles for now to help diagnose any class loading issues
+ // Start the extensiblity and launcher bundles
long activateStart = System.currentTimeMillis();
+ String extensibilityBundleName = "org.apache.tuscany.sca.extensibility.equinox";
+ Bundle extensibilityBundle = allBundles.get(extensibilityBundleName);
+ if ((extensibilityBundle.getState() & Bundle.ACTIVE) == 0) {
+ logger.info("Starting bundle: " + string(extensibilityBundle, false));
+ extensibilityBundle.start();
+ } else {
+ logger.info("Bundle is already started: " + string(extensibilityBundle, false));
+ }
+ if ((launcherBundle.getState() & Bundle.ACTIVE) == 0) {
+ logger.info("Starting bundle: " + string(launcherBundle, false));
+ launcherBundle.start();
+ } else {
+ logger.info("Bundle is already started: " + string(launcherBundle, false));
+ }
+
+ // Start all our bundles for now to help diagnose any class loading issues
for (Bundle bundle: bundleContext.getBundles()) {
- if ((bundle.getState() & Bundle.ACTIVE) == 0) {
- logger.info("Starting bundle: " + string(bundle, false));
- try {
- bundle.start();
- } catch (Exception e) {
- logger.log(Level.SEVERE, e.getMessage(), e);
+ if (bundle.getSymbolicName().startsWith("org.apache.tuscany.sca")) {
+ if ((bundle.getState() & Bundle.ACTIVE) == 0) {
+ logger.info("Starting bundle: " + string(bundle, false));
+ try {
+ bundle.start();
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, e.getMessage(), e);
+ throw e;
+ }
+ logger.info("Bundle: " + string(bundle, false));
}
- logger.info("Bundle: " + string(bundle, false));
}
}
logger.info("Tuscany bundles are started in " + (System.currentTimeMillis() - activateStart) + " ms.");
@@ -182,78 +288,36 @@ public class EquinoxHost {
throw new IllegalStateException(e);
}
}
-
+
+ /**
+ * Stop the Equinox host.
+ */
public void stop() {
try {
- // Uninstall the launcher bundle
- if (launcherActivator != null) {
- launcherActivator.stop(launcherBundle.getBundleContext());
+ // Uninstall all the bundles we've installed
+ for (int i = installedBundles.size() -1; i >= 0; i--) {
+ Bundle bundle = installedBundles.get(i);
+ try {
+ //if (logger.isLoggable(Level.FINE)) {
+ logger.info("Uninstalling bundle: " + string(bundle, false));
+ //}
+ bundle.uninstall();
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, e.getMessage(), e);
+ }
}
- if (launcherBundle != null) {
- logger.info("Uninstalling bundle: " + string(launcherBundle, false));
- launcherBundle.uninstall();
+ installedBundles.clear();
+
+ // Shutdown Eclipse if we started it ourselves
+ if (startedEclipse) {
+ startedEclipse = false;
+ EclipseStarter.shutdown();
}
-
- // Shutdown Eclipse
- EclipseStarter.shutdown();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
- private static File findTuscanyInstallDir() throws IOException {
- String tuscanyDirName = JarFileFinder.getProperty(JarFileFinder.TUSCANY_HOME);
- if (tuscanyDirName != null) {
- File tuscanyInstallDir = new File(tuscanyDirName);
- if (tuscanyInstallDir.exists() && tuscanyInstallDir.isDirectory())
- return tuscanyInstallDir;
- }
- return null;
- }
-
- /**
- * Returns the name of a bundle, or null if the given file is not a bundle.
- *
- * @param file
- * @return
- * @throws IOException
- */
- private static String getBundleName(File file) throws IOException {
- if (!file.exists()) {
- return null;
- }
- String bundleName = null;
- if (file.isDirectory()) {
- File mf = new File(file, "META-INF/MANIFEST.MF");
- if (mf.isFile()) {
- Manifest manifest = new Manifest(new FileInputStream(mf));
- bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
- } else {
- if (file.getPath().endsWith("target/classes")) {
- // Development mode, MANIFEST.MF is outside the bundle location
- mf = new File(file.getParentFile().getParentFile(), "META-INF/MANIFEST.MF");
- if (mf.isFile()) {
- Manifest manifest = new Manifest(new FileInputStream(mf));
- bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
- }
- }
- }
- } else {
- JarFile jar = new JarFile(file, false);
- Manifest manifest = jar.getManifest();
- bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
- jar.close();
- }
- if (bundleName == null) {
- return bundleName;
- }
- int sc = bundleName.indexOf(';');
- if (sc != -1) {
- bundleName = bundleName.substring(0, sc);
- }
- return bundleName;
- }
-
}
diff --git a/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxLauncherBundleHelper.java b/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxLauncherBundleHelper.java
deleted file mode 100644
index 222ac73868..0000000000
--- a/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxLauncherBundleHelper.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.apache.tuscany.sca.node.equinox.launcher;
-
-import static java.lang.System.currentTimeMillis;
-import static java.lang.System.getProperty;
-import static java.lang.System.setProperty;
-import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.installBundle;
-import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.libraryBundle;
-import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.string;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-
-/**
- * Bundle activator which installs Tuscany modules into an OSGi runtime.
- *
- */
-public class EquinoxLauncherBundleHelper implements BundleListener {
- private static Logger logger = Logger.getLogger(EquinoxLauncherBundleHelper.class.getName());
-
- private List<Bundle> installedBundles = new ArrayList<Bundle>();
- private BundleContext bundleContext;
-
- public EquinoxLauncherBundleHelper() {
- super();
- }
-
- public void start(BundleContext bundleContext) throws Exception {
- this.bundleContext = bundleContext;
- this.bundleContext.addBundleListener(this);
-
- // Install the Tuscany bundles
- long start = currentTimeMillis();
-
- // FIXME: SDO bundles dont have the correct dependencies
- setProperty("commonj.sdo.impl.HelperProvider", "org.apache.tuscany.sdo.helper.HelperProviderImpl");
-
- // Get the list of JAR files to install
- String jarFilesProperty = getProperty("org.apache.tuscany.sca.node.launcher.equinox.jarFiles");
- String[] jarFiles = jarFilesProperty.split(";");
-
- // Create a single 'library' bundle for them
- logger.info("Generating third-party library bundle.");
- for (String jarFile: jarFiles) {
- logger.info("Adding third-party jar: " + jarFile);
- }
- long libraryStart = currentTimeMillis();
- InputStream library = libraryBundle(jarFiles);
- logger.info("Third-party library bundle generated in " + (currentTimeMillis() - libraryStart) + " ms.");
- libraryStart = currentTimeMillis();
- Bundle libraryBundle = bundleContext.installBundle("org.apache.tuscany.sca.node.launcher.equinox.libraries", library);
- logger.info("Third-party library bundle installed in " + (currentTimeMillis() - libraryStart) + " ms: " + string(libraryBundle, false));
- installedBundles.add(libraryBundle);
-
- // Get the set of already installed bundles
- Set<String> alreadyInstalledBundleNames = new HashSet<String>();
- for (Bundle bundle: bundleContext.getBundles()) {
- alreadyInstalledBundleNames.add(bundle.getSymbolicName());
- }
-
- // Get the list of bundle files and names to install
- String bundleFilesProperty = getProperty("org.apache.tuscany.sca.node.launcher.equinox.bundleFiles");
- String[] bundleFiles = bundleFilesProperty.split(";");
- String bundleNamesProperty = getProperty("org.apache.tuscany.sca.node.launcher.equinox.bundleNames");
- String[] bundleNames = bundleNamesProperty.split(";");
-
- // Install all the bundles that are not already installed
- for (int i =0, n = bundleFiles.length; i < n; i++) {
- String bundleFile = bundleFiles[i];
- String bundleName = bundleNames[i];
- if (!alreadyInstalledBundleNames.contains(bundleName)) {
- if (bundleName.contains("org.eclipse.jdt.junit")) {
- continue;
- }
- long installStart = currentTimeMillis();
- Bundle bundle = installBundle(bundleContext, bundleFile);
- logger.info("Bundle installed in " + (currentTimeMillis() - installStart) + " ms: " + string(bundle, false));
- installedBundles.add(bundle);
- alreadyInstalledBundleNames.add(bundleName);
- }
- }
-
- long end = currentTimeMillis();
- logger.info("Tuscany bundles are installed in " + (end - start) + " ms.");
- }
-
- public void stop(BundleContext bundleContext) throws Exception {
-
- // Uninstall all the bundles we've installed
- for (int i = installedBundles.size() -1; i >= 0; i--) {
- Bundle bundle = installedBundles.get(i);
- try {
- //if (logger.isLoggable(Level.FINE)) {
- logger.info("Uninstalling bundle: " + string(bundle, false));
- //}
- bundle.uninstall();
- } catch (Exception e) {
- logger.log(Level.SEVERE, e.getMessage(), e);
- }
- }
- installedBundles.clear();
-
- this.bundleContext.removeBundleListener(this);
- this.bundleContext = null;
- }
-
- public void bundleChanged(BundleEvent event) {
- }
-
-}
diff --git a/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/JarFileFinder.java b/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/JarFileFinder.java
deleted file mode 100644
index 0f595df758..0000000000
--- a/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/JarFileFinder.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * 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.node.equinox.launcher;
-
-import static org.apache.tuscany.sca.node.equinox.launcher.NodeLauncherUtil.file;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.logging.Logger;
-
-/**
- *
- */
-public class JarFileFinder {
- /**
- * A file name filter used to filter JAR files.
- */
- static class StandAloneJARFileNameFilter implements FilenameFilter {
-
- public boolean accept(File dir, String name) {
- name = name.toLowerCase();
-
- // Exclude tuscany-sca-all and tuscany-sca-manifest as they duplicate
- // code in the individual runtime module JARs
- if (name.startsWith("tuscany-sca-all")) {
- return false;
- }
- if (name.startsWith("tuscany-sca-manifest")) {
- return false;
- }
-
- // Filter out the Tomcat and Webapp hosts
- if (name.startsWith("tuscany-host-tomcat") || name.startsWith("tuscany-host-webapp")) {
- //FIXME This is temporary
- return false;
- }
-
- // Include JAR and MAR files
- if (name.endsWith(".jar")) {
- return true;
- }
- if (name.endsWith(".mar")) {
- return true;
- }
- return false;
- }
- }
-
- /**
- * A file name filter used to filter JAR files.
- */
- static class WebAppJARFileNameFilter extends StandAloneJARFileNameFilter {
-
- public boolean accept(File dir, String name) {
- if (!super.accept(dir, name)) {
- return false;
- }
- name = name.toLowerCase();
-
- // Exclude servlet-api JARs
- if (name.startsWith("servlet-api")) {
- return false;
- }
-
- // Exclude the Tomcat and Jetty hosts
- if (name.startsWith("tuscany-host-tomcat") || name.startsWith("tuscany-host-jetty")) {
- //FIXME This is temporary
- return false;
- }
-
- return true;
- }
- }
-
- private static final Logger logger = Logger.getLogger(JarFileFinder.class.getName());
-
- static final String TUSCANY_HOME = "TUSCANY_HOME";
- private static final String TUSCANY_PATH = "TUSCANY_PATH";
-
- /**
- * Collect JAR files in the given directory
- * @param directory
- * @param urls
- * @param filter
- * @throws MalformedURLException
- */
- private static void collectJARFiles(File directory, List<URL> urls, FilenameFilter filter)
- throws MalformedURLException {
- String[] files = directory.list(filter);
- if (files != null) {
- URL directoryURL = new URL(directory.toURI().toString() + "/");
- int count = 0;
- for (String file : files) {
- URL url = new URL(directoryURL, file);
- urls.add(url);
- count++;
- }
- if (count != 0) {
- logger.fine("Runtime classpath: " + count
- + " JAR"
- + (count > 1 ? "s" : "")
- + " from "
- + directory.toString());
- }
- }
- }
-
- /**
- * Collect JAR files under the given directory.
- *
- * @param directory
- * @param jarDirectoryURLs
- * @param jarURLs
- * @param filter
- * @throws MalformedURLException
- */
- private static void collectJARFiles(String directory,
- Set<URL> jarDirectoryURLs,
- List<URL> jarURLs,
- FilenameFilter filter) throws MalformedURLException {
- File directoryFile = new File(directory);
- URL directoryURL = directoryFile.toURI().toURL();
- if (!jarDirectoryURLs.contains(directoryURL) && directoryFile.exists()) {
-
- // Collect files under $TUSCANY_HOME
- jarDirectoryURLs.add(directoryURL);
- collectJARFiles(directoryFile, jarURLs, filter);
-
- // Collect files under $TUSCANY_HOME/modules
- File modulesDirectory = new File(directoryFile, "modules");
- URL modulesDirectoryURL = modulesDirectory.toURI().toURL();
- if (!jarDirectoryURLs.contains(modulesDirectoryURL) && modulesDirectory.exists()) {
- jarDirectoryURLs.add(modulesDirectoryURL);
- collectJARFiles(modulesDirectory, jarURLs, filter);
- }
-
- // Collect files under $TUSCANY_HOME/lib
- File libDirectory = new File(directoryFile, "lib");
- URL libDirectoryURL = libDirectory.toURI().toURL();
- if (!jarDirectoryURLs.contains(libDirectoryURL) && libDirectory.exists()) {
- jarDirectoryURLs.add(libDirectoryURL);
- collectJARFiles(libDirectory, jarURLs, filter);
- }
- }
- }
-
- /**
- * Returns a ClassLoader for the Tuscany runtime JARs.
- *
- * @param parentClassLoader
- * @param filter
- *
- * @return
- */
- public static List<URL> findJarFiles(File root, FilenameFilter filter) throws FileNotFoundException,
- URISyntaxException, MalformedURLException {
-
- // Build list of runtime JARs
- Set<URL> jarDirectoryURLs = new HashSet<URL>();
- List<URL> jarURLs = new ArrayList<URL>();
-
- URL url = null;
- if (root != null) {
- url = root.toURI().toURL();
- } else {
- // First determine the path to the launcher class
- String resource = JarFileFinder.class.getName().replace('.', '/') + ".class";
- url = JarFileFinder.class.getClassLoader().getResource(resource);
- if (url == null) {
- throw new FileNotFoundException(resource);
- }
-
- url = getContainer(url, resource);
- }
- URI uri = url.toURI();
-
- // If the launcher class is in a JAR, add all runtime JARs from directory containing
- // that JAR (e.g. the Tuscany modules directory) as well as the ../modules and
- // ../lib directories
- if (url != null && "file".equals(url.getProtocol())) {
-
- File file = new File(uri);
- if (file.exists()) {
- File jarDirectory = file.getParentFile();
- if (jarDirectory != null && jarDirectory.exists()) {
-
- // Collect JAR files from the directory containing the input JAR
- // (e.g. the Tuscany modules directory)
- URL jarDirectoryURL = jarDirectory.toURI().toURL();
- jarDirectoryURLs.add(jarDirectoryURL);
- collectJARFiles(jarDirectory, jarURLs, filter);
-
- File homeDirectory = jarDirectory.getParentFile();
- if (homeDirectory != null && homeDirectory.exists()) {
-
- // Collect JARs from the ../modules directory
- File modulesDirectory = new File(homeDirectory, "modules");
- URL modulesDirectoryURL = modulesDirectory.toURI().toURL();
- if (!jarDirectoryURLs.contains(modulesDirectoryURL) && modulesDirectory.exists()) {
- jarDirectoryURLs.add(modulesDirectoryURL);
- collectJARFiles(modulesDirectory, jarURLs, filter);
- }
-
- // Collect JARs from the ../lib directory
- File libDirectory = new File(homeDirectory, "lib");
- URL libDirectoryURL = libDirectory.toURI().toURL();
- if (!jarDirectoryURLs.contains(libDirectoryURL) && libDirectory.exists()) {
- jarDirectoryURLs.add(libDirectoryURL);
- collectJARFiles(libDirectory, jarURLs, filter);
- }
- }
- }
- }
- }
-
- // Look for a TUSCANY_HOME system property or environment variable
- // Add all the JARs found under $TUSCANY_HOME, $TUSCANY_HOME/modules
- // and $TUSCANY_HOME/lib
- String home = getProperty(TUSCANY_HOME);
- if (home != null && home.length() != 0) {
- logger.fine(TUSCANY_HOME + ": " + home);
- collectJARFiles(home, jarDirectoryURLs, jarURLs, filter);
- }
-
- // Look for a TUSCANY_PATH system property or environment variable
- // Add all the JARs found under $TUSCANY_PATH, $TUSCANY_PATH/modules
- // and $TUSCANY_PATH/lib
- String ext = getProperty(TUSCANY_PATH);
- if (ext != null && ext.length() != 0) {
- logger.fine(TUSCANY_PATH + ": " + ext);
- String separator = getProperty("path.separator");
- for (StringTokenizer tokens = new StringTokenizer(ext, separator); tokens.hasMoreTokens();) {
- collectJARFiles(tokens.nextToken(), jarDirectoryURLs, jarURLs, filter);
- }
- }
-
- return jarURLs;
-
- }
-
-
- /**
- * Returns contribution JARs available on the classpath.
- *
- * @return
- */
- static List<URL> getClassPathEntries(ClassLoader classLoader, boolean recursive) {
- Set<URL> entries = new HashSet<URL>();
- list(entries, classLoader, recursive);
- return new ArrayList<URL>(entries);
- }
-
- /**
- * Collect JARs on the classpath of a URLClassLoader
- * @param urls
- * @param cl
- */
- private static void list(Set<URL> urls, ClassLoader cl, boolean recursive) {
- if (cl == null) {
- return;
- }
-
- // Collect JARs from the URLClassLoader's classpath
- if (cl instanceof URLClassLoader) {
- URL[] jarURLs = ((URLClassLoader)cl).getURLs();
- if (jarURLs != null) {
- for (URL jarURL : jarURLs) {
- urls.add(jarURL);
- }
- }
- }
-
- // Collect JARs from the parent ClassLoader
- if (recursive) {
- list(urls, cl.getParent(), recursive);
- }
- }
-
-
- static String getProperty(final String prop) {
- return AccessController.doPrivileged(new PrivilegedAction<String>() {
- public String run() {
- String value = System.getProperty(prop);
- if (value == null || value.length() == 0) {
- return System.getenv(prop);
- } else {
- return value;
- }
- }
- });
- }
-
- private static URL getContainer(URL resourceURL, String resourceName) {
- URL root = null;
- // "jar:file://....../something.jar!/a/b/c/app.composite"
- try {
- String url = resourceURL.toExternalForm();
- String protocol = resourceURL.getProtocol();
- if ("file".equals(protocol)) {
- // directory contribution
- if (url.endsWith("/" + resourceName)) {
- final String location = url.substring(0, url.length() - resourceName.length() - 1);
- // workaround from evil URL/URI form Maven
- // contributionURL = FileHelper.toFile(new URL(location)).toURI().toURL();
- // Allow privileged access to open URL stream. Add FilePermission to added to
- // security policy file.
- try {
- root = AccessController.doPrivileged(new PrivilegedExceptionAction<URL>() {
- public URL run() throws IOException {
- return file(new URL(location)).toURI().toURL();
- }
- });
- } catch (PrivilegedActionException e) {
- throw (MalformedURLException)e.getException();
- }
- }
-
- } else if ("jar".equals(protocol)) {
- // jar contribution
- String location = url.substring(4, url.lastIndexOf("!/"));
- // workaround for evil URL/URI from Maven
- root = file(new URL(location)).toURI().toURL();
-
- } else if ("wsjar".equals(protocol)) {
- // See https://issues.apache.org/jira/browse/TUSCANY-2219
- // wsjar contribution
- String location = url.substring(6, url.lastIndexOf("!/"));
- // workaround for evil url/uri from maven
- root = file(new URL(location)).toURI().toURL();
-
- } else if (protocol != null && (protocol.equals("bundle") || protocol.equals("bundleresource"))) {
- root = new URL(resourceURL.getProtocol(), resourceURL.getHost(), resourceURL.getPort(), "/");
- }
- } catch (MalformedURLException mfe) {
- throw new IllegalArgumentException(mfe);
- }
- return root;
- }
-
-}
diff --git a/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncher.java b/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncher.java
index f3bb8c04ae..790b1ab48c 100644
--- a/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncher.java
+++ b/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncher.java
@@ -35,15 +35,15 @@ import org.osgi.framework.BundleContext;
public class NodeLauncher {
static final Logger logger = Logger.getLogger(NodeLauncher.class.getName());
- private EquinoxHost host;
+ private EquinoxHost equinoxHost;
private BundleContext bundleContext;
/**
* Constructs a new node launcher.
*/
private NodeLauncher() {
- host = new EquinoxHost();
- bundleContext = host.start();
+ equinoxHost = new EquinoxHost();
+ bundleContext = equinoxHost.start();
}
/**
@@ -121,7 +121,7 @@ public class NodeLauncher {
// Create a node launcher
NodeLauncher launcher = newInstance();
- EquinoxHost equinox = launcher.host;
+ EquinoxHost equinox = launcher.equinoxHost;
Object node = null;
ShutdownThread shutdown = null;
try {
@@ -184,8 +184,8 @@ public class NodeLauncher {
}
public void destroy() {
- if (host != null) {
- host.stop();
+ if (equinoxHost != null) {
+ equinoxHost.stop();
bundleContext = null;
}
}
diff --git a/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherUtil.java b/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherUtil.java
index 0bbf09d101..96e2684cb9 100644
--- a/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherUtil.java
+++ b/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherUtil.java
@@ -32,19 +32,29 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
+import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
+import java.util.StringTokenizer;
import java.util.jar.Attributes;
+import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.logging.Level;
+import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
@@ -60,6 +70,7 @@ import org.osgi.framework.BundleException;
* @version $Rev$ $Date$
*/
final class NodeLauncherUtil {
+ private static final Logger logger = Logger.getLogger(NodeLauncherUtil.class.getName());
private static final String LAUNCHER_EQUINOX_LIBRARIES = "org.apache.tuscany.sca.node.launcher.equinox.libraries";
@@ -74,18 +85,29 @@ final class NodeLauncherUtil {
private static final String NODE_IMPLEMENTATION_LAUNCHER_BOOTSTRAP =
"org.apache.tuscany.sca.implementation.node.launcher.NodeImplementationLauncherBootstrap";
+ private static final String TUSCANY_HOME = "TUSCANY_HOME";
+ private static final String TUSCANY_PATH = "TUSCANY_PATH";
+
/**
- * Collect JAR files under the given directory.
+ * Creates a new node.
+ *
+ * @param configurationURI
+ * @param compositeURI
+ * @param compositeContent
* @param contributions
- * @param bundleContext TODO
+ * @param contributionClassLoader
+ * @param bundleContext
* @throws LauncherException
*/
static Object node(String configurationURI,
String compositeURI,
String compositeContent,
Contribution[] contributions,
- ClassLoader contributionClassLoader, BundleContext bundleContext) throws LauncherException {
+ ClassLoader contributionClassLoader,
+ BundleContext bundleContext) throws LauncherException {
try {
+
+ // Get the node runtime bundle.
Bundle bundle = null;
for (Bundle b : bundleContext.getBundles()) {
if ("org.apache.tuscany.sca.implementation.node.runtime".equals(b.getSymbolicName())) {
@@ -94,9 +116,9 @@ final class NodeLauncherUtil {
}
}
if (bundle == null) {
- throw new IllegalStateException(
- "Bundle org.apache.tuscany.sca.implementation.node.runtime is not installed");
+ throw new IllegalStateException("Bundle org.apache.tuscany.sca.implementation.node.runtime is not installed");
}
+
// Use Java reflection to create the node as only the runtime class
// loader knows the runtime classes required by the node
Class<?> bootstrapClass = bundle.loadClass(NODE_IMPLEMENTATION_LAUNCHER_BOOTSTRAP);
@@ -117,8 +139,7 @@ final class NodeLauncherUtil {
// Construct the node with a composite URI, the composite content and
// the URIs and locations of a list of contributions
- Constructor<?> constructor =
- bootstrapClass.getConstructor(String.class, String.class, String[].class, String[].class);
+ Constructor<?> constructor = bootstrapClass.getConstructor(String.class, String.class, String[].class, String[].class);
String[] uris = new String[contributions.length];
String[] locations = new String[contributions.length];
for (int i = 0; i < contributions.length; i++) {
@@ -131,8 +152,7 @@ final class NodeLauncherUtil {
// Construct the node with a composite URI and the URIs and
// locations of a list of contributions
- Constructor<?> constructor =
- bootstrapClass.getConstructor(String.class, String[].class, String[].class);
+ Constructor<?> constructor = bootstrapClass.getConstructor(String.class, String[].class, String[].class);
String[] uris = new String[contributions.length];
String[] locations = new String[contributions.length];
for (int i = 0; i < contributions.length; i++) {
@@ -142,7 +162,11 @@ final class NodeLauncherUtil {
bootstrap = constructor.newInstance(compositeURI, uris, locations);
}
+ // Get the node instance
Object node = bootstrapClass.getMethod("getNode").invoke(bootstrap);
+
+ // If the SCANodeFactory interface is available in the current classloader, create
+ // an SCANode proxy around the node we've just create
try {
Class<?> type = Class.forName(SCANODE_FACTORY);
type = type.getDeclaredClasses()[0];
@@ -213,26 +237,15 @@ final class NodeLauncherUtil {
}
}
- static File file(URL url) {
- if (url == null || !url.getProtocol().equals("file")) {
- return null;
- } else {
- String filename = url.getFile().replace('/', File.separatorChar);
- int pos = 0;
- while ((pos = filename.indexOf('%', pos)) >= 0) {
- if (pos + 2 < filename.length()) {
- String hexStr = filename.substring(pos + 1, pos + 3);
- char ch = (char)Integer.parseInt(hexStr, 16);
- filename = filename.substring(0, pos) + ch + filename.substring(pos + 3);
- }
- }
- return new File(filename);
- }
- }
-
- static Pattern pattern = Pattern.compile("-([0-9.]+)");
+ private static Pattern pattern = Pattern.compile("-([0-9.]+)");
- private static String version(String jarFile) {
+ /**
+ * Returns the version number to use for the given JAR file.
+ *
+ * @param jarFile
+ * @return
+ */
+ private static String jarVersion(String jarFile) {
Matcher matcher = pattern.matcher(jarFile);
String version = "1.0.0";
if (matcher.find()) {
@@ -246,8 +259,15 @@ final class NodeLauncherUtil {
return version;
}
+ /**
+ * Add the packages found in the given JAR to a set.
+ *
+ * @param jarFile
+ * @param packages
+ * @throws IOException
+ */
private static void addPackages(String jarFile, Set<String> packages) throws IOException {
- String version = ";version=" + version(jarFile);
+ String version = ";version=" + jarVersion(jarFile);
ZipInputStream is = new ZipInputStream(new FileInputStream(file(new URL(jarFile))));
ZipEntry entry;
while ((entry = is.getNextEntry()) != null) {
@@ -264,7 +284,14 @@ final class NodeLauncherUtil {
is.close();
}
- static Manifest libraryManifest(String[] jarFiles) throws IllegalStateException {
+ /**
+ * Generate a manifest from a list of third-party JAR files.
+ *
+ * @param jarFiles
+ * @return
+ * @throws IllegalStateException
+ */
+ static private Manifest thirdPartyLibraryBundleManifest(List<String> jarFiles) throws IllegalStateException {
try {
// List exported packages and bundle classpath entries
@@ -313,9 +340,16 @@ final class NodeLauncherUtil {
}
}
- static InputStream libraryBundle(String[] jarFiles) throws IOException {
+ /**
+ * Generates a library bundle from a list of third-party JARs.
+ *
+ * @param jarFiles
+ * @return
+ * @throws IOException
+ */
+ static InputStream thirdPartyLibraryBundle(List<String> jarFiles) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
- Manifest mf = libraryManifest(jarFiles);
+ Manifest mf = thirdPartyLibraryBundleManifest(jarFiles);
JarOutputStream jos = new JarOutputStream(bos, mf);
jos.close();
return new ByteArrayInputStream(bos.toByteArray());
@@ -327,7 +361,7 @@ final class NodeLauncherUtil {
* @return
* @throws IOException
*/
- static String bundleLocation() throws IOException, URISyntaxException {
+ static String thisBundleLocation() throws IOException, URISyntaxException {
String resource = NodeLauncherUtil.class.getName().replace('.', '/') + ".class";
URL url = NodeLauncherUtil.class.getClassLoader().getResource(resource);
if (url == null) {
@@ -348,10 +382,50 @@ final class NodeLauncherUtil {
}
}
- static Bundle installBundle(BundleContext bundleContext, String location) throws BundleException, IOException {
- // Development mode, copy the MANIFEST.MF file to the bundle location
+ /**
+ * Returns the location of this bundle.
+ *
+ * @param bundle
+ * @return
+ * @throws IOException
+ */
+ static String thisBundleLocation(Bundle bundle) throws IOException, URISyntaxException, ClassNotFoundException {
+ String resource = NodeLauncherUtil.class.getName();
+ Class<?> clazz = bundle.loadClass(NodeLauncherUtil.class.getName());
+ URL url = clazz.getProtectionDomain().getCodeSource().getLocation();
+ if (url == null) {
+ throw new FileNotFoundException(resource);
+ }
+ URI uri = url.toURI();
+
+ String scheme = uri.getScheme();
+ if (scheme.equals("jar")) {
+ String path = uri.toString().substring(4);
+ int i = path.indexOf("!/");
+ path = path.substring(0, i);
+ return path;
+ } else {
+ String path = uri.toString();
+ //path = path.substring(0, path.length() - resource.length());
+ return path;
+ }
+ }
+
+ /**
+ * Install the given bundle.
+ *
+ * @param bundleContext
+ * @param location
+ * @throws BundleException
+ * @throws IOException
+ */
+ static void fixupBundle(String location) throws BundleException, IOException {
+ File target = file(new URL(location));
+ location = target.toURI().toString();
+
+ // For development mode, copy the MANIFEST.MF file to the bundle location as it's
+ // initially outside of target/classes, at the root of the project.
if (location.endsWith("/target/classes/")) {
- File target = file(new URL(location));
File targetManifest = new File(target, "META-INF/MANIFEST.MF");
File sourceManifest = new File(target.getParentFile().getParentFile(), "META-INF/MANIFEST.MF");
targetManifest.getParentFile().mkdirs();
@@ -368,15 +442,19 @@ final class NodeLauncherUtil {
is.close();
os.close();
}
-
- Bundle bundle = bundleContext.installBundle(location);
- return bundle;
}
- static String string(Bundle b, boolean verbose) {
+ /**
+ * Returns a string representation of the given bundle.
+ *
+ * @param b
+ * @param verbose
+ * @return
+ */
+ static String string(Bundle bundle, boolean verbose) {
StringBuffer sb = new StringBuffer();
- sb.append(b.getBundleId()).append(" ").append(b.getSymbolicName());
- int s = b.getState();
+ sb.append(bundle.getBundleId()).append(" ").append(bundle.getSymbolicName());
+ int s = bundle.getState();
if ((s & Bundle.UNINSTALLED) != 0) {
sb.append(" UNINSTALLED");
}
@@ -397,9 +475,441 @@ final class NodeLauncherUtil {
}
if (verbose) {
- sb.append(" ").append(b.getLocation());
- sb.append(" ").append(b.getHeaders());
+ sb.append(" ").append(bundle.getLocation());
+ sb.append(" ").append(bundle.getHeaders());
}
return sb.toString();
}
+
+ /**
+ * Returns the name of a bundle, or null if the given file is not a bundle.
+ *
+ * @param file
+ * @return
+ * @throws IOException
+ */
+ static String bundleName(File file) throws IOException {
+ if (!file.exists()) {
+ return null;
+ }
+ String bundleName = null;
+ if (file.isDirectory()) {
+ File mf = new File(file, "META-INF/MANIFEST.MF");
+ if (mf.isFile()) {
+ Manifest manifest = new Manifest(new FileInputStream(mf));
+ bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
+ } else {
+ if (file.getPath().endsWith("target/classes")) {
+ // Development mode, MANIFEST.MF is outside the bundle location
+ mf = new File(file.getParentFile().getParentFile(), "META-INF/MANIFEST.MF");
+ if (mf.isFile()) {
+ Manifest manifest = new Manifest(new FileInputStream(mf));
+ bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
+ }
+ }
+ }
+ } else {
+ JarFile jar = new JarFile(file, false);
+ Manifest manifest = jar.getManifest();
+ bundleName = manifest.getMainAttributes().getValue(BUNDLE_SYMBOLICNAME);
+ jar.close();
+ }
+ if (bundleName == null) {
+ return bundleName;
+ }
+ int sc = bundleName.indexOf(';');
+ if (sc != -1) {
+ bundleName = bundleName.substring(0, sc);
+ }
+ return bundleName;
+ }
+
+ /**
+ * Collect JAR files in the given directory.
+ *
+ * @param directory
+ * @param urls
+ * @param filter
+ * @throws MalformedURLException
+ */
+ private static void collectClasspathEntries(File directory, Set<URL> urls, FilenameFilter filter) throws MalformedURLException {
+ File[] files = directory.listFiles(filter);
+ if (files != null) {
+ int count = 0;
+ for (File file: files) {
+ urls.add(file.toURI().toURL());
+ count++;
+ }
+ if (count != 0) {
+ logger.info("Runtime classpath: "+ count + " JAR" + (count > 1? "s":"")+ " from " + directory.toString());
+ }
+ }
+ }
+
+ /**
+ * Collect development .../ target/classes directories in the given directory.
+ *
+ * @param directory
+ * @param urls
+ * @param filter
+ * @throws MalformedURLException
+ */
+ private static void collectTargetClassesClasspathEntries(File directory, Set<URL> urls, FilenameFilter filter) throws MalformedURLException {
+ File[] files = directory.listFiles();
+ if (files != null) {
+ int count = 0;
+ for (File file: files) {
+ if (!file.isDirectory()) {
+ continue;
+ }
+ File target = new File(file, "target");
+ if (!target.isDirectory()) {
+ continue;
+ }
+ File classes = new File(target, "classes");
+ if (classes.isDirectory() && filter.accept(target, "classes")) {
+ urls.add(classes.toURI().toURL());
+ count++;
+ }
+ }
+ if (count != 0) {
+ logger.info("Runtime classpath: "+ count + " classes folder" + (count > 1? "s":"")+ " from " + directory.toString());
+ }
+ }
+ }
+
+ /**
+ * Collect JAR files under the given distribution directory.
+ *
+ * @param directory
+ * @param jarDirectoryURLs
+ * @param jarURLs
+ * @param filter
+ * @throws MalformedURLException
+ */
+ private static void collectDistributionClasspathEntries(String directory, Set<URL> jarDirectoryURLs, Set<URL> jarURLs, FilenameFilter filter)
+ throws MalformedURLException {
+ File directoryFile = new File(directory);
+ URL directoryURL = directoryFile.toURI().toURL();
+ if (!jarDirectoryURLs.contains(directoryURL) && directoryFile.exists()) {
+
+ // Collect files under the given directory
+ jarDirectoryURLs.add(directoryURL);
+ collectClasspathEntries(directoryFile, jarURLs, filter);
+
+ // Collect files under <directory>/modules
+ File modulesDirectory = new File(directoryFile, "modules");
+ URL modulesDirectoryURL = modulesDirectory.toURI().toURL();
+ if (!jarDirectoryURLs.contains(modulesDirectoryURL) && modulesDirectory.exists()) {
+ jarDirectoryURLs.add(modulesDirectoryURL);
+ collectClasspathEntries(modulesDirectory, jarURLs, filter);
+ }
+
+ // Collect files under <directory>/lib
+ File libDirectory = new File(directoryFile, "lib");
+ URL libDirectoryURL = libDirectory.toURI().toURL();
+ if (!jarDirectoryURLs.contains(libDirectoryURL) && libDirectory.exists()) {
+ jarDirectoryURLs.add(libDirectoryURL);
+ collectClasspathEntries(libDirectory, jarURLs, filter);
+ }
+ }
+ }
+
+ /**
+ * Determine the Tuscany runtime classpath entries.
+ *
+ * @return
+ */
+ static Set<URL> runtimeClasspathEntries() throws FileNotFoundException,
+ URISyntaxException, MalformedURLException {
+
+ // Build list of runtime JARs
+ Set<URL> jarDirectoryURLs = new HashSet<URL>();
+ Set<URL> jarURLs = new HashSet<URL>();
+
+ // Determine the path to the launcher class
+ URI uri = URI.create(codeLocation(NodeLauncherUtil.class));
+
+ // If the launcher class is in a JAR, add all runtime JARs from directory containing
+ // that JAR (e.g. the Tuscany modules directory) as well as the ../modules and
+ // ../lib directories
+ if (uri.getPath().endsWith(".jar")) {
+
+ File file = new File(uri);
+ if (file.exists()) {
+ File jarDirectory = file.getParentFile();
+ if (jarDirectory != null && jarDirectory.exists()) {
+
+ // Collect JAR files from the directory containing the input JAR
+ // (e.g. the Tuscany modules directory)
+ URL jarDirectoryURL = jarDirectory.toURI().toURL();
+ jarDirectoryURLs.add(jarDirectoryURL);
+ collectClasspathEntries(jarDirectory, jarURLs, new StandAloneJARFileNameFilter());
+
+ File homeDirectory = jarDirectory.getParentFile();
+ if (homeDirectory != null && homeDirectory.exists()) {
+ collectDistributionClasspathEntries(homeDirectory.getAbsolutePath(), jarDirectoryURLs, jarURLs, new StandAloneJARFileNameFilter());
+ }
+ }
+ }
+ } else if (uri.getPath().endsWith("target/classes/")) {
+
+ // Development mode, we're running off classes in a workspace
+ // and not from Maven surefire, collect all bundles in the workspace
+ ClassLoader cl = NodeLauncherUtil.class.getClassLoader();
+ if (!cl.getClass().getName().startsWith("org.apache.maven.surefire")) {
+ File file = new File(uri);
+ if (file.exists()) {
+ File moduleDirectory = file.getParentFile().getParentFile();
+ if (moduleDirectory != null) {
+ File modulesDirectory = moduleDirectory.getParentFile();
+ if (modulesDirectory != null && modulesDirectory.exists() && modulesDirectory.getName().equals("modules")) {
+ collectDevelopmentClasspathEntries(modulesDirectory.getAbsolutePath(), jarDirectoryURLs, jarURLs, new StandAloneDevelopmentClassesFileNameFilter());
+ }
+ }
+ }
+ }
+ }
+
+ // Look for a TUSCANY_HOME system property or environment variable
+ // Add all the JARs found under $TUSCANY_HOME, $TUSCANY_HOME/modules
+ // and $TUSCANY_HOME/lib
+ String home = getProperty(TUSCANY_HOME);
+ if (home != null && home.length() != 0) {
+ logger.info(TUSCANY_HOME + ": " + home);
+ collectDistributionClasspathEntries(home, jarDirectoryURLs, jarURLs, new StandAloneJARFileNameFilter());
+ }
+
+ // Look for a TUSCANY_PATH system property or environment variable
+ // Add all the JARs found under $TUSCANY_PATH, $TUSCANY_PATH/modules
+ // and $TUSCANY_PATH/lib
+ String ext = getProperty(TUSCANY_PATH);
+ if (ext != null && ext.length() != 0) {
+ logger.info(TUSCANY_PATH + ": " + ext);
+ String separator = getProperty("path.separator");
+ for (StringTokenizer tokens = new StringTokenizer(ext, separator); tokens.hasMoreTokens();) {
+ collectDistributionClasspathEntries(tokens.nextToken(), jarDirectoryURLs, jarURLs, new StandAloneJARFileNameFilter());
+ }
+ }
+
+ // Add the classpath entries from the current classloader
+ collectClassLoaderClasspathEntries(jarURLs, NodeLauncherUtil.class.getClassLoader(), false);
+
+ return jarURLs;
+
+ }
+
+ /**
+ * Returns the JAR files on the classpath used by the given classloader.
+ *
+ * @param classLoader
+ * @return
+ */
+ static List<URL> jarFilesOnClasspath(ClassLoader classLoader) {
+ Set<URL> entries = new HashSet<URL>();
+ collectClassLoaderClasspathEntries(entries, classLoader, false);
+ return new ArrayList<URL>(entries);
+ }
+
+ private static String getProperty(final String prop) {
+ return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ public String run() {
+ String value = System.getProperty(prop);
+ if (value == null || value.length() == 0) {
+ return System.getenv(prop);
+ } else {
+ return value;
+ }
+ }
+ });
+ }
+
+ /**
+ * Collect JARs on the classpath of a URLClassLoader.
+ *
+ * @param urls
+ * @param cl
+ */
+ private static void collectClassLoaderClasspathEntries(Set<URL> urls, ClassLoader cl, boolean recursive) {
+ if (cl == null) {
+ return;
+ }
+
+ // Collect JARs from the URLClassLoader's classpath
+ if (cl instanceof URLClassLoader) {
+ URL[] jarURLs = ((URLClassLoader)cl).getURLs();
+ if (jarURLs != null) {
+ for (URL jarURL : jarURLs) {
+ urls.add(jarURL);
+ }
+ }
+ }
+
+ // Collect JARs from the parent ClassLoader
+ if (recursive) {
+ collectClassLoaderClasspathEntries(urls, cl.getParent(), recursive);
+ }
+ }
+
+ /**
+ * A file name filter used to filter JAR files.
+ */
+ private static class StandAloneJARFileNameFilter implements FilenameFilter {
+
+ public boolean accept(File dir, String name) {
+ name = name.toLowerCase();
+
+ // Filter out the Tomcat and Webapp hosts
+ if (name.startsWith("tuscany-host-tomcat") ||
+ name.startsWith("tuscany-host-webapp")) {
+ //FIXME This is temporary
+ return false;
+ }
+
+ // Include JAR and MAR files
+ if (name.endsWith(".jar")) {
+ return true;
+ }
+ if (name.endsWith(".mar")) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * A file name filter used to filter target/classes directories.
+ */
+ private static class StandAloneDevelopmentClassesFileNameFilter implements FilenameFilter {
+
+ public boolean accept(File dir, String name) {
+ name = name.toLowerCase();
+ if (dir.getName().equals("target") && name.equals("classes")) {
+
+ // Filter out the Tomcat and Webapp hosts
+ String dirPath = dir.getAbsolutePath();
+ if (dirPath.endsWith("host-tomcat/target") ||
+ dirPath.endsWith("host-webapp/target")) {
+ //FIXME This is temporary
+ return false;
+ }
+ return true;
+ }
+
+ // Filter out the Tomcat and Webapp hosts
+ if (name.startsWith("tuscany-host-tomcat") ||
+ name.startsWith("tuscany-host-webapp")) {
+ //FIXME This is temporary
+ return false;
+ }
+
+ // Include JAR and MAR files
+ if (name.endsWith(".jar")) {
+ return true;
+ }
+ if (name.endsWith(".mar")) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * A file name filter used to filter JAR files.
+ */
+ private static class WebAppJARFileNameFilter extends StandAloneJARFileNameFilter {
+
+ @Override
+ public boolean accept(File dir, String name) {
+ if (!super.accept(dir, name)) {
+ return false;
+ }
+ name = name.toLowerCase();
+
+ // Exclude servlet-api JARs
+ if (name.startsWith("servlet-api")) {
+ return false;
+ }
+
+ // Exclude the Tomcat and Jetty hosts
+ if (name.startsWith("tuscany-host-tomcat") || name.startsWith("tuscany-host-jetty")) {
+ //FIXME This is temporary
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ /**
+ * Returns the File object representing the given URL.
+ *
+ * @param url
+ * @return
+ */
+ static File file(URL url) {
+ if (url == null || !url.getProtocol().equals("file")) {
+ return null;
+ } else {
+ String filename = url.getFile().replace('/', File.separatorChar);
+ int pos = 0;
+ while ((pos = filename.indexOf('%', pos)) >= 0) {
+ if (pos + 2 < filename.length()) {
+ String hexStr = filename.substring(pos + 1, pos + 3);
+ char ch = (char)Integer.parseInt(hexStr, 16);
+ filename = filename.substring(0, pos) + ch + filename.substring(pos + 3);
+ }
+ }
+ return new File(filename);
+ }
+ }
+
+ /**
+ * Returns the location of the classpath entry, JAR, WAR etc. containing the given class.
+ *
+ * @param clazz
+ * @return
+ */
+ static private String codeLocation(Class<?> clazz) {
+ String filename = clazz.getProtectionDomain().getCodeSource().getLocation().toString();
+ int pos = 0;
+ while ((pos = filename.indexOf('%', pos)) >= 0) {
+ if (pos + 2 < filename.length()) {
+ String hexStr = filename.substring(pos + 1, pos + 3);
+ char ch = (char)Integer.parseInt(hexStr, 16);
+ filename = filename.substring(0, pos) + ch + filename.substring(pos + 3);
+ }
+ }
+ return filename;
+ }
+
+ /**
+ * Collect JAR files under the given distribution directory.
+ *
+ * @param directory
+ * @param jarDirectoryURLs
+ * @param jarURLs
+ * @param filter
+ * @throws MalformedURLException
+ */
+ private static void collectDevelopmentClasspathEntries(String directory, Set<URL> jarDirectoryURLs, Set<URL> jarURLs, FilenameFilter filter)
+ throws MalformedURLException {
+ File directoryFile = new File(directory);
+ URL directoryURL = directoryFile.toURI().toURL();
+ if (!jarDirectoryURLs.contains(directoryURL) && directoryFile.exists()) {
+
+ // Collect files under the given directory
+ jarDirectoryURLs.add(directoryURL);
+ collectTargetClassesClasspathEntries(directoryFile, jarURLs, filter);
+
+ // Collect files under <directory>/thirdparty-library/lib
+ File libDirectory = new File(directoryFile, "thirdparty-library/lib");
+ URL libDirectoryURL = libDirectory.toURI().toURL();
+ if (!jarDirectoryURLs.contains(libDirectoryURL) && libDirectory.exists()) {
+ jarDirectoryURLs.add(libDirectoryURL);
+ collectClasspathEntries(libDirectory, jarURLs, filter);
+ }
+ }
+ }
+
}
diff --git a/branches/sca-equinox/modules/node-launcher-equinox/src/test/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxOSGiHostTestCase.java b/branches/sca-equinox/modules/node-launcher-equinox/src/test/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxOSGiHostTestCase.java
index da0ab774a3..cd3f1e294e 100644
--- a/branches/sca-equinox/modules/node-launcher-equinox/src/test/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxOSGiHostTestCase.java
+++ b/branches/sca-equinox/modules/node-launcher-equinox/src/test/java/org/apache/tuscany/sca/node/equinox/launcher/EquinoxOSGiHostTestCase.java
@@ -33,6 +33,7 @@ import org.osgi.framework.BundleContext;
*
*/
public class EquinoxOSGiHostTestCase {
+
@Test
public void testStartThenStop() {
EquinoxHost host = new EquinoxHost();
@@ -45,17 +46,22 @@ public class EquinoxOSGiHostTestCase {
}
@Test
- public void testStartTwice() {
+ public void testStartThenStopTwice() {
EquinoxHost host = new EquinoxHost();
- host.start();
- try {
- host.start();
- Assert.fail();
- } catch (IllegalStateException e) {
- Assert.assertTrue(IllegalStateException.class.isInstance(e.getCause()));
- } finally {
- host.stop();
+ BundleContext context = host.start();
+ Assert.assertNotNull(context);
+ for (Bundle b : context.getBundles()) {
+ System.out.println(toString(b, false));
}
+ host.stop();
+
+ host = new EquinoxHost();
+ context = host.start();
+ Assert.assertNotNull(context);
+ for (Bundle b : context.getBundles()) {
+ System.out.println(toString(b, false));
+ }
+ host.stop();
}
public static String toString(Bundle b, boolean verbose) {