mirror of https://github.com/apache/activemq.git
parent
f0cb95c792
commit
97cd60fb7e
|
@ -16,14 +16,18 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.activemq.util.osgi;
|
package org.apache.activemq.util.osgi;
|
||||||
|
|
||||||
|
import static org.osgi.framework.wiring.BundleRevision.PACKAGE_NAMESPACE;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
@ -38,6 +42,9 @@ import org.osgi.framework.BundleActivator;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
import org.osgi.framework.BundleEvent;
|
import org.osgi.framework.BundleEvent;
|
||||||
import org.osgi.framework.SynchronousBundleListener;
|
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.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
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 static final Logger LOG = LoggerFactory.getLogger(Activator.class);
|
||||||
|
|
||||||
private final ConcurrentMap<String, Class> serviceCache = new ConcurrentHashMap<String, Class>();
|
private final ConcurrentMap<String, Class<?>> serviceCache = new ConcurrentHashMap<String, Class<?>>();
|
||||||
private final ConcurrentMap<Long, BundleWrapper> bundleWrappers = new ConcurrentHashMap<Long, BundleWrapper>();
|
private final ConcurrentMap<Long, BundleWrapper> bundleWrappers = new ConcurrentHashMap<Long, BundleWrapper>();
|
||||||
private BundleContext bundleContext;
|
private BundleContext bundleContext;
|
||||||
|
private Set<BundleCapability> packageCapabilities = new HashSet<BundleCapability>();
|
||||||
|
|
||||||
// ================================================================
|
// ================================================================
|
||||||
// BundleActivator interface impl
|
// BundleActivator interface impl
|
||||||
|
@ -67,6 +75,9 @@ public class Activator implements BundleActivator, SynchronousBundleListener, Ob
|
||||||
|
|
||||||
debug("activating");
|
debug("activating");
|
||||||
this.bundleContext = bundleContext;
|
this.bundleContext = bundleContext;
|
||||||
|
|
||||||
|
cachePackageCapabilities(Service.class, Transport.class, DiscoveryAgent.class, PersistenceAdapter.class);
|
||||||
|
|
||||||
debug("checking existing bundles");
|
debug("checking existing bundles");
|
||||||
bundleContext.addBundleListener(this);
|
bundleContext.addBundleListener(this);
|
||||||
for (Bundle bundle : bundleContext.getBundles()) {
|
for (Bundle bundle : bundleContext.getBundles()) {
|
||||||
|
@ -78,6 +89,27 @@ public class Activator implements BundleActivator, SynchronousBundleListener, Ob
|
||||||
debug("activated");
|
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<String> packageNames = new HashSet<String>();
|
||||||
|
for (Class<?> clazz: classes) {
|
||||||
|
packageNames.add(clazz.getPackage().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<BundleCapability> 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
|
@Override
|
||||||
public synchronized void stop(BundleContext bundleContext) throws Exception {
|
public synchronized void stop(BundleContext bundleContext) throws Exception {
|
||||||
|
@ -105,12 +137,15 @@ public class Activator implements BundleActivator, SynchronousBundleListener, Ob
|
||||||
|
|
||||||
protected void register(final Bundle bundle) {
|
protected void register(final Bundle bundle) {
|
||||||
debug("checking bundle " + bundle.getBundleId());
|
debug("checking bundle " + bundle.getBundleId());
|
||||||
if( !isImportingUs(bundle) ) {
|
if (isOurBundle(bundle) || isImportingUs(bundle) ) {
|
||||||
debug("The bundle does not import us: "+ bundle.getBundleId());
|
debug("Registering bundle for extension resolution: "+ bundle.getBundleId());
|
||||||
return;
|
|
||||||
}
|
|
||||||
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();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When bundles unload.. we remove them thier cached Class entries from the
|
* When bundles unload.. we remove them thier cached Class entries from the
|
||||||
|
@ -137,7 +172,7 @@ public class Activator implements BundleActivator, SynchronousBundleListener, Ob
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object create(String path) throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException {
|
public Object create(String path) throws IllegalAccessException, InstantiationException, IOException, ClassNotFoundException {
|
||||||
Class clazz = serviceCache.get(path);
|
Class<?> clazz = serviceCache.get(path);
|
||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
StringBuffer warnings = new StringBuffer();
|
StringBuffer warnings = new StringBuffer();
|
||||||
// We need to look for a bundle that has that class.
|
// We need to look for a bundle that has that class.
|
||||||
|
@ -205,20 +240,23 @@ 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) {
|
private boolean isImportingUs(Bundle bundle) {
|
||||||
return isImportingClass(bundle, Service.class)
|
BundleWiring wiring = bundle.adapt(BundleWiring.class);
|
||||||
|| isImportingClass(bundle, Transport.class)
|
List<BundleWire> imports = wiring.getRequiredWires(PACKAGE_NAMESPACE);
|
||||||
|| isImportingClass(bundle, DiscoveryAgent.class)
|
for (BundleWire importWire : imports) {
|
||||||
|| isImportingClass(bundle, PersistenceAdapter.class);
|
if (packageCapabilities.contains(importWire.getCapability())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isImportingClass(Bundle bundle, Class clazz) {
|
|
||||||
try {
|
|
||||||
return bundle.loadClass(clazz.getName())==clazz;
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private static class BundleWrapper {
|
private static class BundleWrapper {
|
||||||
private final Bundle bundle;
|
private final Bundle bundle;
|
||||||
|
|
Loading…
Reference in New Issue