in framework/src/main/java/org/apache/felix/framework/Felix.java [3225:3449]
Bundle installBundle(
Bundle origin, String location, InputStream is)
throws BundleException
{
BundleArchive ba = null;
BundleImpl existing, bundle = null;
// Acquire an install lock.
acquireInstallLock(location);
try
{
// Check to see if the framework is still running;
if ((getState() == Bundle.STOPPING) ||
(getState() == Bundle.UNINSTALLED))
{
throw new BundleException("The framework has been shutdown.");
}
// If bundle location is already installed, then
// return it as required by the OSGi specification.
existing = (BundleImpl) getBundle(location);
if (existing == null)
{
// First generate an identifier for it.
long id = getNextId();
try
{
// Add the bundle to the cache.
ba = m_cache.create(id, getInitialBundleStartLevel(), location, is, m_connectFramework);
}
catch (Exception ex)
{
throw new BundleException(
"Unable to cache bundle: " + location, ex);
}
finally
{
try
{
if (is != null) is.close();
}
catch (IOException ex)
{
m_logger.log(
Logger.LOG_ERROR,
"Unable to close input stream.", ex);
}
}
try
{
// Acquire the global lock to create the bundle,
// since this impacts the global state.
boolean locked = acquireGlobalLock();
if (!locked)
{
throw new BundleException(
"Unable to acquire the global lock to install the bundle.");
}
try
{
bundle = new BundleImpl(this, origin, ba);
}
finally
{
// Always release the global lock.
releaseGlobalLock();
}
if (!bundle.isExtension())
{
Object sm = System.getSecurityManager();
if (sm != null)
{
((SecurityManager) sm).checkPermission(
new AdminPermission(bundle, AdminPermission.LIFECYCLE));
}
}
else
{
m_extensionManager.addExtensionBundle(bundle);
}
}
catch (Throwable ex)
{
// Remove bundle from the cache.
try
{
if (bundle != null)
{
bundle.closeAndDelete();
}
else if (ba != null)
{
ba.closeAndDelete();
}
}
catch (Exception ex1)
{
m_logger.log(bundle,
Logger.LOG_ERROR,
"Could not remove from cache.", ex1);
}
if (ex instanceof BundleException)
{
throw (BundleException) ex;
}
else if (ex instanceof AccessControlException)
{
throw (AccessControlException) ex;
}
else
{
throw new BundleException("Could not create bundle object.", ex);
}
}
// Acquire global lock.
boolean locked = acquireGlobalLock();
if (!locked)
{
// If the calling thread holds bundle locks, then we might not
// be able to get the global lock.
throw new IllegalStateException(
"Unable to acquire global lock to add bundle.");
}
try
{
// Use a copy-on-write approach to add the bundle
// to the installed maps.
Map[] 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].put(location, bundle);
maps[IDENTIFIER_MAP_IDX].put(Long.valueOf(bundle.getBundleId()), bundle);
m_installedBundles = maps;
}
finally
{
releaseGlobalLock();
}
for (Bundle extension : m_extensionManager.resolveExtensionBundles(this))
{
m_extensionManager.startExtensionBundle(this, (BundleImpl) extension);
}
}
}
finally
{
// Always release install lock.
releaseInstallLock(location);
// Always try to close the input stream.
try
{
if (is != null) is.close();
}
catch (IOException ex)
{
m_logger.log(bundle,
Logger.LOG_ERROR,
"Unable to close input stream.", ex);
// Not much else we can do.
}
}
if (existing != null)
{
Set<ServiceReference<org.osgi.framework.hooks.bundle.FindHook>> hooks =
getHookRegistry().getHooks(org.osgi.framework.hooks.bundle.FindHook.class);
if (!hooks.isEmpty())
{
Collection<Bundle> bundles = new ArrayList<>(1);
bundles.add(existing);
bundles = new ShrinkableCollection<>(bundles);
for (ServiceReference<org.osgi.framework.hooks.bundle.FindHook> hook : hooks)
{
org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook, false);
if (fh != null)
{
try
{
m_secureAction.invokeBundleFindHook(
fh, ((BundleImpl) origin)._getBundleContext(), bundles);
}
catch (Throwable th)
{
m_logger.doLog(
hook.getBundle(),
hook,
Logger.LOG_WARNING,
"Problem invoking bundle hook.",
th);
}
}
}
if (origin != this)
{
// If the origin was something else than the system bundle, reject this action if
// the bundle has been removed by the hooks. However, if it is the system bundle,
// the install action should always succeed, regardless of whether the hooks are
// trying to prevent it.
if (bundles.isEmpty())
{
throw new BundleException(
"Bundle installation rejected by hook.",
BundleException.REJECTED_BY_HOOK);
}
}
}
}
else
{
// Fire bundle event.
fireBundleEvent(BundleEvent.INSTALLED, bundle, origin);
}
// Return new bundle.
return (existing != null) ? existing : bundle;
}