moved classes to subpackages, updated ServiceTracker to 4.2 spec, added BundleTracker and BundleDependency, ResourceDependency and some preliminary resource related classes (WIP)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@884327 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/core/pom.xml b/dependencymanager/core/pom.xml
index 2309519..90b08de 100644
--- a/dependencymanager/core/pom.xml
+++ b/dependencymanager/core/pom.xml
@@ -53,7 +53,7 @@
             <Bundle-Description>A bundle that provides a run-time
               service dependency manager.</Bundle-Description>
             <Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
-            <Export-Package>org.apache.felix.dependencymanager,org.apache.felix.dependencymanager.management,org.apache.felix.dependencymanager.tracker</Export-Package>
+            <Export-Package>org.apache.felix.dependencymanager,org.apache.felix.dependencymanager.management,org.apache.felix.dependencymanager.tracker,org.apache.felix.dependencymanager.impl,org.apache.felix.dependencymanager.dependencies,org.apache.felix.dependencymanager.resources</Export-Package>
             <Import-Package>!org.apache.felix.dependencymanager,*</Import-Package>
           </instructions>
         </configuration>
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Dependency.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Dependency.java
index 64d241a..0c2a23a 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Dependency.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Dependency.java
@@ -49,6 +49,14 @@
     public boolean isAvailable();
     
     /**
+     * As soon as the instance is created, keep it around, even if this dependency
+     * goes away.
+     * 
+     * @return <code>true</code> if the dependency is instance bound
+     */
+    public boolean isInstanceBound();
+    
+    /**
      * Starts tracking the dependency. This activates some implementation
      * specific mechanism to do the actual tracking. If the tracking discovers
      * that the dependency becomes available, it should call 
@@ -56,7 +64,7 @@
      * 
      * @param service the service that is associated with this dependency
      */
-    public void start(Service service);
+    public void start(DependencyService service);
     
     /**
      * Stops tracking the dependency. This deactivates the tracking. If the
@@ -64,5 +72,5 @@
      * <code>dependencyUnavaible()</code> before stopping itself to ensure
      * that dependencies that aren't "active" are unavailable.
      */
-    public void stop(Service service);
+    public void stop(DependencyService service);
 }
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
index 88ffcf7..4cc085e 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyActivatorBase.java
@@ -20,6 +20,11 @@
 
 import java.util.List;
 
+import org.apache.felix.dependencymanager.dependencies.ConfigurationDependency;
+import org.apache.felix.dependencymanager.dependencies.ServiceDependency;
+import org.apache.felix.dependencymanager.dependencies.TemporalServiceDependency;
+import org.apache.felix.dependencymanager.impl.Logger;
+import org.apache.felix.dependencymanager.impl.ServiceImpl;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
@@ -95,7 +100,7 @@
      * @return the new service
      */
     public Service createService() {
-        return new ServiceImpl(m_context, m_manager, m_logger);
+        return m_manager.createService();
     }
     
     /**
@@ -104,7 +109,7 @@
      * @return the service dependency
      */
     public ServiceDependency createServiceDependency() {
-        return new ServiceDependency(m_context, m_logger);
+        return m_manager.createServiceDependency();
     }
     
     /**
@@ -114,7 +119,7 @@
      * @return the service dependency
      */
     public TemporalServiceDependency createTemporalServiceDependency() {
-        return new TemporalServiceDependency(m_context, m_logger);
+        return m_manager.createTemporalServiceDependency();
     }
     
     /**
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
index cb1fe44..784519c 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyManager.java
@@ -22,6 +22,11 @@
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.felix.dependencymanager.dependencies.ConfigurationDependency;
+import org.apache.felix.dependencymanager.dependencies.ServiceDependency;
+import org.apache.felix.dependencymanager.dependencies.TemporalServiceDependency;
+import org.apache.felix.dependencymanager.impl.Logger;
+import org.apache.felix.dependencymanager.impl.ServiceImpl;
 import org.osgi.framework.BundleContext;
 
 /**
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyService.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyService.java
new file mode 100644
index 0000000..ed32430
--- /dev/null
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DependencyService.java
@@ -0,0 +1,47 @@
+/*
+ * 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.dependencymanager;
+
+public interface DependencyService {
+    /**
+     * Will be called when the dependency becomes available.
+     * 
+     * @param dependency the dependency
+     */
+    public void dependencyAvailable(Dependency dependency);
+    
+    /**
+     * Will be called when the dependency changes.
+     * 
+     * @param dependency the dependency
+     */
+    public void dependencyUnavailable(Dependency dependency);
+    
+    /**
+     * Will be called when the dependency becomes unavailable.
+     * 
+     * @param dependency the dependency
+     */
+    public void dependencyChanged(Dependency dependency);
+    
+    public Object getService(); // is also defined on the Service interface
+    public void initService(); // was an implementation method
+    public boolean isRegistered(); // impl method
+    public Object[] getCompositionInstances(); // impl method
+}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java
deleted file mode 100644
index bd960b6..0000000
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java
+++ /dev/null
@@ -1,99 +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.dependencymanager;
-
-import java.util.List;
-
-/**
- * Encapsulates the current state of the dependencies of a service. A state is
- * basically an immutable value object.
- * 
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public final class State {
-    private static final String[] STATES = { "?", "inactive", "waiting for required", "tracking optional" };
-    private static final int INACTIVE = 1;
-    private static final int WAITING_FOR_REQUIRED = 2;
-    private static final int TRACKING_OPTIONAL = 3;
-	private final List m_deps;
-	private final int m_state;
-    private String m_stringValue;
-	
-	/**
-	 * Creates a new state instance.
-	 * 
-	 * @param deps the dependencies that determine the state
-	 * @param isActive <code>true</code> if the service is active (started)
-	 */
-	public State(List deps, boolean isActive) {
-		m_deps = deps;
-		// only bother calculating dependencies if we're active
-    	if (isActive) {
-    		boolean allRequiredAvailable = true;
-    		for (int i = 0; i < deps.size(); i++) {
-    			Dependency dep = (Dependency) deps.get(i);
-    			if (dep.isRequired()) {
-    				if (!dep.isAvailable()) {
-    					allRequiredAvailable = false;
-    				}
-    			}
-    		}
-	    	if (allRequiredAvailable) {
-	    		m_state = TRACKING_OPTIONAL;
-	    	}
-	    	else {
-	    		m_state = WAITING_FOR_REQUIRED;
-	    	}
-    	}
-    	else {
-    		m_state = INACTIVE;
-    	}
-	}
-	
-	public boolean isInactive() {
-		return m_state == INACTIVE;
-	}
-	
-	public boolean isWaitingForRequired() {
-		return m_state == WAITING_FOR_REQUIRED;
-	}
-	
-	public boolean isTrackingOptional() {
-		return m_state == TRACKING_OPTIONAL;
-	}
-	
-	public List getDependencies() {
-		return m_deps;
-	}
-	
-	public synchronized String toString() {
-	    if (m_stringValue == null) {
-	        // we only need to determine this once, but we do it lazily
-	        StringBuffer buf = new StringBuffer();
-    		buf.append("State[" + STATES[m_state] + "|");
-    		List deps = m_deps;
-        	for (int i = 0; i < deps.size(); i++) {
-        		Dependency dep = (Dependency) deps.get(i);
-        		buf.append("(" + dep + (dep.isRequired() ? " R" : " O") + (dep.isAvailable() ? " +" : " -") + ")");
-        	}
-        	m_stringValue = buf.toString();
-	    }
-        return m_stringValue;
-	}
-}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/BundleDependency.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/BundleDependency.java
new file mode 100644
index 0000000..8d05ab6
--- /dev/null
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/BundleDependency.java
@@ -0,0 +1,409 @@
+/*
+ * 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.dependencymanager.dependencies;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Dictionary;
+
+import org.apache.felix.dependencymanager.Dependency;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.impl.Logger;
+import org.apache.felix.dependencymanager.impl.ServiceImpl;
+import org.apache.felix.dependencymanager.management.ServiceComponentDependency;
+import org.apache.felix.dependencymanager.tracker.BundleTracker;
+import org.apache.felix.dependencymanager.tracker.BundleTrackerCustomizer;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+
+public class BundleDependency implements Dependency, BundleTrackerCustomizer, ServiceComponentDependency {
+	private final BundleContext m_context;
+	private final Logger m_logger;
+	private boolean m_isStarted;
+	private BundleTracker m_tracker;
+	private int m_stateMask;
+	private boolean m_isAvailable;
+	private boolean m_isRequired;
+	private DependencyService m_service;
+	
+    private Object m_callbackInstance;
+    private String m_callbackAdded;
+    private String m_callbackChanged;
+    private String m_callbackRemoved;
+    private boolean m_autoConfig;
+	private Bundle m_bundleInstance;
+	private Filter m_filter;
+	private long m_bundleId = -1;
+
+
+	public BundleDependency(BundleContext context, Logger logger) {
+		m_context = context;
+		m_logger = logger;
+		m_autoConfig = true;
+	}
+
+	public boolean isAvailable() {
+		return m_isAvailable;
+	}
+
+	public boolean isRequired() {
+		return m_isRequired;
+	}
+	
+	public boolean isInstanceBound() {
+		return false; // TODO for now we are never bound to the service implementation instance
+	}
+
+	public void start(DependencyService service) {
+		synchronized (this) {
+			if (m_isStarted) {
+				throw new IllegalStateException("Dependency was already started." + getName());
+			}
+			m_service = service;
+			m_tracker = new BundleTracker(m_context, m_stateMask, this);
+			m_isStarted = true;
+		}
+		m_tracker.open();
+		System.out.println("START BD " + m_tracker);
+	}
+
+	public void stop(DependencyService service) {
+        synchronized (this) {
+            if (!m_isStarted) {
+                throw new IllegalStateException("Dependency was not started.");
+            }
+            m_isStarted = false;
+        }
+        m_tracker.close();
+        m_tracker = null;
+	}
+
+	public String getName() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public int getState() {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	public String getType() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	public Object addingBundle(Bundle bundle, BundleEvent event) {
+		System.out.println("ADDING " + bundle + " " + event);
+		// if we don't like a bundle, we could reject it here by returning null
+		if (m_bundleId >= 0 && m_bundleId != bundle.getBundleId()) {
+			return null;
+		}
+		Filter filter = m_filter;
+		if (filter != null) {
+			Dictionary headers = bundle.getHeaders();
+			if (!m_filter.match(headers)) {
+				return null;
+			}
+		}
+        return bundle;
+	}
+	
+	public void addedBundle(Bundle bundle, BundleEvent event, Object object) {
+		System.out.println("ADDED " + bundle + " " + event);
+        if (makeAvailable()) {
+            m_service.dependencyAvailable(this);
+        }
+        else {
+            m_service.dependencyChanged(this);
+        }
+        // try to invoke callback, if specified, but only for optional dependencies
+        // because callbacks for required dependencies are handled differently
+        if (!isRequired()) {
+            invokeAdded(bundle);
+        }
+	}
+
+	public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+		System.out.println("MODIFIED " + bundle + " " + event);
+        m_service.dependencyChanged(this);
+        // only invoke the changed callback if the service itself is "active"
+        if (((ServiceImpl) m_service).isRegistered()) {
+            invokeChanged(bundle);
+        }
+	}
+
+	public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+		System.out.println("REMOVED " + bundle + " " + event);
+        if (makeUnavailable()) {
+            m_service.dependencyUnavailable(this);
+        }
+        // try to invoke callback, if specified, but only for optional dependencies
+        // because callbacks for required dependencies are handled differently
+        if (!isRequired()) {
+            invokeRemoved(bundle);
+        }
+	}
+	
+    private synchronized boolean makeAvailable() {
+        if (!m_isAvailable) {
+            m_isAvailable = true;
+            return true;
+        }
+        return false;
+    }
+    
+    private synchronized boolean makeUnavailable() {
+        if ((m_isAvailable) && (m_tracker.getTrackingCount() == 0)) {
+            m_isAvailable = false;
+            return true;
+        }
+        return false;
+    }
+    
+    public void invokeAdded() {
+        invokeAdded(m_bundleInstance);
+    }
+    
+    public void invokeAdded(Bundle serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackAdded != null)) {
+                invokeCallbackMethod(callbackInstances, m_callbackAdded, serviceInstance);
+        }
+    }
+
+    public void invokeChanged(Bundle serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackChanged != null)) {
+//                if (m_reference == null) {
+//                    Thread.dumpStack();
+//                }
+                invokeCallbackMethod(callbackInstances, m_callbackChanged, serviceInstance);
+        }
+    }
+
+    
+    public void invokeRemoved() {
+        invokeRemoved(m_bundleInstance);
+    }
+    
+    public void invokeRemoved(Bundle serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackRemoved != null)) {
+//                if (m_reference == null) {
+//                    Thread.dumpStack();
+//                }
+                invokeCallbackMethod(callbackInstances, m_callbackRemoved, serviceInstance);
+        }
+    }
+    
+
+    
+    
+    private void invokeCallbackMethod(Object[] instances, String methodName, Object service) {
+        for (int i = 0; i < instances.length; i++) {
+            try {
+                invokeCallbackMethod(instances[i], methodName, service);
+            }
+            catch (NoSuchMethodException e) {
+                m_logger.log(Logger.LOG_DEBUG, "Method '" + methodName + "' does not exist on " + instances[i] + ". Callback skipped.");
+            }
+        }
+    }
+
+    private void invokeCallbackMethod(Object instance, String methodName, Object service) throws NoSuchMethodException {
+        Class currentClazz = instance.getClass();
+        boolean done = false;
+        while (!done && currentClazz != null) {
+            done = invokeMethod(instance, currentClazz, methodName,
+                new Class[][] {{Bundle.class}, {Object.class}, {}},
+                new Object[][] {{service}, {service}, {}},
+                false);
+            if (!done) {
+                currentClazz = currentClazz.getSuperclass();
+            }
+        }
+        if (!done && currentClazz == null) {
+            throw new NoSuchMethodException(methodName);
+        }
+    }
+    
+    private boolean invokeMethod(Object object, Class clazz, String name, Class[][] signatures, Object[][] parameters, boolean isSuper) {
+        Method m = null;
+        for (int i = 0; i < signatures.length; i++) {
+            Class[] signature = signatures[i];
+            try {
+                m = clazz.getDeclaredMethod(name, signature);
+                if (!(isSuper && Modifier.isPrivate(m.getModifiers()))) {
+                    m.setAccessible(true);
+                    try {
+                        m.invoke(object, parameters[i]);
+                    }
+                    catch (InvocationTargetException e) {
+                        m_logger.log(Logger.LOG_ERROR, "Exception while invoking method " + m + ".", e);
+                    }
+                    // we did find and invoke the method, so we return true
+                    return true;
+                }
+            }
+            catch (NoSuchMethodException e) {
+                // ignore this and keep looking
+            }
+            catch (Exception e) {
+                // could not even try to invoke the method
+                m_logger.log(Logger.LOG_ERROR, "Exception while trying to invoke method " + m + ".", e);
+            }
+        }
+        return false;
+    }
+    
+    private synchronized Object[] getCallbackInstances() {
+        Object[] callbackInstances = ((ServiceImpl) m_service).getCompositionInstances();
+        if (m_callbackInstance == null) {
+            return callbackInstances;
+        }
+        Object[] res = new Object[callbackInstances.length + 1];
+        res[0] = m_callbackInstance; //this could also be extended to an array...?
+        System.arraycopy(callbackInstances, 0, res, 1, callbackInstances.length);
+        return res;
+    }
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added or removed. When you specify callbacks, the auto configuration 
+     * feature is automatically turned off, because we're assuming you don't need it in this 
+     * case.
+     * 
+     * @param added the method to call when a service was added
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+    public synchronized BundleDependency setCallbacks(String added, String removed) {
+        return setCallbacks(null, added, null, removed);
+    }
+
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added, changed or removed. When you specify callbacks, the auto 
+     * configuration feature is automatically turned off, because we're assuming you don't 
+     * need it in this case.
+     * 
+     * @param added the method to call when a service was added
+     * @param changed the method to call when a service was changed
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+    public synchronized BundleDependency setCallbacks(String added, String changed, String removed) {
+        return setCallbacks(null, added, changed, removed);
+    }
+
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added or removed. They are called on the instance you provide. When you
+     * specify callbacks, the auto configuration feature is automatically turned off, because
+     * we're assuming you don't need it in this case.
+     * 
+     * @param instance the instance to call the callbacks on
+     * @param added the method to call when a service was added
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+    public synchronized BundleDependency setCallbacks(Object instance, String added, String removed) {
+        return setCallbacks(instance, added, null, removed);
+    }
+    
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added, changed or removed. They are called on the instance you provide. When you
+     * specify callbacks, the auto configuration feature is automatically turned off, because
+     * we're assuming you don't need it in this case.
+     * 
+     * @param instance the instance to call the callbacks on
+     * @param added the method to call when a service was added
+     * @param changed the method to call when a service was changed
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+    public synchronized BundleDependency setCallbacks(Object instance, String added, String changed, String removed) {
+        ensureNotActive();
+        // if at least one valid callback is specified, we turn off auto configuration
+        if (added != null || removed != null || changed != null) {
+            setAutoConfig(false);
+        }
+        m_callbackInstance = instance;
+        m_callbackAdded = added;
+        m_callbackChanged = changed;
+        m_callbackRemoved = removed;
+        return this;
+    }
+
+    private void ensureNotActive() {
+        if (m_tracker != null) {
+            throw new IllegalStateException("Cannot modify state while active.");
+        }
+    }
+    public synchronized BundleDependency setAutoConfig(boolean autoConfig) {
+        ensureNotActive();
+        m_autoConfig = autoConfig;
+        return this;
+    }
+    
+    public synchronized BundleDependency setRequired(boolean required) {
+        ensureNotActive();
+        m_isRequired = required;
+        return this;
+    }
+
+	public BundleDependency setBundle(Bundle bundle) {
+		m_bundleId = bundle.getBundleId();
+		return this;
+	}
+
+	public BundleDependency setFilter(String filter) throws IllegalArgumentException {
+		if (filter != null) {
+			try {
+				m_filter = m_context.createFilter(filter);
+			} 
+			catch (InvalidSyntaxException e) {
+				throw new IllegalArgumentException(e.getMessage());
+			}
+		}
+		return this;
+	}
+	
+	public BundleDependency setStateMask(int mask) {
+		m_stateMask = mask;
+		return this;
+	}
+	
+    public synchronized boolean isAutoConfig() {
+        return m_autoConfig;
+    }
+
+    public Bundle getBundle() {
+    	Bundle[] bundles = m_tracker.getBundles();
+    	if (bundles != null && bundles.length > 0) {
+    		return bundles[0];
+    	}
+    	return null;
+    }
+}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ConfigurationDependency.java
similarity index 91%
rename from dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
rename to dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ConfigurationDependency.java
index 3299826..8806373 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ConfigurationDependency.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ConfigurationDependency.java
@@ -16,12 +16,16 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.dependencies;
+
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Dictionary;
 import java.util.Properties;
 
+import org.apache.felix.dependencymanager.Dependency;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.apache.felix.dependencymanager.management.ServiceComponentDependency;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -53,7 +57,7 @@
 	private BundleContext m_context;
 	private String m_pid;
 	private ServiceRegistration m_registration;
-	private volatile Service m_service;
+	private volatile DependencyService m_service;
 	private Dictionary m_settings;
 	private boolean m_propagate;
 	private final Logger m_logger;
@@ -77,6 +81,11 @@
 		return true;
 	}
 	
+	public boolean isInstanceBound() {
+	    // for now, configuration dependencies never are
+	    return false;
+	}
+	
 	/**
 	 * Returns <code>true</code> when configuration properties should be propagated
 	 * as service properties.
@@ -89,14 +98,14 @@
 		return m_settings;
 	}
 	
-	public void start(Service service) {
+	public void start(DependencyService service) {
 		m_service = service;
 		Properties props = new Properties();
 		props.put(Constants.SERVICE_PID, m_pid);
 		m_registration = m_context.registerService(ManagedService.class.getName(), this, props);
 	}
 
-	public void stop(Service service) {
+	public void stop(DependencyService service) {
 		m_registration.unregister();
 		m_service = null;
 	}
@@ -109,7 +118,7 @@
 	public void updated(Dictionary settings) throws ConfigurationException {
 		// if non-null settings come in, we have to instantiate the service and
 		// apply these settings
-		((ServiceImpl) m_service).initService();
+		m_service.initService(); /// <<< CHANGES THE STATE, WHEN IT SHOULD NOT (YET) DO THAT (we should not use m_serviceInstance to determine the state but use a flag var instead)
 		Object service = m_service.getService();
 				
 		Dictionary oldSettings = null; 
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ResourceDependency.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ResourceDependency.java
new file mode 100644
index 0000000..0e024d5
--- /dev/null
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ResourceDependency.java
@@ -0,0 +1,362 @@
+/*
+ * 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.dependencymanager.dependencies;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Properties;
+
+import org.apache.felix.dependencymanager.Dependency;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.impl.Logger;
+import org.apache.felix.dependencymanager.impl.ServiceImpl;
+import org.apache.felix.dependencymanager.resources.Resource;
+import org.apache.felix.dependencymanager.resources.ResourceHandler;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class ResourceDependency implements Dependency, ResourceHandler {
+	private volatile BundleContext m_context;
+	private volatile ServiceRegistration m_registration;
+	private long m_resourceCounter;
+
+    private Object m_callbackInstance;
+    private String m_callbackAdded;
+    private String m_callbackChanged;
+    private String m_callbackRemoved;
+    private boolean m_autoConfig;
+    private final Logger m_logger;
+    private String m_autoConfigInstance;
+    private DependencyService m_service;
+	private boolean m_isRequired;
+	private String m_resourceFilter;
+	private Resource m_resource;
+	private Resource m_trackedResource;
+
+	
+    public ResourceDependency(BundleContext context, Logger logger) {
+    	m_context = context;
+    	m_logger = logger;
+    	m_autoConfig = true;
+    }
+    
+	public synchronized boolean isAvailable() {
+		return m_resourceCounter > 0;
+	}
+
+	public boolean isRequired() {
+		return m_isRequired;
+	}
+	
+	public boolean isInstanceBound() {
+		return false; // TODO for now we are never bound to the service implementation instance
+	}
+
+	public void start(DependencyService service) {
+		m_service = service;
+		Properties props = new Properties();
+		// TODO create constant for this key
+		props.setProperty("filter", m_resourceFilter);
+		m_registration = m_context.registerService(ResourceHandler.class.getName(), this, props);
+		
+	}
+
+	public void stop(DependencyService service) {
+		m_registration.unregister();
+		m_registration = null;
+	}
+
+	public void added(Resource resource) {
+		System.out.println("RD ADDED " + resource);
+		long counter;
+		synchronized (this) {
+			m_resourceCounter++;
+			counter = m_resourceCounter;
+			m_resource = resource; // TODO this really sucks as a way to track a single resource
+		}
+        if (counter == 1) {
+            m_service.dependencyAvailable(this);
+        }
+        else {
+            m_service.dependencyChanged(this);
+        }
+        // try to invoke callback, if specified, but only for optional dependencies
+        // because callbacks for required dependencies are handled differently
+        if (!isRequired()) {
+            invokeAdded(resource);
+        }
+	}
+
+	public void changed(Resource resource) {
+		invokeChanged(resource);
+	}
+
+	public void removed(Resource resource) {
+		long counter;
+		synchronized (this) {
+			m_resourceCounter--;
+			counter = m_resourceCounter;
+		}
+        if (counter == 0) {
+            m_service.dependencyUnavailable(this);
+        }
+        // try to invoke callback, if specified, but only for optional dependencies
+        // because callbacks for required dependencies are handled differently
+        if (!isRequired()) {
+            invokeRemoved(resource);
+        }
+	}
+	
+    public void invokeAdded() {
+    	// TODO fixme
+        //invokeAdded(m_bundleInstance);
+    }
+
+    public void invokeAdded(Resource serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackAdded != null)) {
+                invokeCallbackMethod(callbackInstances, m_callbackAdded, serviceInstance);
+        }
+    }
+
+    public void invokeChanged(Resource serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackChanged != null)) {
+//                if (m_reference == null) {
+//                    Thread.dumpStack();
+//                }
+                invokeCallbackMethod(callbackInstances, m_callbackChanged, serviceInstance);
+        }
+    }
+
+    
+    public void invokeRemoved() {
+    	// TODO fixme
+        //invokeRemoved(m_bundleInstance);
+    }
+    
+    public void invokeRemoved(Resource serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances();
+        if ((callbackInstances != null) && (m_callbackRemoved != null)) {
+//                if (m_reference == null) {
+//                    Thread.dumpStack();
+//                }
+                invokeCallbackMethod(callbackInstances, m_callbackRemoved, serviceInstance);
+        }
+    }
+
+
+
+	
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added or removed. When you specify callbacks, the auto configuration 
+     * feature is automatically turned off, because we're assuming you don't need it in this 
+     * case.
+     * 
+     * @param added the method to call when a service was added
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+    public synchronized ResourceDependency setCallbacks(String added, String removed) {
+        return setCallbacks(null, added, null, removed);
+    }
+
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added, changed or removed. When you specify callbacks, the auto 
+     * configuration feature is automatically turned off, because we're assuming you don't 
+     * need it in this case.
+     * 
+     * @param added the method to call when a service was added
+     * @param changed the method to call when a service was changed
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+    public synchronized ResourceDependency setCallbacks(String added, String changed, String removed) {
+        return setCallbacks(null, added, changed, removed);
+    }
+
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added or removed. They are called on the instance you provide. When you
+     * specify callbacks, the auto configuration feature is automatically turned off, because
+     * we're assuming you don't need it in this case.
+     * 
+     * @param instance the instance to call the callbacks on
+     * @param added the method to call when a service was added
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+    public synchronized ResourceDependency setCallbacks(Object instance, String added, String removed) {
+        return setCallbacks(instance, added, null, removed);
+    }
+    
+    /**
+     * Sets the callbacks for this service. These callbacks can be used as hooks whenever a
+     * dependency is added, changed or removed. They are called on the instance you provide. When you
+     * specify callbacks, the auto configuration feature is automatically turned off, because
+     * we're assuming you don't need it in this case.
+     * 
+     * @param instance the instance to call the callbacks on
+     * @param added the method to call when a service was added
+     * @param changed the method to call when a service was changed
+     * @param removed the method to call when a service was removed
+     * @return this service dependency
+     */
+    public synchronized ResourceDependency setCallbacks(Object instance, String added, String changed, String removed) {
+        ensureNotActive();
+        // if at least one valid callback is specified, we turn off auto configuration
+        if (added != null || removed != null || changed != null) {
+            setAutoConfig(false);
+        }
+        m_callbackInstance = instance;
+        m_callbackAdded = added;
+        m_callbackChanged = changed;
+        m_callbackRemoved = removed;
+        return this;
+    }
+    
+    private void ensureNotActive() {
+        if (m_registration != null) {
+            throw new IllegalStateException("Cannot modify state while active.");
+        }
+    }
+    
+    /**
+     * Sets auto configuration for this service. Auto configuration allows the
+     * dependency to fill in any attributes in the service implementation that
+     * are of the same type as this dependency. Default is on.
+     * 
+     * @param autoConfig the value of auto config
+     * @return this service dependency
+     */
+    public synchronized ResourceDependency setAutoConfig(boolean autoConfig) {
+        ensureNotActive();
+        m_autoConfig = autoConfig;
+        return this;
+    }
+    
+    /**
+     * Sets auto configuration for this service. Auto configuration allows the
+     * dependency to fill in the attribute in the service implementation that
+     * has the same type and instance name.
+     * 
+     * @param instanceName the name of attribute to auto config
+     * @return this service dependency
+     */
+    public synchronized ResourceDependency setAutoConfig(String instanceName) {
+        ensureNotActive();
+        m_autoConfig = (instanceName != null);
+        m_autoConfigInstance = instanceName;
+        return this;
+    }
+    
+    private void invokeCallbackMethod(Object[] instances, String methodName, Object service) {
+        for (int i = 0; i < instances.length; i++) {
+            try {
+                invokeCallbackMethod(instances[i], methodName, service);
+            }
+            catch (NoSuchMethodException e) {
+                m_logger.log(Logger.LOG_DEBUG, "Method '" + methodName + "' does not exist on " + instances[i] + ". Callback skipped.");
+            }
+        }
+    }
+
+    private void invokeCallbackMethod(Object instance, String methodName, Object service) throws NoSuchMethodException {
+        Class currentClazz = instance.getClass();
+        boolean done = false;
+        while (!done && currentClazz != null) {
+            done = invokeMethod(instance, currentClazz, methodName,
+                new Class[][] {{Resource.class}, {Object.class}, {}},
+                new Object[][] {{service}, {service}, {}},
+                false);
+            if (!done) {
+                currentClazz = currentClazz.getSuperclass();
+            }
+        }
+        if (!done && currentClazz == null) {
+            throw new NoSuchMethodException(methodName);
+        }
+    }
+    
+    private boolean invokeMethod(Object object, Class clazz, String name, Class[][] signatures, Object[][] parameters, boolean isSuper) {
+        Method m = null;
+        for (int i = 0; i < signatures.length; i++) {
+            Class[] signature = signatures[i];
+            try {
+                m = clazz.getDeclaredMethod(name, signature);
+                if (!(isSuper && Modifier.isPrivate(m.getModifiers()))) {
+                    m.setAccessible(true);
+                    try {
+                        m.invoke(object, parameters[i]);
+                    }
+                    catch (InvocationTargetException e) {
+                        m_logger.log(Logger.LOG_ERROR, "Exception while invoking method " + m + ".", e);
+                    }
+                    // we did find and invoke the method, so we return true
+                    return true;
+                }
+            }
+            catch (NoSuchMethodException e) {
+                // ignore this and keep looking
+            }
+            catch (Exception e) {
+                // could not even try to invoke the method
+                m_logger.log(Logger.LOG_ERROR, "Exception while trying to invoke method " + m + ".", e);
+            }
+        }
+        return false;
+    }
+    private synchronized Object[] getCallbackInstances() {
+        Object[] callbackInstances = ((ServiceImpl) m_service).getCompositionInstances();
+        if (m_callbackInstance == null) {
+            return callbackInstances;
+        }
+        Object[] res = new Object[callbackInstances.length + 1];
+        res[0] = m_callbackInstance; //this could also be extended to an array...?
+        System.arraycopy(callbackInstances, 0, res, 1, callbackInstances.length);
+        return res;
+    }
+
+	public ResourceDependency setResource(Resource resource) {
+		m_trackedResource = resource;
+		return this;
+	}
+	
+    public synchronized ResourceDependency setRequired(boolean required) {
+        ensureNotActive();
+        m_isRequired = required;
+        return this;
+    }
+
+	public ResourceDependency setFilter(String resourceFilter) {
+		m_resourceFilter = resourceFilter;
+		return this;
+	}
+    public synchronized boolean isAutoConfig() {
+        return m_autoConfig;
+    }
+
+    public Resource getResource() {
+    	System.out.println("Fetching resource");
+    	return m_resource;
+    }
+}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ServiceDependency.java
similarity index 81%
rename from dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
rename to dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ServiceDependency.java
index 5ba1f7d..18671ca 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/ServiceDependency.java
@@ -16,19 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.dependencies;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
 import java.util.AbstractMap;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.felix.dependencymanager.Dependency;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.impl.DefaultNullObject;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.apache.felix.dependencymanager.management.ServiceComponentDependency;
 import org.apache.felix.dependencymanager.tracker.ServiceTracker;
 import org.apache.felix.dependencymanager.tracker.ServiceTrackerCustomizer;
@@ -44,7 +50,7 @@
  */
 public class ServiceDependency implements Dependency, ServiceTrackerCustomizer, ServiceComponentDependency {
     private boolean m_isRequired;
-    protected Service m_service;
+    protected List m_services = new ArrayList();
     protected volatile ServiceTracker m_tracker;
     protected BundleContext m_context;
     private boolean m_isAvailable;
@@ -66,6 +72,7 @@
     private boolean m_autoConfigInvoked;
     private Object m_defaultImplementation;
     private Object m_defaultImplementationInstance;
+    private boolean m_isInstanceBound;
     
     private static final Comparator COMPARATOR = new Comparator() {
         public int getRank(ServiceReference ref) {
@@ -188,6 +195,10 @@
     public synchronized boolean isAutoConfig() {
         return m_autoConfig;
     }
+    
+    public boolean isInstanceBound() {
+        return m_isInstanceBound;
+    }
 
     public synchronized Object getService() {
         Object service = null;
@@ -246,6 +257,45 @@
         }
         return service;
     }
+    
+    // TODO lots of duplication in lookupService()
+    public ServiceReference lookupServiceReference() {
+        ServiceReference service = null;
+        if (m_isStarted) {
+            service = m_tracker.getServiceReference();
+        }
+        else {
+            ServiceReference[] refs = null;
+            ServiceReference ref = null;
+            if (m_trackedServiceName != null) {
+                if (m_trackedServiceFilter != null) {
+                    try {
+                        refs = m_context.getServiceReferences(m_trackedServiceName.getName(), m_trackedServiceFilter);
+                        if (refs != null) {
+                            Arrays.sort(refs, COMPARATOR);
+                            ref = refs[0];
+                        }
+                    }
+                    catch (InvalidSyntaxException e) {
+                        throw new IllegalStateException("Invalid filter definition for dependency.");
+                    }
+                }
+                else if (m_trackedServiceReference != null) {
+                    ref = m_trackedServiceReference;
+                }
+                else {
+                    ref = m_context.getServiceReference(m_trackedServiceName.getName());
+                }
+                if (ref != null) {
+                    service = ref;
+                }
+            }
+            else {
+                throw new IllegalStateException("Could not lookup dependency, no service name specified.");
+            }
+        }
+        return service;
+    }
 
     private Object getNullObject() {
         if (m_nullObject == null) {
@@ -284,45 +334,52 @@
         return m_trackedServiceName;
     }
 
-    public void start(Service service) {
+    public void start(DependencyService service) {
+        boolean needsStarting = false;
         synchronized (this) {
-            if (m_isStarted) {
-                throw new IllegalStateException("Service dependency was already started." + m_trackedServiceName);
-            }
-            m_service = service;
-            if (m_trackedServiceName != null) {
-                if (m_trackedServiceFilter != null) {
-                    try {
-                        m_tracker = new ServiceTracker(m_context, m_context.createFilter(m_trackedServiceFilter), this);
+            m_services.add(service);
+            if (!m_isStarted) {
+                if (m_trackedServiceName != null) {
+                    if (m_trackedServiceFilter != null) {
+                        try {
+                            m_tracker = new ServiceTracker(m_context, m_context.createFilter(m_trackedServiceFilter), this);
+                        }
+                        catch (InvalidSyntaxException e) {
+                            throw new IllegalStateException("Invalid filter definition for dependency.");
+                        }
                     }
-                    catch (InvalidSyntaxException e) {
-                        throw new IllegalStateException("Invalid filter definition for dependency.");
+                    else if (m_trackedServiceReference != null) {
+                        m_tracker = new ServiceTracker(m_context, m_trackedServiceReference, this);
                     }
-                }
-                else if (m_trackedServiceReference != null) {
-                    m_tracker = new ServiceTracker(m_context, m_trackedServiceReference, this);
+                    else {
+                        m_tracker = new ServiceTracker(m_context, m_trackedServiceName.getName(), this);
+                    }
                 }
                 else {
-                    m_tracker = new ServiceTracker(m_context, m_trackedServiceName.getName(), this);
+                    throw new IllegalStateException("Could not create tracker for dependency, no service name specified.");
                 }
+                m_isStarted = true;
+                needsStarting = true;
             }
-            else {
-                throw new IllegalStateException("Could not create tracker for dependency, no service name specified.");
-            }
-            m_isStarted = true;
         }
-        m_tracker.open();
+        if (needsStarting) {
+            m_tracker.open();
+        }
     }
 
-    public void stop(Service service) {
+    public void stop(DependencyService service) {
+        boolean needsStopping = false;
         synchronized (this) {
-            if (!m_isStarted) {
-                throw new IllegalStateException("Service dependency was not started.");
+            m_services.remove(service);
+            if (m_services.size() == 0) {
+                m_isStarted = false;
+                needsStopping = true;
             }
-            m_isStarted = false;
         }
-        m_tracker.close();
-        m_tracker = null;
+        if (needsStopping) {
+            m_tracker.close();
+            m_tracker = null;
+        }
     }
 
     public Object addingService(ServiceReference ref) {
@@ -339,26 +396,26 @@
     }
 
     public void addedService(ServiceReference ref, Object service) {
-        if (makeAvailable()) {
-            m_service.dependencyAvailable(this);
-            // try to invoke callback, if specified, but only for optional dependencies
-            // because callbacks for required dependencies are handled differently
-            if (!isRequired()) {
-                invokeAdded(ref, service);
+        boolean makeAvailable = makeAvailable();
+        
+        Object[] services = m_services.toArray();
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            if (makeAvailable) {
+                ds.dependencyAvailable(this);
+                if (!isRequired()) {
+                    invokeAdded(ds, ref, service);
+                }
             }
-        }
-        else {
-            m_service.dependencyChanged(this);
-            invokeAdded(ref, service);
+            else {
+                ds.dependencyChanged(this);
+                invokeAdded(ds, ref, service);
+            }
         }
     }
 
-    public void invokeAdded() {
-        invokeAdded(m_reference, m_serviceInstance);
-    }
-    
-    public void invokeAdded(ServiceReference reference, Object serviceInstance) {
-        Object[] callbackInstances = getCallbackInstances();
+    public void invokeAdded(DependencyService dependencyService, ServiceReference reference, Object serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances(dependencyService);
         if ((callbackInstances != null) && (m_callbackAdded != null)) {
             invokeCallbackMethod(callbackInstances, m_callbackAdded, reference, serviceInstance);
         }
@@ -367,49 +424,53 @@
     public void modifiedService(ServiceReference ref, Object service) {
         m_reference = ref;
         m_serviceInstance = service;
-        m_service.dependencyChanged(this);
-        // only invoke the changed callback if the service itself is "active"
-        if (((ServiceImpl) m_service).isRegistered()) {
-            invokeChanged(ref, service);
+        
+        Object[] services = m_services.toArray();
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            ds.dependencyChanged(this);
+            if (ds.isRegistered()) {
+                invokeChanged(ds, ref, service);
+            }
         }
     }
 
-    public void invokeChanged(ServiceReference reference, Object serviceInstance) {
-        Object[] callbackInstances = getCallbackInstances();
+    public void invokeChanged(DependencyService dependencyService, ServiceReference reference, Object serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances(dependencyService);
         if ((callbackInstances != null) && (m_callbackChanged != null)) {
             invokeCallbackMethod(callbackInstances, m_callbackChanged, reference, serviceInstance);
         }
     }
 
     public void removedService(ServiceReference ref, Object service) {
-        if (makeUnavailable()) {
-            m_service.dependencyUnavailable(this);
-            // try to invoke callback, if specified, but only for optional dependencies
-            // because callbacks for required dependencies are handled differently
-            if (!isRequired()) {
-                invokeRemoved(ref, service);
+        boolean makeUnavailable = makeUnavailable();
+        
+        Object[] services = m_services.toArray();
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            if (makeUnavailable) {
+                ds.dependencyUnavailable(this);
+                if (!isRequired()) {
+                    invokeRemoved(ds, ref, service);
+                }
+            }
+            else {
+                ds.dependencyChanged(this);
+                invokeRemoved(ds, ref, service);
             }
         }
-        else {
-            m_service.dependencyChanged(this);
-            invokeRemoved(ref, service);
-        }
-        
         // unget what we got in addingService (see ServiceTracker 701.4.1)
         m_context.ungetService(ref);
+
     }
 
-    public void invokeRemoved() {
-        invokeRemoved(m_reference, m_serviceInstance);
-    }
-    
-    public void invokeRemoved(ServiceReference reference, Object serviceInstance) {
-        Object[] callbackInstances = getCallbackInstances();
+    public void invokeRemoved(DependencyService dependencyService, ServiceReference reference, Object serviceInstance) {
+        Object[] callbackInstances = getCallbackInstances(dependencyService);
         if ((callbackInstances != null) && (m_callbackRemoved != null)) {
             invokeCallbackMethod(callbackInstances, m_callbackRemoved, reference, serviceInstance);
         }
     }
-    
+
     protected synchronized boolean makeAvailable() {
         if (!m_isAvailable) {
             m_isAvailable = true;
@@ -426,8 +487,13 @@
         return false;
     }
     
-    private synchronized Object[] getCallbackInstances() {
-        return m_callbackInstance != null ? new Object[] { m_callbackInstance } : ((ServiceImpl) m_service).getCompositionInstances();
+    private synchronized Object[] getCallbackInstances(DependencyService dependencyService) {
+        if (m_callbackInstance == null) {
+            return dependencyService.getCompositionInstances();
+        }
+        else {
+            return new Object[] { m_callbackInstance };
+        }
     }
 
     private void invokeCallbackMethod(Object[] instances, String methodName, ServiceReference reference, Object service) {
@@ -588,6 +654,11 @@
         m_isRequired = required;
         return this;
     }
+    
+    public ServiceDependency setInstanceBound(boolean isInstanceBound) {
+        m_isInstanceBound = isInstanceBound;
+        return this;
+    }
 
     /**
      * Sets auto configuration for this service. Auto configuration allows the
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/TemporalServiceDependency.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/TemporalServiceDependency.java
similarity index 91%
rename from dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/TemporalServiceDependency.java
rename to dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/TemporalServiceDependency.java
index d842503..a531e91 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/TemporalServiceDependency.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/dependencies/TemporalServiceDependency.java
@@ -9,12 +9,15 @@
  * or implied. See the License for the specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.dependencies;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 
+import org.apache.felix.dependencymanager.DependencyActivatorBase;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 
@@ -110,12 +113,18 @@
      * The ServiceTracker calls us here in order to inform about a service arrival.
      */
     public synchronized void addedService(ServiceReference ref, Object service) {
-        if (makeAvailable()) {
-            // So far, our dependency was not satisfied: wrap the service behind our proxy.
+        boolean makeAvailable = makeAvailable();
+        if (makeAvailable) {
             m_serviceInstance = Proxy.newProxyInstance(m_trackedServiceName.getClassLoader(), new Class[] { m_trackedServiceName }, this);
-            m_service.dependencyAvailable(this); // will invoke "added" callbacks, if any.
         }
-        else {
+        Object[] services = m_services.toArray();
+        for (int i = 0; i < services.length; i++) {
+            DependencyService ds = (DependencyService) services[i];
+            if (makeAvailable) {
+                ds.dependencyAvailable(this);
+            }
+        }
+        if (!makeAvailable) {
             notifyAll();
         }
     }
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DefaultNullObject.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/DefaultNullObject.java
similarity index 98%
rename from dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DefaultNullObject.java
rename to dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/DefaultNullObject.java
index 79bb240..910f8cd 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/DefaultNullObject.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/DefaultNullObject.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.impl;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Logger.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/Logger.java
similarity index 99%
rename from dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Logger.java
rename to dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/Logger.java
index ab85366..4d38804 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/Logger.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/Logger.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.impl;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/SerialExecutor.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/SerialExecutor.java
similarity index 97%
rename from dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/SerialExecutor.java
rename to dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/SerialExecutor.java
index 72063c3..addcc95 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/SerialExecutor.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/SerialExecutor.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.impl;
 
 import java.util.LinkedList;
 import java.util.NoSuchElementException;
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java
similarity index 71%
rename from dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
rename to dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java
index e61bce3..d853fcf 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.impl;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
@@ -33,8 +33,19 @@
 import java.util.Map;
 import java.util.Properties;
 
+import org.apache.felix.dependencymanager.Dependency;
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.apache.felix.dependencymanager.DependencyService;
+import org.apache.felix.dependencymanager.Service;
+import org.apache.felix.dependencymanager.ServiceStateListener;
+import org.apache.felix.dependencymanager.dependencies.BundleDependency;
+import org.apache.felix.dependencymanager.dependencies.ConfigurationDependency;
+import org.apache.felix.dependencymanager.dependencies.ResourceDependency;
+import org.apache.felix.dependencymanager.dependencies.ServiceDependency;
 import org.apache.felix.dependencymanager.management.ServiceComponent;
 import org.apache.felix.dependencymanager.management.ServiceComponentDependency;
+import org.apache.felix.dependencymanager.resources.Resource;
+import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
@@ -43,11 +54,12 @@
  *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class ServiceImpl implements Service, ServiceComponent {
+public class ServiceImpl implements Service, DependencyService, ServiceComponent {
     private static final Class[] VOID = new Class[] {};
 	private static final ServiceRegistration NULL_REGISTRATION;
     private static final ServiceStateListener[] SERVICE_STATE_LISTENER_TYPE = new ServiceStateListener[] {};
 
+    private final Object SYNC = new Object();
     private final BundleContext m_context;
     private final DependencyManager m_manager;
 
@@ -71,6 +83,8 @@
     // runtime state (changes because of state changes)
     private Object m_serviceInstance;
     private ServiceRegistration m_registration;
+    private boolean m_isBound;
+    private boolean m_isInstantiated;
 
     // service state listeners
     private final List m_stateListeners = new ArrayList();
@@ -95,7 +109,7 @@
 
     public ServiceImpl(BundleContext context, DependencyManager manager, Logger logger) {
     	m_logger = logger;
-        m_state = new State((List) m_dependencies.clone(), false);
+        m_state = new State((List) m_dependencies.clone(), false, false, false);
         m_context = context;
         m_manager = manager;
         m_callbackInit = "init";
@@ -106,62 +120,134 @@
         m_autoConfig.put(BundleContext.class, Boolean.TRUE);
         m_autoConfig.put(ServiceRegistration.class, Boolean.TRUE);
         m_autoConfig.put(DependencyManager.class, Boolean.TRUE);
+        m_autoConfig.put(Service.class, Boolean.TRUE);
     }
 
+    private void calculateStateChanges() {
+        // see if any of the things we did caused a further change of state
+        State oldState, newState;
+        synchronized (m_dependencies) {
+            oldState = m_state;
+            newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
+            m_state = newState;
+        }
+        calculateStateChanges(oldState, newState);
+    }
+    
     private void calculateStateChanges(final State oldState, final State newState) {
-    	if (oldState.isWaitingForRequired() && newState.isTrackingOptional()) {
-        	m_executor.enqueue(new Runnable() {
-				public void run() {
-					activateService(newState);
-				}});
-    	}
-    	if (oldState.isTrackingOptional() && newState.isWaitingForRequired()) {
-    		m_executor.enqueue(new Runnable() {
-				public void run() {
-					deactivateService(oldState);
-				}});
-    	}
-    	if (oldState.isInactive() && (newState.isTrackingOptional())) {
-    		m_executor.enqueue(new Runnable() {
-				public void run() {
-					activateService(newState);
-				}});
-    	}
-    	if (oldState.isInactive() && (newState.isWaitingForRequired())) {
-    		m_executor.enqueue(new Runnable() {
-				public void run() {
-					startTrackingRequired(newState);
-				}});
-    	}
-    	if ((oldState.isWaitingForRequired()) && newState.isInactive()) {
-    		m_executor.enqueue(new Runnable() {
-				public void run() {
-					stopTrackingRequired(oldState);
-				}});
-    	}
-    	if ((oldState.isTrackingOptional()) && newState.isInactive()) {
-    		m_executor.enqueue(new Runnable() {
-				public void run() {
-					deactivateService(oldState);
-					stopTrackingRequired(oldState);
-				}});
-    	}
-    	m_executor.execute();
+        if (oldState.isInactive() && (newState.isTrackingOptional())) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    activateService(newState);
+                }});
+        }
+        if (oldState.isInactive() && (newState.isWaitingForRequired())) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    startTrackingRequired(newState);
+                }});
+        }
+        if (oldState.isWaitingForRequired() && newState.isTrackingOptional()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    activateService(newState);
+                }});
+        }
+        if ((oldState.isWaitingForRequired()) && newState.isInactive()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    stopTrackingRequired(oldState);
+                }});
+        }
+        if (oldState.isTrackingOptional() && newState.isWaitingForRequiredInstantiated()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    // TODO as far as I can see there is nothing left to do here
+                }});
+        }
+        if (oldState.isTrackingOptional() && newState.isWaitingForRequired()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    deactivateService(oldState);
+                }});
+        }
+        if (oldState.isTrackingOptional() && newState.isBound()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    bindService(oldState);
+                }});
+        }
+        if (oldState.isTrackingOptional() && newState.isInactive()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    deactivateService(oldState);
+                    stopTrackingRequired(oldState);
+                }});
+        }
+        if (oldState.isWaitingForRequiredInstantiated() && newState.isWaitingForRequired()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    deactivateService(oldState);
+                }});
+        }
+        if (oldState.isWaitingForRequiredInstantiated() && newState.isInactive()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    deactivateService(oldState);
+                    stopTrackingRequired(oldState);
+                }});
+        }
+        if (oldState.isWaitingForRequiredInstantiated() && newState.isBound()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    bindService(oldState);
+                }});
+        }
+        if (oldState.isBound() && newState.isWaitingForRequiredInstantiated()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    unbindService(oldState);
+                }});
+        }
+        if (oldState.isBound() && newState.isWaitingForRequired()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    unbindService(oldState);
+                    deactivateService(oldState);
+                }});
+        }
+        if (oldState.isBound() && newState.isInactive()) {
+            m_executor.enqueue(new Runnable() {
+                public void run() {
+                    unbindService(oldState);
+                    deactivateService(oldState);
+                    stopTrackingRequired(oldState);
+                }});
+        }
+        m_executor.execute();
     }
-
+    
     public Service add(final Dependency dependency) {
     	State oldState, newState;
         synchronized (m_dependencies) {
         	oldState = m_state;
             m_dependencies.add(dependency);
         }
-        if (oldState.isTrackingOptional() || (oldState.isWaitingForRequired() && dependency.isRequired())) {
+        if (oldState.isAllRequiredAvailable() || (oldState.isWaitingForRequired() && dependency.isRequired())) {
         	dependency.start(this);
         }
         synchronized (m_dependencies) {
-            newState = new State((List) m_dependencies.clone(), !oldState.isInactive());
+            newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
             m_state = newState;
-            calculateStateChanges(oldState, newState);
+        }
+        calculateStateChanges(oldState, newState);
+        return this;
+    }
+
+    public Service add(List dependencies) {
+        // TODO review if this can be done more smartly
+        for (int i = 0; i < dependencies.size(); i++) {
+            add((Dependency) dependencies.get(i));
         }
         return this;
     }
@@ -172,11 +258,11 @@
         	oldState = m_state;
             m_dependencies.remove(dependency);
         }
-        if (oldState.isTrackingOptional() || (oldState.isWaitingForRequired() && dependency.isRequired())) {
+        if (oldState.isAllRequiredAvailable() || (oldState.isWaitingForRequired() && dependency.isRequired())) {
         	dependency.stop(this);
         }
         synchronized (m_dependencies) {
-            newState = new State((List) m_dependencies.clone(), !oldState.isInactive());
+            newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
             m_state = newState;
         }
         calculateStateChanges(oldState, newState);
@@ -201,11 +287,11 @@
     	State oldState, newState;
         synchronized (m_dependencies) {
         	oldState = m_state;
-            newState = new State((List) m_dependencies.clone(), !oldState.isInactive());
+            newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
             m_state = newState;
         }
         calculateStateChanges(oldState, newState);
-        if (newState.isTrackingOptional()) {
+        if (newState.isAllRequiredAvailable()) {
         	m_executor.enqueue(new Runnable() {
         		public void run() {
         			updateInstance(dependency);
@@ -220,7 +306,7 @@
         synchronized (m_dependencies) {
         	state = m_state;
         }
-        if (state.isTrackingOptional()) {
+        if (state.isAllRequiredAvailable()) {
         	m_executor.enqueue(new Runnable() {
         		public void run() {
         			updateInstance(dependency);
@@ -234,11 +320,11 @@
     	State oldState, newState;
         synchronized (m_dependencies) {
         	oldState = m_state;
-            newState = new State((List) m_dependencies.clone(), !oldState.isInactive());
+            newState = new State((List) m_dependencies.clone(), !oldState.isInactive(), m_isInstantiated, m_isBound);
             m_state = newState;
         }
         calculateStateChanges(oldState, newState);
-        if (newState.isTrackingOptional()) {
+        if (newState.isAllRequiredAvailable()) {
         	m_executor.enqueue(new Runnable() {
         		public void run() {
         			updateInstance(dependency);
@@ -253,7 +339,7 @@
     	State oldState, newState;
         synchronized (m_dependencies) {
         	oldState = m_state;
-            newState = new State((List) m_dependencies.clone(), true);
+            newState = new State((List) m_dependencies.clone(), true, m_isInstantiated, m_isBound);
             m_state = newState;
         }
         calculateStateChanges(oldState, newState);
@@ -263,7 +349,7 @@
     	State oldState, newState;
         synchronized (m_dependencies) {
         	oldState = m_state;
-            newState = new State((List) m_dependencies.clone(), false);
+            newState = new State((List) m_dependencies.clone(), false, m_isInstantiated, m_isBound);
             m_state = newState;
         }
         calculateStateChanges(oldState, newState);
@@ -350,7 +436,7 @@
     	synchronized (m_dependencies) {
     		state = m_state;
     	}
-    	if (state.isTrackingOptional()) {
+    	if (state.isAllRequiredAvailable()) {
     		listener.starting(this);
     		listener.started(this);
     	}
@@ -362,7 +448,7 @@
     	}
 	}
 
-	void removeStateListeners() {
+	public void removeStateListeners() {
     	synchronized (m_stateListeners) {
     		m_stateListeners.clear();
     	}
@@ -422,21 +508,31 @@
 		}
 	}
 
-	private void activateService(State state) {
-		String init, start;
-		synchronized (this) {
-			init = m_callbackInit;
-			start = m_callbackStart;
-		}
+    private void activateService(State state) {
+        String init;
+        synchronized (this) {
+            init = m_callbackInit;
+        }
         // service activation logic, first we initialize the service instance itself
         // meaning it is created if necessary and the bundle context is set
         initService();
-        // then we invoke the init callback so the service can further initialize
-        // itself
-        invoke(init);
         // now is the time to configure the service, meaning all required
         // dependencies will be set and any callbacks called
         configureService(state);
+        // then we invoke the init callback so the service can further initialize
+        // itself
+        invoke(init);
+        // flag that our instance has been created
+        m_isInstantiated = true;
+        // see if any of this caused further state changes
+        calculateStateChanges();
+    }
+
+    private void bindService(State state) {
+        String start;
+        synchronized (this) {
+            start = m_callbackStart;
+        }
         // inform the state listeners we're starting
         stateListenersStarting();
         // invoke the start callback, since we're now ready to be used
@@ -448,13 +544,12 @@
         // inform the state listeners we've started
         stateListenersStarted();
     }
-
-    private void deactivateService(State state) {
-    	String stop, destroy;
-    	synchronized (this) {
-    		stop = m_callbackStop;
-    		destroy = m_callbackDestroy;
-    	}
+    
+    private void unbindService(State state) {
+        String stop;
+        synchronized (this) {
+            stop = m_callbackStop;
+        }
         // service deactivation logic, first inform the state listeners
         // we're stopping
         stateListenersStopping();
@@ -466,12 +561,21 @@
         invoke(stop);
         // inform the state listeners we've stopped
         stateListenersStopped();
+    }
+
+    private void deactivateService(State state) {
+        String destroy;
+        synchronized (this) {
+            destroy = m_callbackDestroy;
+        }
         // invoke the destroy callback
         invoke(destroy);
         // destroy the service instance
         destroyService(state);
+        // flag that our instance was destroyed
+        m_isInstantiated = false;
     }
-
+    
     private void invoke(String name) {
         if (name != null) {
             // invoke method if it exists
@@ -549,7 +653,7 @@
         return clazz.newInstance();
     }
 
-    void initService() {
+    public void initService() {
     	if (m_serviceInstance == null) {
 	        if (m_implementation instanceof Class) {
 	            // instantiate
@@ -611,6 +715,9 @@
             if (((Boolean) m_autoConfig.get(DependencyManager.class)).booleanValue()) {
                 configureImplementation(DependencyManager.class, m_manager, (String) m_autoConfigInstance.get(DependencyManager.class));
             }
+            if (((Boolean) m_autoConfig.get(Service.class)).booleanValue()) {
+                configureImplementation(Service.class, this, (String) m_autoConfigInstance.get(Service.class));
+            }
     	}
     }
 
@@ -665,6 +772,7 @@
                 wrapper.setIllegalState();
             }
         }
+        m_isBound = true;
     }
 
 	private Dictionary calculateServiceProperties() {
@@ -700,6 +808,7 @@
 	}
 
     private void unregisterService() {
+        m_isBound = false;
         if (m_serviceName != null) {
             m_registration.unregister();
             configureImplementation(ServiceRegistration.class, NULL_REGISTRATION);
@@ -718,11 +827,25 @@
         else if (dependency instanceof ConfigurationDependency) {
         	ConfigurationDependency cd = (ConfigurationDependency) dependency;
         	if (cd.isPropagated()) {
-        		// change service properties accordingly
-        		Dictionary props = calculateServiceProperties();
-        		m_registration.setProperties(props);
+        		// change service properties accordingly, but only if the service was already registered
+        	    if (m_registration != null) {
+            		Dictionary props = calculateServiceProperties();
+            		m_registration.setProperties(props);
+        	    }
         	}
         }
+        else if (dependency instanceof BundleDependency) {
+            BundleDependency bd = (BundleDependency) dependency;
+            if (bd.isAutoConfig()) {
+                configureImplementation(Bundle.class, bd.getBundle()); // TODO support AutoConfigName
+            }
+        }
+        else if (dependency instanceof ResourceDependency) {
+            ResourceDependency rd = (ResourceDependency) dependency;
+            if (rd.isAutoConfig()) {
+                configureImplementation(Resource.class, rd.getResource()); // TODO support AutoConfigName
+            }
+        }
     }
 
     /**
@@ -747,7 +870,7 @@
 		                    try {
 		                    	fields[j].setAccessible(true);
 		                        // synchronized makes sure the field is actually written to immediately
-		                        synchronized (new Object()) {
+		                        synchronized (SYNC) {
 		                            fields[j].set(serviceInstance, instance);
 		                        }
 		                    }
@@ -764,30 +887,30 @@
     }
     
     public Object[] getCompositionInstances() {
-      Object[] instances = null;
-      if (m_compositionManagerGetMethod != null) {
-	if (m_compositionManager != null) {
-	  m_compositionManagerInstance = m_compositionManager;
-	}
-	else {
-	  m_compositionManagerInstance = m_serviceInstance;
-	}
-	if (m_compositionManagerInstance != null) {
-	  try {
-	    Method m = m_compositionManagerInstance.getClass().getDeclaredMethod(m_compositionManagerGetMethod, null);
-	    m.setAccessible(true);
-	    instances = (Object[]) m.invoke(m_compositionManagerInstance, null);
-	  }
-	  catch (Exception e) {
-	    m_logger.log(Logger.LOG_ERROR, "Could not obtain instances from the composition manager.", e);
-	    instances = new Object[] { m_serviceInstance };
-	  }
-	}
-      }
-      else {
-	instances = new Object[] { m_serviceInstance };
-      }
-      return instances;
+        Object[] instances = null;
+        if (m_compositionManagerGetMethod != null) {
+            if (m_compositionManager != null) {
+                m_compositionManagerInstance = m_compositionManager;
+            }
+            else {
+                m_compositionManagerInstance = m_serviceInstance;
+            }
+            if (m_compositionManagerInstance != null) {
+                try {
+                    Method m = m_compositionManagerInstance.getClass().getDeclaredMethod(m_compositionManagerGetMethod, null);
+                    m.setAccessible(true);
+                    instances = (Object[]) m.invoke(m_compositionManagerInstance, null);
+                }
+                catch (Exception e) {
+                    m_logger.log(Logger.LOG_ERROR, "Could not obtain instances from the composition manager.", e);
+                    instances = new Object[] { m_serviceInstance };
+                }
+            }
+        }
+        else {
+            instances = new Object[] { m_serviceInstance };
+        }
+        return instances;
     }
 
     private void configureImplementation(Class clazz, Object instance) {
@@ -812,7 +935,41 @@
                 }
                 // for required dependencies, we invoke any callbacks here
                 if (sd.isRequired()) {
-                    sd.invokeAdded();
+                    sd.invokeAdded(this, sd.lookupServiceReference(), sd.lookupService());
+                }
+            }
+            else if (dependency instanceof BundleDependency) {
+                BundleDependency bd = (BundleDependency) dependency;
+                if (bd.isAutoConfig()) {
+                    if (bd.isRequired()) {
+                        configureImplementation(Bundle.class, bd.getBundle()); // TODO AutoConfigName support
+                    }
+                    else {
+                        // for optional services, we do an "ad-hoc" lookup to inject the service if it is
+                        // already available even though the tracker has not yet been started
+                        // TODO !!! configureImplementation(sd.getInterface(), sd.lookupService(), sd.getAutoConfigName());
+                    }
+                }
+                // for required dependencies, we invoke any callbacks here
+                if (bd.isRequired()) {
+                    bd.invokeAdded();
+                }
+            }
+            else if (dependency instanceof ResourceDependency) {
+                ResourceDependency bd = (ResourceDependency) dependency;
+                if (bd.isAutoConfig()) {
+                    if (bd.isRequired()) {
+                        configureImplementation(Resource.class, bd.getResource()); // TODO AutoConfigName support
+                    }
+                    else {
+                        // for optional services, we do an "ad-hoc" lookup to inject the service if it is
+                        // already available even though the tracker has not yet been started
+                        // TODO !!! configureImplementation(sd.getInterface(), sd.lookupService(), sd.getAutoConfigName());
+                    }
+                }
+                // for required dependencies, we invoke any callbacks here
+                if (bd.isRequired()) {
+                    bd.invokeAdded();
                 }
             }
         }
@@ -826,7 +983,7 @@
                 ServiceDependency sd = (ServiceDependency) dependency;
                 // for required dependencies, we invoke any callbacks here
                 if (sd.isRequired()) {
-                    sd.invokeRemoved();
+                    sd.invokeRemoved(this, sd.lookupServiceReference(), sd.lookupService());
                 }
             }
         }
@@ -841,12 +998,13 @@
             throw new IllegalStateException("Cannot modify state while active.");
         }
     }
-    boolean isRegistered() {
+    
+    public boolean isRegistered() {
     	State state;
     	synchronized (m_dependencies) {
     		state = m_state;
     	}
-        return (state.isTrackingOptional());
+        return (state.isAllRequiredAvailable());
     }
 
     // ServiceComponent interface
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java
similarity index 98%
rename from dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java
rename to dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java
index 0ff8473..95087b0 100644
--- a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+package org.apache.felix.dependencymanager.impl;
 
 import java.util.Dictionary;
 
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java
new file mode 100644
index 0000000..2ef448d
--- /dev/null
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java
@@ -0,0 +1,129 @@
+/*
+ * 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.dependencymanager.impl;
+
+import java.util.List;
+
+import org.apache.felix.dependencymanager.Dependency;
+
+/**
+ * Encapsulates the current state of the dependencies of a service. A state is
+ * basically an immutable value object.
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public final class State {
+    private static final String[] STATES = { "?", "inactive", "waiting for required", "tracking optional", "bound", "waiting for required (instantiated)" };
+    private static final int INACTIVE = 1;
+    private static final int WAITING_FOR_REQUIRED = 2;
+    private static final int TRACKING_OPTIONAL = 3;
+    private static final int BOUND = 4;
+    private static final int WAITING_FOR_REQUIRED_INSTANTIATED = 5;
+    private final List m_deps;
+    private final int m_state;
+    private String m_stringValue;
+    
+    /**
+     * Creates a new state instance.
+     * 
+     * @param deps the dependencies that determine the state
+     * @param isActive <code>true</code> if the service is active (started)
+     */
+    public State(List deps, boolean isActive, boolean isInstantiated, boolean isBound /* unused? */) {
+        m_deps = deps;
+        // only bother calculating dependencies if we're active
+        if (isActive) {
+            boolean allRequiredAvailable = true;
+            boolean keepInstanceAround = isInstantiated;
+            for (int i = 0; i < deps.size(); i++) {
+                Dependency dep = (Dependency) deps.get(i);
+                if (dep.isRequired()) {
+                    if (!dep.isAvailable()) {
+                        allRequiredAvailable = false;
+                        if (!dep.isInstanceBound()) {
+                            keepInstanceAround = false;
+                        }
+                    }
+                }
+            }
+            if (allRequiredAvailable) {
+                if (isInstantiated) {
+                    m_state = BOUND;
+                }
+                else {
+                    m_state = TRACKING_OPTIONAL;
+                }
+            }
+            else {
+                if (keepInstanceAround) {
+                    m_state = WAITING_FOR_REQUIRED_INSTANTIATED;
+                }
+                else {
+                    m_state = WAITING_FOR_REQUIRED;
+                }
+            }
+        }
+        else {
+            m_state = INACTIVE;
+        }
+    }
+    
+    public boolean isInactive() {
+        return m_state == INACTIVE;
+    }
+    
+    public boolean isWaitingForRequired() {
+        return m_state == WAITING_FOR_REQUIRED;
+    }
+    
+    public boolean isTrackingOptional() {
+        return m_state == TRACKING_OPTIONAL;
+    }
+    
+    public boolean isBound() {
+        return m_state == BOUND;
+    }
+    
+    public boolean isAllRequiredAvailable() {
+        return isTrackingOptional() || isBound();
+    }
+    
+    public boolean isWaitingForRequiredInstantiated() {
+        return m_state == WAITING_FOR_REQUIRED_INSTANTIATED;
+    }
+    
+    public List getDependencies() {
+        return m_deps;
+    }
+    
+    public synchronized String toString() {
+        if (m_stringValue == null) {
+            // we only need to determine this once, but we do it lazily
+            StringBuffer buf = new StringBuffer();
+            buf.append("State[" + STATES[m_state] + "|");
+            List deps = m_deps;
+            for (int i = 0; i < deps.size(); i++) {
+                Dependency dep = (Dependency) deps.get(i);
+                buf.append("(" + dep + (dep.isRequired() ? " R" : " O") + (dep.isAvailable() ? " +" : " -") + ")");
+            }
+            m_stringValue = buf.toString();
+        }
+        return m_stringValue;
+    }
+}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java
new file mode 100644
index 0000000..3b8e6fb
--- /dev/null
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java
@@ -0,0 +1,122 @@
+/*
+ * 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.dependencymanager.resources;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+public class BundleResourceRepository {
+
+	private final Bundle bundle;
+
+	public BundleResourceRepository(Bundle bundle) {
+		this.bundle = bundle;
+	}
+
+	public synchronized void addHandler(ServiceReference ref, ResourceHandler handler) {
+
+		String filter = (String) ref.getProperty("filter"); // "(&(repository=a)(path=b)(name=*.xml))"
+
+		Filter filterObject = null;
+
+		try {
+			filterObject = FrameworkUtil.createFilter(filter);
+		} catch (InvalidSyntaxException e) {
+			e.printStackTrace();
+			return;
+		}
+
+		Enumeration entries = bundle.findEntries("/", null, true);
+		while (entries.hasMoreElements()) {
+			URL entry = (URL) entries.nextElement();
+
+			Properties props = new Properties();
+			props.setProperty(Resource.REPOSITORY, bundle.getSymbolicName() + "_" + bundle.getVersion());
+			props.setProperty(Resource.PATH, entry.getPath());
+			props.setProperty(Resource.NAME, entry.getFile());
+
+			if (filterObject.match(props))
+				handler.added(new EntryResource(entry));
+
+		}
+	}
+
+	public synchronized void removeHandler(ServiceReference ref, ResourceHandler handler) {
+
+		String filter = (String) ref.getProperty("filter"); // "(&(repository=a)(path=b)(name=*.xml))"
+
+		Filter filterObject = null;
+
+		try {
+			filterObject = FrameworkUtil.createFilter(filter);
+		} catch (InvalidSyntaxException e) {
+			e.printStackTrace();
+			return;
+		}
+
+		Enumeration entries = bundle.findEntries("/", null, true);
+		while (entries.hasMoreElements()) {
+			URL entry = (URL) entries.nextElement();
+
+			Properties props = new Properties();
+			props.setProperty(Resource.REPOSITORY, bundle.getSymbolicName() + "_" + bundle.getVersion());
+			props.setProperty(Resource.PATH, entry.getPath());
+			props.setProperty(Resource.NAME, entry.getFile());
+
+			if (filterObject.match(props))
+				handler.removed(new EntryResource(entry));
+
+		}
+	}
+
+	class EntryResource implements Resource {
+
+		URL entry;
+
+		EntryResource(URL entry) {
+			this.entry = entry;
+		}
+
+		public String getName() {
+			return entry.getFile();
+		}
+
+		public String getPath() {
+			return entry.getPath();
+		}
+
+		public String getRepository() {
+
+			return bundle.getSymbolicName() + "_" + bundle.getVersion();
+		}
+
+		public InputStream openStream() throws IOException {
+			return entry.openStream();
+		}
+	}
+}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java
new file mode 100644
index 0000000..075f5d6
--- /dev/null
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java
@@ -0,0 +1,37 @@
+/*
+ * 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.dependencymanager.resources;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/** Interface that defines a resource. */
+public interface Resource {
+	public static final String PATH = "path";
+	public static final String NAME = "name";
+	public static final String REPOSITORY = "repository";
+	
+	String getName();
+	
+	String getPath();
+	
+	String getRepository();
+	
+	InputStream openStream() throws IOException;
+}
diff --git a/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java
new file mode 100644
index 0000000..79e387e
--- /dev/null
+++ b/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java
@@ -0,0 +1,26 @@
+/*
+ * 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.dependencymanager.resources;
+
+/** Service interface for anybody wanting to be notified of changes to resources. */
+public interface ResourceHandler {
+	void added(Resource resource);
+	void changed(Resource resource);
+	void removed(Resource resource);
+}
diff --git a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java
index 38e8bb2..a97a4f3 100644
--- a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java
+++ b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java
@@ -23,8 +23,8 @@
 import static org.ops4j.pax.exam.CoreOptions.provision;
 
 import org.apache.felix.dependencymanager.DependencyManager;
-import org.apache.felix.dependencymanager.Logger;
 import org.apache.felix.dependencymanager.Service;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
diff --git a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java
index f0d9fb6..adcfb7a 100644
--- a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java
+++ b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java
@@ -29,8 +29,8 @@
 import junit.framework.Assert;
 
 import org.apache.felix.dependencymanager.DependencyManager;
-import org.apache.felix.dependencymanager.Logger;
 import org.apache.felix.dependencymanager.Service;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
@@ -82,7 +82,7 @@
             m_ensure = e;
         }
 
-        public void start() {
+        public void init() {
             try {
                 m_ensure.step(1);
                 org.osgi.service.cm.Configuration conf = m_ca.getConfiguration("test", null);
@@ -125,7 +125,7 @@
             m_ensure = e;
         }
         
-        public void start() {
+        public void init() {
             m_ensure.step(3);
             m_runnable.run();
         }
diff --git a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java
index 6aeba950..73e1e2a 100644
--- a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java
+++ b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java
@@ -50,6 +50,7 @@
      * @param timeout the number of milliseconds to wait
      */
     public synchronized void waitForStep(int nr, int timeout) {
+        final int initialTimeout = timeout;
         while (step <= nr && timeout > 0) {
             try {
                 wait(RESOLUTION);
@@ -58,7 +59,7 @@
             catch (InterruptedException e) {}
         }
         if (step <= nr) {
-            throw new IllegalStateException("Timed out waiting for " + timeout + " ms for step " + nr);
+            throw new IllegalStateException("Timed out waiting for " + initialTimeout + " ms for step " + nr + ", we are still at step " + step);
         }
     }
 }
diff --git a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java
index e453b15..691d551 100644
--- a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java
+++ b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java
@@ -7,8 +7,8 @@
 import java.util.Properties;
 
 import org.apache.felix.dependencymanager.DependencyManager;
-import org.apache.felix.dependencymanager.Logger;
 import org.apache.felix.dependencymanager.Service;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
@@ -82,7 +82,7 @@
             m_ensure = e;
         }
         
-        public void start() {
+        public void init() {
             Thread t = new Thread(this);
             t.start();
         }
@@ -95,7 +95,7 @@
             m_service.invoke();
         }
         
-        public void stop() {
+        public void destroy() {
             m_ensure.step(6);
         }
     }
diff --git a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java
index 37cff66..a1533de 100644
--- a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java
+++ b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java
@@ -23,8 +23,8 @@
 import static org.ops4j.pax.exam.CoreOptions.provision;
 
 import org.apache.felix.dependencymanager.DependencyManager;
-import org.apache.felix.dependencymanager.Logger;
 import org.apache.felix.dependencymanager.Service;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
@@ -85,12 +85,12 @@
             m_ensure = e;
         }
         
-        public void start() {
+        public void init() {
             m_ensure.step(1);
             m_service.invoke();
         }
         
-        public void stop() {
+        public void destroy() {
             m_ensure.step(3);
         }
     }
diff --git a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java
index 30bf35a..d782b1b 100644
--- a/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java
+++ b/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java
@@ -23,8 +23,8 @@
 import static org.ops4j.pax.exam.CoreOptions.provision;
 
 import org.apache.felix.dependencymanager.DependencyManager;
-import org.apache.felix.dependencymanager.Logger;
 import org.apache.felix.dependencymanager.Service;
+import org.apache.felix.dependencymanager.impl.Logger;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.Option;
@@ -104,7 +104,7 @@
             m_ensure = e;
         }
         
-        public void start() {
+        public void init() {
             m_ensure.step(1);
             Thread t = new Thread(this);
             t.start();
@@ -116,7 +116,7 @@
             m_service.invoke();
         }
         
-        public void stop() {
+        public void destroy() {
             m_ensure.step(5);
         }
     }