Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2013-08-29 20:00:15 +0000
committerThomas Watson2013-08-30 16:36:44 +0000
commitf71c31ff5bfff75903926ab7448b1f14a8f91c2c (patch)
tree9819160812466b59fa446955eb207b166b5dcb2b /bundles/org.eclipse.osgi.compatibility.state
parent634c7448ee842e6c320b4efc4014b83be4513be2 (diff)
downloadrt.equinox.framework-f71c31ff5bfff75903926ab7448b1f14a8f91c2c.tar.gz
rt.equinox.framework-f71c31ff5bfff75903926ab7448b1f14a8f91c2c.tar.xz
rt.equinox.framework-f71c31ff5bfff75903926ab7448b1f14a8f91c2c.zip
Bug 416097 - Platform.getPlatformAdmin().getState(false) returns unresolved State
Diffstat (limited to 'bundles/org.eclipse.osgi.compatibility.state')
-rw-r--r--bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/PlatformAdminImpl.java23
-rw-r--r--bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/PlatformBundleListener.java198
-rw-r--r--bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/StateConverter.java13
-rw-r--r--bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java6
4 files changed, 231 insertions, 9 deletions
diff --git a/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/PlatformAdminImpl.java b/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/PlatformAdminImpl.java
index 95cc2bfa0..55ace736b 100644
--- a/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/PlatformAdminImpl.java
+++ b/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/PlatformAdminImpl.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012 IBM Corporation and others. All rights reserved.
+ * Copyright (c) 2012, 2013 IBM Corporation and others. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
@@ -23,17 +23,28 @@ public class PlatformAdminImpl implements PlatformAdmin {
private final StateObjectFactory factory = new StateObjectFactoryImpl();
private final Object monitor = new Object();
private EquinoxContainer equinoxContainer;
+ private BundleContext bc;
private State systemState;
+ private PlatformBundleListener synchronizer;
private ServiceRegistration<PlatformAdmin> reg;
void start(BundleContext context) {
synchronized (this.monitor) {
equinoxContainer = ((BundleContextImpl) context).getContainer();
+ this.bc = context;
}
this.reg = context.registerService(PlatformAdmin.class, this, null);
}
void stop(BundleContext context) {
+ synchronized (this.monitor) {
+ if (synchronizer != null) {
+ context.removeBundleListener(synchronizer);
+ context.removeFrameworkListener(synchronizer);
+ }
+ synchronizer = null;
+ systemState = null;
+ }
this.reg.unregister();
}
@@ -71,16 +82,20 @@ public class PlatformAdminImpl implements PlatformAdmin {
ModuleDatabase database = equinoxContainer.getStorage().getModuleDatabase();
database.readLock();
try {
+ ModuleContainer container = equinoxContainer.getStorage().getModuleContainer();
List<Module> modules = equinoxContainer.getStorage().getModuleContainer().getModules();
for (Module module : modules) {
ModuleRevision current = module.getCurrentRevision();
BundleDescription description = converter.createDescription(current);
state.addBundle(description);
- state.setPlatformProperties(asDictionary(equinoxContainer.getConfiguration().getInitialConfig()));
}
+ state.setPlatformProperties(asDictionary(equinoxContainer.getConfiguration().getInitialConfig()));
+ synchronizer = new PlatformBundleListener(state, converter, database, container);
+ state.setResolverHookFactory(synchronizer);
+ bc.addBundleListener(synchronizer);
+ bc.addFrameworkListener(synchronizer);
+ state.resolve();
state.setTimeStamp(database.getRevisionsTimestamp());
- // TODO add hooks to get the resolution correct
- // TODO add listeners to keep state copy in sync
} finally {
database.readUnlock();
}
diff --git a/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/PlatformBundleListener.java b/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/PlatformBundleListener.java
new file mode 100644
index 000000000..361c30b5c
--- /dev/null
+++ b/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/PlatformBundleListener.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.osgi.compatibility.state;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.eclipse.osgi.container.*;
+import org.eclipse.osgi.internal.resolver.BaseDescriptionImpl.BaseCapability;
+import org.eclipse.osgi.service.resolver.BundleDescription;
+import org.eclipse.osgi.service.resolver.State;
+import org.osgi.framework.*;
+import org.osgi.framework.hooks.resolver.ResolverHook;
+import org.osgi.framework.hooks.resolver.ResolverHookFactory;
+import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.wiring.*;
+
+class PlatformBundleListener implements SynchronousBundleListener, FrameworkListener, ResolverHookFactory {
+
+ private final State systemState;
+ private final StateConverter converter;
+ private final ModuleDatabase database;
+ private final ModuleContainer container;
+ private long lastResolveStamp = -1;
+ private AtomicBoolean gotUnresolved = new AtomicBoolean(false);
+
+ PlatformBundleListener(State systemState, StateConverter converter, ModuleDatabase database, ModuleContainer container) {
+ this.systemState = systemState;
+ this.converter = converter;
+ this.database = database;
+ this.container = container;
+ }
+
+ @Override
+ public void bundleChanged(BundleEvent event) {
+ switch (event.getType()) {
+ case BundleEvent.INSTALLED : {
+ BundleRevision revision = event.getBundle().adapt(BundleRevision.class);
+ if (revision != null) {
+ systemState.addBundle(converter.createDescription(revision));
+ systemState.setTimeStamp(database.getRevisionsTimestamp());
+ }
+ break;
+ }
+ case BundleEvent.UNINSTALLED : {
+ systemState.removeBundle(event.getBundle().getBundleId());
+ systemState.setTimeStamp(database.getRevisionsTimestamp());
+ break;
+ }
+ case BundleEvent.UPDATED : {
+ BundleRevision revision = event.getBundle().adapt(BundleRevision.class);
+ if (revision != null) {
+ systemState.updateBundle(converter.createDescription(revision));
+ systemState.setTimeStamp(database.getRevisionsTimestamp());
+ }
+ break;
+ }
+ case BundleEvent.UNRESOLVED : {
+ gotUnresolved.set(true);
+ break;
+ }
+ case BundleEvent.RESOLVED : {
+ resolve(gotUnresolved.getAndSet(false));
+ break;
+ }
+ default :
+ // do nothing
+ break;
+ }
+ }
+
+ private void resolve(boolean uninstalled) {
+ database.readLock();
+ try {
+ if (lastResolveStamp != database.getRevisionsTimestamp()) {
+ Collection<ModuleRevision> containerRemovalPending = container.getRemovalPending();
+ BundleDescription[] stateRemovalPendingDescs = systemState.getRemovalPending();
+ Collection<BundleDescription> stateRemovalPending = new ArrayList<BundleDescription>(stateRemovalPendingDescs.length);
+ for (BundleDescription description : stateRemovalPendingDescs) {
+ if (!containerRemovalPending.contains(description.getUserObject())) {
+ stateRemovalPending.add(description);
+ }
+ }
+ if (!stateRemovalPending.isEmpty()) {
+ systemState.resolve(stateRemovalPending.toArray(new BundleDescription[stateRemovalPending.size()]), true);
+ } else {
+ systemState.resolve(!uninstalled);
+ }
+ lastResolveStamp = database.getRevisionsTimestamp();
+ systemState.setTimeStamp(database.getRevisionsTimestamp());
+ }
+ } finally {
+ database.readUnlock();
+ }
+ }
+
+ @Override
+ public void frameworkEvent(FrameworkEvent event) {
+ if (event.getType() == FrameworkEvent.PACKAGES_REFRESHED) {
+ resolve(gotUnresolved.getAndSet(false));
+ }
+ }
+
+ @Override
+ public ResolverHook begin(Collection<BundleRevision> triggers) {
+ return new ResolverHook() {
+
+ @Override
+ public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) {
+ BundleDescription desc = (BundleDescription) singleton.getRevision();
+ ModuleRevision revision = (ModuleRevision) desc.getUserObject();
+ if (revision.getWiring() != null) {
+ collisionCandidates.clear();
+ } else {
+ for (Iterator<BundleCapability> iCandidates = collisionCandidates.iterator(); iCandidates.hasNext();) {
+ BundleDescription candDesc = (BundleDescription) iCandidates.next().getRevision();
+ ModuleRevision candRevision = (ModuleRevision) candDesc.getUserObject();
+ if (candRevision.getWiring() == null) {
+ iCandidates.remove();
+ }
+ }
+ }
+ }
+
+ @Override
+ public void filterResolvable(Collection<BundleRevision> candidates) {
+ for (Iterator<BundleRevision> iCandidates = candidates.iterator(); iCandidates.hasNext();) {
+ BundleDescription candDesc = (BundleDescription) iCandidates.next();
+ ModuleRevision candRevision = (ModuleRevision) candDesc.getUserObject();
+ if (candRevision.getWiring() == null) {
+ iCandidates.remove();
+ }
+ }
+ }
+
+ @Override
+ public void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates) {
+ String namespace = requirement.getNamespace();
+ BundleDescription reqDesc = (BundleDescription) requirement.getRevision();
+ ModuleRevision reqRevision = (ModuleRevision) reqDesc.getUserObject();
+ ModuleWiring reqWiring = reqRevision.getWiring();
+ if (reqWiring == null) {
+ candidates.clear();
+ return;
+ }
+ Collection<ModuleWiring> wirings = new ArrayList<ModuleWiring>(1);
+ if ((reqRevision.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
+ if (ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE.equals(namespace) || HostNamespace.HOST_NAMESPACE.equals(namespace)) {
+ wirings.add(reqWiring);
+ } else {
+ List<ModuleWire> hostWires = reqWiring.getRequiredModuleWires(namespace);
+ for (ModuleWire hostWire : hostWires) {
+ ModuleWiring hostWiring = hostWire.getProviderWiring();
+ if (hostWiring != null) {
+ wirings.add(hostWiring);
+ }
+ }
+ }
+ } else {
+ wirings.add(reqWiring);
+ }
+ for (Iterator<BundleCapability> iCandidates = candidates.iterator(); iCandidates.hasNext();) {
+ BaseCapability baseCapability = (BaseCapability) iCandidates.next();
+ Object userObject = baseCapability.getBaseDescription().getUserObject();
+ boolean foundCandidate = false;
+ wirings: for (ModuleWiring wiring : wirings) {
+ List<ModuleWire> wires = wiring.getRequiredModuleWires(namespace);
+ for (ModuleWire wire : wires) {
+ if (userObject instanceof ModuleRevision && userObject.equals(wire.getProvider())) {
+ foundCandidate = true;
+ } else if (userObject instanceof ModuleCapability && userObject.equals(wire.getCapability())) {
+ foundCandidate = true;
+ }
+ if (foundCandidate)
+ break wirings;
+ }
+ }
+ if (!foundCandidate) {
+ iCandidates.remove();
+ }
+ }
+ }
+
+ @Override
+ public void end() {
+ // nothing
+ }
+ };
+ }
+
+}
diff --git a/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/StateConverter.java b/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/StateConverter.java
index 7c6754e7d..dbf45aba4 100644
--- a/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/StateConverter.java
+++ b/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/compatibility/state/StateConverter.java
@@ -1,3 +1,12 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
package org.eclipse.osgi.compatibility.state;
import java.util.*;
@@ -68,7 +77,7 @@ class StateConverter {
}
}
- BundleDescription result = state.getFactory().createBundleDescription(resource.getBundle().getBundleId(), symbolicNameSpecification, version, null, requireBundles.toArray(new BundleSpecification[requireBundles.size()]), fragmentHost.size() == 0 ? null : fragmentHost.get(0), importPackages.toArray(new ImportPackageSpecification[importPackages.size()]), exportPackages.toArray(new ExportPackageDescription[exportPackages.size()]), null, null, requireCapabilities.toArray(new GenericSpecification[requireCapabilities.size()]), provideCapabilities.toArray(new GenericDescription[provideCapabilities.size()]), null);
+ BundleDescription result = state.getFactory().createBundleDescription(resource.getBundle().getBundleId(), symbolicNameSpecification, version, resource.getBundle().getLocation(), requireBundles.toArray(new BundleSpecification[requireBundles.size()]), fragmentHost.size() == 0 ? null : fragmentHost.get(0), importPackages.toArray(new ImportPackageSpecification[importPackages.size()]), exportPackages.toArray(new ExportPackageDescription[exportPackages.size()]), null, null, requireCapabilities.toArray(new GenericSpecification[requireCapabilities.size()]), provideCapabilities.toArray(new GenericDescription[provideCapabilities.size()]), null);
result.setUserObject(resource);
GenericDescription[] genericDescs = result.getGenericCapabilities();
for (GenericDescription genericDesc : genericDescs) {
@@ -85,7 +94,7 @@ class StateConverter {
String packageName = (String) attributes.remove(PackageNamespace.PACKAGE_NAMESPACE);
// remove invalid attributes
attributes.remove(PackageNamespace.CAPABILITY_BUNDLE_SYMBOLICNAME_ATTRIBUTE);
- attributes.remove(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+ attributes.remove(AbstractWiringNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
String declaration = packageName + toString(attributes, "=", true) + toString(directives, ":=", true); //$NON-NLS-1$//$NON-NLS-2$
List<ExportPackageDescription> result = state.getFactory().createExportPackageDescriptions(declaration);
for (ExportPackageDescription export : result) {
diff --git a/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java b/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java
index 60d3f2b30..3abcdfdb6 100644
--- a/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java
+++ b/bundles/org.eclipse.osgi.compatibility.state/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2011 IBM Corporation and others.
+ * Copyright (c) 2004, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -114,7 +114,7 @@ public abstract class BaseDescriptionImpl implements BaseDescription {
this.userObject = userObject;
}
- class BaseCapability implements BundleCapability {
+ public class BaseCapability implements BundleCapability {
private final String namespace;
public BaseCapability(String namespace) {
@@ -151,7 +151,7 @@ public abstract class BaseDescriptionImpl implements BaseDescription {
return System.identityHashCode(BaseDescriptionImpl.this);
}
- protected BaseDescriptionImpl getBaseDescription() {
+ public BaseDescriptionImpl getBaseDescription() {
return BaseDescriptionImpl.this;
}

Back to the top