Implement the extension:=framework part of extension bundles minus the automatic framework restart (FELIX-30).
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@506754 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
index 93357a6..e57965f 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
@@ -1,4 +1,4 @@
-/*
+/*
* 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
@@ -67,9 +67,9 @@
public String getProperty(String name)
{
checkValidity();
-
+
Object sm = System.getSecurityManager();
-
+
if (sm != null)
{
if (!(Constants.FRAMEWORK_VERSION.equals(name) ||
@@ -83,14 +83,14 @@
new java.util.PropertyPermission(name, "read"));
}
}
-
+
return m_felix.getProperty(name);
}
public Bundle getBundle()
{
checkValidity();
-
+
return m_bundle;
}
@@ -98,7 +98,7 @@
throws InvalidSyntaxException
{
checkValidity();
-
+
return new FilterImpl(m_felix.getLogger(), expr);
}
@@ -112,11 +112,11 @@
throws BundleException
{
checkValidity();
-
+
Bundle result = null;
-
+
Object sm = System.getSecurityManager();
-
+
if (sm != null)
{
result = m_felix.installBundle(location, is);
@@ -129,57 +129,57 @@
{
result = m_felix.installBundle(location, is);
}
-
+
return result;
}
public Bundle getBundle(long id)
{
checkValidity();
-
+
return m_felix.getBundle(id);
}
public Bundle[] getBundles()
{
checkValidity();
-
+
return m_felix.getBundles();
}
public void addBundleListener(BundleListener l)
{
checkValidity();
-
+
Object sm = System.getSecurityManager();
-
+
if (sm != null)
{
if (l instanceof SynchronousBundleListener)
{
- ((SecurityManager) sm).checkPermission(new AdminPermission(m_bundle,
+ ((SecurityManager) sm).checkPermission(new AdminPermission(m_bundle,
AdminPermission.LISTENER));
}
}
-
+
m_felix.addBundleListener(m_bundle, l);
}
public void removeBundleListener(BundleListener l)
{
checkValidity();
-
+
Object sm = System.getSecurityManager();
-
+
if (sm != null)
{
if (l instanceof SynchronousBundleListener)
{
- ((SecurityManager) sm).checkPermission(new AdminPermission(m_bundle,
+ ((SecurityManager) sm).checkPermission(new AdminPermission(m_bundle,
AdminPermission.LISTENER));
}
}
-
+
m_felix.removeBundleListener(m_bundle, l);
}
@@ -199,28 +199,28 @@
throws InvalidSyntaxException
{
checkValidity();
-
+
m_felix.addServiceListener(m_bundle, l, s);
}
public void removeServiceListener(ServiceListener l)
{
checkValidity();
-
+
m_felix.removeServiceListener(m_bundle, l);
}
public void addFrameworkListener(FrameworkListener l)
{
checkValidity();
-
+
m_felix.addFrameworkListener(m_bundle, l);
}
public void removeFrameworkListener(FrameworkListener l)
{
checkValidity();
-
+
m_felix.removeFrameworkListener(m_bundle, l);
}
@@ -234,9 +234,9 @@
String[] clazzes, Object svcObj, Dictionary dict)
{
checkValidity();
-
+
Object sm = System.getSecurityManager();
-
+
if (sm != null)
{
if (clazzes != null)
@@ -244,18 +244,18 @@
for (int i = 0;i < clazzes.length;i++)
{
((SecurityManager) sm).checkPermission(
- new ServicePermission(clazzes[i], ServicePermission.REGISTER));
+ new ServicePermission(clazzes[i], ServicePermission.REGISTER));
}
}
}
-
+
return m_felix.registerService(m_bundle, clazzes, svcObj, dict);
}
public ServiceReference getServiceReference(String clazz)
{
checkValidity();
-
+
try
{
ServiceReference[] refs = getServiceReferences(clazz, null);
@@ -355,7 +355,7 @@
public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException
{
checkValidity();
-
+
return m_felix.getAllowedServiceReferences(m_bundle, clazz, filter, false);
}
@@ -364,7 +364,7 @@
throws InvalidSyntaxException
{
checkValidity();
-
+
return m_felix.getAllowedServiceReferences(m_bundle, clazz, filter, true);
}
@@ -372,53 +372,53 @@
public Object getService(ServiceReference ref)
{
checkValidity();
-
+
if (ref == null)
{
throw new NullPointerException("Specified service reference cannot be null.");
}
-
+
Object sm = System.getSecurityManager();
-
+
if (sm != null)
{
String[] objectClass = (String[]) ref.getProperty(Constants.OBJECTCLASS);
-
+
if (objectClass == null)
{
return null;
}
-
+
boolean hasPermission = false;
-
+
for (int i = 0;(i < objectClass.length) && !hasPermission;i++)
{
- try
+ try
{
((SecurityManager) sm).checkPermission(
new ServicePermission(objectClass[i], ServicePermission.GET));
-
+
hasPermission = true;
}
catch (Exception ex)
{
-
+
}
}
-
+
if (!hasPermission)
{
throw new SecurityException("No permission");
}
}
-
+
return m_felix.getService(m_bundle, ref);
}
public boolean ungetService(ServiceReference ref)
{
checkValidity();
-
+
if (ref == null)
{
throw new NullPointerException("Specified service reference cannot be null.");
@@ -431,7 +431,7 @@
public File getDataFile(String s)
{
checkValidity();
-
+
return m_felix.getDataFile(m_bundle, s);
}
@@ -446,8 +446,15 @@
case Bundle.STOPPING:
return;
}
+
+ // As an exception we allow extension bundles to use their bundle
+ // context while not being active.
+ if (m_bundle.getInfo().isExtension())
+ {
+ return;
+ }
}
-
+
throw new IllegalStateException("Invalid BundleContext.");
}
}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index a917ddd..eefa16c 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -1,4 +1,4 @@
-/*
+/*
* 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
@@ -408,8 +408,8 @@
return false;
}
- String[] getSubjectDNs()
+ Object getSignerMatcher()
{
- return m_info.getArchive().getDNChains();
+ return null;
}
}
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleInfo.java b/framework/src/main/java/org/apache/felix/framework/BundleInfo.java
index ca7737c..274b69f 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleInfo.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleInfo.java
@@ -1,4 +1,4 @@
-/*
+/*
* 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
@@ -42,6 +42,11 @@
// been refreshed and completely removed from the framework.
private boolean m_stale = false;
+ // Indicates whether the bundle is an extension, meaning that it is
+ // installed as an extension bundle to the framework (i.e., can not be
+ // removed or updated until a framework restart.
+ private boolean m_extension = false;
+
// Used for bundle locking.
private int m_lockCount = 0;
private Thread m_lockThread = null;
@@ -112,7 +117,7 @@
{
return m_modules[m_modules.length - 1];
}
-
+
/**
* Add a module that corresponds to a new bundle JAR file revision for
* the bundle associated with this <tt>BundleInfo</tt> object.
@@ -141,7 +146,7 @@
return -1;
}
}
-
+
public String getLocation()
{
try
@@ -343,7 +348,7 @@
}
return result;
}
-
+
public int getState()
{
return m_state;
@@ -475,6 +480,16 @@
m_stale = true;
}
+ public boolean isExtension()
+ {
+ return m_extension;
+ }
+
+ public void setExtension(boolean extension)
+ {
+ m_extension = extension;
+ }
+
//
// Locking related methods.
// NOTE: These methods are not synchronized because it is assumed they
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index 1d225f0..71e6f25 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -1,4 +1,4 @@
-/*
+/*
* 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
@@ -19,9 +19,9 @@
package org.apache.felix.framework;
import java.io.*;
-import java.net.URL;
-import java.net.URLStreamHandler;
+import java.net.*;
import java.security.*;
+import java.security.cert.Certificate;
import java.util.*;
import org.apache.felix.framework.cache.*;
@@ -104,7 +104,7 @@
private Set m_executionEnvironmentCache = new HashSet();
// The secure action used to do privileged calls
- private SecureAction m_secureAction = new SecureAction();
+ protected SecureAction m_secureAction = new SecureAction();
private Collection m_trustedCaCerts = null;
@@ -213,20 +213,11 @@
public synchronized void start(MutablePropertyResolver configMutable,
List activatorList)
{
- start(configMutable, activatorList, (Collection) null);
- }
-
- public synchronized void start(
- MutablePropertyResolver configMutable,
- List activatorList, Collection trustedCaCerts)
- {
if (m_frameworkStatus != INITIAL_STATUS)
{
throw new IllegalStateException("Invalid framework status: " + m_frameworkStatus);
}
- m_trustedCaCerts = trustedCaCerts;
-
// The framework is now in its startup sequence.
m_frameworkStatus = STARTING_STATUS;
@@ -265,7 +256,7 @@
try
{
- m_cache = new BundleCache(m_config, m_logger, m_trustedCaCerts);
+ m_cache = new BundleCache(m_config, m_logger);
}
catch (Exception ex)
{
@@ -362,10 +353,8 @@
BundleInfo info = new BundleInfo(
m_logger, new SystemBundleArchive(), null);
systembundle = new SystemBundle(this, info, activatorList);
- // Create a module for the system bundle.
- IModuleDefinition md = new ModuleDefinition(
- systembundle.getExports(), null, null, null);
- systembundle.getInfo().addModule(m_factory.createModule("0", md));
+ systembundle.getInfo().addModule(m_factory.createModule("0",
+ systembundle));
systembundle.getContentLoader().setSearchPolicy(
new R4SearchPolicy(
m_policyCore, systembundle.getInfo().getCurrentModule()));
@@ -559,7 +548,7 @@
fireFrameworkEvent(FrameworkEvent.ERROR, getBundle(0), ex);
m_logger.log(Logger.LOG_ERROR, "Error stopping framework.", ex);
}
-
+
// Finally shutdown the JVM if the framework is running stand-alone.
String embedded = m_config.get(FelixConstants.EMBEDDED_EXECUTION_PROP);
boolean isEmbedded = (embedded == null) ? false : embedded.equals("true");
@@ -568,7 +557,7 @@
m_secureAction.exit(0);
}
}
-
+
/**
* This method actually performs the real shutdown operations of the
* framework in terms of setting the start level to zero, really stopping
@@ -1248,6 +1237,13 @@
private void _startBundle(BundleImpl bundle, boolean record)
throws BundleException
{
+ // The spec doesn't say whether it is possible to start an extension
+ // We just do nothing
+ if (bundle.getInfo().isExtension())
+ {
+ return;
+ }
+
// Set and save the bundle's persistent state to active
// if we are supposed to record state change.
if (record)
@@ -1369,7 +1365,7 @@
PackagePermission perm = new PackagePermission(
imports[i].???,
PackagePermission.IMPORT);
-
+
if (!pd.implies(perm))
{
throw new java.security.AccessControlException(
@@ -1388,7 +1384,7 @@
{
PackagePermission perm = new PackagePermission(
(String) exports[i].getProperties().get(ICapability.PACKAGE_PROPERTY), PackagePermission.EXPORT);
-
+
if (!pd.implies(perm))
{
throw new java.security.AccessControlException(
@@ -1400,7 +1396,7 @@
}
verifyExecutionEnvironment(bundle);
-
+
IModule module = bundle.getInfo().getCurrentModule();
try
{
@@ -1448,7 +1444,7 @@
try
{
// Variable to indicate whether bundle is active or not.
- Exception rethrow = null;
+ Throwable rethrow = null;
// Cannot update an uninstalled bundle.
BundleInfo info = bundle.getInfo();
@@ -1482,11 +1478,6 @@
// get the revision of the new update.
try
{
- IModule module = createModule(
- info.getBundleId(),
- archive.getRevisionCount() - 1,
- info.getCurrentHeader());
-
Object sm = System.getSecurityManager();
if (sm != null)
@@ -1495,10 +1486,37 @@
new AdminPermission(bundle, AdminPermission.LIFECYCLE));
}
+ // We need to check whether this is an update to an
+ // extension bundle (info.isExtension) or an update from
+ // a normal bundle to an extension bundle
+ // (isExtensionBundle())
+ IModule module = createModule(
+ info.getBundleId(),
+ archive.getRevisionCount() - 1,
+ info.getCurrentHeader(),
+ createBundleProtectionDomain(archive),
+ bundle.getInfo().isExtension() || isExtensionBundle(
+ bundle.getInfo().getCurrentHeader()));
+
// Add module to bundle info.
info.addModule(module);
+
+ // If this is an update from a normal to an extension bundle
+ // then attach the extension or else if this already is
+ // an extension bundle then done allow it to be resolved
+ // again as per spec.
+ if (!bundle.getInfo().isExtension() &&
+ isExtensionBundle(bundle.getInfo().getCurrentHeader()))
+ {
+ attachExtensionBundle(bundle);
+ bundle.getInfo().setState(BundleImpl.RESOLVED);
+ }
+ else if (bundle.getInfo().isExtension())
+ {
+ bundle.getInfo().setState(BundleImpl.INSTALLED);
+ }
}
- catch (Exception ex)
+ catch (Throwable ex)
{
try
{
@@ -1512,7 +1530,7 @@
throw ex;
}
}
- catch (Exception ex)
+ catch (Throwable ex)
{
m_logger.log(Logger.LOG_ERROR, "Unable to update the bundle.", ex);
rethrow = ex;
@@ -1523,7 +1541,12 @@
if (rethrow == null)
{
info.setLastModified(System.currentTimeMillis());
- info.setState(Bundle.INSTALLED);
+
+ if (!info.isExtension())
+ {
+ info.setState(Bundle.INSTALLED);
+ }
+
fireBundleEvent(BundleEvent.UNRESOLVED, bundle);
// Mark previous the bundle's old module for removal since
@@ -1740,6 +1763,14 @@
throw new IllegalStateException("The bundle is uninstalled.");
}
+ // Extension Bundles are not removed until the framework is shutdown
+ if (bundle.getInfo().isExtension())
+ {
+ bundle.getInfo().setPersistentStateUninstalled();
+ bundle.getInfo().setState(Bundle.INSTALLED);
+ return;
+ }
+
// The spec says that uninstall should always succeed, so
// catch an exception here if stop() doesn't succeed and
// rethrow it at the end.
@@ -1771,7 +1802,7 @@
((ModuleImpl) target.getInfo().getCurrentModule()).setRemovalPending(true);
// Put bundle in uninstalled bundle array.
- rememberUninstalledBundle(bundle);
+ rememberUninstalledBundle(bundle);
}
else
{
@@ -1926,17 +1957,28 @@
try
{
BundleArchive archive = m_cache.getArchive(id);
- bundle = new BundleImpl(this, createBundleInfo(archive));
+ bundle = new BundleImpl(this, createBundleInfo(archive,
+ isExtensionBundle(archive.getRevision(
+ archive.getRevisionCount() - 1).getManifestHeader())));
+
verifyExecutionEnvironment(bundle);
- Object sm = System.getSecurityManager();
- if (sm != null)
+ if (!bundle.getInfo().isExtension())
{
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(bundle, AdminPermission.LIFECYCLE));
+ Object sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ ((SecurityManager) sm).checkPermission(
+ new AdminPermission(bundle, AdminPermission.LIFECYCLE));
+ }
}
+ else
+ {
+ attachExtensionBundle(bundle);
+ }
+
}
- catch (Exception ex)
+ catch (Throwable ex)
{
// If the bundle is new, then remove it from the cache.
// TODO: Perhaps it should be removed if it is not new too.
@@ -1954,12 +1996,19 @@
}
}
+ if (bundle != null)
+ {
+ ((ModuleImpl) bundle.getInfo().getCurrentModule()).setRemovalPending(true);
+ }
+
if ((System.getSecurityManager() != null) &&
(ex instanceof SecurityException))
{
throw (SecurityException) ex;
}
+ ex.printStackTrace();
+
throw new BundleException("Could not create bundle object.", ex);
}
@@ -2003,6 +2052,68 @@
return bundle;
}
+ private boolean isExtensionBundle(Map headers)
+ {
+ R4Directive dir = ManifestParser.parseExtensionBundleHeader((String)
+ headers.get(Constants.FRAGMENT_HOST));
+
+ return (dir != null) && (Constants.EXTENSION_FRAMEWORK.equals(
+ dir.getValue()) || Constants.EXTENSION_BOOTCLASSPATH.equals(
+ dir.getValue()));
+ }
+
+ private void attachExtensionBundle(BundleImpl bundle) throws Exception
+ {
+ Object sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ ((SecurityManager) sm).checkPermission(
+ new AdminPermission(bundle, AdminPermission.EXTENSIONLIFECYCLE));
+ }
+
+ ProtectionDomain pd = (ProtectionDomain)
+ bundle.getInfo().getCurrentModule().getSecurityContext();
+
+ if (pd != null)
+ {
+ if (!pd.implies(new AllPermission()))
+ {
+ throw new SecurityException("Extension Bundles must have AllPermission");
+ }
+ }
+
+ R4Directive dir = ManifestParser.parseExtensionBundleHeader((String)
+ bundle.getInfo().getCurrentHeader().get(Constants.FRAGMENT_HOST));
+
+ if (!Constants.EXTENSION_FRAMEWORK.equals(dir.getValue()))
+ {
+ throw new BundleException("Unsupported Extension Bundle type: " +
+ dir.getValue(), new UnsupportedOperationException(
+ "Unsupported Extension Bundle type!"));
+ }
+
+ BundleImpl systemBundle = (BundleImpl) getBundle(0);
+ acquireBundleLock(systemBundle);
+
+ try
+ {
+ bundle.getInfo().setExtension(true);
+
+ ((SystemBundle) getBundle(0)).addExtensionBundle(bundle);
+ }
+ catch (Exception ex)
+ {
+ bundle.getInfo().setExtension(false);
+ throw ex;
+ }
+ finally
+ {
+ releaseBundleLock(systemBundle);
+ }
+
+ bundle.getInfo().setState(Bundle.RESOLVED);
+ }
+
/**
* Checks the passed in bundle and checks to see if there is a required execution environment.
* If there is, it gets the execution environment string and verifies that the framework provides it.
@@ -2037,7 +2148,7 @@
* False if none of the provided framework execution environments match
**/
private boolean isMatchingExecutionEnvironment(String bundleEnvironment)
- {
+ {
String frameworkEnvironment = getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
if (frameworkEnvironment == null)
{
@@ -2491,9 +2602,11 @@
// The spec says to throw an error if the bundle
// is stopped, which I assume means not active,
// starting, or stopping.
+ // Additionally, we make an exception for extension bundles
if ((bundle.getInfo().getState() != Bundle.ACTIVE) &&
(bundle.getInfo().getState() != Bundle.STARTING) &&
- (bundle.getInfo().getState() != Bundle.STOPPING))
+ (bundle.getInfo().getState() != Bundle.STOPPING) &&
+ !bundle.getInfo().isExtension())
{
throw new IllegalStateException("Only active bundles can create files.");
}
@@ -2692,7 +2805,7 @@
null,
null,
new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, ((Capability) caps[capIdx]).getPackageName(), false) }));
-
+
// Search through the current providers to find the target
// module.
for (int i = 0; (inUseModules != null) && (i < inUseModules.length); i++)
@@ -2795,6 +2908,39 @@
// Acquire locks for all impacted bundles.
BundleImpl[] bundles = acquireBundleRefreshLocks(targets);
+ boolean restart = false;
+
+ Bundle systemBundle = getBundle(0);
+
+ // We need to restart the framework if either an extension bundle is
+ // refreshed or the system bundle is refreshed and any extension bundle
+ // has been updated or uninstalled.
+ for (int i = 0; (bundles != null) && !restart && (i < bundles.length); i++)
+ {
+ if (bundles[i].getInfo().isExtension())
+ {
+ restart = true;
+ }
+ else if (systemBundle == bundles[i])
+ {
+ Bundle[] allBundles = getBundles();
+ for (int j = 0; !restart && j < allBundles.length; j++)
+ {
+ if (((BundleImpl) allBundles[j]).getInfo().isExtension() &&
+ (allBundles[j].getState() == BundleImpl.INSTALLED))
+ {
+ restart = true;
+ }
+ }
+ }
+ }
+
+ if (restart)
+ {
+// TODO: Extension Bundle - We need a way to restart the framework
+ m_logger.log(Logger.LOG_WARNING, "Framework restart not implemented.");
+ }
+
// Remove any targeted bundles from the uninstalled bundles
// array, since they will be removed from the system after
// the refresh.
@@ -2816,21 +2962,30 @@
RefreshHelper[] helpers = new RefreshHelper[bundles.length];
for (int i = 0; i < bundles.length; i++)
{
- helpers[i] = new RefreshHelper(bundles[i]);
+ if (!bundles[i].getInfo().isExtension())
+ {
+ helpers[i] = new RefreshHelper(bundles[i]);
+ }
}
// Stop, purge or remove, and reinitialize all bundles first.
for (int i = 0; i < helpers.length; i++)
{
- helpers[i].stop();
- helpers[i].purgeOrRemove();
- helpers[i].reinitialize();
+ if (helpers[i] != null)
+ {
+ helpers[i].stop();
+ helpers[i].purgeOrRemove();
+ helpers[i].reinitialize();
+ }
}
// Then restart all bundles that were previously running.
for (int i = 0; i < helpers.length; i++)
{
- helpers[i].restart();
+ if (helpers[i] != null)
+ {
+ helpers[i].restart();
+ }
}
}
}
@@ -2874,7 +3029,7 @@
// Miscellaneous private methods.
//
- private BundleInfo createBundleInfo(BundleArchive archive)
+ private BundleInfo createBundleInfo(BundleArchive archive, boolean isExtension)
throws Exception
{
// Get the bundle manifest.
@@ -2900,10 +3055,30 @@
// ever be one revision at this point, create the module for
// the current revision to be safe.
IModule module = createModule(
- archive.getId(), archive.getRevisionCount() - 1, headerMap);
+ archive.getId(), archive.getRevisionCount() - 1, headerMap,
+ createBundleProtectionDomain(archive), isExtension);
// Finally, create an return the bundle info.
- return new BundleInfo(m_logger, archive, module);
+ BundleInfo info = new BundleInfo(m_logger, archive, module);
+ info.setExtension(isExtension);
+
+ return info;
+ }
+
+ private ProtectionDomain createBundleProtectionDomain(BundleArchive archive)
+ throws Exception
+ {
+// TODO: Security - create a real ProtectionDomain for the Bundle
+ FakeURLStreamHandler handler = new FakeURLStreamHandler();
+ URL context = new URL(null, "location:", handler);
+ CodeSource codesource = new CodeSource(m_secureAction.createURL(context,
+ archive.getLocation(), handler), (Certificate[]) null);
+
+ Permissions allPerms = new Permissions();
+ allPerms.add(new AllPermission());
+ ProtectionDomain pd = new ProtectionDomain(codesource,
+ allPerms);
+ return pd;
}
/**
@@ -2915,7 +3090,8 @@
* @param headerMap The headers map associated with the bundle.
* @return The initialized and/or newly created module.
**/
- private IModule createModule(long targetId, int revision, Map headerMap)
+ private IModule createModule(long targetId, int revision, Map headerMap,
+ Object securityContext, boolean isExtensionBundle)
throws Exception
{
ManifestParser mp = new ManifestParser(m_logger, m_config, headerMap);
@@ -2950,8 +3126,10 @@
// pieces and bind them together.
// Create the module definition for the new module.
+ // Note, in case this is an extension bundle it's exports are removed -
+ // they will be added to the system bundle directly later on.
IModuleDefinition md = new ModuleDefinition(
- mp.getCapabilities(),
+ (isExtensionBundle) ? null : mp.getCapabilities(),
mp.getRequirements(),
mp.getDynamicRequirements(),
mp.getLibraries(m_cache.getArchive(targetId).getRevision(revision)));
@@ -2960,17 +3138,7 @@
IModule module = m_factory.createModule(
Long.toString(targetId) + "." + Integer.toString(revision), md);
- FakeURLStreamHandler handler = new FakeURLStreamHandler();
- URL context = new URL(null, "location:", handler);
- CodeSource codesource = new CodeSource(m_secureAction.createURL(context,
- m_cache.getArchive(targetId).getLocation(),
- handler),
- m_cache.getArchive(targetId).getCertificates());
-
- Permissions allPerms = new Permissions();
- allPerms.add(new AllPermission());
- m_factory.setSecurityContext(module, new ProtectionDomain(codesource,
- allPerms));
+ m_factory.setSecurityContext(module, securityContext);
// Create the content loader from the module archive.
IContentLoader contentLoader = new ContentLoaderImpl(
@@ -3495,7 +3663,8 @@
try
{
BundleInfo info = m_bundle.getInfo();
- BundleInfo newInfo = createBundleInfo(info.getArchive());
+ BundleInfo newInfo = createBundleInfo(info.getArchive(),
+ info.isExtension());
newInfo.syncLock(info);
m_bundle.setInfo(newInfo);
fireBundleEvent(BundleEvent.UNRESOLVED, m_bundle);
diff --git a/framework/src/main/java/org/apache/felix/framework/SignerMatcher.java b/framework/src/main/java/org/apache/felix/framework/SignerMatcher.java
deleted file mode 100644
index 4a06ffc..0000000
--- a/framework/src/main/java/org/apache/felix/framework/SignerMatcher.java
+++ /dev/null
@@ -1,441 +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.felix.framework;
-
-import java.util.*;
-
-import org.osgi.framework.Bundle;
-
-public final class SignerMatcher
-{
- private BundleImpl m_bundleImpl = null;
- private String m_filter = null;
-
- public SignerMatcher(String filter)
- {
- m_filter = filter;
- }
-
- public SignerMatcher(Bundle bundle)
- {
- m_bundleImpl = (BundleImpl) bundle;
- }
-
- public boolean equals(Object o)
- {
- if (!(o instanceof SignerMatcher))
- {
- return false;
- }
-
- String pattern = ((SignerMatcher) o).m_filter;
-
- if (pattern == null)
- {
- return true;
- }
-
- if (m_bundleImpl == null)
- {
- return pattern.trim().equals("\\*");
- }
-
- String[] dns = m_bundleImpl.getSubjectDNs();
-
- if (dns == null)
- {
- return pattern.trim().equals("\\*");
- }
-
- for (int i = 0;i < dns.length;i++)
- {
- if (match(pattern, dns[i]))
- {
- return true;
- }
- }
-
- return false;
- }
-
- private static boolean match(String pattern, String dn)
- {
- try
- {
- return ((pattern != null) && (dn != null)) ?
- matchDN(pattern.toCharArray(), 0, dn.toCharArray(), 0) : false;
- }
- catch (Exception ex)
- {
- // TODO: log this or something
- ex.printStackTrace();
- }
-
- return false;
- }
-
- private static boolean matchDN(char[] pattern, int pPos, char[] dn, int dPos)
- {
- pPos = skip(pattern, pPos, ' ');
-
- if (pPos >= pattern.length)
- {
- return true;
- }
-
- int befor = pPos;
-
- if ((pPos < pattern.length -1) && (pattern[pPos] == '\\') && (pattern[pPos + 1] == '*'))
- {
- pPos = pPos + 1;
- }
-
- switch (pattern[pPos++])
- {
- case '*':
- pPos = skip(pattern, pPos, ' ');
- if ((pPos < pattern.length) && (pattern[pPos] == ';'))
- {
- if (matchDN(pattern, ++pPos, dn, dPos))
- {
- return true;
- }
- return matchDN(pattern, pPos, dn, skipEscapedUntil(dn, dPos, ';') + 1);
- }
- if (pPos >= pattern.length)
- {
- return true;
- }
- return matchRDN(pattern, befor, dn, dPos);
- case '-':
- pPos = skip(pattern, pPos, ' ');
- if ((pPos < pattern.length) && (pattern[pPos] == ';'))
- {
- int next = dPos;
- pPos++;
- do
- {
- if (matchDN(pattern, pPos, dn, next))
- {
- return true;
- }
- next = skipEscapedUntil(dn, next, ';') + 1;
- } while (next < dn.length);
-
- return false;
- }
- if (pPos >= pattern.length)
- {
- return true;
- }
- throw new IllegalArgumentException("[" + pPos + "]" + new String(pattern));
- default:
- break;
- }
-
- return matchRDN(pattern, befor, dn, dPos);
- }
-
- private static boolean matchRDN(char[] pattern, int pPos, char[] dn, int dPos)
- {
- pPos = skip(pattern, pPos, ' ');
-
- if (pPos >= pattern.length)
- {
- return true;
- }
-
- if ((pPos < pattern.length -1) && (pattern[pPos] == '\\') && (pattern[pPos + 1] == '*'))
- {
- pPos = pPos + 1;
- }
-
- switch (pattern[pPos++])
- {
- case '*':
- pPos = skip(pattern, pPos, ' ');
- if ((pPos < pattern.length) && (pattern[pPos] == ','))
- {
- pPos++;
- do
- {
- if (matchKV(pattern, pPos, dn, dPos))
- {
- return true;
- }
-
- int comma = skipEscapedUntil(dn, dPos, ',');
- int colon = skipEscapedUntil(dn, dPos, ';');
-
- dPos = (comma > colon) ? colon : comma;
- } while ((dPos < dn.length) && (dn[dPos++] == ','));
- return false;
- }
- throw new IllegalArgumentException("[" + pPos + "]" + new String(pattern));
- default:
- break;
- }
-
- return matchKV(pattern, pPos - 1, dn, dPos);
- }
-
- private static boolean matchKV(char[] pattern, int pPos, char[] dn, int dPos)
- {
- pPos = skip(pattern, pPos, ' ');
-
- if (pPos >= pattern.length)
- {
- return false;
- }
-
- int equals = skipEscapedUntil(pattern, pPos, '=');
- int comma = skipEscapedUntil(pattern, pPos, ',');
- int colon = skipEscapedUntil(pattern, pPos, ';');
- if (((colon < pattern.length) && (colon < equals)) ||
- ((comma < pattern.length) && (comma < equals)) ||
- (equals >= pattern.length))
- {
- return false;
- }
-
- String key = (String) KEY2OIDSTRING.get(
- new String(pattern, pPos, equals - pPos).toLowerCase(Locale.US).trim());
-
- if (key == null)
- {
- throw new IllegalArgumentException("Bad key [" +
- new String(pattern, pPos, equals - pPos) + "] in [" +
- new String(pattern) + "]");
- }
-
- pPos = equals + 1;
- int keylength = key.length();
- for (int i = 0;i < keylength;i++)
- {
- if ((dPos >= dn.length) || (key.charAt(i) != dn[dPos++]))
- {
- return false;
- }
- }
-
- if ((dPos >= dn.length) || (dn[dPos++] != '='))
- {
- return false;
- }
-
- pPos = skip(pattern, pPos, ' ');
- if ((pPos < pattern.length -1) && (pattern[pPos] == '\\') && (pattern[pPos + 1] == '*'))
- {
- pPos = skip(pattern, pPos + 2, ' ');
- if (pPos >= pattern.length)
- {
- return true;
- }
- comma = skipEscapedUntil(dn, dPos, ',');
- colon = skipEscapedUntil(dn, dPos, ';');
- if ((pattern[pPos] == ',') && (colon > comma))
- {
- return matchKV(pattern, ++pPos, dn, comma + 1);
- }
-
- if (pattern[pPos] == ';' )
- {
- return matchDN(pattern, ++pPos, dn, colon + 1);
- }
-
- return false;
- }
- boolean escaped = false;
- while ((pPos < pattern.length) && (dPos < dn.length))
- {
- switch (Character.toLowerCase(pattern[pPos++]))
- {
- case ' ':
- if ((pattern[pPos - 2] != ' ') && ((dn[dPos++] != ' ') &&
- (dn[--dPos] != ';') && (dn[dPos] != ',')))
- {
- return false;
- }
- break;
- case '\\':
- escaped = !escaped;
- break;
-
- case '(':
- case ')':
- if (escaped)
- {
- if (dn[dPos++] != pattern[pPos - 1])
- {
- return false;
- }
- escaped = false;
- break;
- }
- return false;
- case ';':
- if (!escaped)
- {
- if ((dPos < dn.length) && ((dn[dPos] == ',') || (dn[dPos] == ';')))
- {
- return matchDN(pattern, pPos, dn, skipEscapedUntil(dn, dPos, ';') + 1);
- }
- return false;
- }
- case ',':
- if (!escaped)
- {
- if ((dPos < dn.length) && (dn[dPos] == ','))
- {
- return matchKV(pattern, pPos, dn, dPos + 1);
- }
- return false;
- }
- default:
- if (escaped)
- {
- if (dn[dPos++] != '\\')
- {
- return false;
- }
- escaped = false;
- }
- if (dn[dPos++] != Character.toLowerCase(pattern[pPos - 1]))
- {
- return false;
- }
- break;
- }
- }
-
- pPos = skip(pattern, pPos, ' ');
- if (pPos >= pattern.length)
- {
- if ((dPos >= dn.length) || (dn[dPos] == ',') || (dn[dPos] == ';'))
- {
- return true;
- }
- }
- else
- {
- switch (pattern[pPos++])
- {
- case ',':
- return matchKV(pattern, pPos, dn, dPos);
- case ';':
- return matchDN(pattern, pPos, dn, dPos);
- default:
- break;
- }
- }
-
- return false;
- }
-
- private static final Map KEY2OIDSTRING = new HashMap();
-
- static {
- KEY2OIDSTRING.put("2.5.4.3", "cn");
- KEY2OIDSTRING.put("cn", "cn");
- KEY2OIDSTRING.put("commonname", "cn");
- KEY2OIDSTRING.put("2.5.4.4", "sn");
- KEY2OIDSTRING.put("sn", "sn");
- KEY2OIDSTRING.put("surname", "sn");
- KEY2OIDSTRING.put("2.5.4.6", "c");
- KEY2OIDSTRING.put("c", "c");
- KEY2OIDSTRING.put("countryname", "c");
- KEY2OIDSTRING.put("2.5.4.7", "l");
- KEY2OIDSTRING.put("l", "l");
- KEY2OIDSTRING.put("localityname", "l");
- KEY2OIDSTRING.put("2.5.4.8", "st");
- KEY2OIDSTRING.put("st", "st");
- KEY2OIDSTRING.put("stateorprovincename", "st");
- KEY2OIDSTRING.put("2.5.4.10", "o");
- KEY2OIDSTRING.put("o", "o");
- KEY2OIDSTRING.put("organizationname", "o");
- KEY2OIDSTRING.put("2.5.4.11", "ou");
- KEY2OIDSTRING.put("ou", "ou");
- KEY2OIDSTRING.put("organizationalunitname", "ou");
- KEY2OIDSTRING.put("2.5.4.12", "title");
- KEY2OIDSTRING.put("t", "title");
- KEY2OIDSTRING.put("title", "title");
- KEY2OIDSTRING.put("2.5.4.42", "givenname");
- KEY2OIDSTRING.put("givenname", "givenname");
- KEY2OIDSTRING.put("2.5.4.43", "initials");
- KEY2OIDSTRING.put("initials", "initials");
- KEY2OIDSTRING.put("2.5.4.44", "generationqualifier");
- KEY2OIDSTRING.put("generationqualifier", "generationqualifier");
- KEY2OIDSTRING.put("2.5.4.46", "dnqualifier");
- KEY2OIDSTRING.put("dnqualifier", "dnqualifier");
- KEY2OIDSTRING.put("2.5.4.9", "street");
- KEY2OIDSTRING.put("street", "street");
- KEY2OIDSTRING.put("streetaddress", "street");
- KEY2OIDSTRING.put("0.9.2342.19200300.100.1.25", "dc");
- KEY2OIDSTRING.put("dc", "dc");
- KEY2OIDSTRING.put("domaincomponent", "dc");
- KEY2OIDSTRING.put("0.9.2342.19200300.100.1.1", "uid");
- KEY2OIDSTRING.put("uid", "uid");
- KEY2OIDSTRING.put("userid", "uid");
- KEY2OIDSTRING.put("1.2.840.113549.1.9.1", "emailaddress");
- KEY2OIDSTRING.put("emailaddress", "emailaddress");
- KEY2OIDSTRING.put("2.5.4.5", "serialnumber");
- KEY2OIDSTRING.put("serialnumber", "serialnumber");
- }
-
- private static int skipEscapedUntil(char[] string, int pos, char value)
- {
- boolean escaped = false;
-
- while (pos < string.length)
- {
- switch (string[pos++])
- {
- case '\\':
- escaped = true;
- break;
- default:
- if (!escaped)
- {
- if (string[pos - 1] == value)
- {
- return pos - 1;
- }
- }
- escaped = false;
- break;
- }
- }
-
- return pos;
- }
-
- private static int skip(char[] string, int pos, char value)
- {
- while (pos < string.length)
- {
- if (string[pos] != value)
- {
- break;
- }
- pos++;
- }
-
- return pos;
- }
-}
diff --git a/framework/src/main/java/org/apache/felix/framework/SystemBundle.java b/framework/src/main/java/org/apache/felix/framework/SystemBundle.java
index a8fc45e..5719640 100644
--- a/framework/src/main/java/org/apache/felix/framework/SystemBundle.java
+++ b/framework/src/main/java/org/apache/felix/framework/SystemBundle.java
@@ -1,4 +1,4 @@
-/*
+/*
* 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
@@ -18,25 +18,32 @@
*/
package org.apache.felix.framework;
+import java.io.IOException;
import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.cert.Certificate;
import java.util.*;
-import org.apache.felix.framework.cache.SystemBundleArchive;
-import org.apache.felix.framework.util.FelixConstants;
-import org.apache.felix.framework.util.StringMap;
-import org.apache.felix.framework.util.manifestparser.Capability;
-import org.apache.felix.framework.util.manifestparser.ManifestParser;
-import org.apache.felix.moduleloader.ICapability;
-import org.apache.felix.moduleloader.IContentLoader;
+import org.apache.felix.framework.cache.*;
+import org.apache.felix.framework.util.*;
+import org.apache.felix.framework.util.manifestparser.*;
+import org.apache.felix.moduleloader.*;
import org.osgi.framework.*;
-class SystemBundle extends BundleImpl
+class SystemBundle extends BundleImpl implements IModuleDefinition, PrivilegedAction
{
+ private static final Set m_extensionLocations = new HashSet();
+
private List m_activatorList = null;
- private BundleActivator m_activator = null;
+ private SystemBundleActivator m_activator = null;
private Thread m_shutdownThread = null;
private ICapability[] m_exports = null;
private IContentLoader m_contentLoader = null;
+ private Set m_exportNames = null;
protected SystemBundle(Felix felix, BundleInfo info, List activatorList)
{
@@ -54,7 +61,7 @@
// Add the bundle activator for the start level service.
activatorList.add(new StartLevelActivator(felix));
- // Add the bundle activator for the URL Handlers service.
+ // Add the bundle activator for the url handler service.
activatorList.add(new URLHandlersActivator(felix));
m_activatorList = activatorList;
@@ -67,7 +74,7 @@
// packages should be exported by the system bundle.
try
{
- m_exports = (ICapability[]) ManifestParser.parseExportHeader(
+ m_exports = ManifestParser.parseExportHeader(
getFelix().getConfig().get(Constants.FRAMEWORK_SYSTEMPACKAGES));
}
catch (Exception ex)
@@ -79,9 +86,29 @@
+ getFelix().getConfig().get(Constants.FRAMEWORK_SYSTEMPACKAGES), ex);
}
- m_contentLoader = new SystemBundleContentLoader(getFelix().getLogger());
+ m_contentLoader = new SystemBundleContentLoader();
+ // Initialize header map as a case insensitive map.
+ Map map = new StringMap(false);
+ map.put(FelixConstants.BUNDLE_VERSION,
+ getFelix().getConfig().get(FelixConstants.FELIX_VERSION_PROPERTY));
+ map.put(FelixConstants.BUNDLE_SYMBOLICNAME,
+ FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
+ map.put(FelixConstants.BUNDLE_NAME, "System Bundle");
+ map.put(FelixConstants.BUNDLE_DESCRIPTION,
+ "This bundle is system specific; it implements various system services.");
+ map.put(FelixConstants.EXPORT_SERVICE, "org.osgi.service.packageadmin.PackageAdmin,org.osgi.service.startlevel.StartLevel");
+
+ parseAndAddExports(map);
+
+ ((SystemBundleArchive) getInfo().getArchive()).setManifestHeader(map);
+ }
+
+ private void parseAndAddExports(Map headers)
+ {
StringBuffer exportSB = new StringBuffer("");
+ Set exportNames = new HashSet();
+
for (int i = 0; i < m_exports.length; i++)
{
if (i > 0)
@@ -93,24 +120,13 @@
exportSB.append("; version=\"");
exportSB.append(((Capability) m_exports[i]).getPackageVersion().toString());
exportSB.append("\"");
+
+ exportNames.add(((Capability) m_exports[i]).getPackageName());
}
- // Initialize header map as a case insensitive map.
- Map map = new StringMap(false);
- map.put(FelixConstants.BUNDLE_VERSION,
- getFelix().getConfig().get(FelixConstants.FELIX_VERSION_PROPERTY));
- map.put(FelixConstants.BUNDLE_SYMBOLICNAME,
- FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
- map.put(FelixConstants.BUNDLE_NAME, "System Bundle");
- map.put(FelixConstants.BUNDLE_DESCRIPTION,
- "This bundle is system specific; it implements various system services.");
- map.put(FelixConstants.EXPORT_PACKAGE, exportSB.toString());
- map.put(FelixConstants.EXPORT_SERVICE, "org.osgi.service.packageadmin.PackageAdmin,org.osgi.service.startlevel.StartLevel");
- ((SystemBundleArchive) getInfo().getArchive()).setManifestHeader(map);
+ m_exportNames = exportNames;
- // TODO: FRAMEWORK - We need some systematic way for framework services
- // to add packages and services to the system bundle's headers, something
- // that will allow for them to be independently configured.
+ headers.put(FelixConstants.EXPORT_PACKAGE, exportSB.toString());
}
public ICapability[] getExports()
@@ -123,7 +139,7 @@
return m_contentLoader;
}
- public synchronized void start() throws BundleException
+ public void start() throws BundleException
{
// The system bundle is only started once and it
// is started by the framework.
@@ -156,7 +172,7 @@
* multiple calls to this method, the shutdown thread is only started if
* the framework is still in running state.
*/
- public synchronized void stop()
+ public void stop()
{
Object sm = System.getSecurityManager();
@@ -191,17 +207,17 @@
}
}
- public synchronized void uninstall() throws BundleException
+ public void uninstall() throws BundleException
{
throw new BundleException("Cannot uninstall the system bundle.");
}
- public synchronized void update() throws BundleException
+ public void update() throws BundleException
{
update(null);
}
- public synchronized void update(InputStream is) throws BundleException
+ public void update(InputStream is) throws BundleException
{
Object sm = System.getSecurityManager();
@@ -223,13 +239,13 @@
}
return m_activator;
}
-
+
/**
* Actually shuts down the system bundle. This method does what actually
* the {@link #stop()} method would do for regular bundles. Since the system
* bundle has to shutdown the framework, a separate method is used to stop
* the system bundle during framework shutdown.
- *
+ *
* @throws BundleException If an error occurrs stopping the system bundle
* and any activators "started" on framework start time.
*/
@@ -238,11 +254,266 @@
// Callback from shutdown thread, so do our own stop.
try
{
- getActivator().stop(getInfo().getContext());
+ getFelix().m_secureAction.stopActivator(getActivator(),
+ getInfo().getContext());
}
catch (Throwable throwable)
{
throw new BundleException( "Unable to stop system bundle.", throwable );
}
}
+
+ boolean exports(String packageName)
+ {
+ return m_exportNames.contains(packageName);
+ }
+
+ public ICapability[] getCapabilities()
+ {
+ return m_exports;
+ }
+
+ public IRequirement[] getDynamicRequirements()
+ {
+ return null;
+ }
+
+ public R4Library[] getLibraries()
+ {
+ return null;
+ }
+
+ public IRequirement[] getRequirements()
+ {
+ return null;
+ }
+
+ private final ThreadLocal m_tempBundle = new ThreadLocal();
+
+ void addExtensionBundle(BundleImpl bundle)
+ {
+ if (System.getSecurityManager() != null)
+ {
+ m_tempBundle.set(bundle);
+
+ try
+ {
+ AccessController.doPrivileged(this);
+ }
+ finally
+ {
+ m_tempBundle.set(null);
+ }
+ }
+ else
+ {
+ _addExtensionBundle(bundle);
+ }
+ }
+
+ public Object run()
+ {
+ _addExtensionBundle((BundleImpl) m_tempBundle.get());
+ return null;
+ }
+
+ private void _addExtensionBundle(BundleImpl bundle)
+ {
+ BundleArchive archive = bundle.getInfo().getArchive();
+
+ SystemBundleArchive systemArchive =
+ (SystemBundleArchive) getInfo().getArchive();
+
+ Map headers;
+ ICapability[] exports;
+ try
+ {
+ headers = new StringMap(systemArchive.getManifestHeader(
+ systemArchive.getRevisionCount() - 1), false);
+
+ exports = ManifestParser.parseExportHeader((String)
+ bundle.getInfo().getCurrentHeader().get(Constants.EXPORT_PACKAGE));
+ }
+ catch (Exception ex)
+ {
+ getFelix().getLogger().log(
+ Logger.LOG_ERROR,
+ "Error parsing extension bundle export statement: "
+ + bundle.getInfo().getCurrentHeader().get(Constants.EXPORT_PACKAGE), ex);
+
+ return;
+ }
+
+ try
+ {
+ String url = archive.getRevision(
+ archive.getRevisionCount() -1).getCachedBundleURL();
+ if (url != null)
+ {
+ synchronized (getClass().getClassLoader())
+ {
+ if (!m_extensionLocations.contains(bundle.getSymbolicName()))
+ {
+ Method addURL =
+ URLClassLoader.class.getDeclaredMethod("addURL",
+ new Class[] {URL.class});
+ addURL.setAccessible(true);
+ addURL.invoke(getClass().getClassLoader(),
+ new Object[] {new URL(url)});
+ m_extensionLocations.add(bundle.getSymbolicName());
+ }
+ }
+ }
+ else
+ {
+ getFelix().getLogger().log(Logger.LOG_WARNING,
+ "Unable to add extension bundle to FrameworkClassLoader - Maybe BundleCache does not support URLs?");
+ throw new UnsupportedOperationException(
+ "Unable to add extension bundle to FrameworkClassLoader - Maybe BundleCache does not support URLs?");
+ }
+ }
+ catch (UnsupportedOperationException ex)
+ {
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ getFelix().getLogger().log(Logger.LOG_WARNING,
+ "Unable to add extension bundle to FrameworkClassLoader - Maybe not an URLClassLoader?", ex);
+ throw new UnsupportedOperationException(
+ "Unable to add extension bundle to FrameworkClassLoader - Maybe not an URLClassLoader?");
+ }
+
+ ICapability[] temp = new ICapability[m_exports.length + exports.length];
+
+ System.arraycopy(m_exports, 0, temp, 0, m_exports.length);
+ System.arraycopy(exports, 0, temp, m_exports.length, exports.length);
+
+ m_exports = temp;
+
+ parseAndAddExports(headers);
+
+ systemArchive.setManifestHeader(headers);
+
+ String activatorClass = (String)
+ bundle.getInfo().getCurrentHeader().get(
+ FelixConstants.FELIX_EXTENSION_ACTIVATOR);
+
+ if (activatorClass != null)
+ {
+ try
+ {
+ m_activator.addActivator(((BundleActivator)
+ getClass().getClassLoader().loadClass(
+ activatorClass.trim()).newInstance()),
+ new BundleContextImpl(getFelix(), bundle));
+ }
+ catch (Throwable ex)
+ {
+ getFelix().getLogger().log(Logger.LOG_WARNING,
+ "Unable to start Felix Extension Activator", ex);
+ }
+ }
+ }
+
+ private class SystemBundleContentLoader implements IContentLoader
+ {
+ private ISearchPolicy m_searchPolicy = null;
+ private IURLPolicy m_urlPolicy = null;
+
+ public void open()
+ {
+ // Nothing needed here.
+ }
+
+ public void close()
+ {
+ // Nothing needed here.
+ }
+
+ public IContent getContent()
+ {
+ return null;
+ }
+
+ public ISearchPolicy getSearchPolicy()
+ {
+ return m_searchPolicy;
+ }
+
+ public void setSearchPolicy(ISearchPolicy searchPolicy)
+ {
+ m_searchPolicy = searchPolicy;
+ }
+
+ public IURLPolicy getURLPolicy()
+ {
+ return m_urlPolicy;
+ }
+
+ public void setURLPolicy(IURLPolicy urlPolicy)
+ {
+ m_urlPolicy = urlPolicy;
+ }
+
+ public Class getClass(String name)
+ {
+ if (!m_exportNames.contains(Util.getClassPackage(name)))
+ {
+ return null;
+ }
+
+ try
+ {
+ return getClass().getClassLoader().loadClass(name);
+ }
+ catch (ClassNotFoundException ex)
+ {
+ getFelix().getLogger().log(
+ Logger.LOG_WARNING,
+ ex.getMessage(),
+ ex);
+ }
+ return null;
+ }
+
+ public URL getResource(String name)
+ {
+ return getClass().getClassLoader().getResource(name);
+ }
+
+ public Enumeration getResources(String name)
+ {
+ try
+ {
+ return getClass().getClassLoader().getResources(name);
+ }
+ catch (IOException ex)
+ {
+ return null;
+ }
+ }
+
+ public URL getResourceFromContent(String name)
+ {
+ // There is no content for the system bundle, so return null.
+ return null;
+ }
+
+ public boolean hasInputStream(String urlPath) throws IOException
+ {
+ return (getClass().getClassLoader().getResource(urlPath) != null);
+ }
+
+ public InputStream getInputStream(String urlPath) throws IOException
+ {
+ return getClass().getClassLoader().getResourceAsStream(urlPath);
+ }
+
+ public String findLibrary(String name)
+ {
+ // No native libs associated with the system bundle.
+ return null;
+ }
+ }
}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/SystemBundleActivator.java b/framework/src/main/java/org/apache/felix/framework/SystemBundleActivator.java
index 68e333f..94d74ed 100644
--- a/framework/src/main/java/org/apache/felix/framework/SystemBundleActivator.java
+++ b/framework/src/main/java/org/apache/felix/framework/SystemBundleActivator.java
@@ -1,4 +1,4 @@
-/*
+/*
* 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
@@ -18,7 +18,7 @@
*/
package org.apache.felix.framework;
-import java.util.List;
+import java.util.*;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
@@ -28,6 +28,7 @@
private Felix m_felix = null;
private List m_activatorList = null;
private BundleContext m_context = null;
+ private Map m_activatorContextMap = null;
SystemBundleActivator(Felix felix, List activatorList)
{
@@ -56,7 +57,17 @@
// Stop all activators.
for (int i = 0; i < m_activatorList.size(); i++)
{
- ((BundleActivator) m_activatorList.get(i)).stop(context);
+ if ((m_activatorContextMap != null) &&
+ m_activatorContextMap.containsKey(m_activatorList.get(i)))
+ {
+ ((BundleActivator) m_activatorList.get(i)).stop(
+ (BundleContext) m_activatorContextMap.get(
+ m_activatorList.get(i)));
+ }
+ else
+ {
+ ((BundleActivator) m_activatorList.get(i)).stop(context);
+ }
}
}
}
@@ -65,4 +76,30 @@
{
return m_context;
}
+
+ void addActivator(BundleActivator activator, BundleContext context) throws Exception
+ {
+ if (m_activatorList == null)
+ {
+ m_activatorList = new ArrayList();
+ }
+
+ m_activatorList.add(activator);
+
+ if (context != null)
+ {
+ if (m_activatorContextMap == null)
+ {
+ m_activatorContextMap = new HashMap();
+ }
+
+ m_activatorContextMap.put(activator, context);
+
+ activator.start(context);
+ }
+ else if (m_context != null)
+ {
+ activator.start(m_context);
+ }
+ }
}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/SystemBundleContentLoader.java b/framework/src/main/java/org/apache/felix/framework/SystemBundleContentLoader.java
deleted file mode 100644
index 6fc10df..0000000
--- a/framework/src/main/java/org/apache/felix/framework/SystemBundleContentLoader.java
+++ /dev/null
@@ -1,128 +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.felix.framework;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Enumeration;
-
-import org.apache.felix.moduleloader.*;
-
-public class SystemBundleContentLoader implements IContentLoader
-{
- private Logger m_logger = null;
- private ISearchPolicy m_searchPolicy = null;
- private IURLPolicy m_urlPolicy = null;
-
- public SystemBundleContentLoader(Logger logger)
- {
- m_logger = logger;
- }
-
- public void open()
- {
- // Nothing needed here.
- }
-
- public void close()
- {
- // Nothing needed here.
- }
-
- public IContent getContent()
- {
- return null;
- }
-
- public ISearchPolicy getSearchPolicy()
- {
- return m_searchPolicy;
- }
-
- public void setSearchPolicy(ISearchPolicy searchPolicy)
- {
- m_searchPolicy = searchPolicy;
- }
-
- public IURLPolicy getURLPolicy()
- {
- return m_urlPolicy;
- }
-
- public void setURLPolicy(IURLPolicy urlPolicy)
- {
- m_urlPolicy = urlPolicy;
- }
-
- public Class getClass(String name)
- {
- try
- {
- return getClass().getClassLoader().loadClass(name);
- }
- catch (ClassNotFoundException ex)
- {
- m_logger.log(
- Logger.LOG_WARNING,
- ex.getMessage(),
- ex);
- }
- return null;
- }
-
- public URL getResource(String name)
- {
- return getClass().getClassLoader().getResource(name);
- }
-
- public Enumeration getResources(String name)
- {
- try
- {
- return getClass().getClassLoader().getResources(name);
- }
- catch (IOException ex)
- {
- return null;
- }
- }
-
- public URL getResourceFromContent(String name)
- {
- // There is no content for the system bundle, so return null.
- return null;
- }
-
- public boolean hasInputStream(String urlPath) throws IOException
- {
- return (getClass().getClassLoader().getResource(urlPath) != null);
- }
-
- public InputStream getInputStream(String urlPath) throws IOException
- {
- return getClass().getClassLoader().getResourceAsStream(urlPath);
- }
-
- public String findLibrary(String name)
- {
- // No native libs associated with the system bundle.
- return null;
- }
-}
\ No newline at end of file