use of org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent in project rt.equinox.framework by eclipse.
the class Module method lockStateChange.
/**
* Acquires the module lock for state changes by the current thread for the specified
* transition event. Certain transition events locks may be nested within other
* transition event locks. For example, a resolved transition event lock may be
* nested within a started transition event lock. A stopped transition lock
* may be nested within an updated, unresolved or uninstalled transition lock.
* @param transitionEvent the transition event to acquire the lock for.
* @throws BundleException
*/
protected final void lockStateChange(ModuleEvent transitionEvent) throws BundleException {
boolean previousInterruption = Thread.interrupted();
boolean invalid = false;
try {
boolean acquired = stateChangeLock.tryLock(revisions.getContainer().getModuleLockTimeout(), TimeUnit.SECONDS);
Set<ModuleEvent> currentTransition = Collections.emptySet();
if (acquired) {
boolean isValidTransition = true;
switch(transitionEvent) {
case STARTED:
case UPDATED:
case UNINSTALLED:
case UNRESOLVED:
// These states must be initiating transition states
// no other transition state is allowed when these are kicked off
isValidTransition = stateTransitionEvents.isEmpty();
break;
case RESOLVED:
isValidTransition = VALID_RESOLVED_TRANSITION.containsAll(stateTransitionEvents);
break;
case STOPPED:
isValidTransition = VALID_STOPPED_TRANSITION.containsAll(stateTransitionEvents);
break;
default:
isValidTransition = false;
break;
}
if (!isValidTransition) {
currentTransition = EnumSet.copyOf(stateTransitionEvents);
invalid = true;
stateChangeLock.unlock();
} else {
stateTransitionEvents.add(transitionEvent);
return;
}
} else {
currentTransition = EnumSet.copyOf(stateTransitionEvents);
}
Throwable cause;
if (invalid) {
cause = new IllegalStateException(NLS.bind(Msg.Module_LockStateError, transitionEvent, currentTransition));
} else {
cause = new TimeoutException(NLS.bind(Msg.Module_LockTimeout, revisions.getContainer().getModuleLockTimeout()));
}
String exceptonInfo = toString() + ' ' + transitionEvent + ' ' + currentTransition;
throw new BundleException(Msg.Module_LockError + exceptonInfo, BundleException.STATECHANGE_ERROR, cause);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// $NON-NLS-1$
throw new BundleException(Msg.Module_LockError + toString() + " " + transitionEvent, BundleException.STATECHANGE_ERROR, e);
} finally {
if (previousInterruption) {
Thread.currentThread().interrupt();
}
}
}
use of org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent in project rt.equinox.framework by eclipse.
the class TestModuleContainer method removeFirstListOfCommonEvents.
private List<DummyModuleEvent> removeFirstListOfCommonEvents(List<DummyModuleEvent> events) {
List<DummyModuleEvent> result = new ArrayList<DummyModuleDatabase.DummyModuleEvent>();
if (events.isEmpty()) {
return result;
}
ModuleEvent commonEvent = events.get(0).event;
for (Iterator<DummyModuleEvent> iEvents = events.iterator(); iEvents.hasNext(); ) {
DummyModuleEvent current = iEvents.next();
if (commonEvent.equals(current.event)) {
iEvents.remove();
result.add(current);
} else {
break;
}
}
return result;
}
use of org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent in project rt.equinox.framework by eclipse.
the class Module method start.
/**
* Starts this module
* @param options the options for starting
* @throws BundleException if an errors occurs while starting
*/
public void start(StartOptions... options) throws BundleException {
revisions.getContainer().checkAdminPermission(getBundle(), AdminPermission.EXECUTE);
if (options == null) {
options = new StartOptions[0];
}
ModuleEvent event;
if (StartOptions.LAZY_TRIGGER.isContained(options)) {
setTrigger();
if (stateChangeLock.getHoldCount() > 0 && stateTransitionEvents.contains(ModuleEvent.STARTED)) {
// nothing to do here; the current thread is activating the bundle.
return;
}
}
BundleException startError = null;
boolean lockedStarted = false;
// Indicate we are in the middle of a start.
// This must be incremented before we acquire the STARTED lock the first time.
inStart.incrementAndGet();
try {
lockStateChange(ModuleEvent.STARTED);
lockedStarted = true;
checkValid();
if (StartOptions.TRANSIENT_IF_AUTO_START.isContained(options) && !settings.contains(Settings.AUTO_START)) {
// Do nothing; this is a request to start only if the module is set for auto start
return;
}
checkFragment();
persistStartOptions(options);
if (getStartLevel() > getRevisions().getContainer().getStartLevel()) {
if (StartOptions.TRANSIENT.isContained(options)) {
// it is an error to attempt to transient start a bundle without its start level met
throw new BundleException(Msg.Module_Transient_StartError, BundleException.START_TRANSIENT_ERROR);
}
// Do nothing; start level is not met
return;
}
if (State.ACTIVE.equals(getState()))
return;
if (getState().equals(State.INSTALLED)) {
ResolutionReport report;
// must unlock to avoid out of order locks when multiple unresolved
// bundles are started at the same time from different threads
unlockStateChange(ModuleEvent.STARTED);
lockedStarted = false;
try {
report = getRevisions().getContainer().resolve(Arrays.asList(this), true);
} finally {
lockStateChange(ModuleEvent.STARTED);
lockedStarted = true;
}
// need to check valid again in case someone uninstalled the bundle
checkValid();
ResolutionException e = report.getResolutionException();
if (e != null) {
if (e.getCause() instanceof BundleException) {
throw (BundleException) e.getCause();
}
}
if (State.ACTIVE.equals(getState()))
return;
if (getState().equals(State.INSTALLED)) {
String reportMessage = report.getResolutionReportMessage(getCurrentRevision());
throw new BundleException(Msg.Module_ResolveError + reportMessage, BundleException.RESOLVE_ERROR);
}
}
try {
event = doStart(options);
} catch (BundleException e) {
// must return state to resolved
setState(State.RESOLVED);
startError = e;
// must always publish the STOPPED event on error
event = ModuleEvent.STOPPED;
}
} finally {
if (lockedStarted) {
unlockStateChange(ModuleEvent.STARTED);
}
inStart.decrementAndGet();
}
if (event != null) {
if (!EnumSet.of(ModuleEvent.STARTED, ModuleEvent.LAZY_ACTIVATION, ModuleEvent.STOPPED).contains(event))
// $NON-NLS-1$
throw new IllegalStateException("Wrong event type: " + event);
publishEvent(event);
}
if (startError != null) {
throw startError;
}
}
use of org.eclipse.osgi.container.ModuleContainerAdaptor.ModuleEvent in project rt.equinox.framework by eclipse.
the class Module method stop.
/**
* Stops this module.
* @param options options for stopping
* @throws BundleException if an error occurs while stopping
*/
public void stop(StopOptions... options) throws BundleException {
revisions.getContainer().checkAdminPermission(getBundle(), AdminPermission.EXECUTE);
if (options == null)
options = new StopOptions[0];
ModuleEvent event;
BundleException stopError = null;
lockStateChange(ModuleEvent.STOPPED);
try {
checkValid();
checkFragment();
persistStopOptions(options);
if (!Module.ACTIVE_SET.contains(getState()))
return;
try {
event = doStop();
} catch (BundleException e) {
stopError = e;
// must always publish the STOPPED event
event = ModuleEvent.STOPPED;
}
} finally {
unlockStateChange(ModuleEvent.STOPPED);
}
if (event != null) {
if (!ModuleEvent.STOPPED.equals(event))
// $NON-NLS-1$
throw new IllegalStateException("Wrong event type: " + event);
publishEvent(event);
}
if (stopError != null)
throw stopError;
}
Aggregations