Bug 309457. [DS] Component deactivation in incorrect order
diff --git a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Resolver.java b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Resolver.java
index 2809297..fbe8184 100644
--- a/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Resolver.java
+++ b/bundles/org.eclipse.equinox.ds/src/org/eclipse/equinox/internal/ds/Resolver.java
@@ -325,19 +325,6 @@
 
 				break;
 			case ServiceEvent.UNREGISTERING :
-				Vector newlyUnsatisfiedSCPs;
-				synchronized (syncLock) {
-					serviceReferenceTable.remove(event.getServiceReference());
-					if (scpEnabled.isEmpty())
-						return; // check for any enabled configurations
-
-					newlyUnsatisfiedSCPs = selectNewlyUnsatisfied();
-				}
-				if (!newlyUnsatisfiedSCPs.isEmpty()) {
-					// synchronously dispose newly unsatisfied components
-					instanceProcess.disposeInstances(newlyUnsatisfiedSCPs, ComponentConstants.DEACTIVATION_REASON_REFERENCE);
-				}
-
 				Vector componentsToDispose;
 				synchronized (syncLock) {
 					//check for components with static reference to this service
@@ -345,7 +332,20 @@
 				}
 				//dispose instances from staticUnbind
 				if (componentsToDispose != null) {
-					instanceProcess.disposeInstances(componentsToDispose, ComponentConstants.DEACTIVATION_REASON_UNSPECIFIED);
+					instanceProcess.disposeInstances(componentsToDispose, ComponentConstants.DEACTIVATION_REASON_REFERENCE);
+				}
+
+				Vector newlyUnsatisfiedSCPs;
+				synchronized (syncLock) {
+					serviceReferenceTable.remove(event.getServiceReference());
+					if (scpEnabled.isEmpty())
+						return; // check for any enabled configurations
+
+					newlyUnsatisfiedSCPs = selectNewlyUnsatisfied(event.getServiceReference());
+				}
+				if (!newlyUnsatisfiedSCPs.isEmpty()) {
+					// synchronously dispose newly unsatisfied components
+					instanceProcess.disposeInstances(newlyUnsatisfiedSCPs, ComponentConstants.DEACTIVATION_REASON_REFERENCE);
 				}
 
 				synchronized (syncLock) {
@@ -375,7 +375,7 @@
 
 					// check for newly unsatisfied components and synchronously
 					// dispose them
-					newlyUnsatisfiedSCPs = selectNewlyUnsatisfied();
+					newlyUnsatisfiedSCPs = selectNewlyUnsatisfied(event.getServiceReference());
 				}
 
 				if (!newlyUnsatisfiedSCPs.isEmpty()) {
@@ -534,7 +534,7 @@
 		}
 	}
 
-	private Vector selectNewlyUnsatisfied() {
+	private Vector selectNewlyUnsatisfied(ServiceReference serviceRef) {
 		try {
 			Vector result = (Vector) scpEnabled.clone();
 			for (int k = result.size() - 1; k >= 0; k--) {
@@ -547,7 +547,15 @@
 					// scp and re-run the algorithm
 					Reference reference = (Reference) refs.elementAt(i);
 					if (reference != null) {
-						boolean resolved = !reference.isRequiredFor(scp.serviceComponent) || reference.hasProviders(null);
+						if (serviceRef != null && reference.reference.bind != null && scp.getState() == Component.STATE_ACTIVE && !(reference.dynamicUnbindReference(serviceRef) || reference.staticUnbindReference(serviceRef))) {
+							//make quick test - the service reference is not bound to the current component reference
+							continue;
+						}
+						if (serviceRef != null && !isPossibleMatch(reference, serviceRef)) {
+							// the service reference is not a possible match. Skipping further checks 
+							continue;
+						}
+						boolean resolved = !reference.isRequiredFor(scp.serviceComponent) || reference.hasProviders(this.serviceReferenceTable);
 
 						if (!resolved && scp.isBuilt()) {
 							if (Activator.DEBUG) {
@@ -569,6 +577,30 @@
 		}
 	}
 
+	private boolean isPossibleMatch(Reference reference, ServiceReference serviceRef) {
+		String[] serviceNames = (String[]) serviceRef.getProperty(Constants.OBJECTCLASS);
+		boolean hasName = false;
+		for (int i = 0; i < serviceNames.length; i++) {
+			if (serviceNames[i].equals(reference.interfaceName)) {
+				hasName = true;
+				break;
+			}
+		}
+		if (!hasName) {
+			return false;
+		}
+		// check target filter
+		try {
+			Filter filter = FrameworkUtil.createFilter(reference.target);
+			if (!filter.match(serviceRef)) {
+				return false;
+			}
+		} catch (InvalidSyntaxException e) {
+			return false;
+		}
+		return true;
+	}
+
 	// -- begin *disable* component routines
 	/**
 	 * Disable list of ComponentDescriptions