Slightly modified (improved) the order in which optional dependencies are injected and their callbacks invoked. The callbacks now occur after the start method is invoked, the injections done before.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@738185 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
index 2da0a23..d317267 100644
--- a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
+++ b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceDependency.java
@@ -22,8 +22,11 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.Comparator;
 
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 
@@ -93,6 +96,70 @@
         return service;
     }
 
+    public Object lookupService() {
+        Object service = null;
+        if (m_isStarted) {
+            service = m_tracker.getService();
+        }
+        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, new Comparator() {
+                                public int getRank(ServiceReference ref) {
+                                    Object ranking = ref.getProperty(Constants.SERVICE_RANKING);
+                                    if (ranking != null && (ranking instanceof Integer)) {
+                                        return ((Integer) ranking).intValue();
+                                    }
+                                    return 0;
+                                }
+
+                                public int compare(Object a, Object b) {
+                                    ServiceReference ra = (ServiceReference) a, rb = (ServiceReference) b;
+                                    int ranka = getRank(ra);
+                                    int rankb = getRank(rb);
+                                    if (ranka < rankb) {
+                                        return -1;
+                                    }
+                                    else if (ranka > rankb) {
+                                        return 1;
+                                    }
+                                    return 0;
+                                }});
+                            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 = m_context.getService(ref);
+                }
+            }
+            else {
+                throw new IllegalStateException("Could not lookup dependency, no service name specified.");
+            }
+        }
+        if (service == null) {
+            service = getDefaultImplementation();
+            if (service == null) {
+                service = getNullObject();
+            }
+        }
+        return service;
+    }
+
     private Object getNullObject() {
         if (m_nullObject == null) {
             Class trackedServiceName;
diff --git a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
index 5fbcd35..b19f152 100644
--- a/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
+++ b/dependencymanager/src/main/java/org/apache/felix/dependencymanager/ServiceImpl.java
@@ -503,7 +503,7 @@
             }
         }
     }
-
+    
     private void stopTrackingOptional(State state) {
         Iterator i = state.getDependencies().iterator();
         while (i.hasNext()) {
@@ -767,7 +767,14 @@
             if (dependency instanceof ServiceDependency) {
                 ServiceDependency sd = (ServiceDependency) dependency;
                 if (sd.isAutoConfig()) {
-                    configureImplementation(sd.getInterface(), sd.getService(), sd.getAutoConfigName());
+                    if (sd.isRequired()) {
+                        configureImplementation(sd.getInterface(), sd.getService(), sd.getAutoConfigName());
+                    }
+                    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
+                        configureImplementation(sd.getInterface(), sd.lookupService(), sd.getAutoConfigName());
+                    }
                 }
                 // for required dependencies, we invoke any callbacks here
                 if (sd.isRequired()) {