You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2017/02/06 14:37:51 UTC
svn commit: r1781908 [4/5] - in /felix/trunk/dependencymanager:
cnf/localrepo/ cnf/releaserepo/
org.apache.felix.dependencymanager.annotation/
org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/
org.apache.felix.depend...
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AbstractDecorator.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AbstractDecorator.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AbstractDecorator.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AbstractDecorator.java Mon Feb 6 14:37:49 2017
@@ -20,14 +20,17 @@ package org.apache.felix.dm.impl;
import java.net.URL;
import java.util.Dictionary;
+import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentStateListener;
import org.apache.felix.dm.Dependency;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.context.ComponentContext;
+import org.apache.felix.dm.context.DependencyContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@@ -41,6 +44,7 @@ public abstract class AbstractDecorator
protected volatile DependencyManager m_manager;
private final Map<Object, Component> m_services = new ConcurrentHashMap<>();
private volatile ComponentContext m_decoratorComponent;
+ private final Map<Dependency, Dependency> m_depclones = new HashMap<>();
public abstract Component createService(Object[] properties) throws Exception;
@@ -93,7 +97,14 @@ public abstract class AbstractDecorator
*/
public void addDependency(Dependency ... dependencies) {
for (Component component : m_services.values()) {
- component.add(dependencies);
+ Dependency[] copy = Stream.of(dependencies)
+ .map(d -> (DependencyContext) d)
+ .map(dc -> dc.createCopy())
+ .toArray(Dependency[]::new);
+ for (int i = 0; i < dependencies.length; i ++) {
+ m_depclones.put(dependencies[i], copy[i]);
+ }
+ component.add(copy);
}
}
@@ -102,7 +113,10 @@ public abstract class AbstractDecorator
*/
public void removeDependency(Dependency d) {
for (Component component : m_services.values()) {
- component.remove(d);
+ Dependency copy = m_depclones.remove(d);
+ if (copy != null) {
+ component.remove(copy);
+ }
}
}
@@ -153,13 +167,13 @@ public abstract class AbstractDecorator
}
// callbacks for services
- public void added(ServiceReference ref, Object service) throws Exception {
+ 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);
}
- public void removed(ServiceReference ref, Object service) {
+ public void removed(ServiceReference<?> ref, Object service) {
Component newService;
newService = (Component) m_services.remove(ref);
if (newService == null) {
@@ -168,7 +182,7 @@ public abstract class AbstractDecorator
m_manager.remove(newService);
}
- public void swapped(ServiceReference oldRef, Object oldService, ServiceReference newRef, Object newService) {
+ public void swapped(ServiceReference<?> oldRef, Object oldService, ServiceReference<?> newRef, Object newService) {
Component service = (Component) m_services.remove(oldRef);
if (service == null) {
throw new IllegalStateException("Service should not be null here.");
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/Activator.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/Activator.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/Activator.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/Activator.java Mon Feb 6 14:37:49 2017
@@ -33,14 +33,14 @@ import org.osgi.util.tracker.ServiceTrac
* @see {@link ComponentExecutorFactory}
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class Activator implements BundleActivator, ServiceTrackerCustomizer {
+public class Activator implements BundleActivator, ServiceTrackerCustomizer<ComponentExecutorFactory, ComponentExecutorFactory> {
private BundleContext m_context;
@Override
public void start(BundleContext context) throws Exception {
m_context = context;
Filter filter = context.createFilter("(objectClass=" + ComponentExecutorFactory.class.getName() + ")");
- ServiceTracker tracker = new ServiceTracker(context, filter, this);
+ ServiceTracker<ComponentExecutorFactory, ComponentExecutorFactory> tracker = new ServiceTracker<>(context, filter, this);
tracker.open();
}
@@ -49,19 +49,18 @@ public class Activator implements Bundle
}
@Override
- public Object addingService(ServiceReference reference) {
+ public ComponentExecutorFactory addingService(ServiceReference<ComponentExecutorFactory> reference) {
ComponentExecutorFactory factory = (ComponentExecutorFactory) m_context.getService(reference);
ComponentScheduler.instance().bind(factory);
return factory;
}
@Override
- public void modifiedService(ServiceReference reference, Object service) {
+ public void modifiedService(ServiceReference<ComponentExecutorFactory> reference, ComponentExecutorFactory service) {
}
@Override
- public void removedService(ServiceReference reference, Object service) {
- ComponentExecutorFactory factory = (ComponentExecutorFactory) service;
+ public void removedService(ServiceReference<ComponentExecutorFactory> reference, ComponentExecutorFactory factory) {
ComponentScheduler.instance().unbind(factory);
}
}
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AdapterServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AdapterServiceImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AdapterServiceImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AdapterServiceImpl.java Mon Feb 6 14:37:49 2017
@@ -38,7 +38,8 @@ import org.osgi.framework.ServiceReferen
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class AdapterServiceImpl extends FilterComponent {
- /**
+
+ /**
* Creates a new Adapter Service implementation.
*
* @param dm the dependency manager used to create our internal adapter service
@@ -89,7 +90,7 @@ public class AdapterServiceImpl extends
}
public Component createService(Object[] properties) {
- ServiceReference ref = (ServiceReference) properties[0];
+ ServiceReference<?> ref = (ServiceReference<?>) properties[0];
Object aspect = ref.getProperty(DependencyManager.ASPECT);
String serviceIdToTrack = (aspect != null) ? aspect.toString() : ref.getProperty(Constants.SERVICE_ID).toString();
List<DependencyContext> dependencies = m_component.getDependencies();
@@ -133,7 +134,7 @@ public class AdapterServiceImpl extends
return "Adapter for " + m_adapteeInterface + ((m_adapteeFilter != null) ? " with filter " + m_adapteeFilter : "");
}
- public Dictionary<String, Object> getServiceProperties(ServiceReference ref) {
+ public Dictionary<String, Object> getServiceProperties(ServiceReference<?> ref) {
Dictionary<String, Object> props = new Hashtable<>();
if (m_serviceProperties != null) {
Enumeration<String> e = m_serviceProperties.keys();
@@ -145,16 +146,16 @@ public class AdapterServiceImpl extends
return props;
}
- public Dictionary<String, Object> propagateAdapteeProperties(ServiceReference ref) {
+ public Dictionary<String, Object> propagateAdapteeProperties(ServiceReference<?> ref) {
Dictionary<String, Object> props = new Hashtable<>();
String[] keys = ref.getPropertyKeys();
for (int i = 0; i < keys.length; i++) {
String key = keys[i];
- if (key.equals(DependencyManager.ASPECT) || key.equals(Constants.SERVICE_ID) || key.equals(Constants.SERVICE_RANKING) || key.equals(Constants.OBJECTCLASS)) {
- // do not copy these either
+ if (ServiceUtil.NOT_PROPAGATABLE_SERVICE_PROPERTIES.contains(key)) {
+ // do not copy this key which is not propagatable.
}
else {
- props.put(key, ref.getProperty(key));
+ props.put(key, ref.getProperty(key));
}
}
return props;
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AspectServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AspectServiceImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AspectServiceImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AspectServiceImpl.java Mon Feb 6 14:37:49 2017
@@ -19,14 +19,11 @@
package org.apache.felix.dm.impl;
import java.util.ArrayList;
-import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
-import java.util.Map;
import org.apache.felix.dm.Component;
-import org.apache.felix.dm.ComponentStateListener;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.ServiceDependency;
import org.apache.felix.dm.context.DependencyContext;
@@ -44,7 +41,7 @@ public class AspectServiceImpl extends F
private final String m_swap;
private final int m_ranking;
private final Object m_dependencyCallbackInstance;
-
+
public AspectServiceImpl(DependencyManager dm, Class<?> aspectInterface, String aspectFilter, int ranking, String autoConfig, Object callbackInstance, String add, String change, String remove, String swap) {
super(dm.createComponent());
m_ranking = ranking;
@@ -56,10 +53,10 @@ public class AspectServiceImpl extends F
m_component.setImplementation(new AspectImpl(aspectInterface, autoConfig))
.add(dm.createServiceDependency()
- .setService(aspectInterface, createDependencyFilterForAspect(aspectFilter))
- .setAutoConfig(false)
- .setCallbacks("added", "removed"))
- .setCallbacks("init", null, "stop", null);
+ .setService(aspectInterface, createDependencyFilterForAspect(aspectFilter))
+ .setAutoConfig(false)
+ .setCallbacks("added", "removed"))
+ .setCallbacks("init", null, "stop", null);
// m_component.setDebug("aspectfactory-" + m_ranking);
}
@@ -74,18 +71,8 @@ public class AspectServiceImpl extends F
}
}
- private Hashtable<String, Object> getServiceProperties(ServiceReference ref) {
+ private Hashtable<String, Object> getServiceProperties(ServiceReference<?> originalServiceRef) {
Hashtable<String, Object> props = new Hashtable<>();
- String[] keys = ref.getPropertyKeys();
- for (int i = 0; i < keys.length; i++) {
- String key = keys[i];
- if (key.equals(Constants.SERVICE_ID) || key.equals(Constants.SERVICE_RANKING) || key.equals(DependencyManager.ASPECT) || key.equals(Constants.OBJECTCLASS)) {
- // do not copy these
- }
- else {
- props.put(key, ref.getProperty(key));
- }
- }
if (m_serviceProperties != null) {
Enumeration<String> e = m_serviceProperties.keys();
while (e.hasMoreElements()) {
@@ -93,15 +80,10 @@ public class AspectServiceImpl extends F
props.put(key, m_serviceProperties.get(key));
}
}
- // finally add our aspect property
- props.put(DependencyManager.ASPECT, ref.getProperty(Constants.SERVICE_ID));
- // and the ranking
- props.put(Constants.SERVICE_RANKING, Integer.valueOf(m_ranking));
return props;
}
-
+
class AspectImpl extends AbstractDecorator {
-
private final Class<?> m_aspectInterface;
private final String m_autoConfig;
@@ -114,25 +96,24 @@ public class AspectServiceImpl extends F
* Creates an aspect implementation component for a new original service.
* @param param First entry contains the ref to the original service
*/
+ @SuppressWarnings("unchecked")
@Override
public Component createService(Object[] params) {
// Get the new original service reference.
- ServiceReference ref = (ServiceReference) params[0];
+ ServiceReference<?> originalServiceRef = (ServiceReference<Object>) params[0];
List<DependencyContext> dependencies = m_component.getDependencies();
- // remove our internal dependency, replace it with one that points to the specific service that just was passed in.
+ // Remove our internal dependency, replace it with one that points to the specific service that just was passed in.
dependencies.remove(0);
- Hashtable<String, Object> serviceProperties = getServiceProperties(ref);
+ Hashtable<String, Object> serviceProperties = getServiceProperties(originalServiceRef);
String[] serviceInterfaces = getServiceInterfaces();
- ServiceDependency aspectDependency = (ServiceDependencyImpl)
- m_manager.createServiceDependency().setService(m_aspectInterface, createAspectFilter(ref)).setRequired(true);
+ ServiceDependency aspectDependency = (ServiceDependencyImpl) m_manager.createServiceDependency()
+ .setService(m_aspectInterface, createAspectFilter(originalServiceRef))
+ .setRequired(true)
+ .setPropagate(new AspectPropagateCallback(originalServiceRef), "propagateAspectPropertyChange")
+ .setCallbacks(m_dependencyCallbackInstance, m_add, m_change, m_remove, m_swap);
+
//aspectDependency.setDebug("aspect " + m_ranking);
-
- aspectDependency.setCallbacks(new CallbackProxy(aspectDependency, ref),
- m_add != null ? "addAspect" : null,
- "changeAspect", // We have to propagate in case aspect does not have a change callback
- m_remove != null ? "removeAspect" : null,
- m_swap != null ? "swapAspect" : null);
if (m_autoConfig != null) {
aspectDependency.setAutoConfig(m_autoConfig);
@@ -151,31 +132,12 @@ public class AspectServiceImpl extends F
//service.setDebug("aspectimpl-" + m_ranking);
- configureAutoConfigState(service, m_component);
-
+ configureAutoConfigState(service, m_component);
copyDependencies(dependencies, service);
-
- for (int i = 0; i < m_stateListeners.size(); i++) {
- service.add((ComponentStateListener) m_stateListeners.get(i));
- }
+ m_stateListeners.forEach(service::add);
return service;
}
-
- /**
- * Modify some specific aspect service properties.
- */
- @Override
- public void setServiceProperties(Dictionary<?,?> props) {
- for (Map.Entry<Object, Component> e : super.getServices().entrySet()) {
- ServiceReference originalServiceRef = (ServiceReference) e.getKey();
- Component c = e.getValue();
- // m_serviceProperties is already set to the new service properties; and the getServiceProperties will
- // merge m_serviceProperties with the original service properties.
- Dictionary<String, Object> newProps = getServiceProperties(originalServiceRef);
- c.setServiceProperties(newProps);
- }
- }
-
+
private String[] getServiceInterfaces() {
List<String> serviceNames = new ArrayList<>();
// Of course, we provide the aspect interface.
@@ -188,10 +150,10 @@ public class AspectServiceImpl extends F
}
}
}
- return (String[]) serviceNames.toArray(new String[serviceNames.size()]);
+ return serviceNames.toArray(new String[serviceNames.size()]);
}
- private String createAspectFilter(ServiceReference ref) {
+ private String createAspectFilter(ServiceReference<?> ref) {
Long sid = (Long) ref.getProperty(Constants.SERVICE_ID);
return "(&(|(!(" + Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=" + (m_ranking - 1) + "))(|(" + Constants.SERVICE_ID + "=" + sid + ")(" + DependencyManager.ASPECT + "=" + sid + ")))";
}
@@ -201,61 +163,31 @@ public class AspectServiceImpl extends F
}
}
- class CallbackProxy {
- private final ServiceDependencyImpl m_aspectDependency;
- private final ServiceReference m_originalServiceRef;
-
- CallbackProxy(ServiceDependency aspectDependency, ServiceReference originalServiceRef) {
- m_aspectDependency = (ServiceDependencyImpl) aspectDependency;
- m_originalServiceRef = originalServiceRef;
- }
+ class AspectPropagateCallback {
+ private final ServiceReference<?> m_originalServiceRef;
- private Object[] getDependencyCallbackInstance() {
- return m_dependencyCallbackInstance == null ? m_aspectDependency.getComponentContext().getInstances() : new Object[] { m_dependencyCallbackInstance };
- }
-
- @SuppressWarnings("unused")
- private void addAspect(Component c, ServiceReference ref, Object service) {
- // Just forward "add" service dependency callback.
-
- // Invoke is done on dependency.getInstances() which unfortunately returns this callback instance...
- ServiceEventImpl event = new ServiceEventImpl(ref, service);
- m_aspectDependency.invoke(m_add, event, getDependencyCallbackInstance());
- }
-
- @SuppressWarnings("unused")
- private void changeAspect(Component c, ServiceReference ref, Object service) {
- // Invoke "change" service dependency callback
- if (m_change != null) {
- ServiceEventImpl event = new ServiceEventImpl(ref, service);
- m_aspectDependency.invoke(m_change, event, getDependencyCallbackInstance());
- }
- // Propagate change to immediate higher aspect, or to client using our aspect.
- // We always propagate our own properties, and the ones from the original service, but we don't inherit
- // from lower ranked aspect service properties.
- Dictionary<String, Object> props = getServiceProperties(m_originalServiceRef);
- c.setServiceProperties(props);
- }
-
- @SuppressWarnings("unused")
- private void removeAspect(Component c, ServiceReference ref, Object service) {
- // Just forward "remove" service dependency callback.
- ServiceEventImpl event = new ServiceEventImpl(ref, service);
- m_aspectDependency.invoke(m_remove, event, getDependencyCallbackInstance());
- }
-
- @SuppressWarnings("unused")
- private void swapAspect(Component c, ServiceReference prevRef, Object prev, ServiceReference currRef,
- Object curr) {
- Object[] instances = m_aspectDependency.getComponentContext().getInstances();
- // Just forward "swap" service dependency callback.
- m_aspectDependency.invokeSwap(m_swap, prevRef, prev, currRef, curr, getDependencyCallbackInstance());
- }
+ AspectPropagateCallback(ServiceReference<?> originalServiceRef) {
+ m_originalServiceRef = originalServiceRef;
+ }
- @Override
- public String toString() {
- return "CallbackProxy";
- }
- }
-
+ Hashtable<String, Object> propagateAspectPropertyChange(ServiceReference<?> ref) {
+ // ignore ref, which might come from a lower ranked aspect only apply original service ref.
+ Hashtable<String, Object> props = new Hashtable<>();
+ String[] keys = m_originalServiceRef.getPropertyKeys();
+ for (int i = 0; i < keys.length; i++) {
+ String key = keys[i];
+ if (ServiceUtil.NOT_PROPAGATABLE_SERVICE_PROPERTIES.contains(key)) {
+ // do not copy this key, which is not propagatable.
+ }
+ else {
+ props.put(key, m_originalServiceRef.getProperty(key));
+ }
+ }
+ // finally add our aspect property
+ props.put(DependencyManager.ASPECT, m_originalServiceRef.getProperty(Constants.SERVICE_ID));
+ // and the ranking
+ props.put(Constants.SERVICE_RANKING, Integer.valueOf(m_ranking));
+ return props;
+ }
+ }
}
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/BundleDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/BundleDependencyImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/BundleDependencyImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/BundleDependencyImpl.java Mon Feb 6 14:37:49 2017
@@ -149,7 +149,7 @@ public class BundleDependencyImpl extend
}
Filter filter = m_filter;
if (filter != null) {
- Dictionary<?,?> headers = bundle.getHeaders();
+ Dictionary<String,?> headers = bundle.getHeaders();
if (!m_filter.match(headers)) {
return null;
}
@@ -246,7 +246,7 @@ public class BundleDependencyImpl extend
throw new IllegalStateException("Could not invoke callback");
}
else {
- return (Dictionary<String, Object>) bundle.getHeaders();
+ return ServiceUtil.toR6Dictionary(bundle.getHeaders());
}
}
else {
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/BundleEventImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/BundleEventImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/BundleEventImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/BundleEventImpl.java Mon Feb 6 14:37:49 2017
@@ -42,7 +42,8 @@ public class BundleEventImpl extends Eve
@SuppressWarnings("unchecked")
@Override
public Dictionary<String, Object> getProperties() {
- return getBundle().getHeaders();
+ return ServiceUtil.toR6Dictionary(getBundle().getHeaders());
+
}
public BundleEvent getBundleEvent() {
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ComponentImpl.java Mon Feb 6 14:37:49 2017
@@ -21,6 +21,7 @@ package org.apache.felix.dm.impl;
import static org.apache.felix.dm.ComponentState.INACTIVE;
import static org.apache.felix.dm.ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED;
import static org.apache.felix.dm.ComponentState.STARTING;
+import static org.apache.felix.dm.ComponentState.STARTED;
import static org.apache.felix.dm.ComponentState.STOPPED;
import static org.apache.felix.dm.ComponentState.STOPPING;
import static org.apache.felix.dm.ComponentState.TRACKING_OPTIONAL;
@@ -46,6 +47,8 @@ import java.util.concurrent.CopyOnWriteA
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentDeclaration;
@@ -74,7 +77,7 @@ public class ComponentImpl implements Co
/**
* NullObject ServiceRegistration that is injected in components that don't provide any services.
*/
- private static final ServiceRegistration NULL_REGISTRATION = (ServiceRegistration) Proxy
+ private static final ServiceRegistration<?> NULL_REGISTRATION = (ServiceRegistration<?>) Proxy
.newProxyInstance(ComponentImpl.class.getClassLoader(),
new Class[] { ServiceRegistration.class },
new DefaultNullObject());
@@ -115,7 +118,7 @@ public class ComponentImpl implements Co
/**
* List of Component state listeners. We use a COW list in order to avoid ConcurrentModificationException while iterating on the
- * list and while a component synchronously add more listeners from one of its callback method.
+ * list and while a component synchronously adds more listeners from one of its callback method.
*/
private final List<ComponentStateListener> m_listeners = new CopyOnWriteArrayList<>();
@@ -162,7 +165,7 @@ public class ComponentImpl implements Co
/**
* The component service registration. Can be a NullObject in case the component does not provide a service.
*/
- private volatile ServiceRegistration m_registration;
+ private volatile ServiceRegistration<?> m_registration;
/**
* Map of auto configured fields (BundleContext, ServiceRegistration, DependencyManager, or Component).
@@ -566,6 +569,39 @@ public class ComponentImpl implements Co
}
}
+
+ public void invokeCallback(Object[] instances, String methodName, Class<?>[][] signatures, Supplier<?>[][] parameters, boolean logIfNotFound) {
+ boolean callbackFound = false;
+ for (int i = 0; i < instances.length; i++) {
+ try {
+ InvocationUtil.invokeCallbackMethod(instances[i], methodName, signatures, parameters);
+ callbackFound |= true;
+ }
+ catch (NoSuchMethodException e) {
+ // if the method does not exist, ignore it
+ }
+ catch (InvocationTargetException e) {
+ // the method itself threw an exception, log that
+ m_logger.log(Logger.LOG_ERROR, "Invocation of '" + methodName + "' failed.", e.getCause());
+ callbackFound |= true;
+ }
+ catch (Throwable e) {
+ m_logger.log(Logger.LOG_ERROR, "Could not invoke '" + methodName + "'.", e);
+ }
+ }
+
+ // If the callback is not found, we don't log if the method is on an AbstractDecorator.
+ // (Aspect or Adapter are not interested in user dependency callbacks)
+ if (logIfNotFound && ! callbackFound && ! (getInstance() instanceof AbstractDecorator)) {
+ if (m_logger == null) {
+ System.out.println("\"" + methodName + "\" callback not found on component instances "
+ + Arrays.toString(instances));
+ } else {
+ m_logger.log(LogService.LOG_ERROR, "\"" + methodName + "\" callback not found on component instances "
+ + Arrays.toString(instances));
+ }
+ }
+ }
@Override
public boolean isAvailable() {
@@ -625,7 +661,8 @@ public class ComponentImpl implements Co
return this;
}
- @Override
+ @SuppressWarnings("rawtypes")
+ @Override
public ServiceRegistration getServiceRegistration() {
return m_registration;
}
@@ -635,7 +672,7 @@ public class ComponentImpl implements Co
public <K,V> Dictionary<K, V> getServiceProperties() {
if (m_serviceProperties != null) {
// Applied patch from FELIX-4304
- Hashtable<Object, Object> serviceProperties = new Hashtable<>();
+ Hashtable<String, Object> serviceProperties = new Hashtable<>();
addTo(serviceProperties, m_serviceProperties);
return (Dictionary<K, V>) serviceProperties;
}
@@ -646,7 +683,7 @@ public class ComponentImpl implements Co
@SuppressWarnings("unchecked")
public Component setServiceProperties(final Dictionary<?, ?> serviceProperties) {
getExecutor().execute(() -> {
- Dictionary<Object, Object> properties = null;
+ Dictionary<String, Object> properties = null;
m_serviceProperties = (Dictionary<Object, Object>) serviceProperties;
if ((m_registration != null) && (m_serviceName != null)) {
properties = calculateServiceProperties();
@@ -725,7 +762,7 @@ public class ComponentImpl implements Co
}
public String getName() {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
Object serviceName = m_serviceName;
// If the component provides service(s), return the services as the component name.
if (serviceName instanceof String[]) {
@@ -736,10 +773,10 @@ public class ComponentImpl implements Co
}
sb.append(names[i]);
}
- appendProperties(sb);
+ ServiceUtil.appendProperties(sb, calculateServiceProperties());
} else if (serviceName instanceof String) {
sb.append(serviceName.toString());
- appendProperties(sb);
+ ServiceUtil.appendProperties(sb, calculateServiceProperties());
} else {
// The component does not provide a service, use the component definition as the name.
Object componentDefinition = m_componentDefinition;
@@ -765,26 +802,6 @@ public class ComponentImpl implements Co
return sb.toString();
}
- private String toString(Object implementation) {
- if (implementation instanceof Class) {
- return (((Class<?>) implementation).getName());
- } else {
- // If the implementation instance does not override "toString", just display
- // the class name, else display the component using its toString method
- try {
- Method m = implementation.getClass().getMethod("toString", new Class[0]);
- if (m.getDeclaringClass().equals(Object.class)) {
- return implementation.getClass().getName();
- } else {
- return implementation.toString();
- }
- } catch (java.lang.NoSuchMethodException e) {
- // Just display the class name
- return implementation.getClass().getName();
- }
- }
- }
-
@Override
public BundleContext getBundleContext() {
return m_context;
@@ -869,10 +886,9 @@ public class ComponentImpl implements Co
public Map<String, Long> getCallbacksTime() {
return m_stopwatch;
}
-
- // ---------------------- Package/Private methods ---------------------------
-
- void instantiateComponent() {
+
+ @Override
+ public ComponentContext instantiateComponent() {
m_logger.debug("instantiating component.");
// TODO add more complex factory instantiations of one or more components in a composition here
@@ -932,8 +948,31 @@ public class ComponentImpl implements Co
autoConfigureImplementation(DependencyManager.class, m_manager);
autoConfigureImplementation(Component.class, this);
}
+ return this;
}
+ // ---------------------- Package/Private methods ---------------------------
+
+ private String toString(Object implementation) {
+ if (implementation instanceof Class) {
+ return (((Class<?>) implementation).getName());
+ } else {
+ // If the implementation instance does not override "toString", just display
+ // the class name, else display the component using its toString method
+ try {
+ Method m = implementation.getClass().getMethod("toString", new Class[0]);
+ if (m.getDeclaringClass().equals(Object.class)) {
+ return implementation.getClass().getName();
+ } else {
+ return implementation.toString();
+ }
+ } catch (java.lang.NoSuchMethodException e) {
+ // Just display the class name
+ return implementation.getClass().getName();
+ }
+ }
+ }
+
/**
* Runs the state machine, to see if a change event has to trigger some component state transition.
*/
@@ -1004,7 +1043,7 @@ public class ComponentImpl implements Co
notifyListeners(newState);
return true;
}
- if (oldState == ComponentState.WAITING_FOR_REQUIRED && newState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
+ if (oldState == WAITING_FOR_REQUIRED && newState == INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
instantiateComponent();
invokeAutoConfigDependencies();
invokeAddRequiredDependencies();
@@ -1012,17 +1051,18 @@ public class ComponentImpl implements Co
notifyListeners(newState);
return true;
}
- if (oldState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == ComponentState.TRACKING_OPTIONAL) {
+ if (oldState == INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == TRACKING_OPTIONAL) {
invokeAutoConfigInstanceBoundDependencies();
invokeAddRequiredInstanceBoundDependencies();
notifyListeners(STARTING);
invokeStart();
+ notifyListeners(STARTED);
invokeAddOptionalDependencies();
registerService();
notifyListeners(newState);
return true;
}
- if (oldState == ComponentState.TRACKING_OPTIONAL && newState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
+ if (oldState == TRACKING_OPTIONAL && newState == INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
notifyListeners(STOPPING);
unregisterService();
invokeRemoveOptionalDependencies();
@@ -1032,7 +1072,7 @@ public class ComponentImpl implements Co
notifyListeners(STOPPED);
return true;
}
- if (oldState == ComponentState.INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == ComponentState.WAITING_FOR_REQUIRED) {
+ if (oldState == INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == WAITING_FOR_REQUIRED) {
invoke(m_callbackDestroy);
removeInstanceBoundDependencies();
invokeRemoveRequiredDependencies();
@@ -1042,7 +1082,7 @@ public class ComponentImpl implements Co
}
return true;
}
- if (oldState == ComponentState.WAITING_FOR_REQUIRED && newState == ComponentState.INACTIVE) {
+ if (oldState == WAITING_FOR_REQUIRED && newState == INACTIVE) {
stopDependencies();
destroyComponent();
notifyListeners(newState);
@@ -1053,7 +1093,10 @@ public class ComponentImpl implements Co
}
private void cleanup() {
- m_dependencyEvents.values().forEach(eventList -> eventList.clear());
+ m_dependencyEvents.values().forEach(eventList -> {
+ eventList.forEach(event -> event.close());
+ eventList.clear();
+ });
}
private void invokeStart() {
@@ -1203,29 +1246,33 @@ public class ComponentImpl implements Co
}
private void handleSwapped(DependencyContext dc, Event oldEvent, Event newEvent) {
- if (! m_isStarted) {
- return;
- }
- Set<Event> dependencyEvents = m_dependencyEvents.get(dc);
- dependencyEvents.remove(oldEvent);
- dependencyEvents.add(newEvent);
+ try {
+ if (! m_isStarted) {
+ return;
+ }
+ Set<Event> dependencyEvents = m_dependencyEvents.get(dc);
+ dependencyEvents.remove(oldEvent);
+ dependencyEvents.add(newEvent);
- // Depending on the state, we possible have to invoke the callbacks and update the component instance.
- switch (m_state) {
- case WAITING_FOR_REQUIRED:
- // No need to swap, we don't have yet injected anything
- break;
- case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
- // Only swap *non* instance-bound dependencies
- if (!dc.isInstanceBound()) {
- invokeSwapCallback(dc, oldEvent, newEvent);
- }
- break;
- case TRACKING_OPTIONAL:
- invokeSwapCallback(dc, oldEvent, newEvent);
- break;
- default:
- }
+ // Depending on the state, we possible have to invoke the callbacks and update the component instance.
+ switch (m_state) {
+ case WAITING_FOR_REQUIRED:
+ // No need to swap, we don't have yet injected anything
+ break;
+ case INSTANTIATED_AND_WAITING_FOR_REQUIRED:
+ // Only swap *non* instance-bound dependencies
+ if (!dc.isInstanceBound()) {
+ invokeSwapCallback(dc, oldEvent, newEvent);
+ }
+ break;
+ case TRACKING_OPTIONAL:
+ invokeSwapCallback(dc, oldEvent, newEvent);
+ break;
+ default:
+ }
+ } finally {
+ oldEvent.close();
+ }
}
private boolean allRequiredAvailable() {
@@ -1317,10 +1364,10 @@ public class ComponentImpl implements Co
autoConfigureImplementation(ServiceRegistration.class, m_registration);
// service name can either be a string or an array of strings
- ServiceRegistration registration;
+ ServiceRegistration<?> registration;
// determine service properties
- Dictionary<?,?> properties = calculateServiceProperties();
+ Dictionary<String, Object> properties = calculateServiceProperties();
// register the service
try {
@@ -1353,37 +1400,34 @@ public class ComponentImpl implements Co
}
}
- private Dictionary<Object, Object> calculateServiceProperties() {
- Dictionary<Object, Object> properties = new Hashtable<>();
- for (int i = 0; i < m_dependencies.size(); i++) {
- DependencyContext d = (DependencyContext) m_dependencies.get(i);
- if (d.isPropagated() && d.isAvailable()) {
- Dictionary<Object, Object> dict = d.getProperties();
- addTo(properties, dict);
- }
- }
- // our service properties must not be overriden by propagated dependency properties, so we add our service
- // properties after having added propagated dependency properties.
+ private Dictionary<String, Object> calculateServiceProperties() {
+ Dictionary<String, Object> properties = new Hashtable<>();
+ // First add propagated dependency service properties which does not override our component service properties
+ Predicate<DependencyContext> dependencyPropagated = (dc) -> dc.isPropagated() && dc.isAvailable();
+
+ m_dependencies.stream()
+ .filter(dc -> dependencyPropagated.test(dc))
+ .forEach(dc -> addTo(properties, dc.getProperties()));
+
+ // Now add our component service properties, which overrides previously added propagated dependency service properties
addTo(properties, m_serviceProperties);
- if (properties.size() == 0) {
- properties = null;
- }
- return properties;
+
+ return properties.size() == 0 ? null : properties;
}
- private void addTo(Dictionary<Object, Object> properties, Dictionary<Object, Object> additional) {
+ private void addTo(Dictionary<String, Object> properties, Dictionary<?, Object> additional) {
if (properties == null) {
throw new IllegalArgumentException("Dictionary to add to cannot be null.");
}
if (additional != null) {
- Enumeration<Object> e = additional.keys();
+ Enumeration<?> e = additional.keys();
while (e.hasMoreElements()) {
Object key = e.nextElement();
- properties.put(key, additional.get(key));
+ properties.put(key.toString(), additional.get(key));
}
}
}
-
+
private void destroyComponent() {
m_componentInstance = null;
}
@@ -1525,7 +1569,7 @@ public class ComponentImpl implements Co
m_invokeCallbackCache.clear();
}
}
-
+
private void invoke(String name) {
if (name != null) {
// if a callback instance was specified, look for the method there, if not,
@@ -1562,7 +1606,7 @@ public class ComponentImpl implements Co
}
}
- private void autoConfigureImplementation(Class<?> clazz, Object instance) {
+ void autoConfigureImplementation(Class<?> clazz, Object instance) {
if (((Boolean) m_autoConfig.get(clazz)).booleanValue()) {
configureImplementation(clazz, instance, (String) m_autoConfigInstance.get(clazz));
}
@@ -1577,7 +1621,7 @@ public class ComponentImpl implements Co
* @param instance the object to fill in the implementation class(es) field
* @param instanceName the name of the instance to fill in, or <code>null</code> if not used
*/
- private void configureImplementation(Class<?> clazz, Object instance, String fieldName) {
+ void configureImplementation(Class<?> clazz, Object instance, String fieldName) {
Object[] targets = getInstances();
if (! FieldUtil.injectField(targets, fieldName, clazz, instance, m_logger) && fieldName != null) {
// If the target is an abstract decorator (i.e: an adapter, or an aspect), we must not log warnings
@@ -1637,6 +1681,8 @@ public class ComponentImpl implements Co
m_logger.log(Logger.LOG_ERROR, "Could not obtain instances from the composition manager.", e);
instances = m_componentInstance == null ? new Object[] {} : new Object[] { m_componentInstance };
}
+ } else {
+ return new Object[0];
}
}
else {
@@ -1644,38 +1690,6 @@ public class ComponentImpl implements Co
}
return instances;
}
-
- private void appendProperties(StringBuffer result) {
- Dictionary<Object, Object> properties = calculateServiceProperties();
- if (properties != null) {
- result.append("(");
- Enumeration<?> enumeration = properties.keys();
- while (enumeration.hasMoreElements()) {
- Object key = enumeration.nextElement();
- result.append(key.toString());
- result.append('=');
- Object value = properties.get(key);
- if (value instanceof String[]) {
- String[] values = (String[]) value;
- result.append('{');
- for (int i = 0; i < values.length; i++) {
- if (i > 0) {
- result.append(',');
- }
- result.append(values[i].toString());
- }
- result.append('}');
- }
- else {
- result.append(value.toString());
- }
- if (enumeration.hasMoreElements()) {
- result.append(',');
- }
- }
- result.append(")");
- }
- }
/**
* Executes a task using our component queue. The queue associated to this component is by default a "SerialExecutor", or
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ConfigurationDependencyImpl.java Mon Feb 6 14:37:49 2017
@@ -18,6 +18,8 @@
*/
package org.apache.felix.dm.impl;
+import static org.apache.felix.dm.impl.ServiceUtil.toR6Dictionary;
+
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Hashtable;
@@ -48,7 +50,7 @@ import org.osgi.service.cm.ManagedServic
public class ConfigurationDependencyImpl extends AbstractDependency<ConfigurationDependency> implements ConfigurationDependency, ManagedService {
private volatile Dictionary<String, Object> m_settings;
private volatile String m_pid;
- private ServiceRegistration m_registration;
+ private ServiceRegistration<?> m_registration;
private volatile Class<?> m_configType;
private volatile MetaTypeProviderImpl m_metaType;
private boolean m_mayInvokeUpdateCallback;
@@ -179,7 +181,7 @@ public class ConfigurationDependencyImpl
if (m_metaType != null) {
ms = m_metaType;
}
- m_registration = context.registerService(ManagedService.class.getName(), ms, props);
+ m_registration = context.registerService(ManagedService.class.getName(), ms, toR6Dictionary(props));
}
super.start();
}
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FactoryConfigurationAdapterImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FactoryConfigurationAdapterImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FactoryConfigurationAdapterImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FactoryConfigurationAdapterImpl.java Mon Feb 6 14:37:49 2017
@@ -30,6 +30,7 @@ import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.Logger;
import org.apache.felix.dm.PropertyMetaData;
+import org.apache.felix.dm.context.ComponentContext;
import org.apache.felix.dm.impl.metatype.MetaTypeProviderImpl;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -147,7 +148,7 @@ public class FactoryConfigurationAdapter
}
// Instantiate the component, because we need to invoke the updated callback synchronously, in the CM calling thread.
- ((ComponentImpl) newService).instantiateComponent();
+ ((ComponentContext) newService).instantiateComponent();
CallbackTypeDef callbackInfo = createCallbackType(m_logger, newService, m_configType, settings);
invokeUpdated(newService, callbackInfo);
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FilterComponent.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FilterComponent.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FilterComponent.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/FilterComponent.java Mon Feb 6 14:37:49 2017
@@ -24,6 +24,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
+import java.util.function.Supplier;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentDeclaration;
@@ -80,38 +81,39 @@ public class FilterComponent implements
public String toString() {
return m_component.toString();
}
-
+
public Component add(Dependency ... dependencies) {
- m_component.add(dependencies);
- // Add the dependencies to all already instantiated services.
- // If one dependency from the list is required, we have nothing to do, since our internal
- // service will be stopped/restarted.
- for (Dependency dependency : dependencies) {
- if (((DependencyContext) dependency).isRequired()) {
- return this;
- }
- }
- // Ok, the list contains no required dependencies: add optionals dependencies in already instantiated services.
- Object[] instances = m_component.getInstances();
- if (instances.length > 0) {
- AbstractDecorator ad = (AbstractDecorator) instances[0];
- if (ad != null) {
- ad.addDependency(dependencies);
+ m_component.getExecutor().execute(() -> {
+ m_component.add(dependencies);
+ Object instance = m_component.getInstance();
+ if (instance instanceof AbstractDecorator) {
+ AbstractDecorator ad = (AbstractDecorator) instance;
+ ad.addDependency(dependencies); // will clone the dependencies for each component instance
+ }
+ });
+ return this;
+ }
+
+ public Component remove(Dependency dependency) {
+ m_component.getExecutor().execute(() -> {
+ m_component.remove(dependency);
+ Object instance = m_component.getInstance();
+ if (instance != null && instance instanceof AbstractDecorator) {
+ ((AbstractDecorator) instance).removeDependency(dependency); // will remove the previously cloned dependency
}
- }
+ });
return this;
}
public Component add(ComponentStateListener listener) {
- m_stateListeners.add(listener);
- // Add the listener to all already instantiated services.
- Object[] instances = m_component.getInstances();
- if (instances.length > 0) {
- AbstractDecorator ad = (AbstractDecorator) instances[0];
- if (ad != null) {
- ad.addStateListener(listener);
- }
- }
+ m_component.getExecutor().execute(() -> {
+ m_stateListeners.add(listener);
+ // Add the listener to all already instantiated services.
+ Object instance = m_component.getInstance();
+ if (instance instanceof AbstractDecorator) {
+ ((AbstractDecorator) instance).addStateListener(listener);
+ }
+ });
return this;
}
@@ -128,37 +130,16 @@ public class FilterComponent implements
return m_serviceProperties;
}
- public ServiceRegistration getServiceRegistration() {
+ public ServiceRegistration<?> getServiceRegistration() {
return m_component.getServiceRegistration();
}
- public Component remove(Dependency dependency) {
- m_component.remove(dependency);
- // Remove the dependency (if optional) from all already instantiated services.
- // If the dependency is required, our internal service will be stopped, so in this case
- // we have nothing to do.
- if (!((DependencyContext) dependency).isRequired())
- {
- Object[] instances = m_component.getInstances();
- if (instances.length > 0) {
- AbstractDecorator ad = (AbstractDecorator) instances[0];
- if (ad != null) {
- ad.removeDependency(dependency);
- }
- }
- }
- return this;
- }
-
public Component remove(ComponentStateListener listener) {
m_stateListeners.remove(listener);
// Remove the listener from all already instantiated services.
- Object[] instances = m_component.getInstances();
- if (instances.length > 0) {
- AbstractDecorator ad = (AbstractDecorator) instances[0];
- if (ad != null) {
- ad.removeStateListener(listener);
- }
+ Object instance = m_component.getInstance();
+ if (instance != null && instance instanceof AbstractDecorator) {
+ ((AbstractDecorator) instance).removeStateListener(listener);
}
return this;
}
@@ -228,12 +209,9 @@ public class FilterComponent implements
m_serviceProperties = (Dictionary<String, Object>) serviceProperties;
// Set the properties to all already instantiated services.
if (serviceProperties != null) {
- Object[] instances = m_component.getInstances();
- if (instances.length > 0) {
- AbstractDecorator ad = (AbstractDecorator) instances[0];
- if (ad != null) {
- ad.setServiceProperties(serviceProperties);
- }
+ Object instance = m_component.getInstance();
+ if (instance instanceof AbstractDecorator) {
+ ((AbstractDecorator) instance).setServiceProperties(serviceProperties);
}
}
return this;
@@ -254,6 +232,10 @@ public class FilterComponent implements
public void invokeCallbackMethod(Object[] instances, String methodName, Class<?>[][] signatures, Object[][] parameters, boolean logIfNotFound) {
m_component.invokeCallbackMethod(instances, methodName, signatures, parameters, logIfNotFound);
}
+
+ public void invokeCallback(Object[] instances, String methodName, Class<?>[][] signatures, Supplier<?>[][] paramsSupplier, boolean logIfNotFound) {
+ m_component.invokeCallbackMethod(instances, methodName, signatures, paramsSupplier, logIfNotFound);
+ }
public DependencyManager getDependencyManager() {
return m_component.getDependencyManager();
@@ -367,10 +349,11 @@ public class FilterComponent implements
}
protected void copyDependencies(List<DependencyContext> dependencies, Component component) {
- for (DependencyContext dc : dependencies) {
- DependencyContext copy = dc.createCopy();
-
- component.add(copy);
- }
+ dependencies.stream().map(dc -> dc.createCopy()).forEach(component::add);
}
+
+ @Override
+ public ComponentContext instantiateComponent() {
+ return m_component.instantiateComponent();
+ }
}
\ No newline at end of file
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/InvocationUtil.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/InvocationUtil.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/InvocationUtil.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/InvocationUtil.java Mon Feb 6 14:37:49 2017
@@ -28,7 +28,7 @@ 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 java.util.function.Supplier;
import org.apache.felix.dm.DependencyManager;
import org.osgi.service.cm.ConfigurationException;
@@ -129,6 +129,137 @@ public class InvocationUtil {
throw new NoSuchMethodException(name);
}
+ /**
+ * 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.
+ *
+ * @param instance the instance to invoke the method on
+ * @param methodName the name of the method
+ * @param signatures the ordered list of signatures to look for
+ * @param parameters the parameter values to use for each potential signature
+ * @return whatever the method returns
+ * @throws NoSuchMethodException when no method could be found
+ * @throws IllegalArgumentException when illegal values for this methods arguments are supplied
+ * @throws IllegalAccessException when the method cannot be accessed
+ * @throws InvocationTargetException when the method that was invoked throws an exception
+ */
+ public static Object invokeCallbackMethod(Object instance, String methodName, Class<?>[][] signatures, Supplier<?>[][] parameters) throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
+ Class<?> currentClazz = instance.getClass();
+ while (currentClazz != null && currentClazz != Object.class) {
+ try {
+ return invokeMethod(instance, currentClazz, methodName, signatures, parameters, false);
+ }
+ catch (NoSuchMethodException nsme) {
+ // ignore
+ }
+ currentClazz = currentClazz.getSuperclass();
+ }
+ throw new NoSuchMethodException(methodName);
+ }
+
+ /**
+ * Invoke a method on an instance.
+ *
+ * @param object the instance to invoke the method on
+ * @param clazz the class of the instance
+ * @param name the name of the method
+ * @param signatures the signatures to look for in order
+ * @param paramsSupplier the parameter values for the signatures
+ * @param isSuper <code>true</code> if this is a superclass and we should therefore not look for private methods
+ * @return whatever the method returns
+ * @throws NoSuchMethodException when no method could be found
+ * @throws IllegalArgumentException when illegal values for this methods arguments are supplied
+ * @throws IllegalAccessException when the method cannot be accessed
+ * @throws InvocationTargetException when the method that was invoked throws an exception
+ */
+ public static Object invokeMethod(Object object, Class<?> clazz, String name, Class<?>[][] signatures, Supplier<?>[][] paramsSupplier, boolean isSuper) throws NoSuchMethodException, InvocationTargetException, IllegalArgumentException, IllegalAccessException {
+ if (object == null) {
+ throw new IllegalArgumentException("Instance cannot be null");
+ }
+ if (clazz == null) {
+ throw new IllegalArgumentException("Class cannot be null");
+ }
+
+ // if we're talking to a proxy here, dig one level deeper to expose the
+ // underlying invocation handler (we do the same for injecting instances)
+ if (Proxy.isProxyClass(clazz)) {
+ object = Proxy.getInvocationHandler(object);
+ clazz = object.getClass();
+ }
+
+ Method m = null;
+ for (int i = 0; i < signatures.length; i++) {
+ Class<?>[] signature = signatures[i];
+ m = getDeclaredMethod(clazz, name, signature, isSuper);
+ if (m != null) {
+ Object[] params = new Object[paramsSupplier[i].length];
+ for (int j = 0; j < params.length; j ++) {
+ params[j] = paramsSupplier[i][j].get();
+ }
+ return m.invoke(object, params);
+ }
+ }
+ throw new NoSuchMethodException(name);
+ }
+
+ /**
+ * Gets 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, get the first one it finds.
+ *
+ * @param instance the instance to invoke the method on
+ * @param methodName the name of the method
+ * @param signatures the ordered list of signatures to look for
+ * @return the method found, or null
+ */
+ public static Method getCallbackMethod(Object instance, String methodName, Class<?>[][] signatures) {
+ Class<?> currentClazz = instance.getClass();
+ while (currentClazz != null && currentClazz != Object.class) {
+ Method m = getMethod(instance, currentClazz, methodName, signatures, false);
+ if (m != null) {
+ return m;
+ }
+ currentClazz = currentClazz.getSuperclass();
+ }
+ return null;
+ }
+
+ /**
+ * Get a method on an instance.
+ * TODO: rework this class to avoid code duplication with invokeMethod !
+ *
+ * @param object the instance to invoke the method on
+ * @param clazz the class of the instance
+ * @param name the name of the method
+ * @param signatures the signatures to look for in order
+ * @param isSuper <code>true</code> if this is a superclass and we should therefore not look for private methods
+ * @return the found method, or null if not found
+ */
+ public static Method getMethod(Object object, Class<?> clazz, String name, Class<?>[][] signatures, boolean isSuper) {
+ if (object == null) {
+ throw new IllegalArgumentException("Instance cannot be null");
+ }
+ if (clazz == null) {
+ throw new IllegalArgumentException("Class cannot be null");
+ }
+
+ // if we're talking to a proxy here, dig one level deeper to expose the
+ // underlying invocation handler (we do the same for injecting instances)
+ if (Proxy.isProxyClass(clazz)) {
+ object = Proxy.getInvocationHandler(object);
+ clazz = object.getClass();
+ }
+
+ Method m = null;
+ for (int i = 0; i < signatures.length; i++) {
+ Class<?>[] signature = signatures[i];
+ m = getDeclaredMethod(clazz, name, signature, isSuper);
+ if (m != null) {
+ break;
+ }
+ }
+ return m;
+ }
+
private static Method getDeclaredMethod(Class<?> clazz, String name, Class<?>[] signature, boolean isSuper) {
// first check our cache
Key key = new Key(clazz, name, signature);
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ResourceDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ResourceDependencyImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ResourceDependencyImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ResourceDependencyImpl.java Mon Feb 6 14:37:49 2017
@@ -38,7 +38,7 @@ import org.osgi.framework.ServiceRegistr
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class ResourceDependencyImpl extends AbstractDependency<ResourceDependency> implements ResourceDependency, ResourceHandler, ComponentDependencyDeclaration {
- private volatile ServiceRegistration m_registration;
+ private volatile ServiceRegistration<?> m_registration;
private volatile String m_resourceFilter;
private volatile URL m_trackedResource;
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceDependencyImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceDependencyImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceDependencyImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceDependencyImpl.java Mon Feb 6 14:37:49 2017
@@ -27,6 +27,7 @@ import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
+import java.util.function.Supplier;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentDeclaration;
@@ -51,13 +52,14 @@ public class ServiceDependencyImpl exten
protected volatile Class<?> m_trackedServiceName;
private volatile String m_trackedServiceFilter;
private volatile String m_trackedServiceFilterUnmodified;
- private volatile ServiceReference m_trackedServiceReference;
+ private volatile ServiceReference<?> m_trackedServiceReference;
private volatile Object m_defaultImplementation;
private volatile Object m_defaultImplementationInstance;
private volatile Object m_nullObject;
private volatile boolean m_debug = false;
private volatile String m_debugKey;
private volatile long m_trackedServiceReferenceId;
+ private volatile boolean m_obtainServiceBeforeInjection = true;
public ServiceDependency setDebug(String debugKey) {
m_debugKey = debugKey;
@@ -117,9 +119,9 @@ public class ServiceDependencyImpl exten
* Wraps service properties behind a Map.
*/
private final static class ServicePropertiesMap extends AbstractMap<String, Object> {
- private final ServiceReference m_ref;
+ private final ServiceReference<?> m_ref;
- public ServicePropertiesMap(ServiceReference ref) {
+ public ServicePropertiesMap(ServiceReference<?> ref) {
m_ref = ref;
}
@@ -196,10 +198,17 @@ public class ServiceDependencyImpl exten
return this;
}
- public ServiceDependency setService(Class<?> serviceName, ServiceReference serviceReference) {
+ @SuppressWarnings("rawtypes")
+ public ServiceDependency setService(Class<?> serviceName, ServiceReference serviceReference) {
setService(serviceName, serviceReference, null);
return this;
}
+
+ @Override
+ public ServiceDependency setDereference(boolean obtainServiceBeforeInjection) {
+ m_obtainServiceBeforeInjection = obtainServiceBeforeInjection;
+ return this;
+ }
@Override
public void start() {
@@ -235,9 +244,17 @@ public class ServiceDependencyImpl exten
}
@Override
- public Object addingService(ServiceReference reference) {
+ public Object addingService(@SuppressWarnings("rawtypes") ServiceReference reference) {
try {
- return m_component.getBundleContext().getService(reference);
+ ServiceEventImpl event = new ServiceEventImpl(m_component, reference, null);
+ if (m_obtainServiceBeforeInjection) {
+ Object service = event.getEvent(); // will dereference the service object.
+ if (service == null) {
+ // service concurrently removed, ignore
+ return null;
+ }
+ }
+ return event;
} catch (IllegalStateException e) {
// most likely our bundle is being stopped. Only log an exception if our component is enabled.
if (m_component.isActive()) {
@@ -249,26 +266,57 @@ public class ServiceDependencyImpl exten
}
@Override
- public void addedService(ServiceReference reference, Object service) {
+ public void addedService(@SuppressWarnings("rawtypes") ServiceReference reference, Object event) {
+ ServiceEventImpl evt = (ServiceEventImpl) event;
if (m_debug) {
- System.out.println(m_debugKey + " addedService: ref=" + reference + ", service=" + service);
+ System.out.println(m_debugKey + " addedService: ref=" + reference);
}
- m_component.handleEvent(this, EventType.ADDED,
- new ServiceEventImpl(m_component.getBundle(), m_component.getBundleContext(), reference, service));
+ m_component.handleEvent(this, EventType.ADDED, evt);
}
@Override
- public void modifiedService(ServiceReference reference, Object service) {
- m_component.handleEvent(this, EventType.CHANGED,
- new ServiceEventImpl(m_component.getBundle(), m_component.getBundleContext(), reference, service));
+ public void modifiedService(@SuppressWarnings("rawtypes") ServiceReference reference, Object event) {
+ ServiceEventImpl evt = (ServiceEventImpl) event;
+ m_component.handleEvent(this, EventType.CHANGED, evt);
}
@Override
- public void removedService(ServiceReference reference, Object service) {
- m_component.handleEvent(this, EventType.REMOVED,
- new ServiceEventImpl(m_component.getBundle(), m_component.getBundleContext(), reference, service));
+ public void removedService(@SuppressWarnings("rawtypes") ServiceReference reference, Object event) {
+ ServiceEventImpl evt = (ServiceEventImpl) event;
+ m_component.handleEvent(this, EventType.REMOVED, evt);
}
+ @SuppressWarnings("rawtypes")
+ @Override
+ public void swappedService(final ServiceReference reference, final Object service, final ServiceReference newReference, final Object newService) {
+ ServiceEventImpl evt = (ServiceEventImpl) service;
+ ServiceEventImpl newEvt = (ServiceEventImpl) newService;
+
+ if (m_obtainServiceBeforeInjection) {
+ try {
+ newEvt.getEvent();
+ } catch (IllegalStateException e) {
+ // most likely our bundle is being stopped. Only log an exception if our component is enabled.
+ if (m_component.isActive()) {
+ m_component.getLogger().warn("could not handle service dependency for component %s", e,
+ m_component.getComponentDeclaration().getClassName());
+ }
+ return;
+ }
+ }
+
+ if (m_swap != null) {
+ // it will not trigger a state change, but the actual swap should be scheduled to prevent things
+ // getting out of order.
+ // We delegate the swap handling to the ComponentImpl, which is the class responsible for state management.
+ // The ComponentImpl will first check if the component is in the proper state so the swap method can be invoked.
+ m_component.handleEvent(this, EventType.SWAPPED, evt, newEvt);
+ } else {
+ addedService(newReference, newService);
+ removedService(reference, service);
+ }
+ }
+
@Override
public void invokeCallback(EventType type, Event ... events) {
switch (type) {
@@ -289,10 +337,9 @@ public class ServiceDependencyImpl exten
break;
case SWAPPED:
if (m_swap != null) {
- ServiceEventImpl oldE = (ServiceEventImpl) events[0];
- ServiceEventImpl newE = (ServiceEventImpl) events[1];
- invokeSwap(m_swap, oldE.getReference(), oldE.getEvent(), newE.getReference(), newE.getEvent(),
- getInstances());
+ ServiceEventImpl oldEvent = (ServiceEventImpl) events[0];
+ ServiceEventImpl newEvent = (ServiceEventImpl) events[1];
+ invokeSwap(m_swap, oldEvent, newEvent, getInstances());
}
break;
}
@@ -381,7 +428,7 @@ public class ServiceDependencyImpl exten
}
/** Internal method to set the name, service reference and/or filter. */
- private void setService(Class<?> serviceName, ServiceReference serviceReference, String serviceFilter) {
+ private void setService(Class<?> serviceName, ServiceReference<?> serviceReference, String serviceFilter) {
ensureNotActive();
if (serviceName == null) {
m_trackedServiceName = Object.class;
@@ -461,9 +508,11 @@ public class ServiceDependencyImpl exten
public void invoke(String method, Event e, Object[] instances) {
ServiceEventImpl se = (ServiceEventImpl) e;
- ServicePropertiesMap propertiesMap = new ServicePropertiesMap(se.getReference());
- Dictionary<?,?> properties = se.getProperties();
- m_component.invokeCallbackMethod(instances, method,
+ // Be as lazy as possible, in case no properties or map has to be injected
+ Supplier<Dictionary<?,?>> properties = () -> se.getProperties();
+ Supplier<ServicePropertiesMap> propertiesMap = () -> new ServicePropertiesMap(se.getReference());
+
+ m_component.invokeCallback(instances, method,
new Class[][]{
{Component.class, ServiceReference.class, m_trackedServiceName},
{Component.class, ServiceReference.class, Object.class},
@@ -480,37 +529,37 @@ public class ServiceDependencyImpl exten
{Map.class, m_trackedServiceName},
{m_trackedServiceName, Dictionary.class},
{Dictionary.class, m_trackedServiceName},
- {Object.class},
+ {Object.class},
{}},
- new Object[][]{
- {m_component, se.getReference(), se.getEvent()},
- {m_component, se.getReference(), se.getEvent()},
- {m_component, se.getReference()},
- {m_component, se.getEvent()},
- {m_component, se.getEvent()},
- {m_component},
- {m_component, propertiesMap, se.getEvent()},
- {se.getReference(), se.getEvent()},
- {se.getReference(), se.getEvent()},
- {se.getReference()},
- {se.getEvent()},
- {se.getEvent(), propertiesMap},
- {propertiesMap, se.getEvent()},
- {se.getEvent(), properties},
- {properties, se.getEvent()},
- {se.getEvent()},
- {}}
+ new Supplier[][]{
+ new Supplier<?>[] {() -> m_component, () -> se.getReference(), () -> se.getEvent()},
+ new Supplier<?>[] {() -> m_component, () -> se.getReference(), () -> se.getEvent()},
+ new Supplier<?>[] {() -> m_component, () -> se.getReference()},
+ new Supplier<?>[] {() -> m_component, () -> se.getEvent()},
+ new Supplier<?>[] {() -> m_component, () -> se.getEvent()},
+ new Supplier<?>[] {() -> m_component},
+ new Supplier<?>[] {() -> m_component, () -> propertiesMap.get(), () -> se.getEvent()},
+ new Supplier<?>[] {() -> se.getReference(), () -> se.getEvent()},
+ new Supplier<?>[] {() -> se.getReference(), () -> se.getEvent()},
+ new Supplier<?>[] {() -> se.getReference()},
+ new Supplier<?>[] {() -> se.getEvent()},
+ new Supplier<?>[] {() -> se.getEvent(), () -> propertiesMap.get()},
+ new Supplier<?>[] {() -> propertiesMap.get(), () -> se.getEvent()},
+ new Supplier<?>[] {() -> se.getEvent(), () -> properties.get()},
+ new Supplier<?>[] {() -> properties.get(), () -> se.getEvent()},
+ new Supplier<?>[] {() -> se.getEvent()},
+ {}},
+ true // log if method is not found
);
}
- public void invokeSwap(String swapMethod, ServiceReference previousReference, Object previous,
- ServiceReference currentReference, Object current, Object[] instances) {
+ private void invokeSwap(String swapMethod, ServiceEventImpl previous, ServiceEventImpl current, Object[] instances) {
if (m_debug) {
System.out.println("invoke swap: " + swapMethod + " on component " + m_component + ", instances: " + Arrays.toString(instances) + " - " + ((ComponentDeclaration)m_component).getState());
}
try {
- m_component.invokeCallbackMethod(instances, swapMethod,
+ m_component.invokeCallback(instances, swapMethod,
new Class[][]{
{m_trackedServiceName, m_trackedServiceName},
{Object.class, Object.class},
@@ -519,35 +568,28 @@ public class ServiceDependencyImpl exten
{Component.class, m_trackedServiceName, m_trackedServiceName},
{Component.class, Object.class, Object.class},
{Component.class, ServiceReference.class, m_trackedServiceName, ServiceReference.class, m_trackedServiceName},
- {Component.class, ServiceReference.class, Object.class, ServiceReference.class, Object.class}},
+ {Component.class, ServiceReference.class, Object.class, ServiceReference.class, Object.class},
+ {ServiceReference.class, ServiceReference.class},
+ {Component.class, ServiceReference.class, ServiceReference.class},
+ },
- new Object[][]{
- {previous, current},
- {previous, current},
- {previousReference, previous, currentReference, current},
- {previousReference, previous, currentReference, current}, {m_component, previous, current},
- {m_component, previous, current}, {m_component, previousReference, previous, currentReference, current},
- {m_component, previousReference, previous, currentReference, current}}
- );
+ new Supplier[][]{
+ new Supplier<?>[] {() -> previous.getEvent(), () -> current.getEvent()},
+ new Supplier<?>[] {() -> previous.getEvent(), () -> current.getEvent()},
+ new Supplier<?>[] {() -> previous.getReference(), () -> previous.getEvent(), () -> current.getReference(), () -> current.getEvent()},
+ new Supplier<?>[] {() -> previous.getReference(), () -> previous.getEvent(), () -> current.getReference(), () -> current.getEvent()},
+ new Supplier<?>[] {() -> m_component, () -> previous.getEvent(), () -> current.getEvent()},
+ new Supplier<?>[] {() -> m_component, () -> previous.getEvent(), () -> current.getEvent()},
+ new Supplier<?>[] {() -> m_component, () -> previous.getReference(), () -> previous.getEvent(), () -> current.getReference(), () -> current.getEvent()},
+ new Supplier<?>[] {() -> m_component, () -> previous.getReference(), () -> previous.getEvent(), () -> current.getReference(), () -> current.getEvent()},
+ new Supplier<?>[] {() -> previous.getReference(), () -> current.getReference()},
+ new Supplier<?>[] {() -> m_component, () -> previous.getReference(), () -> current.getReference()}
+ },
+
+ true); // log if not found
} catch (Throwable e) {
m_component.getLogger().err("Could not invoke swap callback", e);
}
}
-
- @Override
- public void swappedService(final ServiceReference reference, final Object service,
- final ServiceReference newReference, final Object newService) {
- if (m_swap != null) {
- // it will not trigger a state change, but the actual swap should be scheduled to prevent things
- // getting out of order.
- // We delegate the swap handling to the ComponentImpl, which is the class responsible for state management.
- // The ComponentImpl will first check if the component is in the proper state so the swap method can be invoked.
- m_component.handleEvent(this, EventType.SWAPPED,
- new ServiceEventImpl(m_component.getBundle(), m_component.getBundleContext(), reference, service),
- new ServiceEventImpl(m_component.getBundle(), m_component.getBundleContext(), newReference, newService));
- } else {
- addedService(newReference, newService);
- removedService(reference, service);
- }
- }
+
}
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceEventImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceEventImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceEventImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceEventImpl.java Mon Feb 6 14:37:49 2017
@@ -20,21 +20,25 @@ package org.apache.felix.dm.impl;
import java.util.Dictionary;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
+import org.apache.felix.dm.Logger;
+import org.apache.felix.dm.context.ComponentContext;
import org.apache.felix.dm.context.Event;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
/**
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ * An event for a service dependency.
+ * Not thread safe, but this class is assumed to be used under the protection of the component serial queue.
*/
public class ServiceEventImpl extends Event {
/**
* The service reference on which a service dependency depends on
*/
- private final ServiceReference m_reference;
-
+ private final ServiceReference<?> m_reference;
+
/**
* The bundle context of the bundle which has created the service dependency. If not null,
* will be used in close method when ugetting the service reference of the dependency.
@@ -49,19 +53,47 @@ public class ServiceEventImpl extends Ev
/**
* Protects in case close is called twice.
*/
- private final AtomicBoolean m_closed = new AtomicBoolean(false);
+ private final AtomicBoolean m_closed = new AtomicBoolean(false);
- public ServiceEventImpl(ServiceReference reference, Object service) {
- this(null, null, reference, service);
- }
+ /**
+ * Our logger.
+ */
+ private final Logger m_logger;
- public ServiceEventImpl(Bundle bundle, BundleContext bundleContext, ServiceReference reference, Object service) {
+ /**
+ * The actual service.
+ */
+ private volatile Object m_service;
+
+ public ServiceEventImpl(ComponentContext ctx, ServiceReference<?> reference, Object service) {
super(service);
- m_bundle = bundle;
- m_bundleContext = bundleContext;
+ m_service = service;
+ m_bundle = ctx.getBundle();
+ m_bundleContext = ctx.getBundleContext();
m_reference = reference;
- }
-
+ m_logger = ctx.getLogger();
+ }
+
+ /**
+ * Returns the actual service, or null if the service reference is invalid.
+ * @return the service or null if the service is not available anymore.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getEvent() {
+ if (m_service == null) {
+ try {
+ m_service = m_bundleContext.getService(m_reference);
+ if (m_service == null) {
+ debug(() -> "Service " + m_reference + " unavailable");
+ }
+ } catch (Exception t) {
+ error(() -> "Could not get service from service reference " + m_reference, t);
+ }
+ }
+ return (T) m_service;
+ }
+
/**
* Returns the bundle which has declared a service dependency.
*/
@@ -79,10 +111,10 @@ public class ServiceEventImpl extends Ev
/**
* Returns the reference service dependency.
*/
- public ServiceReference getReference() {
+ public ServiceReference<?> getReference() {
return m_reference;
}
-
+
@SuppressWarnings("unchecked")
@Override
public Dictionary<String, Object> getProperties() {
@@ -114,10 +146,24 @@ public class ServiceEventImpl extends Ev
@Override
public void close() {
- if (m_bundleContext != null && m_closed.compareAndSet(false, true)) {
- try {
- m_bundleContext.ungetService(m_reference);
- } catch (IllegalStateException e) {}
+ if (m_closed.compareAndSet(false, true)) {
+ if (m_service != null) {
+ try {
+ m_bundleContext.ungetService(m_reference);
+ } catch (IllegalStateException e) {}
+ }
}
}
+
+ private void error(Supplier<String> msg, Exception err) {
+ if (m_logger != null) {
+ m_logger.err("%s", err, msg.get());
+ }
+ }
+
+ private void debug(Supplier<String> msg) {
+ if (m_logger != null) {
+ m_logger.debug("%s", msg.get());
+ }
+ }
}
\ No newline at end of file
Modified: felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceRegistrationImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceRegistrationImpl.java?rev=1781908&r1=1781907&r2=1781908&view=diff
==============================================================================
--- felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceRegistrationImpl.java (original)
+++ felix/trunk/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/ServiceRegistrationImpl.java Mon Feb 6 14:37:49 2017
@@ -29,20 +29,19 @@ import org.osgi.framework.ServiceRegistr
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public final class ServiceRegistrationImpl implements ServiceRegistration {
+public final class ServiceRegistrationImpl implements ServiceRegistration<Object> {
public static final ServiceRegistrationImpl ILLEGAL_STATE = new ServiceRegistrationImpl();
- private volatile ServiceRegistration m_registration;
+ private volatile ServiceRegistration<Object> m_registration;
public ServiceRegistrationImpl() {
m_registration = null;
}
- public ServiceReference getReference() {
+ public ServiceReference<Object> getReference() {
return ensureRegistration().getReference();
}
- @SuppressWarnings("rawtypes")
- public void setProperties(Dictionary dictionary) {
+ public void setProperties(Dictionary<String, ?> dictionary) {
ensureRegistration().setProperties(dictionary);
}
@@ -62,7 +61,7 @@ public final class ServiceRegistrationIm
return ensureRegistration().toString();
}
- private synchronized ServiceRegistration ensureRegistration() {
+ private synchronized ServiceRegistration<Object> ensureRegistration() {
while (m_registration == null) {
try {
wait();
@@ -82,9 +81,10 @@ public final class ServiceRegistrationIm
/**
* Sets the service registration and notifies all waiting parties.
*/
- void setServiceRegistration(ServiceRegistration registration) {
+ @SuppressWarnings("unchecked")
+ <T> void setServiceRegistration(ServiceRegistration<T> registration) {
synchronized (this) {
- m_registration = registration;
+ m_registration = (ServiceRegistration<Object>) registration;
notifyAll();
}
}