/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.aries.subsystem.core.internal;
import java.io.IOException;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.aries.subsystem.ContentHandler;
import org.apache.aries.subsystem.core.archive.ExportPackageCapability;
import org.apache.aries.subsystem.core.archive.ExportPackageHeader;
import org.apache.aries.subsystem.core.archive.ProvideCapabilityCapability;
import org.apache.aries.subsystem.core.archive.ProvideCapabilityHeader;
import org.apache.aries.subsystem.core.archive.SubsystemContentHeader;
import org.apache.aries.subsystem.core.archive.SubsystemExportServiceCapability;
import org.apache.aries.subsystem.core.archive.SubsystemExportServiceHeader;
import org.apache.aries.subsystem.core.internal.BundleResourceInstaller.BundleConstituent;
import org.eclipse.equinox.region.Region;
import org.eclipse.equinox.region.RegionFilter;
import org.eclipse.equinox.region.RegionFilterBuilder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.startlevel.FrameworkStartLevel;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.resource.Resource;
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.CoordinationException;
import org.osgi.service.coordinator.Participant;
import org.osgi.service.subsystem.Subsystem;
import org.osgi.service.subsystem.Subsystem.State;
import org.osgi.service.subsystem.SubsystemConstants;
import org.osgi.service.subsystem.SubsystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StartAction extends AbstractAction {
public static enum Restriction {
NONE,
INSTALL_ONLY,
RESOLVE_ONLY
}
private static final Logger logger = LoggerFactory.getLogger(StartAction.class);
private final Coordination coordination;
private final BasicSubsystem instigator;
private final Restriction restriction;
public StartAction(BasicSubsystem instigator, BasicSubsystem requestor, BasicSubsystem target) {
this(instigator, requestor, target, Restriction.NONE);
}
public StartAction(BasicSubsystem instigator, BasicSubsystem requestor, BasicSubsystem target, Restriction restriction) {
this(instigator, requestor, target, null, restriction);
}
public StartAction(BasicSubsystem instigator, BasicSubsystem requestor, BasicSubsystem target, Coordination coordination) {
this(instigator, requestor, target, coordination, Restriction.NONE);
}
public StartAction(BasicSubsystem instigator, BasicSubsystem requestor, BasicSubsystem target, Coordination coordination, Restriction restriction) {
super(requestor, target, false);
this.instigator = instigator;
this.coordination = coordination;
this.restriction = restriction;
}
private static boolean isTargetStartable(BasicSubsystem instigator, BasicSubsystem requestor, BasicSubsystem target) {
State state = target.getState();
// The following states are illegal.
if (EnumSet.of(State.INSTALL_FAILED, State.UNINSTALLED).contains(state))
throw new SubsystemException("Cannot start from state " + state);
// The following states mean the requested state has already been attained.
if (State.ACTIVE.equals(state))
return false;
// Always start if target is content of requestor.
if (!Utils.isContent(requestor, target)) {
// Always start if target is a dependency of requestor.
if (!Utils.isDependency(requestor, target)) {
// Always start if instigator equals target (explicit start).
if (!instigator.equals(target)) {
// Don't start if instigator is root (restart) and target is not ready.
if (instigator.isRoot() && !target.isReadyToStart()) {
return false;
}
}
}
}
return true;
}
private void installDependencies(BasicSubsystem target, Coordination coordination) throws Exception {
for (Subsystem parent : target.getParents()) {
AccessController.doPrivileged(new StartAction(instigator, target, (BasicSubsystem)parent, coordination, Restriction.INSTALL_ONLY));
}
installDependencies(Collections.<Subsystem>singletonList(target), coordination);
for (Subsystem child : Activator.getInstance().getSubsystems().getChildren(target)) {
AccessController.doPrivileged(new StartAction(instigator, target, (BasicSubsystem)child, coordination, Restriction.INSTALL_ONLY));
}
}
private static void installDependencies(Collection<Subsystem> subsystems, Coordination coordination) throws Exception {
for (Subsystem subsystem : subsystems) {
if (State.INSTALLING.equals(subsystem.getState())) {
BasicSubsystem bs = (BasicSubsystem)subsystem;
bs.computeDependenciesPostInstallation(coordination);
new InstallDependencies().install(bs, null, coordination);
bs.setState(State.INSTALLED);
}
}
}
private Coordination createCoordination() {
Coordination coordination = this.coordination;
if (coordination == null) {
coordination = Utils.createCoordination(target);
}
return coordination;
}
private static class AffectedResources {
private final List<Resource> resources;
private final Collection<BasicSubsystem> subsystemResources;
AffectedResources(BasicSubsystem target) {
LinkedHashSet<Resource> resources = new LinkedHashSet<Resource>();
LinkedHashSet<BasicSubsystem> subsystemResources = new LinkedHashSet<BasicSubsystem>();
Subsystems subsystems = Activator.getInstance().getSubsystems();
for (Resource dep : subsystems.getResourcesReferencedBy(target)) {
if (dep instanceof BasicSubsystem
&& !subsystems.getChildren(target).contains(dep)) {
subsystemResources.add((BasicSubsystem)dep);
}
else if (dep instanceof BundleRevision) {
BundleConstituent constituent = new BundleConstituent(null, (BundleRevision)dep);
if (!target.getConstituents().contains(constituent)) {
for (BasicSubsystem constituentOf : subsystems.getSubsystemsByConstituent(
new BundleConstituent(null, (BundleRevision)dep))) {
subsystemResources.add(constituentOf);
}
}
}
resources.add(dep);
}
for (Subsystem child : subsystems.getChildren(target)) {
subsystemResources.add((BasicSubsystem)child);
resources.add((BasicSubsystem)child);
}
for (Resource resource : target.getResource().getSharedContent()) {
for (BasicSubsystem constituentOf : subsystems.getSubsystemsByConstituent(
resource instanceof BundleRevision ? new BundleConstituent(null, (BundleRevision)resource) : resource)) {
subsystemResources.add(constituentOf);
}
resources.add(resource);
}
subsystemResources.add(target);
this.resources = new ArrayList<Resource>(resources);
this.subsystemResources = subsystemResources;
}
List<Resource> resources() {
return resources;
}
Collection<BasicSubsystem> subsystems() {
return subsystemResources;
}
}
private static AffectedResources computeAffectedResources(BasicSubsystem target) {
return new AffectedResources(target);
}
@Override
public Object run() {
// Protect against re-entry now that cycles are supported.
if (!Activator.getInstance().getLockingStrategy().set(State.STARTING, target)) {
return null;
}
try {
AffectedResources affectedResources;
// We are now protected against re-entry.
// If necessary, install the dependencies.
if (State.INSTALLING.equals(target.getState()) && !Utils.isProvisionDependenciesInstall(target)) {
// Acquire the global write lock while installing dependencies.
Activator.getInstance().getLockingStrategy().writeLock();
try {
// We are now protected against installs, starts, stops, and uninstalls.
// We need a separate coordination when installing
// dependencies because cleaning up the temporary export
// sharing policies must be done while holding the write lock.
Coordination c = Utils.createCoordination(target);
try {
installDependencies(target, c);
// Associated subsystems must be computed after all dependencies
// are installed because some of the dependencies may be
// subsystems. This is safe to do while only holding the read
// lock since we know that nothing can be added or removed.
affectedResources = computeAffectedResources(target);
for (BasicSubsystem subsystem : affectedResources.subsystems()) {
if (State.INSTALLING.equals(subsystem.getState())
&& !Utils.isProvisionDependenciesInstall(subsystem)) {
installDependencies(subsystem, c);
}
}
// Downgrade to the read lock in order to prevent
// installs and uninstalls but allow starts and stops.
Activator.getInstance().getLockingStrategy().readLock();
}
catch (Throwable t) {
c.fail(t);
}
finally {
// This will clean up the temporary export sharing
// policies. Must be done while holding the write lock.
c.end();
}
}
finally {
// Release the global write lock as soon as possible.
Activator.getInstance().getLockingStrategy().writeUnlock();
}
}
else {
// Acquire the read lock in order to prevent installs and
// uninstalls but allow starts and stops.
Activator.getInstance().getLockingStrategy().readLock();
}
try {
// We now hold the read lock and are protected against installs
// and uninstalls.
if (Restriction.INSTALL_ONLY.equals(restriction)) {
return null;
}
// Compute associated subsystems here in case (1) they weren't
// computed previously while holding the write lock or (2) they
// were computed previously and more were subsequently added.
// This is safe to do while only holding the read lock since we
// know that nothing can be added or removed.
affectedResources = computeAffectedResources(target);
// Acquire the global mutual exclusion lock while acquiring the
// state change locks of affected subsystems.
Activator.getInstance().getLockingStrategy().lock();
try {
// We are now protected against cycles.
// Acquire the state change locks of affected subsystems.
Activator.getInstance().getLockingStrategy().lock(affectedResources.subsystems());
}
finally {
// Release the global mutual exclusion lock as soon as possible.
Activator.getInstance().getLockingStrategy().unlock();
}
Coordination coordination = this.coordination;
try {
coordination = createCoordination();
// We are now protected against other starts and stops of the affected subsystems.
if (!isTargetStartable(instigator, requestor, target)) {
return null;
}
// Resolve if necessary.
if (State.INSTALLED.equals(target.getState()))
resolve(instigator, target, target, coordination, affectedResources.subsystems());
if (Restriction.RESOLVE_ONLY.equals(restriction))
return null;
target.setState(State.STARTING);
// Be sure to set the state back to RESOLVED if starting fails.
coordination.addParticipant(new Participant() {
@Override
public void ended(Coordination coordination) throws Exception {
// Nothing.
}
@Override
public void failed(Coordination coordination) throws Exception {
target.setState(State.RESOLVED);
}
});
SubsystemContentHeader header = target.getSubsystemManifest().getSubsystemContentHeader();
if (header != null)
Collections.sort(affectedResources.resources(), new StartResourceComparator(header));
for (Resource resource : affectedResources.resources())
startResource(resource, coordination);
target.setState(State.ACTIVE);
}
catch (Throwable t) {
// We catch exceptions and fail the coordination here to
// ensure we are still holding the state change locks when
// the participant sets the state to RESOLVED.
coordination.fail(t);
}
finally {
try {
// Don't end a coordination that was not begun as part
// of this start action.
if (coordination.getName().equals(Utils.computeCoordinationName(target))) {
coordination.end();
}
}
finally {
// Release the state change locks of affected subsystems.
Activator.getInstance().getLockingStrategy().unlock(affectedResources.subsystems());
}
}
}
finally {
// Release the read lock.
Activator.getInstance().getLockingStrategy().readUnlock();
}
}
catch (CoordinationException e) {
Throwable t = e.getCause();
if (t == null) {
throw new SubsystemException(e);
}
if (t instanceof SecurityException) {
throw (SecurityException)t;
}
if (t instanceof SubsystemException) {
throw (SubsystemException)t;
}
throw new SubsystemException(t);
}
finally {
// Protection against re-entry no longer required.
Activator.getInstance().getLockingStrategy().unset(State.STARTING, target);
}
return null;
}
private static Collection<Bundle> getBundles(BasicSubsystem subsystem) {
Collection<Resource> constituents = Activator.getInstance().getSubsystems().getConstituents(subsystem);
ArrayList<Bundle> result = new ArrayList<Bundle>(constituents.size());
for (Resource resource : constituents) {
if (resource instanceof BundleRevision)
result.add(((BundleRevision)resource).getBundle());
}
result.trimToSize();
return result;
}
private static void emitResolvingEvent(BasicSubsystem subsystem) {
// Don't propagate a RESOLVING event if this is a persisted subsystem
// that is already RESOLVED.
if (State.INSTALLED.equals(subsystem.getState()))
subsystem.setState(State.RESOLVING);
}
private static void emitResolvedEvent(BasicSubsystem subsystem) {
// No need to propagate a RESOLVED event if this is a persisted
// subsystem already in the RESOLVED state.
if (State.RESOLVING.equals(subsystem.getState()))
subsystem.setState(State.RESOLVED);
}
private static void resolveSubsystems(BasicSubsystem instigator, BasicSubsystem target, Coordination coordination, Collection<BasicSubsystem> subsystems) throws Exception {
for (BasicSubsystem subsystem : subsystems) {
resolveSubsystem(instigator, target, subsystem, coordination);
}
}
private static void resolveSubsystem(BasicSubsystem instigator, BasicSubsystem target, BasicSubsystem subsystem, Coordination coordination) throws Exception {
State state = subsystem.getState();
if (State.INSTALLED.equals(state)) {
if (target.equals(subsystem)) {
resolve(instigator, target, subsystem, coordination, Collections.<BasicSubsystem>emptyList());
}
else {
AccessController.doPrivileged(new StartAction(instigator, target, subsystem, coordination, Restriction.RESOLVE_ONLY));
}
}
}
private static void resolveBundles(BasicSubsystem subsystem) {
FrameworkWiring frameworkWiring = Activator.getInstance().getBundleContext().getBundle(0)
.adapt(FrameworkWiring.class);
// TODO I think this is insufficient. Do we need both
// pre-install and post-install environments for the Resolver?
Collection<Bundle> bundles = getBundles(subsystem);
if (!frameworkWiring.resolveBundles(bundles)) {
handleFailedResolution(subsystem, bundles, frameworkWiring);
}
}
private static void resolve(BasicSubsystem instigator, BasicSubsystem target, BasicSubsystem subsystem, Coordination coordination, Collection<BasicSubsystem> subsystems) {
emitResolvingEvent(subsystem);
try {
// The root subsystem should follow the same event pattern for
// state transitions as other subsystems. However, an unresolvable
// root subsystem should have no effect, so there's no point in
// actually doing the resolution work.
if (!subsystem.isRoot()) {
setExportIsolationPolicy(subsystem, coordination);
resolveSubsystems(instigator, target, coordination, subsystems);
resolveBundles(subsystem);
}
emitResolvedEvent(subsystem);
}
catch (Throwable t) {
subsystem.setState(State.INSTALLED);
if (t instanceof SubsystemException)
throw (SubsystemException)t;
throw new SubsystemException(t);
}
}
private static void setExportIsolationPolicy(final BasicSubsystem subsystem, Coordination coordination) throws InvalidSyntaxException {
if (!subsystem.isComposite())
return;
final Region from = ((BasicSubsystem)subsystem.getParents().iterator().next()).getRegion();
final Region to = subsystem.getRegion();
RegionFilterBuilder builder = from.getRegionDigraph().createRegionFilterBuilder();
setExportIsolationPolicy(builder, subsystem.getDeploymentManifest().getExportPackageHeader(), subsystem);
setExportIsolationPolicy(builder, subsystem.getDeploymentManifest().getProvideCapabilityHeader(), subsystem);
setExportIsolationPolicy(builder, subsystem.getDeploymentManifest().getSubsystemExportServiceHeader(), subsystem);
RegionFilter regionFilter = builder.build();
if (regionFilter.getSharingPolicy().isEmpty())
return;
if (logger.isDebugEnabled())
logger.debug("Establishing region connection: from=" + from
+ ", to=" + to + ", filter=" + regionFilter);
try {
from.connectRegion(to, regionFilter);
}
catch (BundleException e) {
// TODO Assume this means that the export sharing policy has already
// been set. Bad assumption?
return;
}
coordination.addParticipant(new Participant() {
@Override
public void ended(Coordination coordination) throws Exception {
// It may be necessary to rollback the export sharing policy
// even when the coordination did not fail. For example, this
// might have been a subsystem whose export sharing policy was
// set just in case it offered dependencies for some other
// subsystem.
unsetExportIsolationPolicyIfNecessary();
}
@Override
public void failed(Coordination coordination) throws Exception {
// Nothing to do because a coordination is always ended.
}
private void unsetExportIsolationPolicyIfNecessary() throws BundleException, InvalidSyntaxException {
if (!EnumSet.of(State.INSTALLING, State.INSTALLED).contains(subsystem.getState())) {
// The subsystem is either RESOLVED or ACTIVE and therefore
// does not require a rollback.
return;
}
// The subsystem is either INSTALLING or INSTALLED and therefore
// requires a rollback since the export sharing policy must only
// be set upon entering the RESOLVED state.
RegionUpdater updater = new RegionUpdater(from, to);
updater.addRequirements(null);
}
});
}
private static void setExportIsolationPolicy(RegionFilterBuilder builder, ExportPackageHeader header, BasicSubsystem subsystem) throws InvalidSyntaxException {
if (header == null)
return;
String policy = RegionFilter.VISIBLE_PACKAGE_NAMESPACE;
for (ExportPackageCapability capability : header.toCapabilities(subsystem)) {
StringBuilder filter = new StringBuilder("(&");
for (Entry<String, Object> attribute : capability.getAttributes().entrySet())
filter.append('(').append(attribute.getKey()).append('=').append(attribute.getValue()).append(')');
filter.append(')');
if (logger.isDebugEnabled())
logger.debug("Allowing " + policy + " of " + filter);
builder.allow(policy, filter.toString());
}
}
private static void setExportIsolationPolicy(RegionFilterBuilder builder, ProvideCapabilityHeader header, BasicSubsystem subsystem) throws InvalidSyntaxException {
if (header == null)
return;
for (ProvideCapabilityHeader.Clause clause : header.getClauses()) {
ProvideCapabilityCapability capability = new ProvideCapabilityCapability(clause, subsystem);
String policy = capability.getNamespace();
Set<Entry<String, Object>> entrySet = capability.getAttributes().entrySet();
StringBuilder filter = new StringBuilder();
if (entrySet.size() > 1) {
filter.append("(&");
}
for (Entry<String, Object> attribute : capability.getAttributes().entrySet()) {
filter.append('(').append(attribute.getKey()).append('=').append(attribute.getValue()).append(')');
}
if (entrySet.size() > 1) {
filter.append(')');
}
if (logger.isDebugEnabled()) {
logger.debug("Allowing policy {} with filter {}", policy, filter);
}
if (filter.length() == 0) {
builder.allowAll(policy);
}
else {
builder.allow(policy, filter.toString());
}
}
}
private static void setExportIsolationPolicy(RegionFilterBuilder builder, SubsystemExportServiceHeader header, BasicSubsystem subsystem) throws InvalidSyntaxException {
if (header == null)
return;
String policy = RegionFilter.VISIBLE_SERVICE_NAMESPACE;
for (SubsystemExportServiceHeader.Clause clause : header.getClauses()) {
SubsystemExportServiceCapability capability = new SubsystemExportServiceCapability(clause, subsystem);
String filter = capability.getDirectives().get(SubsystemExportServiceCapability.DIRECTIVE_FILTER);
if (logger.isDebugEnabled())
logger.debug("Allowing " + policy + " of " + filter);
builder.allow(policy, filter);
}
}
private void startBundleResource(Resource resource, Coordination coordination) throws BundleException {
if (target.isRoot())
// Starting the root subsystem should not affect bundles within the
// root region.
return;
if (Utils.isRegionContextBundle(resource))
// The region context bundle was persistently started elsewhere.
return;
final Bundle bundle = ((BundleRevision)resource).getBundle();
if ((bundle.getState() & (Bundle.STARTING | Bundle.ACTIVE)) != 0)
return;
if (logger.isDebugEnabled()) {
int bundleStartLevel = bundle.adapt(BundleStartLevel.class).getStartLevel();
Bundle systemBundle=Activator.getInstance().getBundleContext().getBundle(0);
int fwStartLevel = systemBundle.adapt(FrameworkStartLevel.class).getStartLevel();
logger.debug("StartAction: starting bundle " + bundle.getSymbolicName()
+ " " + bundle.getVersion().toString()
+ " bundleStartLevel=" + bundleStartLevel
+ " frameworkStartLevel=" + fwStartLevel);
}
bundle.start(Bundle.START_TRANSIENT | Bundle.START_ACTIVATION_POLICY);
if (logger.isDebugEnabled()) {
logger.debug("StartAction: bundle " + bundle.getSymbolicName()
+ " " + bundle.getVersion().toString()
+ " started correctly");
}
if (coordination == null)
return;
coordination.addParticipant(new Participant() {
public void ended(Coordination coordination) throws Exception {
// noop
}
public void failed(Coordination coordination) throws Exception {
bundle.stop();
}
});
}
private void startResource(Resource resource, Coordination coordination) throws BundleException, IOException {
String type = ResourceHelper.getTypeAttribute(resource);
if (SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type)
|| SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type)
|| SubsystemConstants.SUBSYSTEM_TYPE_FEATURE.equals(type)) {
startSubsystemResource(resource, coordination);
} else if (IdentityNamespace.TYPE_BUNDLE.equals(type)) {
startBundleResource(resource, coordination);
} else if (IdentityNamespace.TYPE_FRAGMENT.equals(type)) {
// Fragments are not started.
} else {
if (!startCustomHandler(resource, type, coordination))
throw new SubsystemException("Unsupported resource type: " + type);
}
}
private boolean startCustomHandler(Resource resource, String type, Coordination coordination) {
ServiceReference<ContentHandler> customHandlerRef = CustomResources.getCustomContentHandler(target, type);
if (customHandlerRef != null) {
ContentHandler customHandler = target.getBundleContext().getService(customHandlerRef);
if (customHandler != null) {
try {
customHandler.start(ResourceHelper.getSymbolicNameAttribute(resource), type, target, coordination);
return true;
} finally {
target.getBundleContext().ungetService(customHandlerRef);
}
}
}
return false;
}
private void startSubsystemResource(Resource resource, final Coordination coordination) throws IOException {
final BasicSubsystem subsystem = (BasicSubsystem)resource;
if (!isTargetStartable(instigator, target, subsystem)) {
return;
}
// Subsystems that are content resources of another subsystem must have
// their autostart setting set to started.
if (Utils.isContent(this.target, subsystem))
subsystem.setAutostart(true);
new StartAction(instigator, target, subsystem, coordination).run();
if (coordination == null)
return;
coordination.addParticipant(new Participant() {
public void ended(Coordination coordination) throws Exception {
// noop
}
public void failed(Coordination coordination) throws Exception {
new StopAction(target, subsystem, !subsystem.isRoot()).run();
}
});
}
private static void handleFailedResolution(BasicSubsystem subsystem, Collection<Bundle> bundles, FrameworkWiring wiring) {
logFailedResolution(subsystem, bundles);
throw new SubsystemException("Framework could not resolve the bundles: " + bundles);
}
private static void logFailedResolution(BasicSubsystem subsystem, Collection<Bundle> bundles) {
//work out which bundles could not be resolved
Collection<Bundle> unresolved = new ArrayList<Bundle>();
StringBuilder diagnostics = new StringBuilder();
diagnostics.append(String.format("Unable to resolve bundles for subsystem/version/id %s/%s/%s:\n",
subsystem.getSymbolicName(), subsystem.getVersion(), subsystem.getSubsystemId()));
String fmt = "%d : STATE %s : %s : %s : %s";
for(Bundle bundle:bundles){
if((bundle.getState() & Bundle.RESOLVED) != Bundle.RESOLVED) {
unresolved.add(bundle);
}
String state = null;
switch(bundle.getState()) {
case Bundle.ACTIVE :
state = "ACTIVE";
break;
case Bundle.INSTALLED :
state = "INSTALLED";
break;
case Bundle.RESOLVED :
state = "RESOLVED";
break;
case Bundle.STARTING :
state = "STARTING";
break;
case Bundle.STOPPING :
state = "STOPPING";
break;
case Bundle.UNINSTALLED :
state = "UNINSTALLED";
break;
default :
//convert common states to text otherwise default to just showing the ID
state = "[" + Integer.toString(bundle.getState()) + "]";
break;
}
diagnostics.append(String.format(fmt, bundle.getBundleId(), state,
bundle.getSymbolicName(), bundle.getVersion().toString(),
bundle.getLocation()));
diagnostics.append("\n");
}
logger.error(diagnostics.toString());
}
static void setExportPolicyOfAllInstallingSubsystemsWithProvisionDependenciesResolve(Coordination coordination) throws InvalidSyntaxException {
for (BasicSubsystem subsystem : Activator.getInstance().getSubsystems().getSubsystems()) {
if (!State.INSTALLING.equals(subsystem.getState())
|| Utils.isProvisionDependenciesInstall(subsystem)) {
continue;
}
setExportIsolationPolicy(subsystem, coordination);
}
}
}