- Reworked the aspect API in order to allow to provide aspect parameters by
reusing the Service methods (setComposition/setCallbacks, etc ...).
- Changed return type of method Service.setServiceProperties().
- Fixed wrong synchronize in AbstractDecorator regarding factory configuration adapters.



git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@947378 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 2685e87..57ee254 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
@@ -157,14 +157,8 @@
         return m_manager.createResourceDependency();
     }
 
-    public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object aspectImplementation, Dictionary properties) {
-        return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, aspectImplementation, properties);
-    }
-    public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, Dictionary properties) {
-        return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, factory, factoryCreateMethod, properties);
-    }
-    public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, String attributeName, Dictionary properties) {
-        return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, factory, factoryCreateMethod, attributeName, properties);
+    public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, String attributeName) {
+        return m_manager.createAspectService(serviceInterface, serviceFilter, ranking, attributeName);
     }
     
     public Service createAdapterService(Class serviceInterface, String serviceFilter, String adapterInterface, Object adapterImplementation, Dictionary adapterProperties) {
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 c704526..aeb5e3e 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
@@ -31,7 +31,7 @@
 import org.apache.felix.dm.dependencies.ServiceDependency;
 import org.apache.felix.dm.dependencies.TemporalServiceDependency;
 import org.apache.felix.dm.impl.AdapterImpl;
-import org.apache.felix.dm.impl.AspectImpl;
+import org.apache.felix.dm.impl.AspectServiceImpl;
 import org.apache.felix.dm.impl.BundleAdapterImpl;
 import org.apache.felix.dm.impl.FactoryConfigurationAdapterImpl;
 import org.apache.felix.dm.impl.FactoryConfigurationAdapterMetaTypeImpl;
@@ -177,49 +177,29 @@
      * 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>
+     *  manager.createAspectService(ExistingService.class, "(foo=bar)", 10, "m_aspect")
+     *         .setImplementation(ExistingServiceAspect.class)
+     *         .setServiceProperties(new Hashtable() {{ put("additional", "properties"); }})
+     *         .setComposition("getComposition")
+     *         .setCallbacks(new Handler(), null, "mystart", "mystop", null);
+     * <pre>
+     * </pre>
+     * </blockquote>
+     * 
      * @param serviceInterface the service interface to apply the aspect to
      * @param serviceFilter the filter condition to use with the service interface
-     * @param aspectImplementation the implementation of the aspect
-     * @param aspectProperties additional properties to use with the aspect service registration
+     * @param ranking the level used to organize the aspect chain ordering
+     * @param attributeName, 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 Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object aspectImplementation, Dictionary aspectProperties) {
-        return createService()
-            .setImplementation(new AspectImpl(serviceInterface, serviceFilter, ranking, aspectImplementation, aspectProperties))
-            .add(createServiceDependency()
-                .setService(serviceInterface, createAspectFilter(serviceFilter))
-                .setAutoConfig(false)
-                .setCallbacks("added", "removed")
-            );
+    public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, String attributeName) {
+        return new AspectServiceImpl(this, serviceInterface, serviceFilter, ranking, attributeName);
     }
-    public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, Dictionary aspectProperties) {
-        return createService()
-            .setImplementation(new AspectImpl(serviceInterface, serviceFilter, ranking, factory, factoryCreateMethod, aspectProperties))
-            .add(createServiceDependency()
-                .setService(serviceInterface, createAspectFilter(serviceFilter))
-                .setAutoConfig(false)
-                .setCallbacks("added", "removed")
-            );
-    }
-    public Service createAspectService(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, String attributeName, Dictionary aspectProperties) {
-        return createService()
-            .setImplementation(new AspectImpl(serviceInterface, serviceFilter, ranking, factory, factoryCreateMethod, attributeName, aspectProperties))
-            .add(createServiceDependency()
-                .setService(serviceInterface, createAspectFilter(serviceFilter))
-                .setAutoConfig(false)
-                .setCallbacks("added", "removed")
-            );
-    }
-    private String createAspectFilter(String filter) {
-        // we only want to match services which are not themselves aspects
-        if (filter == null || filter.length() == 0) {
-            return "(!(" + ASPECT + "=*))";
-        }
-        else {
-            return "(&(!(" + ASPECT + "=*))" + filter + ")";
-        }        
-    }
-    
+
     /**
      * Creates a new adapter. The adapter will be applied to any service that
      * matches the specified interface and filter. For each matching service
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
index 16f23d6..cb9803e 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AbstractDecorator.java
@@ -21,11 +21,14 @@
 import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.dependencies.Dependency;
 import org.apache.felix.dm.resources.Resource;
 import org.apache.felix.dm.service.Service;
+import org.apache.felix.dm.service.ServiceStateListener;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.cm.ConfigurationException;
@@ -45,6 +48,90 @@
         throw new NoSuchMethodError("Method updateService not implemented");
     }
     
+    /**
+     * Set some service properties to all already instantiated services.
+     */
+    public void setServiceProperties(Dictionary serviceProperties) {
+        Map services = new HashMap();
+        synchronized (this) {
+            services.putAll(m_services);
+        }
+        Iterator i = services.values().iterator();
+        while (i.hasNext()) {
+            ((Service) i.next()).setServiceProperties(serviceProperties);
+        }
+    }
+    
+    /**
+     * Remove a StateListener from all already instantiated services.
+     */
+    public void addStateListener(ServiceStateListener listener) {
+        Map services = new HashMap();
+        synchronized (this) {
+            services.putAll(m_services);
+        }
+        Iterator i = services.values().iterator();
+        while (i.hasNext()) {
+            ((Service) i.next()).addStateListener(listener);
+        } 
+    }
+
+    /**
+     * Remove a StateListener from all already instantiated services.
+     */
+    public void removeStateListener(ServiceStateListener listener) {
+        Map services = new HashMap();
+        synchronized (this) {
+            services.putAll(m_services);
+        }
+        Iterator i = services.values().iterator();
+        while (i.hasNext()) {
+            ((Service) i.next()).removeStateListener(listener);
+        } 
+    }
+    
+    /**
+     * Add a Dependency to all already instantiated services.
+     */
+    public void addDependency(Dependency d) {
+        Map services = new HashMap();
+        synchronized (this) {
+            services.putAll(m_services);
+        }
+        Iterator i = services.values().iterator();
+        while (i.hasNext()) {
+            ((Service) i.next()).add(d);
+        } 
+    }
+    
+    /**
+     * Add a Dependency to all already instantiated services.
+     */
+    public void addDependencies(List dependencies) {
+        Map services = new HashMap();
+        synchronized (this) {
+            services.putAll(m_services);
+        }
+        Iterator i = services.values().iterator();
+        while (i.hasNext()) {
+            ((Service) i.next()).add(dependencies);
+        } 
+    }
+
+    /**
+     * Remove a Dependency from all instantiated services.
+     */
+    public void removeDependency(Dependency d) {
+        Map services = new HashMap();
+        synchronized (this) {
+            services.putAll(m_services);
+        }
+        Iterator i = services.values().iterator();
+        while (i.hasNext()) {
+            ((Service) i.next()).remove(d);
+        } 
+    }
+    
     // callbacks for FactoryConfigurationAdapterImpl
     public void updated(String pid, Dictionary properties) throws ConfigurationException {
         try {
@@ -74,8 +161,7 @@
         }
     }
 
-    public synchronized void deleted(String pid)
-    {
+    public void deleted(String pid) {
         Service service = null;
         synchronized (this) {
             service = (Service) m_services.remove(pid);
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectImpl.java
deleted file mode 100644
index 72c1436..0000000
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectImpl.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.dm.impl;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.felix.dm.DependencyManager;
-import org.apache.felix.dm.service.Service;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-public class AspectImpl extends AbstractDecorator {
-	private volatile Service m_service;
-	private final Class m_serviceInterface;
-	private final String m_serviceFilter;
-	private final Object m_aspectImplementation;
-    private final Dictionary m_aspectProperties;
-    private final Object m_factory;
-    private final String m_factoryCreateMethod;
-    private final int m_ranking;
-    private final String m_attributeName;
-	
-	public AspectImpl(Class serviceInterface, String serviceFilter, int ranking, Object aspectImplementation, Dictionary properties) {
-		m_serviceInterface = serviceInterface;
-		m_serviceFilter = serviceFilter;
-		m_aspectImplementation = aspectImplementation;
-		m_aspectProperties = properties;
-		m_factory = null;
-		m_factoryCreateMethod = null;
-		m_ranking = ranking;
-        m_attributeName = null;
-	}
-	
-    public AspectImpl(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, Dictionary properties) {
-        m_serviceInterface = serviceInterface;
-        m_serviceFilter = serviceFilter;
-        m_factory = factory;
-        m_factoryCreateMethod = factoryCreateMethod;
-        m_aspectProperties = properties;
-        m_aspectImplementation = null;
-        m_ranking = ranking;
-        m_attributeName = null;
-    }
-    
-    public AspectImpl(Class serviceInterface, String serviceFilter, int ranking, Object factory, String factoryCreateMethod, String attributeName, Dictionary properties) {
-        m_serviceInterface = serviceInterface;
-        m_serviceFilter = serviceFilter;
-        m_factory = factory;
-        m_factoryCreateMethod = factoryCreateMethod;
-        m_attributeName = attributeName;
-        m_aspectProperties = properties;
-        m_aspectImplementation = null;
-        m_ranking = ranking;
-    }
-
-    public Service createService(Object[] properties) {
-        ServiceReference ref = (ServiceReference) properties[0]; 
-        Object service = properties[1];
-        Properties props = new Properties();
-        // first 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));
-        String[] keys = ref.getPropertyKeys();
-        for (int i = 0; i < keys.length; i++) {
-            props.put(keys[i], ref.getProperty(keys[i]));
-        }
-        if (m_aspectProperties != null) {
-            Enumeration e = m_aspectProperties.keys();
-            while (e.hasMoreElements()) {
-                Object key = e.nextElement();
-                props.put(key, m_aspectProperties.get(key));
-            }
-        }
-        List dependencies = m_service.getDependencies();
-        dependencies.remove(0);
-        if (m_aspectImplementation == null) {
-            if (m_attributeName == null) {
-                return m_manager.createService()
-                .setInterface(m_serviceInterface.getName(), props)
-                .setFactory(m_factory, m_factoryCreateMethod)
-                .add(dependencies)
-                .add(m_manager.createServiceDependency()
-                    .setService(m_serviceInterface, createAspectFilter(m_serviceFilter))
-                    .setRequired(true));
-            }
-            else {
-                return m_manager.createService()
-                .setInterface(m_serviceInterface.getName(), props)
-                .setFactory(m_factory, m_factoryCreateMethod)
-                .add(dependencies)
-                .add(m_manager.createServiceDependency()
-                    .setService(m_serviceInterface, createAspectFilter(m_serviceFilter))
-                    .setAutoConfig(m_attributeName)
-                    .setRequired(true));
-            }
-        }
-        else {
-            return m_manager.createService()
-                .setInterface(m_serviceInterface.getName(), props)
-                .setImplementation(m_aspectImplementation)
-                .add(dependencies)
-                .add(m_manager.createServiceDependency()
-                    .setService(m_serviceInterface, createAspectFilter(m_serviceFilter))
-                    .setRequired(true));
-        }
-    }
-    private String createAspectFilter(String filter) {
-        if (filter == null || filter.length() == 0) {
-            return "(|(!(" + Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=" + (m_ranking - 1) + "))";
-        }
-        else {
-            return "(&(|(!(" + Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=" + (m_ranking - 1) + "))" + filter + ")";
-        }
-    }
-}
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
new file mode 100644
index 0000000..b298e68
--- /dev/null
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/AspectServiceImpl.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.impl;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.dependencies.ServiceDependency;
+import org.apache.felix.dm.service.Service;
+import org.apache.felix.dm.service.ServiceStateListener;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Aspect Service implementation. This class extends the FilterService in order to catch
+ * 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)
+    { 
+        super(dm.createService()); // This service will be filtered by our super class, allowing us to take control.
+        m_service.setImplementation(new AspectImpl(aspectInterface, aspectFilter, ranking, autoConfig))
+                 .add(dm.createServiceDependency()
+                      .setService(aspectInterface, createAspectFilter(aspectFilter))
+                      .setAutoConfig(false)
+                      .setCallbacks("added", "removed"));
+    }
+
+    private String createAspectFilter(String filter) {
+        // we only want to match services which are not themselves aspects
+        if (filter == null || filter.length() == 0) {
+            return "(!(" + DependencyManager.ASPECT + "=*))";
+        }
+        else {
+            return "(&(!(" + DependencyManager.ASPECT + "=*))" + filter + ")";
+        }        
+    }
+    
+    /**
+     * This class is the Aspect Implementation. It will create the actual Aspect Service, and
+     * will use the Aspect Service parameters provided by our enclosing class.
+     */
+    class AspectImpl extends AbstractDecorator {
+        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
+      
+        public AspectImpl(Class aspectInterface, String aspectFilter, int ranking, String field) {
+            m_aspectInterface = aspectInterface;
+            m_aspectFilter = aspectFilter;
+            m_ranking = ranking;
+            m_field = field;
+        }
+        
+        public Service createService(Object[] params) {
+            List dependencies = m_service.getDependencies();
+            // remove our internal dependency
+            dependencies.remove(0);
+            Properties serviceProperties = getServiceProperties(params);
+            String[] serviceInterfaces = getServiceInterfaces();
+            Service service = m_manager.createService()
+                .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(dependencies)
+                .add(getAspectDependency());
+            for (int i = 0; i < m_stateListeners.size(); i ++) {
+                service.addStateListener((ServiceStateListener) m_stateListeners.get(i));
+            }
+            return service;                
+        }
+        
+        private Properties getServiceProperties(Object[] params) {
+            ServiceReference ref = (ServiceReference) params[0]; 
+            Object service = params[1];
+            Properties props = new Properties();
+            // first 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));
+            String[] keys = ref.getPropertyKeys();
+            for (int i = 0; i < keys.length; i++) {
+                props.put(keys[i], ref.getProperty(keys[i]));
+            }
+            if (m_serviceProperties != null) {
+                Enumeration e = m_serviceProperties.keys();
+                while (e.hasMoreElements()) {
+                    Object key = e.nextElement();
+                    props.put(key, m_serviceProperties.get(key));
+                }
+            }
+            return props;
+        }
+        
+        private String[] getServiceInterfaces()
+        {
+            List serviceNames = new ArrayList();
+            // Of course, we provide the aspect interface.
+            serviceNames.add(m_aspectInterface.getName());
+            // But also append additional aspect implementation interfaces.
+            if (m_serviceInterfaces != null) {
+                for (int i = 0; i < m_serviceInterfaces.length; i ++) {
+                    if (! m_serviceInterfaces[i].equals(m_aspectInterface.getName())) {
+                        serviceNames.add(m_serviceInterfaces[i]);
+                    }
+                }
+            }
+            return (String[]) serviceNames.toArray(new String[serviceNames.size()]);
+        }
+
+       private Dependency getAspectDependency() {
+           ServiceDependency sd = 
+               m_manager.createServiceDependency()
+                        .setService(m_aspectInterface, createAspectFilter(m_aspectFilter))
+                        .setRequired(true);
+        
+           if (m_field != null) {
+               sd.setAutoConfig(m_field);
+           }
+           return sd;
+        }
+
+       private String createAspectFilter(String filter) {
+           if (filter == null || filter.length() == 0) {
+               return "(|(!(" + Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=" + (m_ranking - 1) + "))";
+           } else {
+               return "(&(|(!(" + Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=" + (m_ranking - 1) + "))" + filter + ")";
+           }
+       }
+    }
+}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/FilterService.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/FilterService.java
new file mode 100644
index 0000000..26719b5
--- /dev/null
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/FilterService.java
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.impl;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.felix.dm.dependencies.Dependency;
+import org.apache.felix.dm.service.Service;
+import org.apache.felix.dm.service.ServiceStateListener;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * This class allows to filter a Service interface. All Aspect/Adapters extends this class
+ * in order to add functionality to the default Service implementation.
+ */
+public class FilterService implements Service
+{
+    protected ServiceImpl m_service;
+    protected List m_stateListeners = new ArrayList();
+    protected String m_init = "init";
+    protected String m_start = "start";
+    protected String m_stop = "stop";
+    protected String m_destroy = "destroy";
+    protected Object m_callbackObject;
+    protected Object m_compositionInstance;
+    protected String m_compositionMethod;
+    protected String[] m_serviceInterfaces;
+    protected Object m_serviceImpl;
+    protected Object m_factory;
+    protected String m_factoryCreateMethod;
+    protected Dictionary m_serviceProperties;
+
+    public FilterService(Service service)
+    {
+        m_service = (ServiceImpl) service;
+    }
+
+    public Service add(Dependency dependency)
+    {
+        m_service.add(dependency);
+        // Add the dependency (if optional) to all already instantiated services.
+        // If the dependency is required, our internal service will be stopped/restarted, so in this case
+        // we have nothing to do.
+        if (! dependency.isRequired()) {
+            AbstractDecorator ad = (AbstractDecorator) m_service.getService();
+            if (ad != null)
+            {
+                ad.addDependency(dependency);
+            }
+        }
+        return this;
+    }
+
+    public Service add(List dependencies)
+    {
+        m_service.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.
+        Iterator it = dependencies.iterator();
+        while (it.hasNext()) {
+            if (((Dependency) it.next()).isRequired()) {
+                return this;
+            }
+        }
+        // Ok, the list contains no required dependencies: add optionals dependencies in already instantiated
+        // services.
+        AbstractDecorator ad = (AbstractDecorator) m_service.getService();
+        if (ad != null)
+        {
+            ad.addDependencies(dependencies);
+        }
+        return this;
+    }
+
+    public void addStateListener(ServiceStateListener listener)
+    {
+        synchronized (this)
+        {
+            m_stateListeners.add(listener);
+        }
+        // Add the listener to all already instantiated services.
+        AbstractDecorator ad = (AbstractDecorator) m_service.getService();
+        if (ad != null)
+        {
+            ad.addStateListener(listener);
+        }
+    }
+
+    public List getDependencies()
+    {
+        return m_service.getDependencies();
+    }
+
+    public Object getService()
+    {
+        return m_service.getService();
+    }
+
+    public synchronized Dictionary getServiceProperties()
+    {
+        return m_serviceProperties;
+    }
+
+    public ServiceRegistration getServiceRegistration()
+    {
+        return m_service.getServiceRegistration();
+    }
+
+    public Service remove(Dependency dependency)
+    {
+        m_service.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 (!dependency.isRequired())
+        {
+            AbstractDecorator ad = (AbstractDecorator) m_service.getService();
+            if (ad != null)
+            {
+                ad.removeDependency(dependency);
+            }
+        }
+        return this;
+    }
+
+    public void removeStateListener(ServiceStateListener listener)
+    {
+        synchronized (this)
+        {
+            m_stateListeners.remove(listener);
+        }
+        // Remove the listener from all already instantiated services.
+        AbstractDecorator ad = (AbstractDecorator) m_service.getService();
+        if (ad != null)
+        {
+            ad.removeStateListener(listener);
+        }
+    }
+
+    public synchronized Service setCallbacks(Object instance, String init, String start, String stop,
+                                             String destroy)
+    {
+        m_service.ensureNotActive();
+        m_callbackObject = instance;
+        m_init = init;
+        m_start = start;
+        m_stop = stop;
+        m_destroy = destroy;
+        return this;
+    }
+
+    public Service setCallbacks(String init, String start, String stop, String destroy)
+    {
+        setCallbacks(null, init, start, stop, destroy);
+        return this;
+    }
+
+    public synchronized Service setComposition(Object instance, String getMethod)
+    {
+        m_service.ensureNotActive();
+        m_compositionInstance = instance;
+        m_compositionMethod = getMethod;
+        return this;
+    }
+
+    public synchronized Service setComposition(String getMethod)
+    {
+        m_service.ensureNotActive();
+        m_compositionMethod = getMethod;
+        return this;
+    }
+
+    public synchronized Service setFactory(Object factory, String createMethod)
+    {
+        m_service.ensureNotActive();
+        m_factory = factory;
+        m_factoryCreateMethod = createMethod;
+        return this;
+    }
+
+    public Service setFactory(String createMethod)
+    {
+        return setFactory(null, createMethod);
+    }
+
+    public synchronized Service setImplementation(Object implementation)
+    {
+        m_service.ensureNotActive();
+        m_serviceImpl = implementation;
+        return this;
+    }
+
+    public Service setInterface(String serviceName, Dictionary properties)
+    {
+        return setInterface(new String[] { serviceName }, properties);
+    }
+
+    public synchronized Service setInterface(String[] serviceInterfaces, Dictionary properties) {
+        m_service.ensureNotActive();
+        if (serviceInterfaces != null) {
+            m_serviceInterfaces = new String[serviceInterfaces.length];
+            System.arraycopy(serviceInterfaces, 0, m_serviceInterfaces, 0, serviceInterfaces.length);
+            m_serviceProperties = properties;
+        }
+        return this;
+    }
+
+    public Service setServiceProperties(Dictionary serviceProperties)
+    {
+        synchronized (this)
+        {
+            m_serviceProperties = serviceProperties;
+        }
+        // Set the properties to all already instantiated services.
+        if (serviceProperties != null) {
+            AbstractDecorator ad = (AbstractDecorator) m_service.getService();
+            if (ad != null)
+            {
+                ad.setServiceProperties(serviceProperties);
+            }
+        }
+        return this;
+    }
+
+    public void start()
+    {
+        m_service.start();
+    }
+
+    public void stop()
+    {
+        m_service.stop();
+    }
+}
\ No newline at end of file
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceImpl.java
index 36381c4..88fe9f1 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/impl/ServiceImpl.java
@@ -422,11 +422,12 @@
 	    return null;
 	}
 
-	public synchronized void setServiceProperties(Dictionary serviceProperties) {
+	public synchronized Service setServiceProperties(Dictionary serviceProperties) {
 	    m_serviceProperties = serviceProperties;
 	    if ((m_registration != null) && (m_serviceName != null)) {
 	        m_registration.setProperties(calculateServiceProperties());
 	    }
+	    return this;
 	}
 
 	// service state listener methods
@@ -991,7 +992,7 @@
         }
     }
 
-    private void ensureNotActive() {
+    protected void ensureNotActive() {
     	State state;
     	synchronized (m_dependencies) {
     		state = m_state;
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dm/service/Service.java b/dependencymanager/core/src/main/java/org/apache/felix/dm/service/Service.java
index c84fdff..8c06db6 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dm/service/Service.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dm/service/Service.java
@@ -136,7 +136,7 @@
      * 
      * @param serviceProperties the properties
      */
-    public void setServiceProperties(Dictionary serviceProperties);
+    public Service setServiceProperties(Dictionary serviceProperties);
     
     /**
      * Sets the names of the methods used as callbacks. These methods, when found, are