Aligned the aspect and adapter features. Added support for callback methods. Updated the documentation.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1079720 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
index 81a9835..817388d 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyActivatorBase.java
@@ -189,19 +189,61 @@
      * Creates a new aspect service.
      * 
      * @return the aspect service
+     * @see DependencyManager#createAspectService(Class, String, int, String)
      */
     public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String attributeName) {
         return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, attributeName);
     }
+    
+    /**
+     * Creates a new aspect service.
+     * 
+     * @return the aspect service
+     * @see DependencyManager#createAspectService(Class, String, int)
+     */
+    public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking) {
+        return m_manager.createAspectService(serviceInterface, serviceFilter, ranking);
+    }
+    
+    /**
+     * Creates a new aspect service.
+     * 
+     * @return the aspect service
+     * @see DependencyManager#createAspectService(Class, String, int, String, String, String)
+     */
+    public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String add, String change, String remove) {
+        return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, add, change, remove);
+    }
 
     /**
      * Creates a new adapter service.
      * 
      * @return the adapter service
+     * @see DependencyManager#createAdapterService(Class, String)
      */
     public Component createAdapterService(Class serviceInterface, String serviceFilter) {
         return m_manager.createAdapterService(serviceInterface, serviceFilter);
     }
+    
+    /**
+     * Creates a new adapter service.
+     * 
+     * @return the adapter service
+     * @see DependencyManager#createAdapterService(Class, String, String)
+     */
+    public Component createAdapterService(Class serviceInterface, String serviceFilter, String autoConfig) {
+        return m_manager.createAdapterService(serviceInterface, serviceFilter, autoConfig);
+    }
+    
+    /**
+     * Creates a new adapter service.
+     * 
+     * @return the adapter service
+     * @see DependencyManager#createAdapterService(Class, String, String, String, String)
+     */
+    public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove) {
+        return m_manager.createAdapterService(serviceInterface, serviceFilter, add, change, remove);
+    }
 
     /**
      * Creates a new resource adapter service.
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
index 6522a9c..62910bc 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/DependencyManager.java
@@ -167,20 +167,73 @@
      * <h3>Usage Example</h3>
      * 
      * <blockquote><pre>
-     *  manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_aspect")
-     *         .setImplementation(ExistingServiceAspect.class)
-     *         .setServiceProperties(new Hashtable() {{ put("additional", "properties"); }});
+     * manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_service")
+     *     .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 attributeName the aspect implementation field name where to inject original service. 
+     * @param autoConfig the aspect implementation field name where to inject original service. 
      *     If null, any field matching the original service will be injected.
      * @return a service that acts as a factory for generating aspects
      */
-    public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String attributeName) {
-        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, attributeName);
+    public Component createAspectService(Class serviceInterface, String serviceFilter, int ranking, String autoConfig) {
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, autoConfig, null, null, null);
+    }
+    /**
+     * 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)
+     *     .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
+     * @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);
+    }
+    /**
+     * 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 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
+     * @return a service that acts as a factory for generating aspects
+     */
+    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);
     }
     
     /**
@@ -195,18 +248,69 @@
      * <h3>Usage Example</h3>
      * 
      * <blockquote><pre>
-     *  manager.createAdapterService(AdapteeService.class, "(foo=bar)")
-     *         // The interface to use when registering adapter
-     *         .setInterface(AdapterService.class, new Hashtable() {{ put("additional", "properties"); }})
-     *         // the implementation of the adapter
-     *         .setImplementation(AdapterImpl.class);
+     * manager.createAdapterService(AdapteeService.class, "(foo=bar)")
+     *     .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+     *     .setImplementation(AdapterImpl.class);
      * </pre></blockquote>
+     * 
      * @param serviceInterface the service interface to apply the adapter to
      * @param serviceFilter the filter condition to use with the service interface
      * @return a service that acts as a factory for generating adapters
      */
     public Component createAdapterService(Class serviceInterface, String serviceFilter) {
-        return new AdapterServiceImpl(this, serviceInterface, serviceFilter);
+        return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, null, null, null);
+    }
+    /**
+     * Creates a new adapter. The adapter will be applied to any service that
+     * matches the specified interface and filter. For each matching service
+     * an adapter will be created based on the adapter implementation class.
+     * The adapter will be registered with the specified interface and existing properties
+     * from 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.createAdapterService(AdapteeService.class, "(foo=bar)", "m_service")
+     *     .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+     *     .setImplementation(AdapterImpl.class);
+     * </pre></blockquote>
+     * 
+     * @param serviceInterface the service interface to apply the adapter to
+     * @param serviceFilter the filter condition to use with the service interface
+     * @param autoConfig the name of the member to inject the service into
+     * @return a service that acts as a factory for generating adapters
+     */
+    public Component createAdapterService(Class serviceInterface, String serviceFilter, String autoConfig) {
+        return new AdapterServiceImpl(this, serviceInterface, serviceFilter, autoConfig, null, null, null);
+    }
+    /**
+     * Creates a new adapter. The adapter will be applied to any service that
+     * matches the specified interface and filter. For each matching service
+     * an adapter will be created based on the adapter implementation class.
+     * The adapter will be registered with the specified interface and existing properties
+     * from 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.createAdapterService(AdapteeService.class, "(foo=bar)", "add", "change", "remove")
+     *     .setInterface(AdapterService.class, new Hashtable() {{ put("extra", "property"); }})
+     *     .setImplementation(AdapterImpl.class);
+     * </pre></blockquote>
+     * 
+     * @param serviceInterface the service interface to apply the adapter to
+     * @param serviceFilter the filter condition to use with the service interface
+     * @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
+     * @return a service that acts as a factory for generating adapters
+     */
+    public Component createAdapterService(Class serviceInterface, String serviceFilter, String add, String change, String remove) {
+        return new AdapterServiceImpl(this, serviceInterface, serviceFilter, null, add, change, remove);
     }
         
     /**
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java
index a2c7fc9..4aebed3 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AdapterServiceImpl.java
@@ -25,6 +25,7 @@
 import org.apache.felix.dm.ComponentStateListener;
 import org.apache.felix.dm.Dependency;
 import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.ServiceDependency;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 
@@ -36,14 +37,18 @@
 {
     /**
      * Creates a new Adapter Service implementation.
+     * 
      * @param dm the dependency manager used to create our internal adapter service
      * @param adapteeInterface the service interface to apply the adapter to
      * @param adapteeFilter the filter condition to use with the service interface
+     * @param add
+     * @param change
+     * @param remove
      */
-    public AdapterServiceImpl(DependencyManager dm, Class adapteeInterface, String adapteeFilter)
+    public AdapterServiceImpl(DependencyManager dm, Class adapteeInterface, String adapteeFilter, String autoConfig, String add, String change, String remove)
     {
         super(dm.createComponent()); // This service will be filtered by our super class, allowing us to take control.
-        m_service.setImplementation(new AdapterImpl(adapteeInterface, adapteeFilter))
+        m_service.setImplementation(new AdapterImpl(adapteeInterface, adapteeFilter, autoConfig, add, change, remove))
                  .add(dm.createServiceDependency()
                       .setService(adapteeInterface, adapteeFilter)
                       .setAutoConfig(false)
@@ -53,10 +58,18 @@
     public class AdapterImpl extends AbstractDecorator {
         private final Class m_adapteeInterface;
         private final String m_adapteeFilter;
+        private final String m_add;
+        private final String m_change;
+        private final String m_remove;
+        private final String m_autoConfig;
         
-        public AdapterImpl(Class adapteeInterface, String adapteeFilter) {
+        public AdapterImpl(Class adapteeInterface, String adapteeFilter, String autoConfig, String add, String change, String remove) {
             m_adapteeInterface = adapteeInterface;
             m_adapteeFilter = adapteeFilter;
+            m_autoConfig = autoConfig;
+            m_add = add;
+            m_change = change;
+            m_remove = remove;
         }
         
         public Component createService(Object[] properties) {
@@ -81,15 +94,23 @@
             }
             List dependencies = m_service.getDependencies();
             dependencies.remove(0);
+            ServiceDependency dependency = m_manager.createServiceDependency()
+                 .setService(m_adapteeInterface, ref)
+                 .setRequired(true);
+            if (m_autoConfig != null) {
+                dependency.setAutoConfig(m_autoConfig);
+            }
+            if (m_add != null || m_change != null || m_remove != null) {
+                dependency.setCallbacks(m_add, m_change, m_remove);
+            }
+            
             Component service = m_manager.createComponent()
                 .setInterface(m_serviceInterfaces, props)
                 .setImplementation(m_serviceImpl)
                 .setFactory(m_factory, m_factoryCreateMethod) // if not set, no effect
                 .setComposition(m_compositionInstance, m_compositionMethod) // if not set, no effect
                 .setCallbacks(m_callbackObject, m_init, m_start, m_stop, m_destroy) // if not set, no effect
-                .add(m_manager.createServiceDependency()
-                     .setService(m_adapteeInterface, ref)
-                     .setRequired(true));
+                .add(dependency);
             
             configureAutoConfigState(service, m_service);
             
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectServiceImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectServiceImpl.java
index 8ba2c61..d1f2a92 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectServiceImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectServiceImpl.java
@@ -23,11 +23,11 @@
 import java.util.List;
 import java.util.Properties;
 
+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.Component;
 import org.apache.felix.dm.ServiceDependency;
-import org.apache.felix.dm.ComponentStateListener;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
 
@@ -36,10 +36,10 @@
  * some Service methods for configuring actual aspect service implementation.
  */
 public class AspectServiceImpl extends FilterService {
-    public AspectServiceImpl(DependencyManager dm, Class aspectInterface, String aspectFilter, int ranking, String autoConfig)
+    public AspectServiceImpl(DependencyManager dm, Class aspectInterface, String aspectFilter, int ranking, String autoConfig, String add, String change, String remove)
     { 
         super(dm.createComponent()); // This service will be filtered by our super class, allowing us to take control.
-        m_service.setImplementation(new AspectImpl(aspectInterface, aspectFilter, ranking, autoConfig))
+        m_service.setImplementation(new AspectImpl(aspectInterface, aspectFilter, ranking, autoConfig, add, change, remove))
              .add(dm.createServiceDependency()
                   .setService(aspectInterface, createDependencyFilterForAspect(aspectFilter))
                   .setAutoConfig(false)
@@ -64,13 +64,19 @@
         private final Class m_aspectInterface; // the service decorated by this aspect
         private final String m_aspectFilter; // the service filter decorated by this aspect
         private final int m_ranking; // the aspect ranking
-        private final String m_field; // the aspect impl field name where to inject decorated service
+        private final String m_autoConfig; // the aspect impl field name where to inject decorated service
+        private final String m_add;
+        private final String m_change;
+        private final String m_remove;
       
-        public AspectImpl(Class aspectInterface, String aspectFilter, int ranking, String field) {
+        public AspectImpl(Class aspectInterface, String aspectFilter, int ranking, String autoConfig, String add, String change, String remove) {
             m_aspectInterface = aspectInterface;
             m_aspectFilter = aspectFilter;
             m_ranking = ranking;
-            m_field = field;
+            m_autoConfig = autoConfig;
+            m_add = add;
+            m_change = change;
+            m_remove = remove;
         }
         
         public Component createService(Object[] params) {
@@ -80,13 +86,21 @@
             // replace it with one that points to the specific service that just was passed in
             Properties serviceProperties = getServiceProperties(params);
             String[] serviceInterfaces = getServiceInterfaces();
+            ServiceReference ref = (ServiceReference) params[0];
+            ServiceDependency dependency = m_manager.createServiceDependency().setService(m_aspectInterface, createAspectFilter(ref)).setRequired(true);
+            if (m_autoConfig != null) {
+                dependency.setAutoConfig(m_autoConfig);
+            }
+            if (m_add != null || m_change != null || m_remove != null) {
+                dependency.setCallbacks(m_add, m_change, m_remove);
+            }
             Component service = m_manager.createComponent()
                 .setInterface(serviceInterfaces, serviceProperties)
                 .setImplementation(m_serviceImpl)
                 .setFactory(m_factory, m_factoryCreateMethod) // if not set, no effect
                 .setComposition(m_compositionInstance, m_compositionMethod) // if not set, no effect
                 .setCallbacks(m_callbackObject, m_init, m_start, m_stop, m_destroy) // if not set, no effect
-                .add(getAspectDependency(params));
+                .add(dependency);
             
             configureAutoConfigState(service, m_service);
             
@@ -142,15 +156,6 @@
             return (String[]) serviceNames.toArray(new String[serviceNames.size()]);
         }
 
-        private Dependency getAspectDependency(Object[] params) {
-            ServiceReference ref = (ServiceReference) params[0];
-            ServiceDependency sd = m_manager.createServiceDependency().setService(m_aspectInterface, createAspectFilter(ref)).setRequired(true);
-            if (m_field != null) {
-                sd.setAutoConfig(m_field);
-            }
-            return sd;
-        }
-
         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 + ")))";