use of org.eclipse.osgi.container.Module.State in project rt.equinox.framework by eclipse.
the class ModuleContainer method update.
/**
* Updates the specified module with a new revision. The specified
* builder is used to create a new {@link ModuleRevision revision}
* which will become the {@link Module#getCurrentRevision() current}
* revision of the new module.
* @param module the module to update
* @param builder the builder used to create the revision for the update.
* @param revisionInfo the revision info for the new revision, may be {@code null}.
* @throws BundleException if some error occurs updating the module
*/
public void update(Module module, ModuleRevisionBuilder builder, Object revisionInfo) throws BundleException {
long id = builder.getId();
ModuleRevisionBuilder adaptBuilder = getAdaptor().adaptModuleRevisionBuilder(ModuleEvent.UPDATED, module, builder, revisionInfo);
if (adaptBuilder != null) {
// be sure to restore the id from the original builder
adaptBuilder.setInternalId(id);
builder = adaptBuilder;
}
checkAdminPermission(module.getBundle(), AdminPermission.LIFECYCLE);
String name = builder.getSymbolicName();
boolean nameLocked = false;
try {
// Attempt to lock the name
try {
if (name != null && !(nameLocked = nameLocks.tryLock(name, 5, TimeUnit.SECONDS))) {
// $NON-NLS-1$
throw new BundleException("Failed to obtain id locks for installation.", BundleException.STATECHANGE_ERROR);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// $NON-NLS-1$
throw new BundleException("Failed to obtain id locks for installation.", BundleException.STATECHANGE_ERROR, e);
}
Collection<Module> collisionCandidates = Collections.emptyList();
moduleDatabase.readLock();
try {
// Collect existing bundles with the same name and version as the bundle we want to install
// This is to perform the collision check below
List<ModuleCapability> sameIdentity = moduleDatabase.findCapabilities(getIdentityRequirement(name, builder.getVersion()));
if (!sameIdentity.isEmpty()) {
collisionCandidates = new ArrayList<>(1);
for (ModuleCapability identity : sameIdentity) {
ModuleRevision equinoxRevision = identity.getRevision();
if (!equinoxRevision.isCurrent())
continue;
Module m = equinoxRevision.getRevisions().getModule();
if (m.equals(module))
// don't worry about the updating modules revisions
continue;
// need to prevent duplicates here; this is in case a revisions object contains multiple revision objects.
if (!collisionCandidates.contains(m))
collisionCandidates.add(m);
}
}
} finally {
moduleDatabase.readUnlock();
}
// This is from the perspective of the module being updated
if (module != null && !collisionCandidates.isEmpty()) {
adaptor.getModuleCollisionHook().filterCollisions(ModuleCollisionHook.UPDATING, module, collisionCandidates);
}
if (!collisionCandidates.isEmpty()) {
throw new BundleException(NLS.bind(Msg.ModuleContainer_NameCollision, name, builder.getVersion()), BundleException.DUPLICATE_BUNDLE_ERROR);
}
module.lockStateChange(ModuleEvent.UPDATED);
State previousState;
try {
module.checkValid();
previousState = module.getState();
if (Module.ACTIVE_SET.contains(previousState)) {
// throwing an exception from stop terminates update
module.stop(StopOptions.TRANSIENT);
}
if (Module.RESOLVED_SET.contains(previousState)) {
// set the state to installed and publish unresolved event
module.setState(State.INSTALLED);
adaptor.publishModuleEvent(ModuleEvent.UNRESOLVED, module, module);
}
moduleDatabase.update(module, builder, revisionInfo);
} finally {
module.unlockStateChange(ModuleEvent.UPDATED);
}
// only publish updated event on success
adaptor.publishModuleEvent(ModuleEvent.UPDATED, module, module);
if (Module.ACTIVE_SET.contains(previousState)) {
try {
// restart the module if necessary
module.start(StartOptions.TRANSIENT_RESUME);
} catch (BundleException e) {
getAdaptor().publishContainerEvent(ContainerEvent.ERROR, module, e);
}
}
} finally {
if (nameLocked)
nameLocks.unlock(name);
}
}
use of org.eclipse.osgi.container.Module.State in project rt.equinox.framework by eclipse.
the class TestModuleContainer method doTestStartOnResolve.
private void doTestStartOnResolve(boolean enabled) throws BundleException, IOException {
Map<String, String> configuration = new HashMap<String, String>();
if (!enabled) {
configuration.put(EquinoxConfiguration.PROP_MODULE_AUTO_START_ON_RESOLVE, Boolean.toString(false));
}
DummyContainerAdaptor adaptor = new DummyContainerAdaptor(new DummyCollisionHook(false), configuration);
ModuleContainer container = adaptor.getContainer();
// install the system.bundle
Module systemBundle = installDummyModule("system.bundle.MF", Constants.SYSTEM_BUNDLE_LOCATION, Constants.SYSTEM_BUNDLE_SYMBOLICNAME, null, null, container);
ResolutionReport report = container.resolve(Arrays.asList(systemBundle), true);
Assert.assertNull("Failed to resolve system.bundle.", report.getResolutionException());
systemBundle.start();
// install a bunch of modules
Map<String, String> manifest = new HashMap<String, String>();
List<Module> modules = new ArrayList<Module>();
for (int i = 0; i < 5; i++) {
manifest.clear();
manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2");
manifest.put(Constants.BUNDLE_SYMBOLICNAME, "module." + i);
manifest.put(Constants.IMPORT_PACKAGE, "export");
Module module = installDummyModule(manifest, manifest.get(Constants.BUNDLE_SYMBOLICNAME), container);
try {
module.start();
fail("expected a bundle exception.");
} catch (BundleException e) {
// do nothing
}
modules.add(module);
}
manifest.clear();
manifest.put(Constants.BUNDLE_MANIFESTVERSION, "2");
manifest.put(Constants.BUNDLE_SYMBOLICNAME, "exporter");
manifest.put(Constants.EXPORT_PACKAGE, "export");
installDummyModule(manifest, manifest.get(Constants.BUNDLE_SYMBOLICNAME), container);
report = container.resolve(Collections.<Module>emptySet(), false);
Assert.assertNull("Found a error.", report.getResolutionException());
State expectedState = enabled ? State.ACTIVE : State.RESOLVED;
for (Module module : modules) {
Assert.assertEquals("Wrong state.", expectedState, module.getState());
}
}
use of org.eclipse.osgi.container.Module.State in project rt.equinox.framework by eclipse.
the class ModuleContainer method uninstall.
/**
* Uninstalls the specified module.
* @param module the module to uninstall
* @throws BundleException if some error occurs uninstalling the module
*/
public void uninstall(Module module) throws BundleException {
checkAdminPermission(module.getBundle(), AdminPermission.LIFECYCLE);
module.lockStateChange(ModuleEvent.UNINSTALLED);
State previousState;
try {
module.checkValid();
previousState = module.getState();
if (Module.ACTIVE_SET.contains(module.getState())) {
try {
module.stop(StopOptions.TRANSIENT);
} catch (BundleException e) {
adaptor.publishContainerEvent(ContainerEvent.ERROR, module, e);
}
}
if (Module.RESOLVED_SET.contains(previousState)) {
// set the state to installed and publish unresolved event
module.setState(State.INSTALLED);
adaptor.publishModuleEvent(ModuleEvent.UNRESOLVED, module, module);
}
moduleDatabase.uninstall(module);
module.setState(State.UNINSTALLED);
} finally {
module.unlockStateChange(ModuleEvent.UNINSTALLED);
}
adaptor.publishModuleEvent(ModuleEvent.UNINSTALLED, module, module);
}
use of org.eclipse.osgi.container.Module.State in project rt.equinox.framework by eclipse.
the class ModuleContainer method unresolve0.
private Collection<Module> unresolve0(Collection<Module> initial) {
Map<ModuleRevision, ModuleWiring> wiringCopy;
List<Module> refreshTriggers;
Collection<ModuleRevision> toRemoveRevisions;
Collection<ModuleWiring> toRemoveWirings;
Map<ModuleWiring, Collection<ModuleWire>> toRemoveWireLists;
long timestamp;
moduleDatabase.readLock();
try {
checkSystemExtensionRefresh(initial);
timestamp = moduleDatabase.getRevisionsTimestamp();
wiringCopy = moduleDatabase.getWiringsCopy();
refreshTriggers = new ArrayList<>(getRefreshClosure(initial, wiringCopy));
toRemoveRevisions = new ArrayList<>();
toRemoveWirings = new ArrayList<>();
toRemoveWireLists = new HashMap<>();
for (Iterator<Module> iTriggers = refreshTriggers.iterator(); iTriggers.hasNext(); ) {
Module module = iTriggers.next();
boolean first = true;
for (ModuleRevision revision : module.getRevisions().getModuleRevisions()) {
ModuleWiring removedWiring = wiringCopy.remove(revision);
if (removedWiring != null) {
toRemoveWirings.add(removedWiring);
List<ModuleWire> removedWires = removedWiring.getRequiredModuleWires(null);
for (ModuleWire wire : removedWires) {
Collection<ModuleWire> providerWires = toRemoveWireLists.get(wire.getProviderWiring());
if (providerWires == null) {
providerWires = new ArrayList<>();
toRemoveWireLists.put(wire.getProviderWiring(), providerWires);
}
providerWires.add(wire);
}
}
if (!first || revision.getRevisions().isUninstalled()) {
toRemoveRevisions.add(revision);
}
first = false;
}
if (module.getState().equals(State.UNINSTALLED)) {
iTriggers.remove();
}
}
moduleDatabase.sortModules(refreshTriggers, Sort.BY_START_LEVEL, Sort.BY_DEPENDENCY);
} finally {
moduleDatabase.readUnlock();
}
Module systemModule = moduleDatabase.getModule(0);
if (refreshTriggers.contains(systemModule) && Module.ACTIVE_SET.contains(systemModule.getState())) {
refreshSystemModule();
return Collections.emptyList();
}
Collection<Module> modulesLocked = new ArrayList<>(refreshTriggers.size());
Collection<Module> modulesUnresolved = new ArrayList<>();
try {
// lock.
synchronized (stateLockMonitor) {
try {
// go in reverse order
for (ListIterator<Module> iTriggers = refreshTriggers.listIterator(refreshTriggers.size()); iTriggers.hasPrevious(); ) {
Module refreshModule = iTriggers.previous();
refreshModule.lockStateChange(ModuleEvent.UNRESOLVED);
modulesLocked.add(refreshModule);
}
} catch (BundleException e) {
// TODO throw some appropriate exception
throw new IllegalStateException(Msg.ModuleContainer_StateLockError, e);
}
}
// Stop any active bundles and remove non-active modules from the refreshTriggers
for (ListIterator<Module> iTriggers = refreshTriggers.listIterator(refreshTriggers.size()); iTriggers.hasPrevious(); ) {
Module refreshModule = iTriggers.previous();
State previousState = refreshModule.getState();
if (Module.ACTIVE_SET.contains(previousState)) {
try {
refreshModule.stop(StopOptions.TRANSIENT);
} catch (BundleException e) {
adaptor.publishContainerEvent(ContainerEvent.ERROR, refreshModule, e);
}
} else {
iTriggers.remove();
}
}
// do a sanity check on states of the modules, they must be INSTALLED, RESOLVED or UNINSTALLED
for (Module module : modulesLocked) {
if (Module.ACTIVE_SET.contains(module.getState())) {
// $NON-NLS-1$ //$NON-NLS-2$
throw new IllegalStateException("Module is in the wrong state: " + module + ": " + module.getState());
}
}
// finally apply the unresolve to the database
moduleDatabase.writeLock();
try {
if (timestamp != moduleDatabase.getRevisionsTimestamp())
// need to try again
return null;
// remove any wires from unresolved wirings that got removed
for (Map.Entry<ModuleWiring, Collection<ModuleWire>> entry : toRemoveWireLists.entrySet()) {
List<ModuleWire> provided = entry.getKey().getProvidedModuleWires(null);
provided.removeAll(entry.getValue());
entry.getKey().setProvidedWires(provided);
for (ModuleWire removedWire : entry.getValue()) {
// invalidate the wire
removedWire.invalidate();
}
}
// remove any revisions that got removed as part of the refresh
for (ModuleRevision removed : toRemoveRevisions) {
removed.getRevisions().removeRevision(removed);
moduleDatabase.removeCapabilities(removed);
}
// invalidate any removed wiring objects
for (ModuleWiring moduleWiring : toRemoveWirings) {
moduleWiring.invalidate();
}
moduleDatabase.setWiring(wiringCopy);
// check for any removal pendings
moduleDatabase.cleanupRemovalPending();
} finally {
moduleDatabase.writeUnlock();
}
// set the state of modules to unresolved
for (Module module : modulesLocked) {
if (State.RESOLVED.equals(module.getState())) {
module.setState(State.INSTALLED);
modulesUnresolved.add(module);
}
}
} finally {
for (Module module : modulesLocked) {
module.unlockStateChange(ModuleEvent.UNRESOLVED);
}
}
// publish unresolved events after giving up all locks
for (Module module : modulesUnresolved) {
adaptor.publishModuleEvent(ModuleEvent.UNRESOLVED, module, module);
}
return refreshTriggers;
}
Aggregations