FELIX-5164: Add support for callback instance in Aspects.


git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1724135 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyActivatorBase.java b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyActivatorBase.java
index 9be94f7..07b0b98 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyActivatorBase.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyActivatorBase.java
@@ -222,6 +222,16 @@
     }
     	
     /**
+     * Creates a new aspect service.
+     * 
+     * @return the aspect service
+     * @see DependencyManager#createAspectService(Class, String, int, Object, String, String, String, String)
+     */
+    public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, Object callbackInstance, String add, String change, String remove, String swap) {    
+        return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, callbackInstance, add, change, remove, swap);
+    }
+        
+    /**
      * Creates a new adapter service.
      * 
      * @return the adapter service
diff --git a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyManager.java b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyManager.java
index 7074ef3..d26a10f 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyManager.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/DependencyManager.java
@@ -638,7 +638,7 @@
      * @return a service that acts as a factory for generating aspects
      */
     public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String autoConfig) {
-        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null, null);
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null, null, null);
     }
 
     /**
@@ -664,7 +664,7 @@
      * @return a service that acts as a factory for generating aspects
      */
     public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking) {
-        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null, null);
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, null, null, null, null);
     }
 
     /**
@@ -695,7 +695,7 @@
     public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String add,
         String change, String remove)
     {
-        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, null);
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, add, change, remove, null);
     }
 
     /**
@@ -727,7 +727,40 @@
     public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, String add,
         String change, String remove, String swap)
     {
-        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, add, change, remove, swap);
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, null, add, change, remove, swap);
+    }
+
+    /**
+     * Creates a new aspect. The aspect will be applied to any service that
+     * matches the specified interface and filter. For each matching service
+     * an aspect will be created based on the aspect implementation class.
+     * The aspect will be registered with the same interface and properties
+     * as the original service, plus any extra properties you supply here.
+     * It will also inherit all dependencies, and if you declare the original
+     * service as a member it will be injected.
+     * 
+     * <h3>Usage Example</h3>
+     * 
+     * <blockquote><pre>
+     * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "add", "change", "remove")
+     *     .setImplementation(ExistingServiceAspect.class)
+     * );
+     * </pre></blockquote>
+     * 
+     * @param serviceInterface the service interface to apply the aspect to
+     * @param serviceFilter the filter condition to use with the service interface
+     * @param ranking the level used to organize the aspect chain ordering
+     * @param callbackInstance the instance to invoke the callbacks on, or null if the callbacks have to be invoked on the aspect itself
+     * @param add name of the callback method to invoke on add
+     * @param change name of the callback method to invoke on change
+     * @param remove name of the callback method to invoke on remove
+     * @param swap name of the callback method to invoke on swap
+     * @return a service that acts as a factory for generating aspects
+     */
+    public Component createAspectService(Class<?> serviceInterface, String serviceFilter, int ranking, Object callbackInstance, 
+        String add, String change, String remove, String swap)        
+    {
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, null, callbackInstance, add, change, remove, swap);
     }
 
     /**
diff --git a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AspectServiceImpl.java b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AspectServiceImpl.java
index 9b33df4..5adce5b 100644
--- a/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AspectServiceImpl.java
+++ b/dependencymanager/org.apache.felix.dependencymanager/src/org/apache/felix/dm/impl/AspectServiceImpl.java
@@ -43,15 +43,17 @@
 	private final String m_change;
 	private final String m_remove;
 	private final String m_swap;
-	private int m_ranking;
+	private final int m_ranking;
+    private final Object m_dependencyCallbackInstance;
 
-	public AspectServiceImpl(DependencyManager dm, Class<?> aspectInterface, String aspectFilter, int ranking, String autoConfig, String add, String change, String remove, String swap) {
+	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());
-		this.m_ranking = ranking;
-		this.m_add = add;
-		this.m_change = change;
-		this.m_remove = remove;
-		this.m_swap = swap;
+		m_ranking = ranking;
+		m_add = add;
+		m_change = change;
+		m_remove = remove;
+		m_swap = swap;
+		m_dependencyCallbackInstance = callbackInstance;
 		
 		m_component.setImplementation(new AspectImpl(aspectInterface, autoConfig))
 			.add(dm.createServiceDependency()
@@ -208,6 +210,10 @@
             m_aspectDependency = (ServiceDependencyImpl) aspectDependency;
             m_originalServiceRef = 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) {
@@ -215,7 +221,7 @@
         	
         	// Invoke is done on dependency.getInstances() which unfortunately returns this callback instance...
         	ServiceEventImpl event = new ServiceEventImpl(ref, service);
-        	m_aspectDependency.invoke(m_add, event, m_aspectDependency.getComponentContext().getInstances());
+        	m_aspectDependency.invoke(m_add, event, getDependencyCallbackInstance());
         }
 
         @SuppressWarnings("unused")
@@ -223,7 +229,7 @@
             // Invoke "change" service dependency callback
             if (m_change != null) {
             	ServiceEventImpl event = new ServiceEventImpl(ref, service);
-                m_aspectDependency.invoke(m_change, event, m_aspectDependency.getComponentContext().getInstances());
+                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
@@ -236,7 +242,7 @@
 		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, m_aspectDependency.getComponentContext().getInstances());
+        	m_aspectDependency.invoke(m_remove, event, getDependencyCallbackInstance());
         }
 
         @SuppressWarnings("unused")
@@ -244,7 +250,7 @@
                                 Object curr) {
         	Object[] instances = m_aspectDependency.getComponentContext().getInstances();        	        	
             // Just forward "swap" service dependency callback.
-        	m_aspectDependency.invokeSwap(m_swap, prevRef, prev, currRef, curr, m_aspectDependency.getComponentContext().getInstances());
+        	m_aspectDependency.invokeSwap(m_swap, prevRef, prev, currRef, curr, getDependencyCallbackInstance());
         }
         
         @Override