FELIX-321 Added support for propagating configuration properties to services.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@553759 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
index 1787345..31410e4 100644
--- a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
+++ b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
@@ -53,6 +53,7 @@
private ServiceRegistration m_registration;
private volatile Service m_service;
private Dictionary m_settings;
+ private boolean m_propagate;
public ConfigurationDependency(BundleContext context) {
m_context = context;
@@ -66,6 +67,14 @@
return true;
}
+ public boolean isPropagated() {
+ return m_propagate;
+ }
+
+ public Dictionary getConfiguration() {
+ return m_settings;
+ }
+
public void start(Service service) {
m_service = service;
Properties props = new Properties();
@@ -125,6 +134,12 @@
return this;
}
+ public ConfigurationDependency setPropagate(boolean propagate) {
+ ensureNotActive();
+ m_propagate = propagate;
+ return this;
+ }
+
private void ensureNotActive() {
if (m_service != null) {
throw new IllegalStateException("Cannot modify state while active.");
diff --git a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
index 5d101b8..183cf07 100644
--- a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
+++ b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
@@ -24,9 +24,11 @@
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Dictionary;
+import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
+import java.util.Properties;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
@@ -38,16 +40,6 @@
*/
public class ServiceImpl implements Service {
private static final ServiceRegistration NULL_REGISTRATION;
-// private static final int STARTING = 1;
-// private static final int WAITING_FOR_REQUIRED = 2;
-// private static final int TRACKING_OPTIONAL = 3;
-// private static final int STOPPING = 4;
-// private static final String[] STATE_NAMES = {
-// "(unknown)",
-// "starting",
-// "waiting for required dependencies",
-// "tracking optional dependencies",
-// "stopping"};
private static final ServiceStateListener[] SERVICE_STATE_LISTENER_TYPE = new ServiceStateListener[] {};
private final BundleContext m_context;
@@ -67,7 +59,6 @@
private ArrayList m_dependencies = new ArrayList();
// runtime state (calculated from dependencies)
-// private int m_state;
private State m_state;
// runtime state (changes because of state changes)
@@ -79,11 +70,8 @@
// work queue
private final SerialExecutor m_executor = new SerialExecutor();
-// final LinkedList m_workQueue = new LinkedList();
-// Runnable m_active;
public ServiceImpl(BundleContext context) {
-// m_state = STARTING;
m_state = new State((List) m_dependencies.clone(), false);
m_context = context;
m_callbackInit = "init";
@@ -95,22 +83,17 @@
private void calculateStateChanges(final State oldState, final State newState) {
if (oldState.isWaitingForRequired() && newState.isTrackingOptional()) {
- // TODO service needs to be activated
- // activateService(newState);
m_executor.enqueue(new Runnable() {
public void run() {
activateService(newState);
}});
}
if (oldState.isTrackingOptional() && newState.isWaitingForRequired()) {
- // TODO service needs to be deactivated
- // deactivateService(oldState);
m_executor.enqueue(new Runnable() {
public void run() {
deactivateService(oldState);
}});
}
-
if (oldState.isInactive() && (newState.isTrackingOptional())) {
m_executor.enqueue(new Runnable() {
public void run() {
@@ -153,37 +136,6 @@
m_state = newState;
calculateStateChanges(oldState, newState);
}
-// executeWorkInQueue();
-// if ((state == WAITING_FOR_REQUIRED) && dependency.isRequired()) {
-// // if we're waiting for required dependencies, and
-// // this is a required dependency, start tracking it
-// // ...otherwise, we don't need to do anything yet
-// final ServiceImpl impl = this;
-// m_workQueue.addLast(new Runnable() {
-// public void run() {
-// dependency.start(impl);
-// }});
-// }
-// if (state == TRACKING_OPTIONAL) {
-// // start tracking the dependency
-// final ServiceImpl impl = this;
-// m_workQueue.addLast(new Runnable() {
-// public void run() {
-// dependency.start(impl);
-// }});
-// // TODO review this logic
-// if (dependency.isRequired() && !dependency.isAvailable()) {
-// // if this is a required dependency and it can not
-// // be resolved right away, then we need to go back to
-// // the waiting for required state, until this
-// // dependency is available
-// m_workQueue.addLast(new Runnable() {
-// public void run() {
-// deactivateService();
-// }});
-// }
-// }
-// executeWorkInQueue();
return this;
}
@@ -201,27 +153,6 @@
m_state = newState;
}
calculateStateChanges(oldState, newState);
-// int state;
-// synchronized (m_dependencies) {
-// state = m_state;
-// m_dependencies.remove(dependency);
-// }
-// if (state == TRACKING_OPTIONAL) {
-// // if we're tracking optional dependencies, then any
-// // dependency that is removed can be stopped without
-// // causing state changes
-// dependency.stop(this);
-// }
-// if ((state == WAITING_FOR_REQUIRED) && dependency.isRequired()) {
-// // if we're waiting for required dependencies, then
-// // we only need to stop tracking the dependency if it
-// // too is required; this might trigger a state change
-// dependency.stop(this);
-// // TODO review this logic
-// if (allRequiredDependenciesAvailable()) {
-// activateService();
-// }
-// }
return this;
}
@@ -255,19 +186,6 @@
});
m_executor.execute();
}
-
-// int oldState, newState;
-// synchronized (m_dependencies) {
-// oldState = m_state;
-// newState = calculateState();
-// }
-// if (dependency.isRequired() && (oldState == WAITING_FOR_REQUIRED) && (newState == TRACKING_OPTIONAL)) {
-// activateService();
-// }
-// // TODO review, only update optional deps here??? nonono probably not
-// if ((!dependency.isRequired()) && (oldState == TRACKING_OPTIONAL)) {
-// updateInstance(dependency);
-// }
}
public void dependencyChanged(final Dependency dependency) {
@@ -283,13 +201,6 @@
});
m_executor.execute();
}
-// int state;
-// synchronized (m_dependencies) {
-// state = m_state;
-// }
-// if (state == TRACKING_OPTIONAL) {
-// updateInstance(dependency);
-// }
}
public void dependencyUnavailable(final Dependency dependency) {
@@ -308,18 +219,6 @@
});
m_executor.execute();
}
-// int oldState, newState;
-// synchronized (m_dependencies) {
-// oldState = m_state;
-// newState = calculateState();
-// }
-// if (dependency.isRequired() && (oldState == TRACKING_OPTIONAL) && (newState == WAITING_FOR_REQUIRED)) {
-// deactivateService();
-// }
-// if (oldState == TRACKING_OPTIONAL) {
-// updateInstance(dependency);
-// }
-// // TODO note the slight asymmmetry with dependencyAvailable()
}
public synchronized void start() {
@@ -330,13 +229,6 @@
m_state = newState;
}
calculateStateChanges(oldState, newState);
-// if ((m_state != STARTING) && (m_state != STOPPING)) {
-// throw new IllegalStateException("Cannot start from state " + STATE_NAMES[m_state]);
-// }
-// startTrackingRequired();
-// if (allRequiredDependenciesAvailable() && (m_state == WAITING_FOR_REQUIRED)) {
-// activateService();
-// }
}
public synchronized void stop() {
@@ -347,16 +239,6 @@
m_state = newState;
}
calculateStateChanges(oldState, newState);
-// if ((m_state != WAITING_FOR_REQUIRED) && (m_state != TRACKING_OPTIONAL)) {
-// if ((m_state > 0) && (m_state < STATE_NAMES.length)) {
-// throw new IllegalStateException("Cannot stop from state " + STATE_NAMES[m_state]);
-// }
-// throw new IllegalStateException("Cannot stop from unknown state.");
-// }
-// if (m_state == TRACKING_OPTIONAL) {
-// deactivateService();
-// }
-// stopTrackingRequired();
}
public synchronized Service setInterface(String serviceName, Dictionary properties) {
@@ -401,8 +283,8 @@
public synchronized void setServiceProperties(Dictionary serviceProperties) {
m_serviceProperties = serviceProperties;
- if (isRegistered() && (m_serviceName != null) && (m_serviceProperties != null)) {
- m_registration.setProperties(m_serviceProperties);
+ if (isRegistered() && (m_serviceName != null)) {
+ m_registration.setProperties(calculateServiceProperties());
}
}
@@ -629,12 +511,17 @@
configureImplementation(ServiceRegistration.class, wrapper);
// service name can either be a string or an array of strings
ServiceRegistration registration;
+
+ // determine service properties
+ Dictionary properties = calculateServiceProperties();
+
+ // register the service
try {
if (m_serviceName instanceof String) {
- registration = m_context.registerService((String) m_serviceName, m_serviceInstance, m_serviceProperties);
+ registration = m_context.registerService((String) m_serviceName, m_serviceInstance, properties);
}
else {
- registration = m_context.registerService((String[]) m_serviceName, m_serviceInstance, m_serviceProperties);
+ registration = m_context.registerService((String[]) m_serviceName, m_serviceInstance, properties);
}
wrapper.setServiceRegistration(registration);
}
@@ -645,6 +532,38 @@
}
}
}
+
+ private Dictionary calculateServiceProperties() {
+ Dictionary properties = new Properties();
+ addTo(properties, m_serviceProperties);
+ for (int i = 0; i < m_dependencies.size(); i++) {
+ Dependency d = (Dependency) m_dependencies.get(i);
+ if (d instanceof ConfigurationDependency) {
+ ConfigurationDependency cd = (ConfigurationDependency) d;
+ if (cd.isPropagated()) {
+ Dictionary dict = cd.getConfiguration();
+ addTo(properties, dict);
+ }
+ }
+ }
+ if (properties.size() == 0) {
+ properties = null;
+ }
+ return properties;
+ }
+
+ private void addTo(Dictionary properties, Dictionary additional) {
+ if (properties == null) {
+ throw new IllegalArgumentException("Dictionary to add to cannot be null.");
+ }
+ if (additional != null) {
+ Enumeration e = additional.keys();
+ while (e.hasMoreElements()) {
+ Object key = e.nextElement();
+ properties.put(key, additional.get(key));
+ }
+ }
+ }
private void unregisterService() {
if (m_serviceName != null) {
@@ -662,6 +581,14 @@
configureImplementation(sd.getInterface(), sd.getService());
}
}
+ else if (dependency instanceof ConfigurationDependency) {
+ ConfigurationDependency cd = (ConfigurationDependency) dependency;
+ if (cd.isPropagated()) {
+ // change service properties accordingly
+ Dictionary props = calculateServiceProperties();
+ m_registration.setProperties(props);
+ }
+ }
}
/**