{
throw new IllegalStateException("Cannot update an uninstalled bundle.");
}
else
{
throw new BundleException(
"Bundle " + bundle
+ " cannot be update, since it is either starting or stopping.");
}
}
// We must release the lock and close the input stream, so do both
// in a finally block.
try
{
// Variable to indicate whether bundle is active or not.
Throwable rethrow = null;
final int oldState = bundle.getState();
// First get the update-URL from our header.
String updateLocation = (String)
((BundleRevisionImpl) bundle.adapt(BundleRevision.class))
.getHeaders().get(Constants.BUNDLE_UPDATELOCATION);
// If no update location specified, use original location.
if (updateLocation == null)
{
updateLocation = bundle._getLocation();
}
// Stop the bundle if it is active, but do not change its
// persistent state.
if (oldState == Bundle.ACTIVE)
{
stopBundle(bundle, false);
}
try
{
// Revising the bundle creates a new revision, which modifies
// the global state, so we need to acquire the global lock
// before revising.
boolean locked = acquireGlobalLock();
if (!locked)
{
throw new BundleException(
"Cannot acquire global lock to update the bundle.");
}
try
{
// Try to revise.
boolean wasExtension = bundle.isExtension();
bundle.revise(updateLocation, is);
// Verify bundle revision.
try
{
Object sm = System.getSecurityManager();
if (sm != null)
{
((SecurityManager) sm).checkPermission(
new AdminPermission(bundle, AdminPermission.LIFECYCLE));
}
// If this is an update from a normal to an extension bundle
// then attach the extension
if (!wasExtension && bundle.isExtension())
{
m_extensionManager.addExtensionBundle(this, bundle);
// TODO: REFACTOR - Perhaps we could move this into extension manager.
m_resolver.addRevision(m_extensionManager.getRevision());
// TODO: REFACTOR - Not clear why this is here. We should look at all of these steps more closely.
setBundleStateAndNotify(bundle, Bundle.RESOLVED);
}
else if (wasExtension)
{
setBundleStateAndNotify(bundle, Bundle.INSTALLED);
}
}
catch (Throwable ex)
{
try
{
bundle.rollbackRevise();
}
catch (Exception busted)
{
m_logger.log(
bundle, Logger.LOG_ERROR, "Unable to rollback.", busted);
}
throw ex;
}
}
finally
{
// Always release the global lock.
releaseGlobalLock();
}
}
catch (Throwable ex)
{
m_logger.log(
bundle, Logger.LOG_ERROR, "Unable to update the bundle.", ex);
rethrow = ex;
}
// Set new state, mark as needing a refresh, and fire updated event
// if successful.
if (rethrow == null)
{
bundle.setLastModified(System.currentTimeMillis());
if (!bundle.isExtension())
{
setBundleStateAndNotify(bundle, Bundle.INSTALLED);
}
else
{
m_extensionManager.startExtensionBundle(this, bundle);
}
fireBundleEvent(BundleEvent.UNRESOLVED, bundle);
fireBundleEvent(BundleEvent.UPDATED, bundle);
// Acquire global lock to check if we should auto-refresh.
boolean locked = acquireGlobalLock();
// If we did not get the global lock, then do not try to
// auto-refresh.
if (locked)
{
try
{
if (!m_dependencies.hasDependents(bundle)
&& !bundle.isExtension())
{
try
{
List<Bundle> list = new ArrayList<Bundle>(1);
list.add(bundle);
refreshPackages(list, null);
}
catch (Exception ex)
{
m_logger.log(bundle,
Logger.LOG_ERROR,
"Unable to immediately purge the bundle revisions.", ex);
}
}
}
finally
{
// Always release the global lock.
releaseGlobalLock();
}
}
}
// If the old state was active, but the new revision is a fragment,
// then mark the persistent state to inactive.
if ((oldState == Bundle.ACTIVE)
&& Util.isFragment(bundle.adapt(BundleRevision.class)))
{
bundle.setPersistentStateInactive();
m_logger.log(bundle, Logger.LOG_WARNING,
"Previously active bundle was updated to a fragment, resetting state to inactive: "
+ bundle);
}
// Otherwise, restart the bundle if it was previously active,
// but do not change its persistent state.
else if (oldState == Bundle.ACTIVE)
{
startBundle(bundle, Bundle.START_TRANSIENT);
}
// If update failed, rethrow exception.
if (rethrow != null)
{
if (rethrow instanceof AccessControlException)
{
throw (AccessControlException) rethrow;
}
else if (rethrow instanceof BundleException)
{
throw (BundleException) rethrow;
}
else
{
throw new BundleException(
"Update of bundle " + bundle + " failed.", rethrow);
}
}
}
finally