diff --git a/activemq-broker/src/main/java/org/apache/activemq/util/osgi/Activator.java b/activemq-broker/src/main/java/org/apache/activemq/util/osgi/Activator.java index 9674ab482f..80a143157f 100644 --- a/activemq-broker/src/main/java/org/apache/activemq/util/osgi/Activator.java +++ b/activemq-broker/src/main/java/org/apache/activemq/util/osgi/Activator.java @@ -16,14 +16,18 @@ */ package org.apache.activemq.util.osgi; +import static org.osgi.framework.wiring.BundleRevision.PACKAGE_NAMESPACE; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Properties; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -38,6 +42,9 @@ import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleEvent; import org.osgi.framework.SynchronousBundleListener; +import org.osgi.framework.wiring.BundleCapability; +import org.osgi.framework.wiring.BundleWire; +import org.osgi.framework.wiring.BundleWiring; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,9 +57,10 @@ public class Activator implements BundleActivator, SynchronousBundleListener, Ob private static final Logger LOG = LoggerFactory.getLogger(Activator.class); - private final ConcurrentMap serviceCache = new ConcurrentHashMap(); + private final ConcurrentMap> serviceCache = new ConcurrentHashMap>(); private final ConcurrentMap bundleWrappers = new ConcurrentHashMap(); private BundleContext bundleContext; + private Set packageCapabilities = new HashSet(); // ================================================================ // BundleActivator interface impl @@ -67,6 +75,9 @@ public class Activator implements BundleActivator, SynchronousBundleListener, Ob debug("activating"); this.bundleContext = bundleContext; + + cachePackageCapabilities(Service.class, Transport.class, DiscoveryAgent.class, PersistenceAdapter.class); + debug("checking existing bundles"); bundleContext.addBundleListener(this); for (Bundle bundle : bundleContext.getBundles()) { @@ -78,6 +89,27 @@ public class Activator implements BundleActivator, SynchronousBundleListener, Ob debug("activated"); } + /** + * Caches the package capabilities that are needed for a set of interface classes + * + * @param classes interfaces we want to track + */ + private void cachePackageCapabilities(Class ... classes) { + BundleWiring ourWiring = bundleContext.getBundle().adapt(BundleWiring.class); + Set packageNames = new HashSet(); + for (Class clazz: classes) { + packageNames.add(clazz.getPackage().getName()); + } + + List ourExports = ourWiring.getCapabilities(PACKAGE_NAMESPACE); + for (BundleCapability ourExport : ourExports) { + String ourPkgName = (String) ourExport.getAttributes().get(PACKAGE_NAMESPACE); + if (packageNames.contains(ourPkgName)) { + packageCapabilities.add(ourExport); + } + } + } + @Override public synchronized void stop(BundleContext bundleContext) throws Exception { @@ -105,11 +137,14 @@ public class Activator implements BundleActivator, SynchronousBundleListener, Ob protected void register(final Bundle bundle) { debug("checking bundle " + bundle.getBundleId()); - if( !isImportingUs(bundle) ) { - debug("The bundle does not import us: "+ bundle.getBundleId()); - return; + if (isOurBundle(bundle) || isImportingUs(bundle) ) { + debug("Registering bundle for extension resolution: "+ bundle.getBundleId()); + bundleWrappers.put(bundle.getBundleId(), new BundleWrapper(bundle)); } - bundleWrappers.put(bundle.getBundleId(), new BundleWrapper(bundle)); + } + + private boolean isOurBundle(final Bundle bundle) { + return bundle.getBundleId() == bundleContext.getBundle().getBundleId(); } /** @@ -137,7 +172,7 @@ public class Activator implements BundleActivator, SynchronousBundleListener, Ob @Override public Object create(String path) throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException { - Class clazz = serviceCache.get(path); + Class clazz = serviceCache.get(path); if (clazz == null) { StringBuffer warnings = new StringBuffer(); // We need to look for a bundle that has that class. @@ -205,19 +240,22 @@ public class Activator implements BundleActivator, SynchronousBundleListener, Ob } } + /** + * We consider a bundle to be a candidate for objects if it imports at least + * one of the packages of our interfaces + * + * @param bundle + * @return + */ private boolean isImportingUs(Bundle bundle) { - return isImportingClass(bundle, Service.class) - || isImportingClass(bundle, Transport.class) - || isImportingClass(bundle, DiscoveryAgent.class) - || isImportingClass(bundle, PersistenceAdapter.class); - } - - private boolean isImportingClass(Bundle bundle, Class clazz) { - try { - return bundle.loadClass(clazz.getName())==clazz; - } catch (ClassNotFoundException e) { - return false; + BundleWiring wiring = bundle.adapt(BundleWiring.class); + List imports = wiring.getRequiredWires(PACKAGE_NAMESPACE); + for (BundleWire importWire : imports) { + if (packageCapabilities.contains(importWire.getCapability())) { + return true; + } } + return false; } private static class BundleWrapper {