Fixes for bundle adapters. Added missing methods to DAB.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@910568 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
index a4004a5..4b07c24 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
@@ -23,6 +23,7 @@
import org.apache.felix.dm.dependencies.BundleDependency;
import org.apache.felix.dm.dependencies.ConfigurationDependency;
+import org.apache.felix.dm.dependencies.ResourceDependency;
import org.apache.felix.dm.dependencies.ServiceDependency;
import org.apache.felix.dm.dependencies.TemporalServiceDependency;
import org.apache.felix.dm.impl.Logger;
@@ -142,10 +143,26 @@
public BundleDependency createBundleDependency() {
return m_manager.createBundleDependency();
}
+
+ public ResourceDependency createResourceDependency() {
+ return m_manager.createResourceDependency();
+ }
public Service createAspectService(Class serviceInterface, String serviceFilter, Object aspectImplementation, Dictionary properties) {
return m_manager.createAspectService(serviceInterface, serviceFilter, aspectImplementation, properties);
}
+
+ public Service createAdapterService(Class serviceInterface, String serviceFilter, Class adapterInterface, Object adapterImplementation, Dictionary adapterProperties) {
+ return m_manager.createAdapterService(serviceInterface, serviceFilter, adapterInterface, adapterImplementation, adapterProperties);
+ }
+
+ public Service createResourceAdapter(String resourceFilter, Class adapterInterface, Dictionary adapterProperties, Object adapterImplementation, boolean propagate) {
+ return m_manager.createResourceAdapterService(resourceFilter, adapterInterface, adapterProperties, adapterImplementation, propagate);
+ }
+
+ public Service createBundleAdapterService(int bundleStateMask, String bundleFilter, Object adapterImplementation, String adapterInterface, Dictionary adapterProperties, boolean propagate) {
+ return m_manager.createBundleAdapterService(bundleStateMask, bundleFilter, adapterImplementation, adapterInterface, adapterProperties, propagate);
+ }
/**
* Cleans up all services and their dependencies.
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
index b5e1868..f608e16 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
@@ -186,7 +186,7 @@
* It will also inherit all dependencies, and if you declare the original
* service as a member it will be injected.
*
- * @param serviceInterface the service interface to apply the aspect to
+ * @param serviceInterface the service interface to apply the adapter to
* @param serviceFilter the filter condition to use with the service interface
* @param adapterInterface the interface to use when registering adapters
* @param adapterImplementation the implementation of the adapter
@@ -244,11 +244,13 @@
* @param bundleFilter the filter to apply to the bundle manifest
* @param adapterImplementation the implementation of the adapter
* @param adapterInterface the interface to use when registering adapters
+ * @param adapterProperties additional properties to use with the service registration
+ * @param propagate <code>true</code> if properties from the bundle should be propagated to the service
* @return a service that acts as a factory for generating bundle adapters
*/
- public Service createBundleAdapterService(int bundleStateMask, String bundleFilter, Object adapterImplementation, Class adapterInterface) {
+ public Service createBundleAdapterService(int bundleStateMask, String bundleFilter, Object adapterImplementation, String adapterInterface, Dictionary adapterProperties, boolean propagate) {
return createService()
- .setImplementation(new BundleAdapterImpl(bundleStateMask, bundleFilter, adapterImplementation, adapterInterface))
+ .setImplementation(new BundleAdapterImpl(bundleStateMask, bundleFilter, adapterImplementation, adapterInterface, adapterProperties, propagate))
.add(createBundleDependency()
.setFilter(bundleFilter)
.setStateMask(bundleStateMask)
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/BundleDependency.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/BundleDependency.java
index 3466606..87474b6 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/BundleDependency.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/dependencies/BundleDependency.java
@@ -75,4 +75,6 @@
BundleDependency setFilter(String filter) throws IllegalArgumentException;
BundleDependency setStateMask(int mask);
+
+ BundleDependency setPropagate(boolean propagate);
}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
index 218d2e7..7cf3478 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
@@ -25,6 +25,7 @@
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.resources.Resource;
import org.apache.felix.dm.service.Service;
+import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
public abstract class AbstractDecorator {
@@ -69,6 +70,24 @@
}
}
+ // callbacks for bundles
+ public void added(Bundle bundle) {
+ Service newService = createService(new Object[] { bundle });
+ m_services.put(bundle, newService);
+ m_manager.add(newService);
+ }
+
+ public void removed(Bundle bundle) {
+ Service newService = (Service) m_services.remove(bundle);
+ if (newService == null) {
+ System.out.println("Service should not be null here, dumping stack.");
+ Thread.dumpStack();
+ }
+ else {
+ m_manager.remove(newService);
+ }
+ }
+
public void stop() {
Iterator i = m_services.values().iterator();
while (i.hasNext()) {
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/BundleAdapterImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/BundleAdapterImpl.java
index 6fc4897..2f9a9dc 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/BundleAdapterImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/BundleAdapterImpl.java
@@ -18,36 +18,80 @@
*/
package org.apache.felix.dm.impl;
-import org.apache.felix.dm.DependencyManager;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.dm.service.Service;
import org.osgi.framework.Bundle;
-public class BundleAdapterImpl {
- private final int m_stateMask;
- private final String m_filter;
- private final Object m_impl;
- private volatile DependencyManager m_manager;
- private final Class m_iface;
+public class BundleAdapterImpl extends AbstractDecorator {
+ private volatile Service m_service;
+ private final String m_resourceFilter;
+ private final Object m_adapterImplementation;
+ private final Object m_adapterInterface;
+ private final Dictionary m_adapterProperties;
+ private final boolean m_propagate;
+ private final int m_bundleStateMask;
- public BundleAdapterImpl(int stateMask, String filter, Object impl, Class iface) {
- m_stateMask = stateMask;
- m_filter = filter;
- m_impl = impl;
- m_iface = iface;
- }
+ public BundleAdapterImpl(int bundleStateMask, String bundleFilter, Object adapterImplementation, String adapterInterface, Dictionary adapterProperties, boolean propagate) {
+ m_bundleStateMask = bundleStateMask;
+ m_resourceFilter = bundleFilter;
+ m_adapterImplementation = adapterImplementation;
+ m_adapterInterface = adapterInterface;
+ m_adapterProperties = adapterProperties;
+ m_propagate = propagate;
+ }
+
+ public BundleAdapterImpl(int bundleStateMask, String bundleFilter, Object adapterImplementation, String[] adapterInterfaces, Dictionary adapterProperties, boolean propagate) {
+ m_bundleStateMask = bundleStateMask;
+ m_resourceFilter = bundleFilter;
+ m_adapterImplementation = adapterImplementation;
+ m_adapterInterface = adapterInterfaces;
+ m_adapterProperties = adapterProperties;
+ m_propagate = propagate;
+ }
- public void added(Bundle bundle) {
- // TODO decorator be smarter:
- m_manager.add(m_manager.createService()
- .setInterface(m_iface.getName(), null)
- .setImplementation(m_impl)
- .add(m_manager.createBundleDependency()
- .setBundle(bundle)
- .setStateMask(m_stateMask)
- .setRequired(true)
- )
- );
- }
-
- public void removed(Bundle bundle) {
+ public Service createService(Object[] properties) {
+ Bundle bundle = (Bundle) properties[0];
+ Properties props = new Properties();
+ if (m_adapterProperties != null) {
+ Enumeration e = m_adapterProperties.keys();
+ while (e.hasMoreElements()) {
+ Object key = e.nextElement();
+ props.put(key, m_adapterProperties.get(key));
+ }
+ }
+ List dependencies = m_service.getDependencies();
+ // the first dependency is always the dependency on the bundle, which
+ // will be replaced with a more specific dependency below
+ dependencies.remove(0);
+ if (m_adapterInterface instanceof String) {
+ return m_manager.createService()
+ .setInterface((String) m_adapterInterface, props)
+ .setImplementation(m_adapterImplementation)
+ .add(dependencies)
+ .add(m_manager.createBundleDependency()
+ .setBundle(bundle)
+ .setPropagate(m_propagate)
+ .setCallbacks(null, "changed", null)
+ .setAutoConfig(true)
+ .setRequired(true)
+ );
+ }
+ else {
+ return m_manager.createService()
+ .setInterface((String[]) m_adapterInterface, props)
+ .setImplementation(m_adapterImplementation)
+ .add(dependencies)
+ .add(m_manager.createBundleDependency()
+ .setBundle(bundle)
+ .setPropagate(m_propagate)
+ .setCallbacks(null, "changed", null)
+ .setAutoConfig(true)
+ .setRequired(true)
+ );
+ }
}
}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java
index ab748a7..8bb09b9 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/BundleDependencyImpl.java
@@ -18,11 +18,13 @@
*/
package org.apache.felix.dm.impl.dependencies;
+import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.List;
import org.apache.felix.dm.dependencies.BundleDependency;
+import org.apache.felix.dm.impl.DefaultNullObject;
import org.apache.felix.dm.impl.Logger;
import org.apache.felix.dm.impl.tracker.BundleTracker;
import org.apache.felix.dm.impl.tracker.BundleTrackerCustomizer;
@@ -49,6 +51,11 @@
private Bundle m_bundleInstance;
private Filter m_filter;
private long m_bundleId = -1;
+ private boolean m_propagate;
+ private String m_autoConfigInstance;
+ private Object m_nullObject;
+ private boolean m_autoConfigInvoked;
+
public BundleDependencyImpl(BundleContext context, Logger logger) {
super(logger);
@@ -297,7 +304,7 @@
public synchronized BundleDependency setCallbacks(Object instance, String added, String changed, String removed) {
ensureNotActive();
// if at least one valid callback is specified, we turn off auto configuration
- if (added != null || removed != null || changed != null) {
+ if ((added != null || removed != null || changed != null) && ! m_autoConfigInvoked) {
setAutoConfig(false);
}
m_callbackInstance = instance;
@@ -315,6 +322,15 @@
public synchronized BundleDependency setAutoConfig(boolean autoConfig) {
ensureNotActive();
m_autoConfig = autoConfig;
+ m_autoConfigInvoked = true;
+ return this;
+ }
+
+ public synchronized BundleDependency setAutoConfig(String instanceName) {
+ ensureNotActive();
+ m_autoConfig = (instanceName != null);
+ m_autoConfigInstance = instanceName;
+ m_autoConfigInvoked = true;
return this;
}
@@ -323,7 +339,13 @@
setIsRequired(required);
return this;
}
-
+
+ public BundleDependency setPropagate(boolean propagate) {
+ ensureNotActive();
+ m_propagate = propagate;
+ return this;
+ }
+
public BundleDependency setBundle(Bundle bundle) {
m_bundleId = bundle.getBundleId();
return this;
@@ -359,18 +381,53 @@
}
public Object getAutoConfigInstance() {
- // TODO Auto-generated method stub
- return null;
+ return lookupBundle();
}
+ public Object lookupBundle() {
+ Object service = null;
+ if (m_isStarted) {
+ service = getBundle();
+ }
+ else {
+ Bundle[] bundles = m_context.getBundles();
+ for (int i = 0; i < bundles.length; i++) {
+ if ((bundles[i].getState() & m_stateMask) > 0) {
+ if (m_filter.match(bundles[i].getHeaders())) {
+ service = bundles[i];
+ break;
+ }
+ }
+ }
+ }
+ if (service == null && isAutoConfig()) {
+ // TODO does it make sense to add support for custom bundle impls?
+// service = getDefaultImplementation();
+ if (service == null) {
+ service = getNullObject();
+ }
+ }
+ return service;
+ }
+
+ private Object getNullObject() {
+ if (m_nullObject == null) {
+ try {
+ m_nullObject = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { Bundle.class }, new DefaultNullObject());
+ }
+ catch (Exception e) {
+ m_logger.log(Logger.LOG_ERROR, "Could not create null object for Bundle.", e);
+ }
+ }
+ return m_nullObject;
+ }
+
public String getAutoConfigName() {
- // TODO Auto-generated method stub
- return null;
+ return m_autoConfigInstance;
}
public Class getAutoConfigType() {
- // TODO Auto-generated method stub
- return null;
+ return Bundle.class;
}
public void invokeAdded(DependencyService service) {
@@ -396,7 +453,6 @@
}
public boolean isPropagated() {
- // TODO Auto-generated method stub
- return false;
+ return m_propagate;
}
}