blob: 3d6e280c0ace10043e7659f49fdab329cd3ec25d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.launch;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.*;
import java.security.*;
import java.util.*;
import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.util.Headers;
import org.eclipse.osgi.internal.baseadaptor.DevClassPathHelper;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.*;
import org.osgi.framework.launch.Framework;
/**
* The System Bundle implementation for the Equinox Framework.
*
* @since 3.5
*/
public class Equinox implements Framework {
private static final String implName = "org.eclipse.osgi.framework.internal.core.EquinoxLauncher"; //$NON-NLS-1$
/**@GuardedBy this*/
private Framework impl;
private final boolean useSeparateCL;
private final Map configuration;
public Equinox(Map configuration) {
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new AllPermission());
useSeparateCL = FrameworkProperties.inUse();
this.configuration = configuration == null ? Collections.EMPTY_MAP : new HashMap(configuration);
}
private Framework createImpl() {
if (System.getSecurityManager() == null)
return createImpl0();
return (Framework) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return createImpl0();
}
});
}
Framework createImpl0() {
try {
Class implClazz = getImplClass();
Constructor constructor = implClazz.getConstructor(new Class[] {Map.class});
return (Framework) constructor.newInstance(new Object[] {configuration});
} catch (ClassNotFoundException e) {
throw new NoClassDefFoundError(implName);
} catch (IllegalAccessException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
} catch (InstantiationException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private Class getImplClass() throws ClassNotFoundException {
ClassLoader thisCL = this.getClass().getClassLoader();
if (!(useSeparateCL && (thisCL instanceof URLClassLoader)))
return Class.forName(implName);
URL[] cp = getFrameworkURLs((URLClassLoader) thisCL);
EquinoxFWClassLoader fwCL = new EquinoxFWClassLoader(cp, thisCL);
return fwCL.loadClass(implName);
}
private URL[] getFrameworkURLs(URLClassLoader frameworkLoader) {
// use the classpath of the framework class loader
URL[] cp = frameworkLoader.getURLs();
ArrayList result = new ArrayList(cp.length);
for (int i = 0; i < cp.length; i++) {
// need to add only the urls for the framework and any framework fragments
InputStream manifest = null;
try {
if (cp[i].getFile().endsWith("/")) { //$NON-NLS-1$
manifest = new URL(cp[i], org.eclipse.osgi.framework.internal.core.Constants.OSGI_BUNDLE_MANIFEST).openStream();
} else {
manifest = new URL("jar:" + cp[i].toExternalForm() + "!/" + org.eclipse.osgi.framework.internal.core.Constants.OSGI_BUNDLE_MANIFEST).openStream(); //$NON-NLS-1$ //$NON-NLS-2$
}
Map headers = ManifestElement.parseBundleManifest(manifest, new Headers(10));
String bsnSpec = getValue(headers, Constants.BUNDLE_SYMBOLICNAME);
if (bsnSpec == null)
continue;
String internalBSN = org.eclipse.osgi.framework.internal.core.Constants.getInternalSymbolicName();
if (internalBSN.equals(bsnSpec)) {
// this is the framework
addDevClassPaths(cp[i], bsnSpec, result);
result.add(cp[i]);
} else {
if (!isFrameworkFragment(headers, internalBSN))
continue;
// this is for a framework extension
addDevClassPaths(cp[i], bsnSpec, result);
result.add(cp[i]);
}
} catch (IOException e) {
continue; // no manifest;
} catch (BundleException e) {
continue; // bad manifest;
} finally {
if (manifest != null)
try {
manifest.close();
} catch (IOException e) {
// ignore
}
}
}
return (URL[]) result.toArray(new URL[result.size()]);
}
private void addDevClassPaths(URL cp, String bsn, ArrayList result) {
if (!cp.getPath().endsWith("/")) //$NON-NLS-1$
return;
String[] devPaths = DevClassPathHelper.getDevClassPath(bsn);
if (devPaths == null)
return;
for (int i = 0; i < devPaths.length; i++)
try {
char lastChar = devPaths[i].charAt(devPaths[i].length() - 1);
URL url;
if ((devPaths[i].endsWith(".jar") || (lastChar == '/' || lastChar == '\\'))) //$NON-NLS-1$
url = new URL(cp, devPaths[i]);
else
url = new URL(cp, devPaths[i] + "/"); //$NON-NLS-1$
result.add(url);
} catch (MalformedURLException e) {
continue;
}
}
private boolean isFrameworkFragment(Map headers, String internalBSN) {
String hostBSN = getValue(headers, Constants.FRAGMENT_HOST);
return internalBSN.equals(hostBSN) || Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(hostBSN);
}
private String getValue(Map headers, String key) {
String headerSpec = (String) headers.get(key);
if (headerSpec == null)
return null;
ManifestElement[] elements;
try {
elements = ManifestElement.parseHeader(key, headerSpec);
} catch (BundleException e) {
return null;
}
if (elements == null)
return null;
return elements[0].getValue();
}
private synchronized Framework getImpl() {
if (impl == null)
impl = createImpl();
return impl;
}
public void init() throws BundleException {
getImpl().init();
}
public FrameworkEvent waitForStop(long timeout) throws InterruptedException {
return getImpl().waitForStop(timeout);
}
public Enumeration findEntries(String path, String filePattern, boolean recurse) {
return getImpl().findEntries(path, filePattern, recurse);
}
public BundleContext getBundleContext() {
return getImpl().getBundleContext();
}
public long getBundleId() {
return getImpl().getBundleId();
}
public URL getEntry(String path) {
return getImpl().getEntry(path);
}
public Enumeration getEntryPaths(String path) {
return getImpl().getEntryPaths(path);
}
public Dictionary getHeaders() {
return getImpl().getHeaders();
}
public Dictionary getHeaders(String locale) {
return getImpl().getHeaders(locale);
}
public long getLastModified() {
return getImpl().getLastModified();
}
public String getLocation() {
return getImpl().getLocation();
}
public ServiceReference[] getRegisteredServices() {
return getImpl().getRegisteredServices();
}
public URL getResource(String name) {
return getImpl().getResource(name);
}
public Enumeration getResources(String name) throws IOException {
return getImpl().getResources(name);
}
public ServiceReference[] getServicesInUse() {
return getImpl().getServicesInUse();
}
public int getState() {
return getImpl().getState();
}
public String getSymbolicName() {
return getImpl().getSymbolicName();
}
public boolean hasPermission(Object permission) {
return getImpl().hasPermission(permission);
}
public Class loadClass(String name) throws ClassNotFoundException {
return getImpl().loadClass(name);
}
public void start(int options) throws BundleException {
getImpl().start(options);
}
public void start() throws BundleException {
getImpl().start();
}
public void stop(int options) throws BundleException {
getImpl().stop(options);
}
public void stop() throws BundleException {
getImpl().stop();
}
public void uninstall() throws BundleException {
getImpl().uninstall();
}
public void update() throws BundleException {
getImpl().update();
}
public void update(InputStream in) throws BundleException {
getImpl().update(in);
}
public Map getSignerCertificates(int signersType) {
return getImpl().getSignerCertificates(signersType);
}
public Version getVersion() {
return getImpl().getVersion();
}
}