You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pa...@apache.org on 2007/02/13 00:49:44 UTC
svn commit: r506754 -
/incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/
Author: pauls
Date: Mon Feb 12 15:49:43 2007
New Revision: 506754
URL: http://svn.apache.org/viewvc?view=rev&rev=506754
Log:
Implement the extension:=framework part of extension bundles minus the automatic framework restart (FELIX-30).
Removed:
incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SignerMatcher.java
incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundleContentLoader.java
Modified:
incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleInfo.java
incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundle.java
incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundleActivator.java
Modified: incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java?view=diff&rev=506754&r1=506753&r2=506754
==============================================================================
--- incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java (original)
+++ incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleContextImpl.java Mon Feb 12 15:49:43 2007
@@ -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.");
}
}
Modified: incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java?view=diff&rev=506754&r1=506753&r2=506754
==============================================================================
--- incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java (original)
+++ incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleImpl.java Mon Feb 12 15:49:43 2007
@@ -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;
}
}
Modified: incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleInfo.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleInfo.java?view=diff&rev=506754&r1=506753&r2=506754
==============================================================================
--- incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleInfo.java (original)
+++ incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/BundleInfo.java Mon Feb 12 15:49:43 2007
@@ -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;
@@ -473,6 +478,16 @@
public void setStale()
{
m_stale = true;
+ }
+
+ public boolean isExtension()
+ {
+ return m_extension;
+ }
+
+ public void setExtension(boolean extension)
+ {
+ m_extension = extension;
}
//
Modified: incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?view=diff&rev=506754&r1=506753&r2=506754
==============================================================================
--- incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original)
+++ incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Mon Feb 12 15:49:43 2007
@@ -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())
+ {
+ Object sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ ((SecurityManager) sm).checkPermission(
+ new AdminPermission(bundle, AdminPermission.LIFECYCLE));
+ }
+ }
+ else
{
- ((SecurityManager) sm).checkPermission(
- new AdminPermission(bundle, AdminPermission.LIFECYCLE));
+ 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);
Modified: incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundle.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundle.java?view=diff&rev=506754&r1=506753&r2=506754
==============================================================================
--- incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundle.java (original)
+++ incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundle.java Mon Feb 12 15:49:43 2007
@@ -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;
}
}
}
Modified: incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundleActivator.java
URL: http://svn.apache.org/viewvc/incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundleActivator.java?view=diff&rev=506754&r1=506753&r2=506754
==============================================================================
--- incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundleActivator.java (original)
+++ incubator/felix/trunk/framework/src/main/java/org/apache/felix/framework/SystemBundleActivator.java Mon Feb 12 15:49:43 2007
@@ -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);
+ }
}
}
}
@@ -64,5 +75,31 @@
public BundleContext getBundleContext()
{
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);
+ }
}
}