FELIX-5192: ConfigurationDependency race condition when component is stopped.
FELIX-5193: Factory Pid Adapter race condition when component is stopped.
Removed Eclipse warnings. Reworked the way configuration exception is handled.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1731471 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/org.apache.felix.dependencymanager.benchmark/src/org/apache/felix/dm/benchmark/controller/impl/ScenarioControllerImpl.java b/dependencymanager/org.apache.felix.dependencymanager.benchmark/src/org/apache/felix/dm/benchmark/controller/impl/ScenarioControllerImpl.java
index ccf0f56..b27e312 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.benchmark/src/org/apache/felix/dm/benchmark/controller/impl/ScenarioControllerImpl.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.benchmark/src/org/apache/felix/dm/benchmark/controller/impl/ScenarioControllerImpl.java
@@ -299,17 +299,6 @@
}
/**
- * Initialize the latches used to track when all scenario bundle components are started or stopped.
- */
- private void initLatches() {
- m_startLatch = new CountDownLatch(ARTISTS
- + (ARTISTS * (ALBUMS + (ALBUMS * TRACKS))));
-
- m_stopLatch = new CountDownLatch(ARTISTS
- + (ARTISTS * (ALBUMS + (ALBUMS * TRACKS))));
- }
-
- /**
* Returns the time consumed by the given runnable, ²ch is executed by this method.
*/
private long durationOf(Runnable scenario) {
diff --git a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/AspectWithCallbacksServiceDependencyTest.java b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/AspectWithCallbacksServiceDependencyTest.java
index 9905aac..afe581d 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/AspectWithCallbacksServiceDependencyTest.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.itest/src/org/apache/felix/dm/itest/api/AspectWithCallbacksServiceDependencyTest.java
@@ -20,11 +20,8 @@
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
-import org.apache.felix.dm.itest.api.AspectBaseTest.ServiceAspect;
-import org.apache.felix.dm.itest.api.AspectBaseTest.ServiceInterface;
import org.apache.felix.dm.itest.util.Ensure;
import org.apache.felix.dm.itest.util.TestBase;
-import org.osgi.framework.ServiceReference;
/**
diff --git a/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/conf/Configurator.java b/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/conf/Configurator.java
index 727f284..beafc6c 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/conf/Configurator.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/conf/Configurator.java
@@ -21,7 +21,6 @@
import java.io.IOException;
import java.util.Hashtable;
-import org.apache.felix.dependencymanager.samples.hello.api.ServiceConsumerConf;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.log.LogService;
diff --git a/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/hello/annot/ServiceConsumer.java b/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/hello/annot/ServiceConsumer.java
index 7d3e5bf..5f81710 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/hello/annot/ServiceConsumer.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/hello/annot/ServiceConsumer.java
@@ -18,8 +18,6 @@
*/
package org.apache.felix.dependencymanager.samples.hello.annot;
-import java.util.Dictionary;
-
import org.apache.felix.dm.annotation.api.Component;
import org.apache.felix.dm.annotation.api.ConfigurationDependency;
import org.apache.felix.dm.annotation.api.ServiceDependency;
diff --git a/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/hello/api/ServiceConsumer.java b/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/hello/api/ServiceConsumer.java
index a5097b7..b49fac0 100644
--- a/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/hello/api/ServiceConsumer.java
+++ b/dependencymanager/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/hello/api/ServiceConsumer.java
@@ -18,8 +18,7 @@
*/
package org.apache.felix.dependencymanager.samples.hello.api;
-import java.util.Dictionary;
-
+import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.log.LogService;
/**
@@ -32,7 +31,7 @@
volatile LogService log;
ServiceConsumerConf conf;
- protected void updated(ServiceConsumerConf conf) {
+ protected void updated(ServiceConsumerConf conf) throws ConfigurationException {
this.conf = conf;
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AbstractDecorator.java b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AbstractDecorator.java
index 044166b..b3dded5 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AbstractDecorator.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AbstractDecorator.java
@@ -40,14 +40,16 @@
public abstract class AbstractDecorator {
protected volatile DependencyManager m_manager;
private final Map<Object, Component> m_services = new ConcurrentHashMap<>();
-
- public abstract Component createService(Object[] properties);
+ private volatile ComponentContext m_decoratorComponent;
+
+ public abstract Component createService(Object[] properties) throws Exception;
/**
* Catches our DependencyManager handle from our component init method.
*/
public void init(Component c) {
m_manager = c.getDependencyManager();
+ m_decoratorComponent = (ComponentContext) c;
}
/**
@@ -55,8 +57,8 @@
* For now, it's only used by the FactoryConfigurationAdapterImpl class,
* but it might also make sense to use this for Resource Adapters ...
*/
- public void updateService(Object[] properties) {
- throw new NoSuchMethodError("Method updateService not implemented");
+ public void updateService(Object[] properties) throws Exception {
+ throw new NoSuchMethodException("Method updateService not implemented");
}
/**
@@ -104,29 +106,27 @@
}
}
- // callbacks for FactoryConfigurationAdapterImpl
- public void updated(String pid, @SuppressWarnings("rawtypes") Dictionary properties) throws ConfigurationException {
- try {
- Component service = m_services.get(pid);
- if (service == null) {
- service = createService(new Object[] { properties });
- m_services.put(pid, service);
- m_manager.add(service);
- }
- else {
- updateService(new Object[] { properties, service });
- }
+ // callbacks for FactoryConfigurationAdapterImpl from the ConfigAdmin thread
+ @SuppressWarnings("rawtypes")
+ public void updated(String pid, Dictionary properties) throws ConfigurationException {
+ // FELIX-5193: invoke the updated callback in the internal decorator component queue, in order
+ // to safely detect if the component is still active or not.
+ InvocationUtil.invokeUpdated(m_decoratorComponent.getExecutor(), () -> updatedSafe(pid, properties));
+ }
+
+ @SuppressWarnings("rawtypes")
+ private void updatedSafe(String pid, Dictionary properties) throws Exception {
+ if (!m_decoratorComponent.isActive()) {
+ // Our decorator component has been removed: ignore the configuration update.
+ return;
}
- catch (Throwable t) {
- if (t instanceof ConfigurationException) {
- throw (ConfigurationException) t;
- }
- else if (t.getCause() instanceof ConfigurationException) {
- throw (ConfigurationException) t.getCause();
- }
- else {
- throw new ConfigurationException(null, "Could not create service for ManagedServiceFactory Pid " + pid, t);
- }
+ Component service = m_services.get(pid);
+ if (service == null) {
+ service = createService(new Object[] { properties });
+ m_services.put(pid, service);
+ m_manager.add(service);
+ } else {
+ updateService(new Object[] { properties, service });
}
}
@@ -138,7 +138,7 @@
}
// callbacks for resources
- public void added(URL resource) {
+ public void added(URL resource) throws Exception {
Component newService = createService(new Object[] { resource });
m_services.put(resource, newService);
m_manager.add(newService);
@@ -153,7 +153,7 @@
}
// callbacks for services
- public void added(ServiceReference ref, Object service) {
+ public void added(ServiceReference ref, Object service) throws Exception {
Component newService = createService(new Object[] { ref, service });
m_services.put(ref, newService);
m_manager.add(newService);
@@ -177,7 +177,7 @@
}
// callbacks for bundles
- public void added(Bundle bundle) {
+ public void added(Bundle bundle) throws Exception {
Component newService = createService(new Object[] { bundle });
m_services.put(bundle, newService);
m_manager.add(newService);
diff --git a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/Configurable.java b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/Configurable.java
index e05e985..2ca5c3e 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/Configurable.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/Configurable.java
@@ -112,6 +112,7 @@
return result;
}
+ @SuppressWarnings("unchecked")
private Object convert(ParameterizedType type, String key, Object value) throws Exception {
Class<?> resultType = (Class<?>) type.getRawType();
if (Class.class.isAssignableFrom(resultType)) {
@@ -171,6 +172,7 @@
throw new RuntimeException("Unhandled type: " + type);
}
+ @SuppressWarnings({ "unchecked", "rawtypes" })
private Object convert(Type type, String key, Object value, boolean useImplicitDefault) throws Exception {
if (type instanceof ParameterizedType) {
return convert((ParameterizedType) type, key, value);
diff --git a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java
index 5725161..3749fac 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java
@@ -18,16 +18,10 @@
*/
package org.apache.felix.dm.impl;
-import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Objects;
import java.util.Properties;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;
@@ -61,7 +55,6 @@
private final Logger m_logger;
private final BundleContext m_context;
private boolean m_needsInstance = true;
- private final static int UPDATE_MAXWAIT = 30000; // max time to wait until a component has handled a configuration change event.
public ConfigurationDependencyImpl() {
this(null, null);
@@ -250,7 +243,7 @@
}
return m_settings;
}
-
+
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public void updated(final Dictionary settings) throws ConfigurationException {
@@ -272,43 +265,12 @@
// callback is invoked safely. So, we use a Callable and a FutureTask that allows to handle the
// configuration update through the component executor. We still wait for the result because
// in case of any configuration error, we have to return it from the current thread.
+ // Notice that scheduling the handling of the configuration update in the component queue also
+ // allows to safely check if the component is still active (it could be being stopped concurrently:
+ // see the invokeUpdated method which tests if our dependency is still alive (by calling super.istarted()
+ // method).
- Callable<ConfigurationException> result = new Callable<ConfigurationException>() {
- @Override
- public ConfigurationException call() throws Exception {
- try {
- invokeUpdated(settings); // either the callback instance or the component instances, if available.
- } catch (ConfigurationException e) {
- return e;
- }
- return null;
- }
- };
-
- // Schedule the configuration update in the component executor. In Normal case, the task is immediately executed.
- // But in a highly concurrent system, and if the component is being reconfigured, the component may be currently busy
- // (handling a service dependency event for example), so the task will be enqueued in the component executor, and
- // we'll wait for the task execution by using a FutureTask:
-
- FutureTask<ConfigurationException> ft = new FutureTask<>(result);
- m_component.getExecutor().execute(ft);
-
- try {
- ConfigurationException confError = ft.get(UPDATE_MAXWAIT, TimeUnit.MILLISECONDS);
- if (confError != null) {
- throw confError; // will be logged by the Configuration Admin service;
- }
- }
-
- catch (ExecutionException error) {
- throw new ConfigurationException(null, "Configuration update error, unexpected exception.", error);
- } catch (InterruptedException error) {
- // will be logged by the Configuration Admin service;
- throw new ConfigurationException(null, "Configuration update interrupted.", error);
- } catch (TimeoutException error) {
- // will be logged by the Configuration Admin service;
- throw new ConfigurationException(null, "Component did not handle configuration update timely.", error);
- }
+ InvocationUtil.invokeUpdated(m_component.getExecutor(), () -> invokeUpdated(settings));
// At this point, we have accepted the configuration.
synchronized (this) {
@@ -337,8 +299,8 @@
case ADDED:
try {
invokeUpdated(m_settings);
- } catch (ConfigurationException e) {
- logConfigurationException(e);
+ } catch (Throwable err) {
+ logConfigurationException(err);
}
break;
case CHANGED:
@@ -386,9 +348,18 @@
return new CallbackTypeDef(sigs, args);
}
- private void invokeUpdated(Dictionary<?, ?> settings) throws ConfigurationException {
+ // Called from the configuration component internal queue.
+ private void invokeUpdated(Dictionary<?, ?> settings) throws Exception {
if (m_updateInvokedCache.compareAndSet(false, true)) {
+ // FELIX-5192: we have to handle the following race condition: one thread stops a component (removes it from a DM object);
+ // another thread removes the configuration (from ConfigurationAdmin). in this case we may be called in our
+ // ManagedService.updated(null), but our component instance has been destroyed and does not exist anymore.
+ // In this case: do nothing.
+ if (! super.isStarted()) {
+ return;
+ }
+
// FELIX-5155: if component impl is an internal DM adapter, we must not invoke the callback on it
// because in case there is an external callback instance specified for the configuration callback,
// then we don't want to invoke it now. The external callback instance will be invoked
@@ -400,11 +371,8 @@
return;
}
- Object[] instances = super.getInstances(); // either the callback instance or the component instances
- if (instances == null) {
- return;
- }
-
+ Object[] instances = super.getInstances(); // never null, either the callback instance or the component instances
+
CallbackTypeDef callbackInfo = createCallbackType(m_logger, m_component, m_configType, settings);
boolean callbackFound = false;
for (int i = 0; i < instances.length; i++) {
@@ -412,24 +380,9 @@
InvocationUtil.invokeCallbackMethod(instances[i], m_add, callbackInfo.m_sigs, callbackInfo.m_args);
callbackFound |= true;
}
- catch (InvocationTargetException e) {
- // The component has thrown an exception during it's callback invocation.
- if (e.getTargetException() instanceof ConfigurationException) {
- // the callback threw an OSGi ConfigurationException: just re-throw it.
- throw (ConfigurationException) e.getTargetException();
- }
- else {
- // wrap the callback exception into a ConfigurationException.
- throw new ConfigurationException(null, "Configuration update failed", e.getTargetException());
- }
- }
catch (NoSuchMethodException e) {
// if the method does not exist, ignore it
}
- catch (Throwable t) {
- // wrap any other exception as a ConfigurationException.
- throw new ConfigurationException(null, "Configuration update failed", t);
- }
}
if (! callbackFound) {
@@ -445,7 +398,7 @@
}
}
- private void logConfigurationException(ConfigurationException e) {
- m_logger.log(Logger.LOG_ERROR, "Got exception while handling configuration update for pid " + m_pid, e);
+ private void logConfigurationException(Throwable err) {
+ m_logger.log(Logger.LOG_ERROR, "Got exception while handling configuration update for pid " + m_pid, err);
}
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FactoryConfigurationAdapterImpl.java b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FactoryConfigurationAdapterImpl.java
index 9d1c978..3578950 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FactoryConfigurationAdapterImpl.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FactoryConfigurationAdapterImpl.java
@@ -18,7 +18,8 @@
*/
package org.apache.felix.dm.impl;
-import java.lang.reflect.InvocationTargetException;
+import static org.apache.felix.dm.impl.ConfigurationDependencyImpl.createCallbackType;
+
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
@@ -36,8 +37,6 @@
import org.osgi.service.metatype.MetaTypeProvider;
import org.osgi.service.metatype.ObjectClassDefinition;
-import static org.apache.felix.dm.impl.ConfigurationDependencyImpl.createCallbackType;
-
/**
* Factory configuration adapter service implementation. This class extends the FilterService in order to catch
* some Service methods for configuring actual adapter service implementation.
@@ -128,7 +127,7 @@
* Method called from our superclass, when we need to create a service.
*/
@SuppressWarnings("unchecked")
- public Component createService(Object[] properties) {
+ public Component createService(Object[] properties) throws Exception {
Dictionary<String, ?> settings = (Dictionary<String, ?>) properties[0];
Component newService = m_manager.createComponent();
@@ -160,7 +159,7 @@
* the configuration has changed.
*/
@SuppressWarnings("unchecked")
- public void updateService(Object[] properties) {
+ public void updateService(Object[] properties) throws Exception {
Dictionary<String, ?> cmSettings = (Dictionary<String, ?>) properties[0];
Component service = (Component) properties[1];
CallbackTypeDef callbackInfo = createCallbackType(m_logger, service, m_configType, cmSettings);
@@ -173,7 +172,7 @@
}
}
- private void invokeUpdated(Component service, CallbackTypeDef callbackInfo) {
+ private void invokeUpdated(Component service, CallbackTypeDef callbackInfo) throws Exception {
boolean callbackFound = false;
Object[] instances = getUpdateCallbackInstances(service);
for (Object instance : instances) {
@@ -181,16 +180,9 @@
InvocationUtil.invokeCallbackMethod(instance, m_update, callbackInfo.m_sigs, callbackInfo.m_args);
callbackFound |= true;
}
- catch (InvocationTargetException e) {
- // The component has thrown an exception during it's callback invocation.
- handleException(e.getTargetException());
- }
catch (NoSuchMethodException e) {
// if the method does not exist, ignore it
}
- catch (Throwable t) {
- handleException(t); // will rethrow a runtime exception.
- }
}
if (! callbackFound) {
@@ -247,25 +239,6 @@
return props;
}
-
- private void handleException(Throwable t) {
- if (m_logger != null) {
- m_logger.log(Logger.LOG_ERROR, "Got exception while handling configuration update for factory pid " + m_factoryPid, t);
- } else {
-
- }
- if (t instanceof InvocationTargetException) {
- // Our super class will check if the target exception is itself a ConfigurationException.
- // In this case, it will simply re-thrown.
- throw new RuntimeException(((InvocationTargetException) t).getTargetException());
- }
- else if (t instanceof RuntimeException) {
- throw (RuntimeException) t;
- }
- else {
- throw new RuntimeException(t);
- }
- }
}
/**
diff --git a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/InvocationUtil.java b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/InvocationUtil.java
index 880eba2..e452e3c 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/InvocationUtil.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/InvocationUtil.java
@@ -25,6 +25,12 @@
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
+import org.osgi.service.cm.ConfigurationException;
/**
* Utility methods for invoking callbacks. Lookups of callbacks are accellerated by using a LRU cache.
@@ -47,6 +53,19 @@
}
/**
+ * Interface internally used to handle a ConfigurationAdmin update synchronously, in a component executor queue.
+ */
+ @FunctionalInterface
+ public interface ConfigurationHandler {
+ public void handle() throws Exception;
+ }
+
+ /**
+ * Max time to wait until a configuration update callback has returned.
+ */
+ private final static int UPDATED_MAXWAIT = 30000; // max time to wait until a CM update has completed
+
+ /**
* Invokes a callback method on an instance. The code will search for a callback method with
* the supplied name and any of the supplied signatures in order, invoking the first one it finds.
*
@@ -202,4 +221,44 @@
return size() > m_size;
}
}
+
+ /**
+ * Invokes a configuration update callback synchronously, but through the component executor queue.
+ */
+ public static void invokeUpdated(Executor queue, ConfigurationHandler handler) throws ConfigurationException {
+ Callable<Exception> result = () -> {
+ try {
+ handler.handle();
+ } catch (Exception e) {
+ return e;
+ }
+ return null;
+ };
+
+ FutureTask<Exception> ft = new FutureTask<>(result);
+ queue.execute(ft);
+
+ try {
+ Exception err = ft.get(UPDATED_MAXWAIT, TimeUnit.MILLISECONDS);
+ if (err != null) {
+ throw err;
+ }
+ }
+
+ catch (ConfigurationException e) {
+ throw e;
+ }
+
+ catch (Throwable error) {
+ Throwable rootCause = error.getCause();
+ if (rootCause != null) {
+ if (rootCause instanceof ConfigurationException) {
+ throw (ConfigurationException) rootCause;
+ }
+ throw new ConfigurationException("", "Configuration update error, unexpected exception.", rootCause);
+ } else {
+ throw new ConfigurationException("", "Configuration update error, unexpected exception.", error);
+ }
+ }
+ }
}
diff --git a/dependencymanager/org.apache.felix.dependencymanager/test/org/apache/felix/dm/impl/ConfigurationDependencyImplTest.java b/dependencymanager/org.apache.felix.dependencymanager/test/org/apache/felix/dm/impl/ConfigurationDependencyImplTest.java
index af82ff0..04bebdc 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/test/org/apache/felix/dm/impl/ConfigurationDependencyImplTest.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/test/org/apache/felix/dm/impl/ConfigurationDependencyImplTest.java
@@ -75,6 +75,7 @@
super(ensure);
}
+ @SuppressWarnings("rawtypes")
@Override
public void updated(Dictionary config) throws ConfigurationException {
super.updated(config);
@@ -126,6 +127,7 @@
m_ensure = ensure;
}
+ @SuppressWarnings("rawtypes")
public void updated(Dictionary config) throws ConfigurationException {
m_ensure.step();
@@ -141,6 +143,7 @@
m_ensure.step();
}
+ @SuppressWarnings("rawtypes")
private void assertConfiguration(Dictionary cfg) {
assertEquals("isTrue", "true", cfg.get("true"));
assertEquals("getValue", "42", cfg.get("value"));
@@ -229,9 +232,11 @@
ConfigurationDependencyImpl result = new ConfigurationDependencyImpl(bc, mockLogger);
result.setCallback(service, "updated").setPid("does.not.matter");
result.setComponentContext(component);
+ result.start();
return result;
}
+ @SuppressWarnings("rawtypes")
private Dictionary createDictionary() {
Dictionary<String, Object> result = new Hashtable<>();
result.put("true", "true");
diff --git a/dependencymanager/org.apache.felix.dependencymanager/test/test/Ensure.java b/dependencymanager/org.apache.felix.dependencymanager/test/test/Ensure.java
index 4d2378f..ff2c308 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/test/test/Ensure.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/test/test/Ensure.java
@@ -49,7 +49,7 @@
}
}
- public void setStream(PrintStream output) {
+ public static void setStream(PrintStream output) {
STREAM = output;
}