All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ops4j.pax.web.utils.ClassPathUtil Maven / Gradle / Ivy

Go to download

Pax Web is a OSGi Http Service based on Jetty 6. Detailed information to be found at http://wiki.ops4j.org/confluence/x/AYAz.

There is a newer version: 9.0.18
Show newest version
/*
 * Copyright 2012 Achim Nierbeck.
 *
 * Licensed  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.ops4j.pax.web.utils;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author achim
 * 
 */
public class ClassPathUtil {

	/**
	 * Logger.
	 */
	private static final Logger LOG = LoggerFactory
			.getLogger(ClassPathUtil.class);

	private ClassPathUtil() {
		// munch
	}

	/**
	 * Returns a list of urls to jars that composes the Bundle-ClassPath.
	 * 
	 * @param bundle
	 *            the bundle from which the class path should be taken
	 * 
	 * @return list or urls to jars that composes the Bundle-ClassPath.
	 */
	public static URL[] getClassPathJars(final Bundle bundle) {
		final List urls = new ArrayList();
		final String bundleClasspath = (String) bundle.getHeaders().get(
				"Bundle-ClassPath");
		if (bundleClasspath != null) {
			String[] segments = bundleClasspath.split(",");
			for (String segment : segments) {
				final URL url = bundle.getEntry(segment);
				if (url != null) {
					if (url.toExternalForm().endsWith("jar")) {
						LOG.debug("Using url: " + url);
						try {
							URL jarUrl = new URL("jar:" + url.toExternalForm()
									+ "!/");
							urls.add(jarUrl);
						} catch (MalformedURLException ignore) {
							LOG.debug(ignore.getMessage());
						}
					}
				}
			}
		}
		LOG.debug("Bundle-ClassPath URLs: " + urls);
		// adds the depending bundles to the "classloader" space
		urls.addAll(getLocationsOfBundlesInClassSpace(bundle));
		return urls.toArray(new URL[urls.size()]);
	}

	/**
	 * Gets the locations of the bundles in the Class Space. Beware, in Karaf
	 * this will return the URL with which the bundle was originally
	 * provisioned, i.e. could potentially return wrap:..., mvn:..., etc. and
	 * even include URL parameters (i.e. ?Webapp-Context=...).
	 * 
	 * @param bundle
	 *            the bundle for which to perform the lookup
	 * 
	 * @return list of locations of bundles in class space
	 * 
	 */

	private static List getLocationsOfBundlesInClassSpace(Bundle bundle) {
		List urls = new ArrayList();
		Set importedBundles = getBundlesInClassSpace(bundle,
				new HashSet());
		for (Bundle importedBundle : importedBundles) {
			URL url = getLocationOfBundle(importedBundle);
			if (url != null) {
				urls.add(url);
			}
		}
		return urls;
	}

	private static URL getLocationOfBundle(Bundle importedBundle) {
		URL url = null;
		try {
			url = new URL(importedBundle.getLocation());
		} catch (MalformedURLException e) {
			try {
				url = importedBundle.getEntry("/");
				// CHECKSTYLE:SKIP
			} catch (Exception e2) {
				LOG.warn("Exception while calculating location of bundle", e);
			}
		}
		return url;
	}

	/**
	 * Gets a list of bundles that are imported or required by this bundle.
	 * 
	 * @param bundle
	 *            the bundle for which to perform the lookup
	 * 
	 * @return list of imported and required bundles
	 * 
	 */
	public static Set getBundlesInClassSpace(Bundle bundle,
			Set bundleSet) {
		return getBundlesInClassSpace(bundle.getBundleContext(), bundle,
				bundleSet);
	}

	private static Set getBundlesInClassSpace(BundleContext context,
			Bundle bundle, Set bundleSet) {
		Set bundles = new HashSet(); // The set containing the
														// bundles either being
														// imported or required
		if (bundle == null) {
			LOG.error("Incoming bundle is null");
			return bundles;
		}
		if (context == null) {
			LOG.error("Incoming context is null");
			return bundles;
		}

        BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
        if (bundleWiring == null) {
            LOG.error("BundleWiring is null for: " + bundle);
            return bundles;
        }
        
		// This will give us all required Wires (including require-bundle)
		List requiredWires = bundleWiring.getRequiredWires(null);
		for (BundleWire bundleWire : requiredWires) {
			Bundle exportingBundle = bundleWire.getCapability().getRevision()
					.getBundle();

			if (exportingBundle.getBundleId() == 0) {
				continue; //system bundle is skipped this one isn't needed
			}
			if (!bundles.contains(exportingBundle)) {
				bundles.add(exportingBundle);
			}
		}

		Set transitiveBundles = new HashSet();

		if (!bundleSet.containsAll(bundles)) { //now let's scan transitively 
			bundles.removeAll(bundleSet);
			bundleSet.addAll(bundles);
			for (Bundle importedBundle : bundles) {
				transitiveBundles.addAll(getBundlesInClassSpace(context,
						importedBundle, bundleSet));
			}
		}
		
        // Sanity checkpoint to remove uninstalled bundles
        Iterator bundleIterator = bundleSet.iterator();
        while (bundleIterator.hasNext()) {
            Bundle auxBundle = bundleIterator.next();
            if (auxBundle.getState() == Bundle.UNINSTALLED) {
                bundleIterator.remove();
            }
        }

		return bundleSet;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy