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
This commit is contained in:
jsdelfino 2008-09-22 01:03:53 +00:00
parent 5b2c0562e8
commit a770a0cd29
12 changed files with 819 additions and 739 deletions

View file

@ -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) {

View file

@ -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);
// 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();
// Manually call the LauncherBundleActivator for now
launcherActivator = new EquinoxLauncherBundleHelper();
launcherActivator.start(launcherBundle.getBundleContext());
// Start all bundles for now to help diagnose any class loading issues
long activateStart = System.currentTimeMillis();
// Get the already installed bundles
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);
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 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));
}
// 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 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.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;
}
}

View file

@ -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) {
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}
private static Pattern pattern = Pattern.compile("-([0-9.]+)");
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);
}
}
}
}

View file

@ -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) {

View file

@ -1,27 +0,0 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Apache Tuscany SCA Calculator RCP Sample
Bundle-SymbolicName: sample.calculator.rcp;singleton:=true
Bundle-Version: 1.4.0.SNAPSHOT
Bundle-Activator: calculator.rcp.Activator
Bundle-Vendor: The Apache Software Foundation
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-ActivationPolicy: lazy
Import-Package: org.apache.tuscany.sca.extensibility.equinox;version="1.4.0",
org.apache.tuscany.sca.node;version="1.4.0",
org.osoa.sca;version="1.4.0",
org.osoa.sca.annotations;version="1.4.0"
Bundle-ClassPath: .,
cglib-nodep-2.1_3.jar,
jaxb-impl-2.1.7.jar,
activation-1.1.jar,
jsr250-api-1.0.jar,
jsr181-api-1.0-MR1.jar,
jaxb-api-2.1.jar,
stax-api-1.0-2.jar,
jaxws-api-2.1.jar,
geronimo-commonj_1.1_spec-1.0.jar,
XmlSchema-1.3.2.jar,
wstx-asl-3.2.1.jar

View file

@ -0,0 +1 @@
This directory contains a generated MANIFEST.MF file.

View file

@ -41,30 +41,35 @@
<artifactId>tuscany-node-api</artifactId>
<version>1.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.tuscany.sca</groupId>
<artifactId>tuscany-node-impl</artifactId>
<version>1.4-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.tuscany.sca</groupId>
<artifactId>tuscany-implementation-java-runtime</artifactId>
<version>1.4-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.tuscany.sca</groupId>
<artifactId>tuscany-implementation-node-runtime</artifactId>
<version>1.4-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.tuscany.sca</groupId>
<artifactId>tuscany-extensibility-equinox</artifactId>
<version>1.4-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.tuscany.sca</groupId>
<artifactId>tuscany-node-launcher-equinox</artifactId>
@ -173,6 +178,34 @@
</classpathContainers>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>1.4.3</version>
<extensions>true</extensions>
<executions>
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<goals>
<goal>manifest</goal>
</goals>
<configuration>
<instructions>
<Bundle-Version>1.4</Bundle-Version>
<Bundle-SymbolicName>sample.calculator.rcp;singleton:=true</Bundle-SymbolicName>
<Bundle-Description>${pom.name}</Bundle-Description>
<Bundle-Activator>calculator.rcp.Activator</Bundle-Activator>
<Eclipse-LazyStart>true</Eclipse-LazyStart>
<Export-Package>calculator.rcp*</Export-Package>
</instructions>
<manifestLocation>${basedir}/META-INF</manifestLocation>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>

View file

@ -20,7 +20,6 @@ package calculator.rcp;
import java.io.File;
import org.apache.tuscany.sca.extensibility.equinox.EquinoxServiceDiscoverer;
import org.apache.tuscany.sca.node.SCANode;
import org.apache.tuscany.sca.node.equinox.launcher.Contribution;
import org.apache.tuscany.sca.node.equinox.launcher.NodeLauncher;
@ -42,28 +41,18 @@ public class Activator extends AbstractUIPlugin {
private NodeLauncher launcher;
private SCANode node;
/**
* The constructor
*/
public Activator() {
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
launcher = NodeLauncher.newInstance();
node = launcher.createNode("Calculator.composite", new Contribution("c1", new File("target/classes").toURI().toString()));
node.start();
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
plugin = null;
super.stop(context);

View file

@ -29,9 +29,6 @@ import org.eclipse.ui.PlatformUI;
*/
public class Application implements IApplication {
/* (non-Javadoc)
* @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
*/
public Object start(IApplicationContext context) {
Display display = PlatformUI.createDisplay();
try {
@ -45,9 +42,6 @@ public class Application implements IApplication {
}
}
/* (non-Javadoc)
* @see org.eclipse.equinox.app.IApplication#stop()
*/
public void stop() {
final IWorkbench workbench = PlatformUI.getWorkbench();
if (workbench == null)