Copied: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java
 (from r883744, 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java)
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java&r1=883744&r2=884327&rev=884327&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
 (original)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceImpl.java
 Wed Nov 25 23:04:32 2009
@@ -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:[email protected]";>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

Copied: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java
 (from r883483, 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java)
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java&r1=883483&r2=884327&rev=884327&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/ServiceRegistrationImpl.java
 (original)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/ServiceRegistrationImpl.java
 Wed Nov 25 23:04:32 2009
@@ -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;
 

Copied: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java
 (from r883483, 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java)
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java?p2=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java&p1=felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java&r1=883483&r2=884327&rev=884327&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/State.java
 (original)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/impl/State.java
 Wed Nov 25 23:04:32 2009
@@ -16,10 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.dependencymanager;
+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.
@@ -27,73 +29,101 @@
  * @author <a href="mailto:[email protected]";>Felix Project Team</a>
  */
 public final class State {
-    private static final String[] STATES = { "?", "inactive", "waiting for 
required", "tracking optional" };
+    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 final List m_deps;
-       private final int m_state;
+    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) {
-               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();
-           }
+    
+    /**
+     * 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;
-       }
+    }
 }

Added: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java?rev=884327&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java
 (added)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/BundleResourceRepository.java
 Wed Nov 25 23:04:32 2009
@@ -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();
+               }
+       }
+}

Added: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java?rev=884327&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java
 (added)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/Resource.java
 Wed Nov 25 23:04:32 2009
@@ -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;
+}

Added: 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java?rev=884327&view=auto
==============================================================================
--- 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java
 (added)
+++ 
felix/trunk/dependencymanager/core/src/main/java/org/apache/felix/dependencymanager/resources/ResourceHandler.java
 Wed Nov 25 23:04:32 2009
@@ -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);
+}

Modified: 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java?rev=884327&r1=884326&r2=884327&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java
 (original)
+++ 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ComponentLifeCycleTest.java
 Wed Nov 25 23:04:32 2009
@@ -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;

Modified: 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java?rev=884327&r1=884326&r2=884327&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java
 (original)
+++ 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ConfigurationDependencyTest.java
 Wed Nov 25 23:04:32 2009
@@ -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();
         }

Modified: 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java?rev=884327&r1=884326&r2=884327&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java
 (original)
+++ 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/Ensure.java
 Wed Nov 25 23:04:32 2009
@@ -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);
         }
     }
 }

Modified: 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java?rev=884327&r1=884326&r2=884327&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java
 (original)
+++ 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/MultipleServiceDependencyTest.java
 Wed Nov 25 23:04:32 2009
@@ -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);
         }
     }

Modified: 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java?rev=884327&r1=884326&r2=884327&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java
 (original)
+++ 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/ServiceDependencyTest.java
 Wed Nov 25 23:04:32 2009
@@ -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);
         }
     }

Modified: 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java
URL: 
http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java?rev=884327&r1=884326&r2=884327&view=diff
==============================================================================
--- 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java
 (original)
+++ 
felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dependencymanager/test/TemporalServiceDependencyTest.java
 Wed Nov 25 23:04:32 2009
@@ -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);
         }
     }


Reply via email to