aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRené Brandstetter2013-10-24 14:34:00 (EDT)
committerLars Vogel2014-03-19 19:35:37 (EDT)
commit02523c9397a80075c73124b6f488cd2e07322166 (patch)
treebf9d4d3fd8e8b9146559bc1f0f3545765ffc1c44
parent4c6cc509ff49a98ed3f7dabdbe1b06c635576d71 (diff)
downloadeclipse.platform.ui-02523c9397a80075c73124b6f488cd2e07322166.zip
eclipse.platform.ui-02523c9397a80075c73124b6f488cd2e07322166.tar.gz
eclipse.platform.ui-02523c9397a80075c73124b6f488cd2e07322166.tar.bz2
Bug 419749 – [e4 Workbench] - Remove the deprecated PackageAdminrefs/changes/72/17772/10
Remove of the deprecated PackageAdmin from the "org.eclipse.e4.ui.workbench" bundle. The relevant changes are: - fragment detection with BundleRevision - bundle lookup by symbolic name via BundleTracker - topoSort dependency resolving via BundleWiring Change-Id: Ic127de678b2fc726b7a3fd9ca97fafb109fb0bfb Signed-off-by: René Brandstetter <Rene.Brandstetter@gmx.net>
-rw-r--r--bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Activator.java76
-rw-r--r--bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/BundleFinder.java122
-rw-r--r--bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java76
-rw-r--r--bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/URIHelper.java10
4 files changed, 234 insertions, 50 deletions
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Activator.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Activator.java
index 9d54b31..4861b3a 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Activator.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/Activator.java
@@ -7,9 +7,11 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * René Brandstetter - Bug 419749 - [Workbench] [e4 Workbench] - Remove the deprecated PackageAdmin
******************************************************************************/
package org.eclipse.e4.ui.internal.workbench;
+import java.util.List;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.eclipse.osgi.service.debug.DebugTrace;
@@ -20,9 +22,12 @@ import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
-import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.util.tracker.BundleTracker;
import org.osgi.util.tracker.ServiceTracker;
+/**
+ * BundleActivator to access the required OSGi services.
+ */
public class Activator implements BundleActivator {
/**
* The bundle symbolic name.
@@ -32,11 +37,16 @@ public class Activator implements BundleActivator {
private static Activator activator;
private BundleContext context;
- private ServiceTracker locationTracker;
- private ServiceTracker pkgAdminTracker;
+ private ServiceTracker<Location, Location> locationTracker;
- private ServiceTracker debugTracker;
- private ServiceTracker logTracker;
+ private ServiceTracker<DebugOptions, DebugOptions> debugTracker;
+ private ServiceTracker<LogService, LogService> logTracker;
+
+ /** Tracks all bundles which are in the state: RESOLVED, STARTING, ACTIVE or STOPPING. */
+ private BundleTracker<List<Bundle>> resolvedBundles;
+
+ /** A BundleTrackerCustomizer which is able to resolve a bundle to the a symbolic name. */
+ private final BundleFinder bundleFinder = new BundleFinder();
private DebugTrace trace;
@@ -57,34 +67,12 @@ public class Activator implements BundleActivator {
}
/**
- * @return the PackageAdmin service from this bundle
- */
- public PackageAdmin getBundleAdmin() {
- if (pkgAdminTracker == null) {
- if (context == null)
- return null;
- pkgAdminTracker = new ServiceTracker(context, PackageAdmin.class.getName(), null);
- pkgAdminTracker.open();
- }
- return (PackageAdmin) pkgAdminTracker.getService();
- }
-
- /**
* @param bundleName
- * the bundle id
+ * the bundle symbolic name
* @return A bundle if found, or <code>null</code>
*/
public Bundle getBundleForName(String bundleName) {
- Bundle[] bundles = getBundleAdmin().getBundles(bundleName, null);
- if (bundles == null)
- return null;
- // Return the first bundle that is not installed or uninstalled
- for (int i = 0; i < bundles.length; i++) {
- if ((bundles[i].getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0) {
- return bundles[i];
- }
- }
- return null;
+ return bundleFinder.findBundle(bundleName);
}
/**
@@ -106,22 +94,23 @@ public class Activator implements BundleActivator {
// ignore this. It should never happen as we have tested the
// above format.
}
- locationTracker = new ServiceTracker(context, filter, null);
+ locationTracker = new ServiceTracker<Location, Location>(context, filter, null);
locationTracker.open();
}
- return (Location) locationTracker.getService();
+ return locationTracker.getService();
}
public void start(BundleContext context) throws Exception {
activator = this;
this.context = context;
+
+ // track required bundles
+ resolvedBundles = new BundleTracker<List<Bundle>>(context, Bundle.RESOLVED
+ | Bundle.STARTING | Bundle.ACTIVE | Bundle.STOPPING, bundleFinder);
+ resolvedBundles.open();
}
public void stop(BundleContext context) throws Exception {
- if (pkgAdminTracker != null) {
- pkgAdminTracker.close();
- pkgAdminTracker = null;
- }
if (locationTracker != null) {
locationTracker.close();
locationTracker = null;
@@ -135,16 +124,22 @@ public class Activator implements BundleActivator {
logTracker.close();
logTracker = null;
}
+ if (resolvedBundles != null) {
+ // the close of the BundleTracker will also remove all entries form the BundleFinder
+ resolvedBundles.close();
+ resolvedBundles = null;
+ }
}
public DebugOptions getDebugOptions() {
if (debugTracker == null) {
if (context == null)
return null;
- debugTracker = new ServiceTracker(context, DebugOptions.class.getName(), null);
+ debugTracker = new ServiceTracker<DebugOptions, DebugOptions>(context,
+ DebugOptions.class.getName(), null);
debugTracker.open();
}
- return (DebugOptions) debugTracker.getService();
+ return debugTracker.getService();
}
public DebugTrace getTrace() {
@@ -169,12 +164,13 @@ public class Activator implements BundleActivator {
public LogService getLogService() {
LogService logService = null;
if (logTracker != null) {
- logService = (LogService) logTracker.getService();
+ logService = logTracker.getService();
} else {
if (context != null) {
- logTracker = new ServiceTracker(context, LogService.class.getName(), null);
+ logTracker = new ServiceTracker<LogService, LogService>(context,
+ LogService.class.getName(), null);
logTracker.open();
- logService = (LogService) logTracker.getService();
+ logService = logTracker.getService();
}
}
if (logService == null) {
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/BundleFinder.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/BundleFinder.java
new file mode 100644
index 0000000..10d724d
--- /dev/null
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/BundleFinder.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * 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
+ * René Brandstetter - Bug 419749 - [Workbench] [e4 Workbench] - Remove the deprecated PackageAdmin
+ ******************************************************************************/
+
+package org.eclipse.e4.ui.internal.workbench;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+
+/**
+ * A simple {@link BundleTrackerCustomizer} which is able to resolve a bundle by its symbolic name.
+ */
+/*
+ * TODO: This implementation can probably be removed after a switch to OSGi 6 which will have the
+ * possibility to lookup bundles with the FrameworkWiring#findProviders(Requirement) method.
+ */
+final class BundleFinder implements BundleTrackerCustomizer<List<Bundle>> {
+
+ /** Map of bundle symbolic name to the corresponding bundles (hint: different versions). */
+ private final ConcurrentMap<String, List<Bundle>> trackedBundles = new ConcurrentHashMap<String, List<Bundle>>();
+
+ /**
+ * Resolves the latest bundle with the given bundle symbolic name.
+ * <p>
+ * The latest means the bundle with the highest version.
+ * </p>
+ * @param symbolicName
+ * the bundle symbolic name
+ * @return the latest bundle with the given bundle symbolic name
+ */
+ public Bundle findBundle(String symbolicName) {
+ List<Bundle> bundlesWithSameSymName = trackedBundles.get(symbolicName);
+ if (bundlesWithSameSymName == null)
+ return null;
+
+ List<Bundle> snapshot = new ArrayList<Bundle>(bundlesWithSameSymName);
+
+ switch (snapshot.size()) {
+ case 0:
+ return null;
+ case 1:
+ return snapshot.get(0);
+ default:
+ Collections.sort(snapshot, VersionComperator.INSTANCE); // sort the snapshot by version
+ return snapshot.get(0); // the highest is the first entry in the list
+ }
+ }
+
+ @Override
+ public List<Bundle> addingBundle(Bundle bundle, BundleEvent event) {
+ String bundleSymName = bundle.getSymbolicName();
+
+ List<Bundle> bundlesWithSameSymName = trackedBundles.get(bundleSymName);
+ if (bundlesWithSameSymName == null) {
+ bundlesWithSameSymName = new CopyOnWriteArrayList<Bundle>();
+
+ if (trackedBundles.putIfAbsent(bundleSymName, bundlesWithSameSymName) != null) {
+ // some other thread has won the race, so we use his List object
+ bundlesWithSameSymName = trackedBundles.get(bundleSymName);
+ }
+ }
+
+ bundlesWithSameSymName.add(bundle);
+
+ // return the list to mark that we want to be informed about other changes of the bundle and
+ // to remove the bundle in the #removedBundle() method without a lookup in the
+ // #trackedBundles map
+ return bundlesWithSameSymName;
+ }
+
+ @Override
+ public void modifiedBundle(Bundle bundle, BundleEvent event, List<Bundle> bundlesWithSameSymName) {
+ // not of interest
+ }
+
+ @Override
+ public void removedBundle(Bundle bundle, BundleEvent event, List<Bundle> bundlesWithSameSymName) {
+ // the object is the list which was returned inside the #addingBundle() method and so we
+ // don't need a lookup in the #trackedBundles to find the list
+ bundlesWithSameSymName.remove(bundle);
+ }
+
+ /**
+ * A simple {@link Comparator} which orders the bundles by their version in ascending order.
+ */
+ private static final class VersionComperator implements Comparator<Bundle> {
+ /** A Singleton instance of this {@link Comparator} (the compare is done state-less). */
+ public static final Comparator<Bundle> INSTANCE = new VersionComperator();
+
+ private VersionComperator() {
+ }
+
+ @Override
+ public int compare(Bundle bundle1, Bundle bundle2) {
+ if (bundle1 == null) {
+ return bundle2 == null ? 0 : 1; // null elements at the end of the list
+ }
+
+ if (bundle2 == null) {
+ return -1; // null elements at the end of the list
+ }
+
+ return bundle2.getVersion().compareTo(bundle1.getVersion()); // newest version first
+ }
+ }
+}
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
index 99c661a..6720b96 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/ModelAssembler.java
@@ -8,6 +8,7 @@
* Contributors:
* Tom Schindl<tom.schindl@bestsolution.at> - initial API and implementation
* Lars Vogel <Lars.Vogel@gmail.com> - Bug 430075, 430080
+ * René Brandstetter - Bug 419749 - [Workbench] [e4 Workbench] - Remove the deprecated PackageAdmin
******************************************************************************/
package org.eclipse.e4.ui.internal.workbench;
@@ -20,6 +21,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.inject.Inject;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IContributor;
@@ -47,8 +49,9 @@ import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EContentsEList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.osgi.framework.Bundle;
-import org.osgi.service.packageadmin.PackageAdmin;
-import org.osgi.service.packageadmin.RequiredBundle;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
/**
*
@@ -204,7 +207,7 @@ public class ModelAssembler {
/**
* @param extensions
- * @param b
+ * @param afterFragments
*/
private void runProcessors(IExtension[] extensions, Boolean afterFragments) {
for (IExtension extension : extensions) {
@@ -335,7 +338,6 @@ public class ModelAssembler {
return extensions;
}
- PackageAdmin admin = Activator.getDefault().getBundleAdmin();
final Map<String, Collection<IExtension>> mappedExtensions = new HashMap<String, Collection<IExtension>>();
// Captures the bundles that are listed as requirements for a particular bundle.
final Map<String, Collection<String>> requires = new HashMap<String, Collection<String>>();
@@ -376,9 +378,13 @@ public class ModelAssembler {
// now populate the dependency graph
for (String bundleId : mappedExtensions.keySet()) {
assert requires.containsKey(bundleId) && depends.containsKey(bundleId);
- for (RequiredBundle requiredBundle : admin.getRequiredBundles(bundleId)) {
+
+ // can only be one, because ExtensionPoints require the singleton setting
+ // on a bundle
+ Bundle requiredBundle = Activator.getDefault().getBundleForName(bundleId);
+ if (requiredBundle != null) {
assert requiredBundle.getSymbolicName().equals(bundleId);
- for (Bundle dependentBundle : requiredBundle.getRequiringBundles()) {
+ for (Bundle dependentBundle : resolveRequiringBundle(requiredBundle)) {
if (!mappedExtensions.containsKey(dependentBundle.getSymbolicName())) {
// not a contributor of an extension
continue;
@@ -432,6 +438,64 @@ public class ModelAssembler {
return extensions;
}
+ /**
+ * Returns the bundles that currently require the given bundle.
+ * <p>
+ * If this required bundle is required and then re-exported by another bundle then all the
+ * requiring bundles of the re-exporting bundle are included in the returned array.
+ * </p>
+ * @return An unmodifiable {@link Iterable} set of bundles currently requiring this required
+ * bundle. An empty {@link Iterable} will be returned if the given {@code Bundle} object
+ * has become stale or no bundles require the given bundle.
+ * @throws NullPointerException
+ * if the given bundle is <code>null</code>
+ */
+ private static Iterable<Bundle> resolveRequiringBundle(Bundle bundle) {
+ BundleWiring providerWiring = bundle.adapt(BundleWiring.class);
+ if (!providerWiring.isInUse()) {
+ return Collections.emptySet();
+ }
+
+ Set<Bundle> requiring = new HashSet<Bundle>();
+
+ addRequirers(requiring, providerWiring);
+ return Collections.unmodifiableSet(requiring);
+ }
+
+ /**
+ * Recursively collects all bundles which depend-on/require the given {@link BundleWiring}.
+ * <p>
+ * All re-exports will be followed and also be contained in the result.
+ * </p>
+ * @param requiring
+ * the result which will contain all the bundles which require the given
+ * {@link BundleWiring}
+ * @param providerWiring
+ * the {@link BundleWiring} for which the requirers should be resolved
+ * @throws NullPointerException
+ * if either the requiring or the providerWiring is <code>null</code>
+ */
+ private static void addRequirers(Set<Bundle> requiring, BundleWiring providerWiring) {
+ List<BundleWire> requirerWires = providerWiring
+ .getProvidedWires(BundleNamespace.BUNDLE_NAMESPACE);
+ if (requirerWires == null) {
+ // we don't hold locks while checking the graph, just return if no longer isInUse
+ return;
+ }
+ for (BundleWire requireBundleWire : requirerWires) {
+ Bundle requirer = requireBundleWire.getRequirer().getBundle();
+ if (requiring.contains(requirer)) {
+ continue;
+ }
+ requiring.add(requirer);
+ String reExport = requireBundleWire.getRequirement().getDirectives()
+ .get(BundleNamespace.REQUIREMENT_VISIBILITY_DIRECTIVE);
+ if (BundleNamespace.VISIBILITY_REEXPORT.equals(reExport)) {
+ addRequirers(requiring, requireBundleWire.getRequirerWiring());
+ }
+ }
+ }
+
// FIXME Should we not reuse ModelUtils???
private static MApplicationElement findElementById(MApplicationElement element, String id) {
if (id == null || id.length() == 0)
diff --git a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/URIHelper.java b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/URIHelper.java
index f8a9d86..e47daa0 100644
--- a/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/URIHelper.java
+++ b/bundles/org.eclipse.e4.ui.workbench/src/org/eclipse/e4/ui/internal/workbench/URIHelper.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * René Brandstetter - Bug 419749 - [Workbench] [e4 Workbench] - Remove the deprecated PackageAdmin
******************************************************************************/
package org.eclipse.e4.ui.internal.workbench;
@@ -16,8 +17,8 @@ import java.net.URISyntaxException;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.spi.RegistryContributor;
import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.BundleRevision;
import org.osgi.service.log.LogService;
-import org.osgi.service.packageadmin.PackageAdmin;
/**
* Collection of URI-related utilities
@@ -45,12 +46,13 @@ public class URIHelper {
final private static String FRAGMENT_SEGMENT = "fragment/"; //$NON-NLS-1$
static public String constructPlatformURI(Bundle bundle) {
- PackageAdmin packageAdmin = Activator.getDefault().getBundleAdmin();
- if (packageAdmin == null)
+ BundleRevision bundleRevision = bundle.adapt(BundleRevision.class);
+ if (bundleRevision == null)
return null;
+
StringBuffer tmp = new StringBuffer();
tmp.append(PLATFORM_SCHEMA);
- if ((packageAdmin.getBundleType(bundle) & PackageAdmin.BUNDLE_TYPE_FRAGMENT) > 0)
+ if ((bundleRevision.getTypes() & BundleRevision.TYPE_FRAGMENT) == BundleRevision.TYPE_FRAGMENT)
tmp.append(FRAGMENT_SEGMENT);
else
tmp.append(PLUGIN_SEGMENT);