Added a feature to use an external instance/method to provide properties to propagate. Implemented it for all dependencies plus the resource adapter. Other adapters still under consideration.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@963265 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 0584721..2e6b07d 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
@@ -161,6 +161,10 @@
return m_manager.createResourceAdapterService(resourceFilter, propagate, callbackInstance, callbackChanged);
}
+ public Service createResourceAdapter(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackChanged) {
+ return m_manager.createResourceAdapterService(resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, callbackChanged);
+ }
+
public Service createBundleAdapterService(int bundleStateMask, String bundleFilter, boolean propagate) {
return m_manager.createBundleAdapterService(bundleStateMask, bundleFilter, propagate);
}
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 6f78610..afcf517 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
@@ -238,6 +238,10 @@
return new ResourceAdapterServiceImpl(this, resourceFilter, propagate, callbackInstance, callbackChanged);
}
+ public Service createResourceAdapterService(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackChanged) {
+ return new ResourceAdapterServiceImpl(this, resourceFilter, propagateCallbackInstance, propagateCallbackMethod, callbackInstance, callbackChanged);
+ }
+
/**
* Creates a new bundle adapter. The adapter will be applied to any bundle that
* matches the specified bundle state mask and filter condition. For each matching
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java
index 333d66f..aa76552 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/ResourceDependency.java
@@ -102,5 +102,7 @@
public ResourceDependency setPropagate(boolean propagate);
+ public ResourceDependency setPropagate(Object instance, String method);
+
public ResourceDependency setInstanceBound(boolean isInstanceBound);
}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/InvocationUtil.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/InvocationUtil.java
index fba52fa..73a5bfb 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/InvocationUtil.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/InvocationUtil.java
@@ -6,12 +6,11 @@
import java.lang.reflect.Proxy;
public class InvocationUtil {
- public static void invokeCallbackMethod(Object instance, String methodName, Class[][] signatures, Object[][] parameters) throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+ public static Object invokeCallbackMethod(Object instance, String methodName, Class[][] signatures, Object[][] parameters) throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
Class currentClazz = instance.getClass();
while (currentClazz != null) {
try {
- invokeMethod(instance, currentClazz, methodName, signatures, parameters, false);
- return;
+ return invokeMethod(instance, currentClazz, methodName, signatures, parameters, false);
}
catch (NoSuchMethodException nsme) {
// ignore
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java
index 7406f44..1082317 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ResourceAdapterServiceImpl.java
@@ -25,6 +25,7 @@
import org.apache.felix.dm.Dependency;
import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ResourceDependency;
import org.apache.felix.dm.Service;
import org.apache.felix.dm.ServiceStateListener;
@@ -51,13 +52,36 @@
.setCallbacks("added", "removed"));
}
+ public ResourceAdapterServiceImpl(DependencyManager dm, String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod, Object callbackInstance, String callbackChanged) {
+ super(dm.createService()); // This service will be filtered by our super class, allowing us to take control.
+ m_callbackInstance = callbackInstance;
+ m_callbackChanged = callbackChanged;
+ m_service.setImplementation(new ResourceAdapterImpl(resourceFilter, propagateCallbackInstance, propagateCallbackMethod))
+ .add(dm.createResourceDependency()
+ .setFilter(resourceFilter)
+ .setAutoConfig(false)
+ .setCallbacks("added", "removed"));
+ }
+
public class ResourceAdapterImpl extends AbstractDecorator {
private final String m_resourceFilter;
private final boolean m_propagate;
+ private final Object m_propagateCallbackInstance;
+ private final String m_propagateCallbackMethod;
public ResourceAdapterImpl(String resourceFilter, boolean propagate) {
+ this(resourceFilter, propagate, null, null);
+ }
+
+ public ResourceAdapterImpl(String resourceFilter, Object propagateCallbackInstance, String propagateCallbackMethod) {
+ this(resourceFilter, true, propagateCallbackInstance, propagateCallbackMethod);
+ }
+
+ private ResourceAdapterImpl(String resourceFilter, boolean propagate, Object propagateCallbackInstance, String propagateCallbackMethod) {
m_resourceFilter = resourceFilter;
m_propagate = propagate;
+ m_propagateCallbackInstance = propagateCallbackInstance;
+ m_propagateCallbackMethod = propagateCallbackMethod;
}
public Service createService(Object[] properties) {
@@ -74,18 +98,21 @@
// the first dependency is always the dependency on the resource, which
// will be replaced with a more specific dependency below
dependencies.remove(0);
+ ResourceDependency resourceDependency = m_manager.createResourceDependency()
+ .setResource(resource)
+ .setPropagate(m_propagate)
+ .setCallbacks(m_callbackInstance, null, m_callbackChanged, null)
+ .setAutoConfig(true)
+ .setRequired(true);
+ resourceDependency.setPropagate(m_propagate);
+ resourceDependency.setPropagate(m_propagateCallbackInstance, m_propagateCallbackMethod);
Service service = m_manager.createService()
.setInterface(m_serviceInterfaces, props)
.setImplementation(m_serviceImpl)
.setFactory(m_factory, m_factoryCreateMethod) // if not set, no effect
.setComposition(m_compositionInstance, m_compositionMethod) // if not set, no effect
.setCallbacks(m_callbackObject, m_init, m_start, m_stop, m_destroy) // if not set, no effect
- .add(m_manager.createResourceDependency()
- .setResource(resource)
- .setPropagate(m_propagate)
- .setCallbacks(m_callbackInstance, null, m_callbackChanged, null)
- .setAutoConfig(true)
- .setRequired(true));
+ .add(resourceDependency);
for (int i = 0; i < dependencies.size(); i++) {
service.add(((Dependency) dependencies.get(i)).createCopy());
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 380300e..0482cec 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,6 +18,7 @@
*/
package org.apache.felix.dm.impl.dependencies;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Dictionary;
@@ -27,6 +28,7 @@
import org.apache.felix.dm.Dependency;
import org.apache.felix.dm.ServiceComponentDependency;
import org.apache.felix.dm.impl.DefaultNullObject;
+import org.apache.felix.dm.impl.InvocationUtil;
import org.apache.felix.dm.impl.Logger;
import org.apache.felix.dm.impl.tracker.BundleTracker;
import org.apache.felix.dm.impl.tracker.BundleTrackerCustomizer;
@@ -35,6 +37,7 @@
import org.osgi.framework.BundleEvent;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.log.LogService;
public class BundleDependencyImpl extends DependencyBase implements BundleDependency, BundleTrackerCustomizer, ServiceComponentDependency {
private final BundleContext m_context;
@@ -43,7 +46,6 @@
private int m_stateMask = Bundle.INSTALLED | Bundle.RESOLVED | Bundle.ACTIVE;
private List m_services = new ArrayList();
private boolean m_isAvailable;
-
private Object m_callbackInstance;
private String m_callbackAdded;
private String m_callbackChanged;
@@ -52,12 +54,13 @@
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;
+ private boolean m_propagate;
+ private Object m_propagateCallbackInstance;
+ private String m_propagateCallbackMethod;
-
public BundleDependencyImpl(BundleContext context, Logger logger) {
super(logger);
m_context = context;
@@ -356,12 +359,6 @@
return this;
}
- public BundleDependency setPropagate(boolean propagate) {
- ensureNotActive();
- m_propagate = propagate;
- return this;
- }
-
public BundleDependency setBundle(Bundle bundle) {
m_bundleId = bundle.getBundleId();
return this;
@@ -461,10 +458,42 @@
invokeRemoved(service, m_bundleInstance);
m_bundleInstance = null;
}
-
+
+ public BundleDependency setPropagate(boolean propagate) {
+ ensureNotActive();
+ m_propagate = propagate;
+ return this;
+ }
+
+ public BundleDependency setPropagate(Object instance, String method) {
+ setPropagate(instance != null && method != null);
+ m_propagateCallbackInstance = instance;
+ m_propagateCallbackMethod = method;
+ return this;
+ }
+
public Dictionary getProperties() {
- // TODO Auto-generated method stub
- return null;
+ Bundle bundle = lookupBundle();
+ if (bundle != null) {
+ if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
+ try {
+ return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, new Class[][] {{ Bundle.class }}, new Object[][] {{ bundle }});
+ }
+ catch (InvocationTargetException e) {
+ m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
+ }
+ catch (Exception e) {
+ m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
+ }
+ throw new IllegalStateException("Could not invoke callback");
+ }
+ else {
+ return bundle.getHeaders();
+ }
+ }
+ else {
+ throw new IllegalStateException("cannot find bundle");
+ }
}
public boolean isPropagated() {
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java
index e55665e..267cd85 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ConfigurationDependencyImpl.java
@@ -38,6 +38,7 @@
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
+import org.osgi.service.log.LogService;
/**
* Configuration dependency that can track the availability of a (valid) configuration.
@@ -65,11 +66,13 @@
private ServiceRegistration m_registration;
protected List m_services = new ArrayList();
private Dictionary m_settings;
- private boolean m_propagate;
private String m_callback;
private boolean m_isStarted;
private final Set m_updateInvokedCache = new HashSet();
private MetaTypeProviderImpl m_metaType;
+ private boolean m_propagate;
+ private Object m_propagateCallbackInstance;
+ private String m_propagateCallbackMethod;
public ConfigurationDependencyImpl(BundleContext context, Logger logger) {
super(logger);
@@ -324,8 +327,35 @@
return false;
}
+ public ConfigurationDependency setPropagate(Object instance, String method) {
+ setPropagate(instance != null && method != null);
+ m_propagateCallbackInstance = instance;
+ m_propagateCallbackMethod = method;
+ return this;
+ }
+
public Dictionary getProperties() {
- return getConfiguration();
+ Dictionary config = getConfiguration();
+ if (config != null) {
+ if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
+ try {
+ return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, new Class[][] {{ Dictionary.class }, {}}, new Object[][] {{ config }, {}});
+ }
+ catch (InvocationTargetException e) {
+ m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
+ }
+ catch (Exception e) {
+ m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
+ }
+ throw new IllegalStateException("Could not invoke callback");
+ }
+ else {
+ return config;
+ }
+ }
+ else {
+ throw new IllegalStateException("cannot find configuration");
+ }
}
public BundleContext getBundleContext() {
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java
index 428e1fb..df09ddc 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ResourceDependencyImpl.java
@@ -18,6 +18,7 @@
*/
package org.apache.felix.dm.impl.dependencies;
+import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Dictionary;
@@ -29,9 +30,11 @@
import org.apache.felix.dm.ResourceHandler;
import org.apache.felix.dm.Service;
import org.apache.felix.dm.ServiceComponentDependency;
+import org.apache.felix.dm.impl.InvocationUtil;
import org.apache.felix.dm.impl.Logger;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.log.LogService;
public class ResourceDependencyImpl extends DependencyBase implements ResourceDependency, ResourceHandler, DependencyActivation, ServiceComponentDependency {
private volatile BundleContext m_context;
@@ -51,6 +54,8 @@
private List m_resources = new ArrayList();
private URL m_resourceInstance;
private boolean m_propagate;
+ private Object m_propagateCallbackInstance;
+ private String m_propagateCallbackMethod;
public ResourceDependencyImpl(BundleContext context, Logger logger) {
super(logger);
@@ -430,15 +435,36 @@
return this;
}
+ public ResourceDependency setPropagate(Object instance, String method) {
+ setPropagate(instance != null && method != null);
+ m_propagateCallbackInstance = instance;
+ m_propagateCallbackMethod = method;
+ return this;
+ }
+
public Dictionary getProperties() {
URL resource = lookupResource();
if (resource != null) {
- Properties props = new Properties();
- props.setProperty(ResourceHandler.HOST, resource.getHost());
- props.setProperty(ResourceHandler.PATH, resource.getPath());
- props.setProperty(ResourceHandler.PROTOCOL, resource.getProtocol());
- props.setProperty(ResourceHandler.PORT, Integer.toString(resource.getPort()));
- return props;
+ if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
+ try {
+ return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, new Class[][] {{ URL.class }}, new Object[][] {{ resource }});
+ }
+ catch (InvocationTargetException e) {
+ m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
+ }
+ catch (Exception e) {
+ m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
+ }
+ throw new IllegalStateException("Could not invoke callback");
+ }
+ else {
+ Properties props = new Properties();
+ props.setProperty(ResourceHandler.HOST, resource.getHost());
+ props.setProperty(ResourceHandler.PATH, resource.getPath());
+ props.setProperty(ResourceHandler.PROTOCOL, resource.getProtocol());
+ props.setProperty(ResourceHandler.PORT, Integer.toString(resource.getPort()));
+ return props;
+ }
}
else {
throw new IllegalStateException("cannot find resource");
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
index 86e1043..76a3306 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/dependencies/ServiceDependencyImpl.java
@@ -18,6 +18,7 @@
*/
package org.apache.felix.dm.impl.dependencies;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.util.AbstractMap;
import java.util.ArrayList;
@@ -27,12 +28,14 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Properties;
import java.util.Set;
import org.apache.felix.dm.Dependency;
import org.apache.felix.dm.ServiceComponentDependency;
import org.apache.felix.dm.ServiceDependency;
import org.apache.felix.dm.impl.DefaultNullObject;
+import org.apache.felix.dm.impl.InvocationUtil;
import org.apache.felix.dm.impl.Logger;
import org.apache.felix.dm.impl.tracker.ServiceTracker;
import org.apache.felix.dm.impl.tracker.ServiceTrackerCustomizer;
@@ -40,6 +43,7 @@
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
/**
* Service dependency that can track an OSGi service.
@@ -69,6 +73,9 @@
private Object m_defaultImplementationInstance;
private boolean m_isAvailable;
private ServiceReference[] m_references;
+ private boolean m_propagate;
+ private Object m_propagateCallbackInstance;
+ private String m_propagateCallbackMethod;
private static final Comparator COMPARATOR = new Comparator() {
public int getRank(ServiceReference ref) {
@@ -805,12 +812,51 @@
}
public Dictionary getProperties() {
- // TODO Auto-generated method stub
- return null;
+ ServiceReference reference = lookupServiceReference();
+ Object service = lookupService();
+ if (reference != null) {
+ if (m_propagateCallbackInstance != null && m_propagateCallbackMethod != null) {
+ try {
+ return (Dictionary) InvocationUtil.invokeCallbackMethod(m_propagateCallbackInstance, m_propagateCallbackMethod, new Class[][] {{ ServiceReference.class, Object.class }, { ServiceReference.class }}, new Object[][] {{ reference, service }, { reference }});
+ }
+ catch (InvocationTargetException e) {
+ m_logger.log(LogService.LOG_WARNING, "Exception while invoking callback method", e.getCause());
+ }
+ catch (Exception e) {
+ m_logger.log(LogService.LOG_WARNING, "Exception while trying to invoke callback method", e);
+ }
+ throw new IllegalStateException("Could not invoke callback");
+ }
+ else {
+ Properties props = new Properties();
+ String[] keys = reference.getPropertyKeys();
+ for (int i = 0; i < keys.length; i++) {
+ if (!(keys[i].equals(Constants.SERVICE_ID) || keys[i].equals(Constants.SERVICE_PID))) {
+ props.put(keys[i], reference.getProperty(keys[i]));
+ }
+ }
+ return props;
+ }
+ }
+ else {
+ throw new IllegalStateException("cannot find service reference");
+ }
}
public boolean isPropagated() {
- // TODO Auto-generated method stub
- return false;
+ return m_propagate;
+ }
+
+ public ServiceDependency setPropagate(boolean propagate) {
+ ensureNotActive();
+ m_propagate = propagate;
+ return this;
+ }
+
+ public ServiceDependency setPropagate(Object instance, String method) {
+ setPropagate(instance != null && method != null);
+ m_propagateCallbackInstance = instance;
+ m_propagateCallbackMethod = method;
+ return this;
}
}