in framework/src/main/java/org/apache/felix/framework/Felix.java [655:990]
public void init(final FrameworkListener... listeners) throws BundleException
{
// The system bundle can only be initialized if it currently isn't started.
acquireBundleLock(this,
Bundle.INSTALLED | Bundle.RESOLVED | Bundle.STARTING | Bundle.ACTIVE);
try
{
if ((getState() == Bundle.INSTALLED) || (getState() == Bundle.RESOLVED))
{
String security = (String) m_configMap.get(Constants.FRAMEWORK_SECURITY);
if (security != null)
{
if (System.getSecurityManager() != null)
{
throw new SecurityException("SecurityManager already installed");
}
security = security.trim();
if (Constants.FRAMEWORK_SECURITY_OSGI.equalsIgnoreCase(security) || (security.length() == 0))
{
System.setSecurityManager(m_securityManager = new SecurityManager());
}
else
{
try
{
System.setSecurityManager(m_securityManager =
(SecurityManager) Class.forName(security).newInstance());
}
catch (Throwable t)
{
SecurityException se =
new SecurityException(
"Unable to install custom SecurityManager: " + security);
se.initCause(t);
throw se;
}
}
}
// Generate a framework UUID.
// Spec says we get a new UUID for each invocation of init().
m_configMutableMap.put(
FelixConstants.FRAMEWORK_UUID,
Util.randomUUID("true".equalsIgnoreCase(_getProperty(FelixConstants.FRAMEWORK_UUID_SECURE))));
// Initialize event dispatcher.
m_dispatcher.startDispatching();
// Create the bundle cache, if necessary, so that we can reload any
// installed bundles.
m_cache = (BundleCache)
m_configMutableMap.get(FelixConstants.FRAMEWORK_BUNDLECACHE_IMPL);
if (m_cache == null)
{
try
{
m_cache = new BundleCache(m_logger, m_configMap);
}
catch (Exception ex)
{
m_logger.log(Logger.LOG_ERROR, "Error creating bundle cache.", ex);
throw new BundleException("Error creating bundle cache.", ex);
}
}
// If this is the first time init is called, check to see if
// we need to flush the bundle cache.
if (getState() == Bundle.INSTALLED)
{
String clean = (String) m_configMap.get(Constants.FRAMEWORK_STORAGE_CLEAN);
if ((clean != null)
&& clean.equalsIgnoreCase(Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT))
{
try
{
m_cache.delete();
}
catch (Exception ex)
{
throw new BundleException("Unable to flush bundle cache.", ex);
}
}
if (m_connectFramework != null)
{
m_connectFramework.initialize(m_cache.getCacheDir(), (Map) m_configMap);
}
}
// Initialize installed bundle data structures.
Map[] maps = new Map[] {
new HashMap<String, BundleImpl>(1),
new TreeMap<Long, BundleImpl>()
};
m_uninstalledBundles = new ArrayList<BundleImpl>(0);
// Add the system bundle to the set of installed bundles.
maps[LOCATION_MAP_IDX].put(_getLocation(), this);
maps[IDENTIFIER_MAP_IDX].put(new Long(0), this);
m_installedBundles = maps;
try
{
getResolver().removeRevision(m_extensionManager.getRevision());
m_extensionManager.removeExtensionBundles();
m_extensionManager.updateRevision(this, m_configMap);
if (!m_configMutableMap.containsKey(Constants.FRAMEWORK_SYSTEMPACKAGES))
{
m_configMutableMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES, m_extensionManager.getRevision().getHeaders().get(Constants.EXPORT_PACKAGE));
}
getResolver().addRevision(m_extensionManager.getRevision());
}
catch (Exception ex)
{
// This should not throw an exception, but if so, lets convert it to
// a runtime exception.
throw new BundleException("Exception creating system bundle revision", ex);
}
// Manually resolve the system bundle, which will cause its
// state to be set to RESOLVED.
try
{
m_resolver.resolve(
Collections.singleton(adapt(BundleRevision.class)),
Collections.EMPTY_SET);
}
catch (ResolutionException ex)
{
// This should never happen.
throw new BundleException(
"Unresolved constraint in System Bundle:"
+ ex.getUnresolvedRequirements());
}
// Reload the cached bundles before creating and starting the
// system bundle, since we want all cached bundles to be reloaded
// when we activate the system bundle and any subsequent system
// bundle activators passed into the framework constructor.
BundleArchive[] archives = null;
// First get cached bundle identifiers.
try
{
archives = m_cache.getArchives(m_connectFramework);
}
catch (Exception ex)
{
m_logger.log(Logger.LOG_ERROR, "Unable to list saved bundles.", ex);
archives = null;
}
// Create system bundle activator and bundle context so we can activate it.
setActivator(new SystemBundleActivator());
setBundleContext(new BundleContextImpl(m_logger, this, this));
boolean javaVersionChanged = handleJavaVersionChange();
// Now load all cached bundles.
for (int i = 0; (archives != null) && (i < archives.length); i++)
{
try
{
// Keep track of the max bundle ID currently in use since we
// will need to use this as our next bundle ID value if the
// persisted value cannot be read.
m_nextId = Math.max(m_nextId, archives[i].getId() + 1);
// It is possible that a bundle in the cache was previously
// uninstalled, but not completely deleted (perhaps because
// of a crash or a locked file), so if we see an archive
// with an UNINSTALLED persistent state, then try to remove
// it now.
if (archives[i].getPersistentState() == Bundle.UNINSTALLED)
{
archives[i].closeAndDelete();
}
// Otherwise re-install the cached bundle.
else
{
// Install the cached bundle.
reloadBundle(archives[i], javaVersionChanged);
}
}
catch (Exception ex)
{
fireFrameworkEvent(FrameworkEvent.ERROR, this, ex);
try
{
m_logger.log(
Logger.LOG_ERROR,
"Unable to re-install " + archives[i].getLocation(),
ex);
}
catch (Exception ex2)
{
m_logger.log(
Logger.LOG_ERROR,
"Unable to re-install cached bundle.",
ex);
}
// TODO: FRAMEWORK - Perhaps we should remove the cached bundle?
}
}
for (Bundle extension : m_extensionManager.resolveExtensionBundles(this))
{
m_extensionManager.startExtensionBundle(this, (BundleImpl) extension);
}
if (m_connectFramework != null)
{
m_connectFramework.newBundleActivator().ifPresent(m_activatorList::add);
}
// Now that we have loaded all cached bundles and have determined the
// max bundle ID of cached bundles, we need to try to load the next
// bundle ID from persistent storage. In case of failure, we should
// keep the max value.
m_nextId = Math.max(m_nextId, loadNextId());
// The framework is now in its startup sequence.
setBundleStateAndNotify(this, Bundle.STARTING);
// Now it is possible for threads to wait for the framework to stop,
// so create a gate for that purpose.
m_shutdownGate = new ThreadGate();
// add framework listeners
if ( listeners != null )
{
for(final FrameworkListener fl : listeners)
{
addFrameworkListener(this, fl);
}
}
// Start services
m_resolver.start();
m_fwkWiring.start();
m_fwkStartLevel.start();
try
{
Felix.m_secureAction.startActivator(
getActivator(), _getBundleContext());
}
catch (Throwable ex)
{
m_logger.log(Logger.LOG_ERROR, "Unable to start system bundle.", ex);
throw new RuntimeException("Unable to start system bundle.");
}
// We have to check with the security provider (if there is one).
// This is to avoid having bundles in the cache that have been tampered with
SecurityProvider sp = getFramework().getSecurityProvider();
if ((sp != null) && (System.getSecurityManager() != null))
{
boolean locked = acquireGlobalLock();
if (!locked)
{
throw new BundleException(
"Unable to acquire the global lock to check the bundle.");
}
try
{
for (Object bundle : m_installedBundles[IDENTIFIER_MAP_IDX].values())
{
try
{
if (bundle != this)
{
setBundleProtectionDomain(((BundleImpl) bundle).adapt(BundleRevisionImpl.class));
}
}
catch (Exception ex)
{
((BundleImpl) bundle).close();
maps = new Map[] {
new HashMap<String, BundleImpl>(m_installedBundles[LOCATION_MAP_IDX]),
new TreeMap<Long, BundleImpl>(m_installedBundles[IDENTIFIER_MAP_IDX])
};
maps[LOCATION_MAP_IDX].remove(((BundleImpl) bundle)._getLocation());
maps[IDENTIFIER_MAP_IDX].remove(new Long(((BundleImpl) bundle).getBundleId()));
m_installedBundles = maps;
m_logger.log(
Logger.LOG_ERROR,
"Bundle in cache doesn't pass security check anymore.",
ex);
}
}
}
finally
{
// Always release the global lock.
releaseGlobalLock();
}
}
m_extensionManager.startPendingExtensionBundles(Felix.this);
m_fwkWiring.refreshBundles(null);
// Clear the cache of classes coming from the system bundle.
// This is only used for Felix.getBundle(Class clazz) to speed
// up class lookup for the system bundle.
synchronized (m_systemBundleClassCache)
{
m_systemBundleClassCache.clear();
}
}
}
catch (Throwable t)
{
stopBundle(this, false);
if (m_cache != null)
{
m_cache.release();
m_cache = null;
}
__setState(Bundle.INSTALLED);
throw t;
}
finally
{
releaseBundleLock(this);
if ( listeners != null )
{
for(final FrameworkListener fl : listeners)
{
removeFrameworkListener(this, fl);
}
}
}
}