summaryrefslogtreecommitdiffstats
path: root/branches/sca-equinox/modules/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherUtil.java
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/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherUtil.java
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/node-launcher-equinox/src/main/java/org/apache/tuscany/sca/node/equinox/launcher/NodeLauncherUtil.java598
1 files changed, 554 insertions, 44 deletions
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);
+ }
+ }
+ }
+
}