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();
         }
     }