felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From clem...@apache.org
Subject svn commit: r1492155 [2/4] - in /felix/trunk/ipojo/runtime: composite-it/src/it/ipojo-composite-import-export-test/src/test/java/org/apache/felix/ipojo/runtime/core/importer/ composite-it/src/it/ipojo-composite-import-export-test/src/test/resources/ co...
Date Wed, 12 Jun 2013 11:38:30 GMT
Modified: felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-policies/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/comparator/CheckServiceProvider.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-policies/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/comparator/CheckServiceProvider.java?rev=1492155&r1=1492154&r2=1492155&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-policies/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/comparator/CheckServiceProvider.java (original)
+++ felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-policies/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/comparator/CheckServiceProvider.java Wed Jun 12 11:38:27 2013
@@ -38,8 +38,8 @@ public class CheckServiceProvider implem
 
     public Properties getProps() {
         Properties props = new Properties();
-        props.put("fs", new Integer(fs.getInt()));
-        props.put("fs2", new Integer(fs2.getInt()));
+        props.put("fs", fs.getInt());
+        props.put("fs2", fs2.getInt());
 
         int[] grades = new int[fss.length];
 

Modified: felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-policies/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/comparator/TestComparator.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-policies/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/comparator/TestComparator.java?rev=1492155&r1=1492154&r2=1492155&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-policies/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/comparator/TestComparator.java (original)
+++ felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-policies/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/comparator/TestComparator.java Wed Jun 12 11:38:27 2013
@@ -63,10 +63,11 @@ public class TestComparator extends Comm
 
         CheckService cs = (CheckService) osgiHelper.getServiceObject(ref);
         Properties result = cs.getProps();
-        int fsGrade = ((Integer) result.get("fs")).intValue();
-        int fs2Grade = ((Integer) result.get("fs2")).intValue();
+        int fsGrade = (Integer) result.get("fs");
+        int fs2Grade = (Integer) result.get("fs2");
         int[] fssGrades = (int[]) result.get("fss");
 
+        // We should have been injected with the highest one.
         assertEquals("fs grade -1", 2, fsGrade);
         assertEquals("fs2 grade -1", 2, fs2Grade);
         assertEquals("fss grade size -1", 2, fssGrades.length);
@@ -112,8 +113,8 @@ public class TestComparator extends Comm
 
         CheckService cs = (CheckService) osgiHelper.getServiceObject(ref);
         Properties result = cs.getProps();
-        int fsGrade = ((Integer) result.get("fs")).intValue();
-        int fs2Grade = ((Integer) result.get("fs2")).intValue();
+        int fsGrade = (Integer) result.get("fs");
+        int fs2Grade = (Integer) result.get("fs2");
         int[] fssGrades = (int[]) result.get("fss");
 
         assertEquals("fs grade -1", 2, fsGrade);
@@ -151,7 +152,7 @@ public class TestComparator extends Comm
 
     private ComponentInstance createGrade(int grade) {
         Properties props = new Properties();
-        props.put("grade", new Integer(grade));
+        props.put("grade", grade);
         return ipojoHelper.createComponentInstance(gradeFactory, props);
     }
 

Modified: felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/TestDependencyArchitecture.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/TestDependencyArchitecture.java?rev=1492155&r1=1492154&r2=1492155&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/TestDependencyArchitecture.java (original)
+++ felix/trunk/ipojo/runtime/core-it/src/it/ipojo-core-service-dependency-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/TestDependencyArchitecture.java Wed Jun 12 11:38:27 2013
@@ -165,9 +165,7 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps = ((Architecture) osgiHelper.getServiceObject(arch_ps)).getInstanceDescription();
         ProvidedServiceHandlerDescription psh = getPSDesc(id_ps);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
         assertEquals("Check POJO creation", id_ps.getCreatedObjects().length, 1);
-        assertTrue("Check service reference - 1", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
 
         fooProvider1.stop();
 
@@ -200,8 +198,7 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps = ((Architecture) osgiHelper.getServiceObject(arch_ps)).getInstanceDescription();
         psh = getPSDesc(id_ps);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
-        assertTrue("Check service reference - 1", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
+
 
         fooProvider1.stop();
 
@@ -258,9 +255,7 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps = ((Architecture) osgiHelper.getServiceObject(arch_ps)).getInstanceDescription();
         ProvidedServiceHandlerDescription psh = getPSDesc(id_ps);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
         assertEquals("Check POJO creation", id_ps.getCreatedObjects().length, 1);
-        assertTrue("Check service reference - 1", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
 
         fooProvider1.stop();
 
@@ -293,8 +288,6 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps = ((Architecture) osgiHelper.getServiceObject(arch_ps)).getInstanceDescription();
         psh = getPSDesc(id_ps);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
-        assertTrue("Check service reference - 1", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
 
         fooProvider1.stop();
 
@@ -350,9 +343,7 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps = ((Architecture) osgiHelper.getServiceObject(arch_ps)).getInstanceDescription();
         ProvidedServiceHandlerDescription psh = getPSDesc(id_ps);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
         assertEquals("Check POJO creation", id_ps.getCreatedObjects().length, 1);
-        assertTrue("Check service reference - 1", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
 
         fooProvider1.stop();
 
@@ -385,8 +376,6 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps = ((Architecture) osgiHelper.getServiceObject(arch_ps)).getInstanceDescription();
         psh = getPSDesc(id_ps);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
-        assertTrue("Check service reference - 1", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
 
         fooProvider1.stop();
 
@@ -451,9 +440,7 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps1 = ((Architecture) osgiHelper.getServiceObject(arch_ps1)).getInstanceDescription();
         ProvidedServiceHandlerDescription psh = getPSDesc(id_ps1);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
         assertEquals("Check POJO creation", id_ps1.getCreatedObjects().length, 1);
-        assertTrue("Check service reference - 2", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
 
         // Start a second foo service provider
         fooProvider2.start();
@@ -488,8 +475,6 @@ public class TestDependencyArchitecture 
         ProvidedServiceHandlerDescription psh2 = getPSDesc(id_ps2);
         assertEquals("Check POJO creation", id_ps1.getCreatedObjects().length, 1);
         assertEquals("Check POJO creation", id_ps2.getCreatedObjects().length, 1);
-        assertTrue("Check service reference - 3.1", dhd.getDependencies()[0].getUsedServices().contains(psh1.getProvidedServices()[0].getServiceReference()));
-        assertTrue("Check service reference - 3.2", dhd.getDependencies()[0].getUsedServices().contains(psh2.getProvidedServices()[0].getServiceReference()));
         assertEquals("Check used ref - 3 (" + dhd.getDependencies()[0].getUsedServices().size() + ")", dhd.getDependencies()[0].getUsedServices().size(), 2);
 
         fooProvider2.stop();
@@ -516,9 +501,7 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps1 = ((Architecture) osgiHelper.getServiceObject(arch_ps1)).getInstanceDescription();
         psh = getPSDesc(id_ps1);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
         assertEquals("Check POJO creation", id_ps1.getCreatedObjects().length, 1);
-        assertTrue("Check service reference - 1", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
         assertEquals("Check used ref - 5 ", dhd.getDependencies()[0].getUsedServices().size(), 1);
 
         fooProvider1.stop();
@@ -555,8 +538,6 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps1 = ((Architecture) osgiHelper.getServiceObject(arch_ps1)).getInstanceDescription();
         psh = getPSDesc(id_ps2);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
-        assertTrue("Check service reference - 4", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
         assertEquals("Check used ref - 7 ", dhd.getDependencies()[0].getUsedServices().size(), 1);
 
         fooProvider2.stop();
@@ -612,9 +593,7 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps1 = ((Architecture) osgiHelper.getServiceObject(arch_ps1)).getInstanceDescription();
         ProvidedServiceHandlerDescription psh = getPSDesc(id_ps1);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
         assertEquals("Check POJO creation", id_ps1.getCreatedObjects().length, 1);
-        assertTrue("Check service reference - 1", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
 
         // Start a second foo service provider
         fooProvider2.start();
@@ -648,8 +627,6 @@ public class TestDependencyArchitecture 
         ProvidedServiceHandlerDescription psh2 = getPSDesc(id_ps2);
         assertEquals("Check POJO creation", id_ps1.getCreatedObjects().length, 1);
         assertEquals("Check POJO creation", id_ps2.getCreatedObjects().length, 1);
-        assertTrue("Check service reference - 2.1", dhd.getDependencies()[0].getUsedServices().contains(psh1.getProvidedServices()[0].getServiceReference()));
-        assertTrue("Check service reference - 2.2", dhd.getDependencies()[0].getUsedServices().contains(psh2.getProvidedServices()[0].getServiceReference()));
 
         fooProvider2.stop();
 
@@ -674,9 +651,7 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps1 = ((Architecture) osgiHelper.getServiceObject(arch_ps1)).getInstanceDescription();
         psh = getPSDesc(id_ps1);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
         assertEquals("Check POJO creation", id_ps1.getCreatedObjects().length, 1);
-        assertTrue("Check service reference - 3", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
 
         fooProvider1.stop();
 
@@ -709,8 +684,6 @@ public class TestDependencyArchitecture 
         dhd = getDependencyDesc(id_dep);
         //id_ps1 = ((Architecture) osgiHelper.getServiceObject(arch_ps1)).getInstanceDescription();
         psh = getPSDesc(id_ps2);
-        assertEquals("Check Service Reference equality", psh.getProvidedServices()[0].getServiceReference(), dhd.getDependencies()[0].getServiceReference());
-        assertTrue("Check service reference - 4", dhd.getDependencies()[0].getUsedServices().contains(psh.getProvidedServices()[0].getServiceReference()));
 
         fooProvider2.stop();
 

Modified: felix/trunk/ipojo/runtime/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/pom.xml?rev=1492155&r1=1492154&r2=1492155&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/pom.xml (original)
+++ felix/trunk/ipojo/runtime/core/pom.xml Wed Jun 12 11:38:27 2013
@@ -63,6 +63,13 @@
             <artifactId>org.osgi.compendium</artifactId>
             <version>4.2.0</version>
         </dependency>
+        <!-- We use the FilterImpl of Felix in tests -->
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>4.2.1</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.ipojo.metadata</artifactId>
@@ -143,6 +150,7 @@
                             org.objectweb.asm;-split-package:=merge-last,
                             org.objectweb.asm.commons;-split-package:=merge-last,
                             org.apache.felix.ipojo.metadata,
+                            org.apache.felix.ipojo.dependency.impl,
                             <!-- Compendium packages -->
                             org.osgi.service.cm,
                             org.osgi.service.log
@@ -162,6 +170,7 @@
                             org.apache.felix.ipojo.handlers.providedservice.*; version="${ipojo.package.version}",
                             org.apache.felix.ipojo.handlers.configuration; version="${ipojo.package.version}",
                             org.apache.felix.ipojo.context; version="${ipojo.package.version}",
+                            org.apache.felix.ipojo.dependency.interceptors; version="${ipojo.package.version}",
                             <!-- Compendium packages -->
                             org.osgi.service.cm,
                             org.osgi.service.log

Modified: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java?rev=1492155&r1=1492154&r2=1492155&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java (original)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/IPojoContext.java Wed Jun 12 11:38:27 2013
@@ -23,6 +23,7 @@ import java.io.InputStream;
 import java.util.Collection;
 import java.util.Dictionary;
 
+import org.apache.felix.ipojo.dependency.interceptors.TransformedServiceReference;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
@@ -65,7 +66,12 @@ public class IPojoContext implements Bun
      * @param context the bundle context
      */
     public IPojoContext(BundleContext context) {
-        m_bundleContext = context;
+        if (context instanceof IPojoContext) {
+            m_bundleContext = ((IPojoContext) context).getGlobalContext();
+            m_serviceContext = ((IPojoContext) context).getServiceContext();
+        } else {
+            m_bundleContext = context;
+        }
     }
 
     /**
@@ -266,6 +272,10 @@ public class IPojoContext implements Bun
      * @see org.osgi.framework.BundleContext#getService(org.osgi.framework.ServiceReference)
      */
     public <S> S getService(ServiceReference<S> ref) {
+        //TODO Move this somewhere else
+        if (ref instanceof TransformedServiceReference) {
+            ref = ((TransformedServiceReference<S>) ref).getWrappedReference();
+        }
         if (m_serviceContext == null) {
             return m_bundleContext.getService(ref);
         } else {
@@ -469,6 +479,10 @@ public class IPojoContext implements Bun
      * @see org.osgi.framework.BundleContext#ungetService(org.osgi.framework.ServiceReference)
      */
     public boolean ungetService(ServiceReference reference) {
+        //TODO Move this somewhere else
+        if (reference instanceof TransformedServiceReference) {
+            reference = ((TransformedServiceReference) reference).getWrappedReference();
+        }
         if (m_serviceContext == null) {
             return m_bundleContext.ungetService(reference);
         } else {

Modified: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PolicyServiceContext.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PolicyServiceContext.java?rev=1492155&r1=1492154&r2=1492155&view=diff
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PolicyServiceContext.java (original)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/PolicyServiceContext.java Wed Jun 12 11:38:27 2013
@@ -25,6 +25,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Dictionary;
 
+import org.apache.felix.ipojo.dependency.interceptors.TransformedServiceReference;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
@@ -176,6 +177,9 @@ public class PolicyServiceContext implem
      * @see org.apache.felix.ipojo.ServiceContext#getService(org.osgi.framework.ServiceReference)
      */
     public Object getService(ServiceReference ref) {
+        if (ref instanceof TransformedServiceReference) {
+            ref = ((TransformedServiceReference) ref).getWrappedReference();
+        }
         switch(m_policy) { // NOPMD No break needed as we return in each branch.
             case LOCAL:
                 // The reference comes from the local scope

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ComparatorBasedServiceRankingInterceptor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ComparatorBasedServiceRankingInterceptor.java?rev=1492155&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ComparatorBasedServiceRankingInterceptor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ComparatorBasedServiceRankingInterceptor.java Wed Jun 12 11:38:27 2013
@@ -0,0 +1,65 @@
+/*
+ * 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.ipojo.dependency.impl;
+
+import org.apache.felix.ipojo.dependency.interceptors.ServiceRankingInterceptor;
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.osgi.framework.ServiceReference;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * A comparator based version of the ranking interceptor.
+ */
+public class ComparatorBasedServiceRankingInterceptor implements ServiceRankingInterceptor {
+
+    private final Comparator<ServiceReference> m_comparator;
+
+    public ComparatorBasedServiceRankingInterceptor(Comparator<ServiceReference> cmp) {
+        this.m_comparator = cmp;
+    }
+
+
+    public void open(DependencyModel dependency) {    }
+
+    public List<ServiceReference> getServiceReferences(DependencyModel dependency, List<ServiceReference> matching) {
+        List<ServiceReference> copy = new ArrayList<ServiceReference>(matching);
+        Collections.sort(copy, m_comparator);
+        return copy;
+    }
+
+    public List<ServiceReference> onServiceArrival(DependencyModel dependency, List<ServiceReference> matching, ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    public List<ServiceReference> onServiceDeparture(DependencyModel dependency, List<ServiceReference> matching,
+                                                     ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    public List<ServiceReference> onServiceModified(DependencyModel dependency, List<ServiceReference> matching, ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    public void close(DependencyModel dependency) {  }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/DependencyProperties.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/DependencyProperties.java?rev=1492155&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/DependencyProperties.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/DependencyProperties.java Wed Jun 12 11:38:27 2013
@@ -0,0 +1,99 @@
+/*
+ * 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.ipojo.dependency.impl;
+
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.dependency.interceptors.ServiceTrackingInterceptor;
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.apache.felix.ipojo.util.Log;
+import org.osgi.framework.*;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+/**
+ * Builds the properties used to checks if an interceptor matches a specific dependency.
+ */
+public class DependencyProperties {
+
+    //TODO Externalize and use constants
+
+    public static  Dictionary<String, ?> getDependencyProperties(DependencyModel dependency) {
+        Dictionary<String, Object> properties = new Hashtable<String, Object>();
+
+        // Instance, and Factory and Bundle (name, symbolic name, version)
+        properties.put(Factory.INSTANCE_NAME_PROPERTY, dependency.getComponentInstance().getInstanceName());
+        properties.put("instance.state", dependency.getComponentInstance().getState());
+        properties.put("factory.name", dependency.getComponentInstance().getFactory().getFactoryName());
+        final Bundle bundle = dependency.getBundleContext().getBundle();
+        properties.put("bundle.symbolicName", bundle.getSymbolicName());
+        if (bundle.getVersion() != null) {
+            properties.put("bundle.version", bundle.getVersion().toString());
+        }
+
+        // Dependency specification, and id
+        properties.put("dependency.specification", dependency.getSpecification().getName());
+        properties.put("dependency.id", dependency.getId());
+        properties.put("dependency.state", dependency.getState());
+
+        // We also provide the objectclass property, and to be compliant with the osgi specification,
+        // we put an array in the dictionary
+        properties.put(Constants.OBJECTCLASS, new String[] { dependency.getSpecification().getName()});
+
+        return properties;
+    }
+
+    /**
+     * Checks that the 'target' property of the service reference matches the dependency.
+     * @param reference the reference
+     * @param dependency the dependency
+     * @param context a bundle context used to build the filter
+     * @return {@literal true} if the target's property of reference matches the dependency.
+     */
+    public static boolean match(ServiceReference reference, DependencyModel dependency, BundleContext context) {
+        Object v = reference.getProperty(ServiceTrackingInterceptor.TARGET_PROPERTY);
+        Filter filter = null;
+        if (v == null) {
+            return false; // Invalid interceptor
+        }
+        if (v instanceof Filter) {
+            filter = (Filter) v;
+        } else if (v instanceof String) {
+            try {
+                filter = context.createFilter((String) v);
+            } catch (InvalidSyntaxException e) {
+                dependency.getComponentInstance().getFactory().getLogger().log(Log.ERROR,
+                        "Cannot build filter from the target property : " + v, e);
+            }
+        }
+
+        if (filter == null) {
+            return false; // Invalid interceptor.
+        }
+
+        Dictionary<String, ?> properties = getDependencyProperties(dependency);
+
+        return filter.match(properties);
+    }
+
+    public static boolean match(ServiceReference reference, DependencyModel dependency) {
+        return match(reference, dependency, dependency.getBundleContext());
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/EmptyBasedServiceRankingInterceptor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/EmptyBasedServiceRankingInterceptor.java?rev=1492155&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/EmptyBasedServiceRankingInterceptor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/EmptyBasedServiceRankingInterceptor.java Wed Jun 12 11:38:27 2013
@@ -0,0 +1,56 @@
+/*
+ * 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.ipojo.dependency.impl;
+
+import org.apache.felix.ipojo.dependency.interceptors.ServiceRankingInterceptor;
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.osgi.framework.ServiceReference;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * An empty version of the ranking interceptor.
+ */
+public class EmptyBasedServiceRankingInterceptor implements ServiceRankingInterceptor {
+
+    public void open(DependencyModel dependency) { }
+
+    public List<ServiceReference> getServiceReferences(DependencyModel dependency, List<ServiceReference> matching) {
+        return matching;
+    }
+
+    public List<ServiceReference> onServiceArrival(DependencyModel dependency, List<ServiceReference> matching, ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    public List<ServiceReference> onServiceDeparture(DependencyModel dependency, List<ServiceReference> matching,
+                                                     ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    public List<ServiceReference> onServiceModified(DependencyModel dependency, List<ServiceReference> matching, ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    public void close(DependencyModel dependency) {  }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/FilterBasedServiceTrackingInterceptor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/FilterBasedServiceTrackingInterceptor.java?rev=1492155&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/FilterBasedServiceTrackingInterceptor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/FilterBasedServiceTrackingInterceptor.java Wed Jun 12 11:38:27 2013
@@ -0,0 +1,63 @@
+/*
+ * 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.ipojo.dependency.impl;
+
+import org.apache.felix.ipojo.dependency.interceptors.ServiceTrackingInterceptor;
+import org.apache.felix.ipojo.dependency.interceptors.TransformedServiceReference;
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * An implementation of the service tracking interceptor using a filter.
+ */
+public class FilterBasedServiceTrackingInterceptor implements ServiceTrackingInterceptor {
+
+    private final Filter m_filter;
+
+    public FilterBasedServiceTrackingInterceptor(Filter filter) {
+        m_filter = filter;
+    }
+
+    public void open(DependencyModel dependency) {
+
+    }
+
+    public <S> TransformedServiceReference<S> accept(DependencyModel dependency, BundleContext context, TransformedServiceReference<S> ref) {
+        if (ServiceReferenceUtils.match(m_filter, ref) && dependency.match(ref)) {
+            return ref;
+        } else {
+            return null;
+        }
+    }
+
+    public void close(DependencyModel dependency) {
+
+    }
+
+    public <S> S getService(DependencyModel dependency, S service, ServiceReference<S> reference) {
+        return service;
+    }
+
+    public void ungetService(DependencyModel dependency, boolean noMoreUsage, ServiceReference reference) {
+
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ServiceReferenceManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ServiceReferenceManager.java?rev=1492155&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ServiceReferenceManager.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ServiceReferenceManager.java Wed Jun 12 11:38:27 2013
@@ -0,0 +1,770 @@
+/*
+ * 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.ipojo.dependency.impl;
+
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.dependency.interceptors.ServiceRankingInterceptor;
+import org.apache.felix.ipojo.dependency.interceptors.ServiceTrackingInterceptor;
+import org.apache.felix.ipojo.dependency.interceptors.TransformedServiceReference;
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.apache.felix.ipojo.util.Log;
+import org.apache.felix.ipojo.util.Tracker;
+import org.apache.felix.ipojo.util.TrackerCustomizer;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+
+import java.util.*;
+
+/**
+ * This class is handling the transformations between the base service set and the selected service set.
+ * It handles the matching services and the selected service set.
+ * As this class is tied to the dependency model, it reuses the same locks objects.
+ */
+public class ServiceReferenceManager implements TrackerCustomizer {
+
+    /**
+     * The dependency.
+     */
+    private final DependencyModel m_dependency;
+    /**
+     * The list of all matching service references. This list is a
+     * subset of tracked references. This set is computed according
+     * to the filter and the {@link DependencyModel#match(ServiceReference)} method.
+     */
+    private final Map<ServiceReference, TransformedServiceReference> m_matchingReferences = new
+            LinkedHashMap<ServiceReference, TransformedServiceReference>();
+    /**
+     * The comparator to sort service references.
+     */
+    private Comparator<ServiceReference> m_comparator;
+    /**
+     * The LDAP filter object selecting service references
+     * from the set of providers providing the required specification.
+     */
+    private Filter m_filter;
+    /**
+     * The list of selected service references.
+     */
+    private List<? extends ServiceReference> m_selectedReferences = new ArrayList<ServiceReference>();
+    /**
+     * The service ranking interceptor.
+     */
+    private ServiceRankingInterceptor m_rankingInterceptor;
+    /**
+     * Service interceptor tracker.
+     */
+    private Tracker m_rankingInterceptorTracker;
+    private Tracker m_trackingInterceptorTracker;
+    /**
+     * The set of tracking interceptors.
+     * TODO this set should be ranking according to the OSGi ranking policy.
+     * The filter is always the last interceptor.
+     */
+    private LinkedList<ServiceTrackingInterceptor> m_trackingInterceptors = new
+            LinkedList<ServiceTrackingInterceptor>();
+
+    /**
+     * Creates the service reference manager.
+     *
+     * @param dep        the dependency
+     * @param filter     the filter
+     * @param comparator the comparator
+     */
+    public ServiceReferenceManager(DependencyModel dep, Filter filter, Comparator<ServiceReference> comparator) {
+        m_dependency = dep;
+        m_filter = filter;
+        if (m_filter != null) {
+            m_trackingInterceptors.addLast(new FilterBasedServiceTrackingInterceptor(m_filter));
+        }
+        if (comparator != null) {
+            m_comparator = comparator;
+            m_rankingInterceptor = new ComparatorBasedServiceRankingInterceptor(comparator);
+        } else {
+            m_rankingInterceptor = new EmptyBasedServiceRankingInterceptor();
+        }
+    }
+
+    public void open() {
+        m_trackingInterceptorTracker = new Tracker(m_dependency.getBundleContext(),
+                ServiceTrackingInterceptor.class.getName(),
+                new TrackerCustomizer() {
+
+                    public boolean addingService(ServiceReference reference) {
+                        return DependencyProperties.match(reference, m_dependency);
+                    }
+
+                    public void addedService(ServiceReference reference) {
+                        ServiceTrackingInterceptor interceptor = (ServiceTrackingInterceptor) m_trackingInterceptorTracker
+                                .getService(reference);
+
+                        if (interceptor != null) {
+                            addTrackingInterceptor(interceptor);
+                        } else {
+                            m_dependency.getComponentInstance().getFactory().getLogger().log(Log.ERROR,
+                                    "Cannot retrieve the interceptor object from service reference " + reference
+                                            .getProperty(Constants.SERVICE_ID) + " - " + reference.getProperty
+                                            (Factory.INSTANCE_NAME_PROPERTY));
+                        }
+                    }
+
+                    public void modifiedService(ServiceReference reference, Object service) {
+                        // Not supported yet.
+                        // TODO it would be nice to support the modification of the interceptor TARGET property.
+                    }
+
+                    public void removedService(ServiceReference reference, Object service) {
+                        if (service != null && m_trackingInterceptors.contains(service)) {
+                            removeTrackingInterceptor((ServiceTrackingInterceptor) service);
+                        }
+                    }
+                });
+
+        m_trackingInterceptorTracker.open();
+
+        // Initialize the service interceptor tracker.
+        m_rankingInterceptorTracker = new Tracker(m_dependency.getBundleContext(), ServiceRankingInterceptor.class.getName(),
+                new TrackerCustomizer() {
+
+                    public boolean addingService(ServiceReference reference) {
+                        return DependencyProperties.match(reference, m_dependency);
+                    }
+
+                    public void addedService(ServiceReference reference) {
+                        ServiceRankingInterceptor interceptor = (ServiceRankingInterceptor) m_rankingInterceptorTracker
+                                .getService(reference);
+                        if (interceptor != null) {
+                            setRankingInterceptor(interceptor);
+                        } else {
+                            m_dependency.getComponentInstance().getFactory().getLogger().log(Log.ERROR,
+                                    "Cannot retrieve the interceptor object from service reference " + reference
+                                            .getProperty(Constants.SERVICE_ID) + " - " + reference.getProperty
+                                            (Factory.INSTANCE_NAME_PROPERTY));
+                        }
+                    }
+
+                    public void modifiedService(ServiceReference reference, Object service) {
+                        // Not supported yet.
+                        // TODO it would be nice to support the modification of the interceptor TARGET property.
+                    }
+
+                    public void removedService(ServiceReference reference, Object service) {
+                        if (service == m_rankingInterceptor) {
+                            m_rankingInterceptor.close(m_dependency);
+                            // Do we have another one ?
+                            ServiceReference anotherReference = m_rankingInterceptorTracker.getServiceReference();
+                            if (anotherReference != null) {
+                                ServiceRankingInterceptor interceptor = (ServiceRankingInterceptor) m_rankingInterceptorTracker
+                                        .getService(anotherReference);
+                                if (interceptor != null) setRankingInterceptor(interceptor);
+                            } else if (m_comparator != null) {
+                                // If we have a comparator, we restore the comparator.
+                                setComparator(m_comparator);
+                            } else {
+                                // If we have neither comparator nor interceptor use an empty interceptor.
+                                setRankingInterceptor(new EmptyBasedServiceRankingInterceptor());
+                            }
+                        }
+                    }
+                });
+        m_rankingInterceptorTracker.open();
+    }
+
+    private void addTrackingInterceptor(ServiceTrackingInterceptor interceptor) {
+        // A new interceptor arrives. Insert it at the beginning of the list.
+        ChangeSet changeset;
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            m_trackingInterceptors.addFirst(interceptor);
+            interceptor.open(m_dependency);
+            changeset = computeChangesInMatchingServices();
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+        m_dependency.onChange(changeset);
+    }
+
+    private void removeTrackingInterceptor(ServiceTrackingInterceptor interceptor) {
+        ChangeSet changeset;
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            m_trackingInterceptors.remove(interceptor);
+            interceptor.close(m_dependency);
+            changeset = computeChangesInMatchingServices();
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+        m_dependency.onChange(changeset);
+    }
+
+    private ChangeSet computeChangesInMatchingServices() {
+        if (m_dependency.getTracker() == null || m_dependency.getTracker().getServiceReferences() == null) {
+            // Tracker closed, no problem
+            return new ChangeSet(Collections.<ServiceReference>emptyList(),
+                    Collections.<ServiceReference>emptyList(),
+                    Collections.<ServiceReference>emptyList(),
+                    null,
+                    null,
+                    null,
+                    null);
+        }
+        // The set of interceptor has changed.
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            // The tracker is open, we must recheck all services.
+            ServiceReference oldBest = getFirstService();
+            // Recompute the matching services.
+            m_matchingReferences.clear();
+            for (ServiceReference reference : m_dependency.getTracker().getServiceReferencesList()) {
+                TransformedServiceReference ref = new TransformedServiceReferenceImpl(reference);
+                ref = accept(ref);
+                if (ref != null) {
+                    m_matchingReferences.put(reference, ref);
+                }
+            }
+
+            // We have the new matching set.
+            List<ServiceReference> beforeRanking = getSelectedServices();
+
+            final List<ServiceReference> allServices = getMatchingServices();
+            List<ServiceReference> references;
+            if (allServices.isEmpty()) {
+                references = Collections.emptyList();
+            } else {
+                references = m_rankingInterceptor.getServiceReferences(m_dependency, allServices);
+            }
+
+            RankingResult result = computeDifferences(beforeRanking, references);
+            m_selectedReferences = result.selected;
+
+            ServiceReference newFirst = getFirstService();
+            ServiceReference modified = null;
+            if (ServiceReferenceUtils.haveSameServiceId(oldBest, newFirst) && ServiceReferenceUtils
+                    .haveSameProperties(oldBest, newFirst)) {
+                modified = newFirst;
+            }
+            return new ChangeSet(getSelectedServices(), result.departures, result.arrivals, oldBest, getFirstService(),
+                    null, modified);
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+    }
+
+    public List<ServiceReference> getMatchingServices() {
+        try {
+            m_dependency.acquireReadLockIfNotHeld();
+            return new ArrayList<ServiceReference>(m_matchingReferences.values());
+        } finally {
+            m_dependency.releaseReadLockIfHeld();
+        }
+    }
+
+    public List<ServiceReference> getSelectedServices() {
+        try {
+            m_dependency.acquireReadLockIfNotHeld();
+            return new ArrayList<ServiceReference>(m_selectedReferences);
+        } finally {
+            m_dependency.releaseReadLockIfHeld();
+        }
+    }
+
+    public ServiceReference getFirstService() {
+        try {
+            m_dependency.acquireReadLockIfNotHeld();
+            if (m_selectedReferences.isEmpty()) {
+                return null;
+            }
+            return m_selectedReferences.get(0);
+        } finally {
+            m_dependency.releaseReadLockIfHeld();
+        }
+    }
+
+    public boolean contains(ServiceReference ref) {
+        try {
+            m_dependency.acquireReadLockIfNotHeld();
+            return m_selectedReferences.contains(ref);
+        } finally {
+            m_dependency.releaseReadLockIfHeld();
+        }
+    }
+
+    public void reset() {
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            m_rankingInterceptor.close(m_dependency);
+            for (ServiceTrackingInterceptor interceptor : m_trackingInterceptors) {
+                interceptor.close(m_dependency);
+            }
+            m_trackingInterceptors.clear();
+            m_matchingReferences.clear();
+            m_selectedReferences = new ArrayList<TransformedServiceReference>();
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+
+    }
+
+    public boolean addingService(ServiceReference reference) {
+        // We accept all service references except if we are frozen or broken. In these case, just ignore everything.
+
+        // We are doing two tests, we must get the read lock
+        try {
+            m_dependency.acquireReadLockIfNotHeld();
+            return !(m_dependency.getState() == DependencyModel.BROKEN || m_dependency.isFrozen());
+        } finally {
+            m_dependency.releaseReadLockIfHeld();
+        }
+    }
+
+    /**
+     * Checks if the given reference is accepted.
+     * This method is called when holding the write lock on the dependency.
+     *
+     * @param reference the reference
+     * @param <S>
+     * @return the transformed reference, null if rejected
+     */
+    private <S> TransformedServiceReference<S> accept(TransformedServiceReference<S> reference) {
+        TransformedServiceReference<S> accumulator = reference;
+        for (ServiceTrackingInterceptor interceptor : m_trackingInterceptors) {
+            TransformedServiceReference<S> accepted = interceptor.accept(m_dependency, m_dependency.getBundleContext(), reference);
+            if (accepted != null) {
+                accumulator = accepted;
+            } else {
+                // refused by an interceptor
+                m_dependency.getComponentInstance().getFactory().getLogger().log(Log.INFO,
+                        "The service reference " + reference.getProperty(Constants.SERVICE_ID) + " was rejected by " +
+                                "interceptor " + interceptor);
+                return null;
+            }
+        }
+
+        return accumulator;
+    }
+
+    public void addedService(ServiceReference reference) {
+        // A service was added to the tracker.
+
+        // First, check is the tracking interceptors are accepting it.
+        // The transformed reference is creates and check outside of the protected region.
+        TransformedServiceReference ref = new TransformedServiceReferenceImpl(reference);
+
+        boolean match;
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            ref = accept(ref);
+            if (ref != null) {
+                m_matchingReferences.put(reference, ref);
+            }
+            match = ref != null;
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+
+        if (match) {
+            // Callback invoked outside of locks.
+            // The called method is taking the write lock anyway.
+            onNewMatchingService(ref);
+        }
+    }
+
+    private void onNewMatchingService(TransformedServiceReference reference) {
+        ServiceReference oldFirst;
+        RankingResult result;
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            // We store the currently 'first' service reference.
+            oldFirst = getFirstService();
+
+            // We apply our ranking strategy.
+            result = applyRankingOnArrival(reference);
+            // Set the selected services.
+            m_selectedReferences = result.selected;
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+        // Fire the event (outside from the synchronized region)
+        fireUpdate(getSelectedServices(), result.departures, result.arrivals, oldFirst,
+                getFirstService(), null, null);
+    }
+
+    private void onModificationOfAMatchingService(TransformedServiceReference reference, Object service) {
+        ServiceReference oldFirst;
+        RankingResult result;
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            // We store the currently 'first' service reference.
+            oldFirst = getFirstService();
+
+            // We apply our ranking strategy.
+            result = applyRankingOnModification(reference);
+            // Set the selected services.
+            m_selectedReferences = result.selected;
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+        // Fire the event (outside from the synchronized region)
+        fireUpdate(getSelectedServices(), result.departures, result.arrivals, oldFirst,
+                getFirstService(), service, reference);
+    }
+
+    private RankingResult applyRankingOnModification(ServiceReference reference) {
+        // TODO we are holding the lock here.
+        List<ServiceReference> beforeRanking = getSelectedServices();
+        List<ServiceReference> references = m_rankingInterceptor.onServiceModified(m_dependency, getMatchingServices(),
+                reference);
+        return computeDifferences(beforeRanking, references);
+    }
+
+    private void fireUpdate(List<ServiceReference> selectedServices, List<ServiceReference> departures,
+                            List<ServiceReference> arrivals, ServiceReference oldFirst,
+                            ServiceReference firstService, Object service, ServiceReference modified) {
+        ChangeSet set = new ChangeSet(selectedServices, departures, arrivals, oldFirst, firstService, service, modified);
+        m_dependency.onChange(set);
+    }
+
+    private RankingResult applyRankingOnArrival(ServiceReference ref) {
+        // TODO we are holding the lock here.
+        List<ServiceReference> beforeRanking = getSelectedServices();
+        List<ServiceReference> references = m_rankingInterceptor.onServiceArrival(m_dependency, getMatchingServices(),
+                ref);
+        // compute the differences
+        return computeDifferences(beforeRanking, references);
+
+    }
+
+    private RankingResult applyRankingOnDeparture(ServiceReference ref) {
+        // TODO we are holding the lock here.
+        List<ServiceReference> beforeRanking = getSelectedServices();
+        List<ServiceReference> references = m_rankingInterceptor.onServiceDeparture(m_dependency, getMatchingServices(),
+                ref);
+        return computeDifferences(beforeRanking, references);
+    }
+
+    private RankingResult computeDifferences(List<ServiceReference> beforeRanking, List<ServiceReference> ranked) {
+        // compute the differences
+        List<ServiceReference> departures = new ArrayList<ServiceReference>();
+        List<ServiceReference> arrivals = new ArrayList<ServiceReference>();
+        // All references that are no more in the set are considered as leaving services.
+        for (ServiceReference old : beforeRanking) {
+            if (!ServiceReferenceUtils.containsReferenceById(ranked, old)) {
+                departures.add(old);
+            }
+        }
+        // All references that are in `references` but not in `beforeRanking` are new services
+        for (ServiceReference newRef : ranked) {
+            if (!ServiceReferenceUtils.containsReferenceById(beforeRanking, newRef)) {
+                arrivals.add(newRef);
+            }
+        }
+
+        return new RankingResult(departures, arrivals, ranked);
+    }
+
+    public void modifiedService(ServiceReference reference, Object service) {
+        // We are handling a modified event, we have three case to handle
+        // 1) the service was matching and does not match anymore -> it's a departure.
+        // 2) the service was not matching and matches -> it's an arrival
+        // 3) the service was matching and still matches -> it's a modification.
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+
+            if (m_matchingReferences.containsKey(reference)) {
+                // do we still accept the reference
+                TransformedServiceReference initial = m_matchingReferences.get(reference);
+                TransformedServiceReference accepted = new TransformedServiceReferenceImpl(reference);
+                accepted = accept(accepted);
+                if (accepted == null) {
+                    // case 1
+                    m_matchingReferences.remove(reference);
+                    onDepartureOfAMatchingService(initial, service);
+                } else {
+                    // Do we have a real change
+                    if (!ServiceReferenceUtils.haveSameProperties(initial, accepted)) {
+                        // case 3
+                        m_matchingReferences.put(reference, accepted);
+                        onModificationOfAMatchingService(accepted, service);
+                    }
+                }
+            } else {
+                // Base does not contain the service, let's try to add it.
+                TransformedServiceReference transformed = new TransformedServiceReferenceImpl(reference);
+                transformed = accept(transformed);
+                if (transformed != null) {
+                    // case 2
+                    m_matchingReferences.put(reference, transformed);
+                    onNewMatchingService(transformed);
+                }
+            }
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+    }
+
+    public void onDepartureOfAMatchingService(TransformedServiceReference reference, Object service) {
+        ServiceReference oldFirst;
+        RankingResult result = null;
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            // We store the currently 'first' service reference.
+            oldFirst = getFirstService();
+            // We apply our ranking strategy.
+            result = applyRankingOnDeparture(reference);
+            // Set the selected services.
+            m_selectedReferences = result.selected;
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+        // Fire the event (outside from the synchronized region)
+        fireUpdate(getSelectedServices(), result.departures, result.arrivals, oldFirst,
+                getFirstService(), service, null);
+    }
+
+    public void removedService(ServiceReference reference, Object service) {
+        // A service is leaving
+        // 1 - the service was in the matching set => real departure
+        // 2 - the service was not in the matching set => nothing do do.
+
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            TransformedServiceReference initial = m_matchingReferences.remove(reference);
+            if (initial != null) {
+                // Case 1
+                onDepartureOfAMatchingService(initial, service);
+            }
+            // else case 2.
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+
+    }
+
+    /**
+     * A new filter is set.
+     * We have to recompute the set of matching services.
+     *
+     * @param filter  the new filter
+     * @param tracker the tracker
+     */
+    public ChangeSet setFilter(Filter filter, Tracker tracker) {
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            m_filter = filter;
+
+            if (!m_trackingInterceptors.isEmpty()) {
+                ServiceTrackingInterceptor interceptor = m_trackingInterceptors.getLast();
+                if (interceptor != null && interceptor instanceof FilterBasedServiceTrackingInterceptor) {
+                    // Remove it first.
+                    m_trackingInterceptors.removeLast();
+                }
+            }
+
+            if (m_filter != null) {
+                // Add the new one.
+                ServiceTrackingInterceptor newInterceptor = new FilterBasedServiceTrackingInterceptor(m_filter);
+                m_trackingInterceptors.addLast(newInterceptor);
+            }
+
+            if (tracker == null) {
+                // Tracker closed, no problem
+                return new ChangeSet(Collections.<ServiceReference>emptyList(),
+                        Collections.<ServiceReference>emptyList(),
+                        Collections.<ServiceReference>emptyList(),
+                        null,
+                        null,
+                        null,
+                        null);
+            } else {
+                // The tracker is open, we must recheck all services.
+                ServiceReference oldBest = getFirstService();
+
+                // Recompute the matching services.
+                m_matchingReferences.clear();
+                for (ServiceReference reference : tracker.getServiceReferencesList()) {
+                    TransformedServiceReference ref = new TransformedServiceReferenceImpl(reference);
+                    ref = accept(ref);
+                    if (ref != null) {
+                        m_matchingReferences.put(reference, ref);
+                    }
+                }
+
+                // We have the new matching set.
+
+                List<ServiceReference> beforeRanking = getSelectedServices();
+
+                final List<ServiceReference> allServices = getMatchingServices();
+                List<ServiceReference> references;
+                if (allServices.isEmpty()) {
+                    references = Collections.emptyList();
+                } else {
+                    references = m_rankingInterceptor.getServiceReferences(m_dependency, allServices);
+                }
+
+                RankingResult result = computeDifferences(beforeRanking, references);
+                m_selectedReferences = result.selected;
+                return new ChangeSet(getSelectedServices(), result.departures, result.arrivals, oldBest, getFirstService(),
+                        null, null);
+            }
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+    }
+
+    public boolean isEmpty() {
+        try {
+            m_dependency.acquireReadLockIfNotHeld();
+            return m_selectedReferences.isEmpty();
+        } finally {
+            m_dependency.releaseReadLockIfHeld();
+        }
+    }
+
+    public Comparator<ServiceReference> getComparator() {
+        try {
+            m_dependency.acquireReadLockIfNotHeld();
+            return m_comparator;
+        } finally {
+            m_dependency.releaseReadLockIfHeld();
+        }
+    }
+
+    public void setComparator(Comparator<ServiceReference> cmp) {
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            m_comparator = cmp;
+            // Be aware that this method will release the lock to call the dependency callback.
+            setRankingInterceptor(new ComparatorBasedServiceRankingInterceptor(cmp));
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+    }
+
+    public Filter getFilter() {
+        try {
+            m_dependency.acquireReadLockIfNotHeld();
+            return m_filter;
+        } finally {
+            m_dependency.releaseReadLockIfHeld();
+        }
+    }
+
+    public void setRankingInterceptor(ServiceRankingInterceptor interceptor) {
+        m_dependency.getComponentInstance().getFactory().getLogger().log(Log.INFO, "Dependency " + m_dependency.getId
+                () + " is getting a new ranking interceptor : " + interceptor);
+        ChangeSet changeSet;
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            ServiceReference oldBest = getFirstService();
+            List<ServiceReference> beforeRanking = getSelectedServices();
+            m_rankingInterceptor = interceptor;
+            m_rankingInterceptor.open(m_dependency);
+
+            final List<ServiceReference> allServices = getMatchingServices();
+            List<ServiceReference> references = Collections.emptyList();
+            if (!allServices.isEmpty()) {
+                references = m_rankingInterceptor.getServiceReferences(m_dependency, allServices);
+            }
+            RankingResult result = computeDifferences(beforeRanking, references);
+            m_selectedReferences = result.selected;
+            changeSet = new ChangeSet(getSelectedServices(), result.departures, result.arrivals, oldBest,
+                    getFirstService(), null, null);
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+        // Calling onChange outside of the lock.
+        m_dependency.onChange(changeSet);
+    }
+
+    public void close() {
+        reset();
+    }
+
+    public void invalidateMatchingServices() {
+        ChangeSet changeset;
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            m_matchingReferences.clear();
+            changeset = computeChangesInMatchingServices();
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+        m_dependency.onChange(changeset);
+    }
+
+    public void invalidateSelectedServices() {
+        ChangeSet changeset;
+        try {
+            m_dependency.acquireWriteLockIfNotHeld();
+            ServiceReference oldBest = getFirstService();
+            List<ServiceReference> beforeRanking = getSelectedServices();
+            m_selectedReferences.clear();
+            final List<ServiceReference> allServices = getMatchingServices();
+            List<ServiceReference> references = Collections.emptyList();
+            if (!allServices.isEmpty()) {
+                references = m_rankingInterceptor.getServiceReferences(m_dependency, allServices);
+            }
+            RankingResult result = computeDifferences(beforeRanking, references);
+            m_selectedReferences = result.selected;
+            changeset = new ChangeSet(getSelectedServices(), result.departures, result.arrivals, oldBest,
+                    getFirstService(), null, null);
+        } finally {
+            m_dependency.releaseWriteLockIfHeld();
+        }
+
+        m_dependency.onChange(changeset);
+    }
+
+    private class RankingResult {
+        final List<ServiceReference> departures;
+        final List<ServiceReference> arrivals;
+        final List<ServiceReference> selected;
+
+        private RankingResult(List<ServiceReference> departures, List<ServiceReference> arrivals,
+                              List<ServiceReference> selected) {
+            this.departures = departures;
+            this.arrivals = arrivals;
+            this.selected = selected;
+        }
+    }
+
+    public class ChangeSet {
+        public final List<ServiceReference> selected;
+        public final List<ServiceReference> departures;
+        public final List<ServiceReference> arrivals;
+        public final ServiceReference oldFirstReference;
+        public final ServiceReference newFirstReference;
+        public final Object service;
+        public final ServiceReference modified;
+
+        public ChangeSet(List<ServiceReference> selectedServices,
+                         List<ServiceReference> departures, List<ServiceReference> arrivals,
+                         ServiceReference oldFirst, ServiceReference newFirst,
+                         Object service, ServiceReference modified) {
+            this.selected = selectedServices;
+            this.departures = departures;
+            this.arrivals = arrivals;
+            this.oldFirstReference = oldFirst;
+            this.newFirstReference = newFirst;
+            this.service = service;
+            this.modified = modified;
+        }
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ServiceReferenceUtils.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ServiceReferenceUtils.java?rev=1492155&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ServiceReferenceUtils.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/ServiceReferenceUtils.java Wed Jun 12 11:38:27 2013
@@ -0,0 +1,127 @@
+/*
+ * 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.ipojo.dependency.impl;
+
+import org.apache.felix.ipojo.context.ServiceReferenceImpl;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+
+import java.util.List;
+
+/**
+ * Some utility methods to handle service references.
+ */
+public class ServiceReferenceUtils {
+    /**
+     * Checks if the given service reference match the current filter.
+     * This method aims to avoid calling {@link org.osgi.framework.Filter#match(org.osgi.framework.ServiceReference)}
+     * method when manipulating a composite reference. In fact, this method thrown
+     * a {@link ClassCastException} on Equinox.
+     *
+     * @param ref the service reference to check.
+     * @return <code>true</code> if the service reference matches.
+     */
+    public static boolean match(Filter filter, ServiceReference ref) {
+        boolean match = true;
+        if (filter != null) {
+            if (ref instanceof ServiceReferenceImpl) {
+                // Can't use the match(ref) as it throw a class cast exception on Equinox.
+                //noinspection unchecked
+                match = filter.match(((ServiceReferenceImpl) ref).getProperties());
+            } else { // Non composite reference.
+                match = filter.match(ref);
+            }
+        }
+        return match;
+    }
+
+    /**
+     * Checks whether a list of service references contains a reference with the same {@literal service.id} as the
+     * given reference.
+     * @param references the list of reference
+     * @param ref the reference
+     * @return {@literal true} if references contains a reference with the same service.id as ref.
+     */
+    public static boolean containsReferenceById(List<? extends ServiceReference> references, ServiceReference ref) {
+        return getServiceReferenceById(references, ref) != null;
+    }
+
+    /**
+     * Gets a service reference with the same service.id as the given reference from the given list.
+     * @param references the list of references
+     * @param ref the reference
+     * @return the service reference from references having the same service.id as ref. {@literal null} if there is
+     * no such reference in the list.
+     */
+    public static ServiceReference getServiceReferenceById(List<? extends ServiceReference> references,
+                                                           ServiceReference ref) {
+        Object id = ref.getProperty(Constants.SERVICE_ID);
+        for (ServiceReference reference : references) {
+            if (reference.getProperty(Constants.SERVICE_ID).equals(id)) {
+                return reference;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Checks whether the two references has the same properties and their value are equals.
+     * @param ref1 first reference
+     * @param ref2 second reference
+     * @return {@literal true} if the two references have the same properties and their values are equals.
+     */
+    public static boolean haveSameProperties(ServiceReference ref1, ServiceReference ref2) {
+        if (ref2 == null  && ref1 == null) {
+            return true;
+        }
+
+        if ((ref1 == null) || (ref2 == null)) {
+            return false;
+        }
+
+        String[] keys = ref2.getPropertyKeys();
+
+        if (ref2.getPropertyKeys().length != keys.length) {
+            return false;
+        }
+
+        for (String key : keys) {
+            if (! ref2.getProperty(key).equals(ref1.getProperty(key))) {
+                return false;
+            }
+        }
+
+        return true;
+
+
+    }
+
+    /**
+     * Checks whether two service references have the same service id.
+     * @param ref1 first reference
+     * @param ref2 second reference
+     * @return {@literal true} if the two references have the same service.id, {@literal false} otherwise.
+     */
+    public static boolean haveSameServiceId(ServiceReference ref1, ServiceReference ref2) {
+        return !(ref1 == null || ref2 == null)
+                && ref1.getProperty(Constants.SERVICE_ID).equals(ref2.getProperty(Constants.SERVICE_ID));
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/TransformedServiceReferenceImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/TransformedServiceReferenceImpl.java?rev=1492155&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/TransformedServiceReferenceImpl.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/impl/TransformedServiceReferenceImpl.java Wed Jun 12 11:38:27 2013
@@ -0,0 +1,170 @@
+/*
+ * 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.ipojo.dependency.impl;
+
+import org.apache.felix.ipojo.dependency.interceptors.TransformedServiceReference;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+import java.util.*;
+
+/**
+ * Implements transformed service reference.
+ */
+public class TransformedServiceReferenceImpl<S> implements TransformedServiceReference<S> {
+
+    private final ServiceReference<S> m_origin;
+    private Map<String, Object> m_properties = new HashMap<String, Object>();
+
+    public TransformedServiceReferenceImpl(ServiceReference<S> origin) {
+        this.m_origin = origin;
+        // Copy properties
+        for (String key : origin.getPropertyKeys()) {
+            m_properties.put(key, origin.getProperty(key));
+        }
+    }
+
+    public TransformedServiceReferenceImpl<S> addProperty(String name, Object value) {
+        if (FORBIDDEN_KEYS.contains(name)) {
+            throw new IllegalArgumentException("Cannot change the property " + name);
+        }
+        m_properties.put(name, value);
+        return this;
+    }
+
+    public TransformedServiceReference<S> addPropertyIfAbsent(String name, Object value) {
+        if (! contains(name)) {
+            addProperty(name, value);
+        }
+        return this;
+    }
+
+    public Object get(String name) {
+        return m_properties.get(name);
+    }
+
+    public TransformedServiceReferenceImpl<S> removeProperty(String name) {
+        if (FORBIDDEN_KEYS.contains(name)) {
+            throw new IllegalArgumentException("Cannot change the property " + name);
+        }
+        // Store a null value.
+        m_properties.put(name, null);
+        return this;
+    }
+
+    public boolean contains(String name) {
+        return m_properties.get(name) != null;
+    }
+
+    public ServiceReference<S> getWrappedReference() {
+        if (m_origin instanceof TransformedServiceReferenceImpl) {
+            return ((TransformedServiceReferenceImpl<S>) m_origin).getWrappedReference();
+        } else {
+            return m_origin;
+        }
+    }
+
+    public Object getProperty(String key) {
+        return m_properties.get(key);
+    }
+
+    public String[] getPropertyKeys() {
+        List<String> keys = new ArrayList<String>();
+        for (Map.Entry<String, Object> entry : m_properties.entrySet()) {
+            if (entry.getValue() != null) {
+                keys.add(entry.getKey());
+            }
+        }
+        return keys.toArray(new String[keys.size()]);
+    }
+
+    public Bundle getBundle() {
+        return m_origin.getBundle();
+    }
+
+    public Bundle[] getUsingBundles() {
+        return m_origin.getUsingBundles();
+    }
+
+    public boolean isAssignableTo(Bundle bundle, String className) {
+        return m_origin.isAssignableTo(bundle, className);
+    }
+
+    /**
+     * Compares two service references.
+     * This method is not delegated as we may have modified some of the properties using for the ranking.
+     * @param reference the reference
+     * @return 0, 1 or -1 depending of the reference.
+     */
+    public int compareTo(Object reference) {
+        ServiceReference other = (ServiceReference) reference;
+
+        Long id = (Long) getProperty(Constants.SERVICE_ID);
+        Long otherId = (Long) other.getProperty(Constants.SERVICE_ID);
+
+        if (id.equals(otherId)) {
+            return 0; // same service
+        }
+
+        Object rankObj = getProperty(Constants.SERVICE_RANKING);
+        Object otherRankObj = other.getProperty(Constants.SERVICE_RANKING);
+
+        // If no rank, then spec says it defaults to zero.
+        rankObj = (rankObj == null) ? new Integer(0) : rankObj;
+        otherRankObj = (otherRankObj == null) ? new Integer(0) : otherRankObj;
+
+        // If rank is not Integer, then spec says it defaults to zero.
+        Integer rank = (rankObj instanceof Integer)
+                ? (Integer) rankObj : new Integer(0);
+        Integer otherRank = (otherRankObj instanceof Integer)
+                ? (Integer) otherRankObj : new Integer(0);
+
+        // Sort by rank in ascending order.
+        if (rank.compareTo(otherRank) < 0) {
+            return -1; // lower rank
+        } else if (rank.compareTo(otherRank) > 0) {
+            return 1; // higher rank
+        }
+
+        // If ranks are equal, then sort by service id in descending order.
+        return (id.compareTo(otherId) < 0) ? 1 : -1;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof ServiceReference) {
+            Object id1 = ((ServiceReference) o).getProperty(Constants.SERVICE_ID);
+            Object id2 = this.getProperty(Constants.SERVICE_ID);
+            return id1 == id2;
+        }
+        return m_origin.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+        return m_origin.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return getWrappedReference().toString() + m_properties;
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/interceptors/DefaultDependencyInterceptor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/interceptors/DefaultDependencyInterceptor.java?rev=1492155&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/interceptors/DefaultDependencyInterceptor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/interceptors/DefaultDependencyInterceptor.java Wed Jun 12 11:38:27 2013
@@ -0,0 +1,59 @@
+/*
+ * 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.ipojo.dependency.interceptors;
+
+import org.apache.felix.ipojo.util.DependencyModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A default implementation of the dependency interceptor.
+ * It manages the dependency list guarded by the monitor lock.
+ */
+public class DefaultDependencyInterceptor implements DependencyInterceptor {
+
+    /**
+     * The set of managed dependencies.
+     * Access must be guarded by the monitor lock.
+     */
+    protected final List<DependencyModel> dependencies = new ArrayList<DependencyModel>();
+
+
+    /**
+     * Closes the interception of the given dependency.
+     * @param dependency the dependency stopping its use of the interceptor
+     */
+    public void close(DependencyModel dependency) {
+        synchronized (this) {
+            dependencies.remove(dependency);
+        }
+    }
+
+    /**
+     * Opens the interception of the given dependency.
+     * @param dependency the dependency starting using the interceptor.
+     */
+    public void open(DependencyModel dependency) {
+        synchronized (this) {
+            dependencies.add(dependency);
+        }
+    }
+}

Added: felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/interceptors/DefaultServiceRankingInterceptor.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/interceptors/DefaultServiceRankingInterceptor.java?rev=1492155&view=auto
==============================================================================
--- felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/interceptors/DefaultServiceRankingInterceptor.java (added)
+++ felix/trunk/ipojo/runtime/core/src/main/java/org/apache/felix/ipojo/dependency/interceptors/DefaultServiceRankingInterceptor.java Wed Jun 12 11:38:27 2013
@@ -0,0 +1,71 @@
+/*
+ * 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.ipojo.dependency.interceptors;
+
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.osgi.framework.ServiceReference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Default implementation of the default service ranking interceptor.
+ * This implementation does not sort the given set, so returns it as it is.
+ *
+ * It also provides an `invalidateSelectedServices` method notifying all managed dependencies of a change in the
+ * selection service set.
+ *
+ * onDeparture, onArrival and onModified methods delegates to the getServiceReferences method.
+ */
+public class DefaultServiceRankingInterceptor extends DefaultDependencyInterceptor implements
+        ServiceRankingInterceptor {
+
+    /**
+     * Notifies the managed dependencies of a change in the set of services selected by this interceptor.
+     * The dependency will call the getServiceReferences method to recompute the set of selected services.
+     */
+    public void invalidateSelectedServices() {
+        List<DependencyModel> list = new ArrayList<DependencyModel>();
+        synchronized (this) {
+            list.addAll(dependencies);
+        }
+
+        for (DependencyModel dep : list) {
+            dep.invalidateSelectedServices();
+        }
+    }
+
+
+    public List<ServiceReference> getServiceReferences(DependencyModel dependency, List<ServiceReference> matching) {
+        return matching;
+    }
+
+    public List<ServiceReference> onServiceArrival(DependencyModel dependency, List<ServiceReference> matching, ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    public List<ServiceReference> onServiceDeparture(DependencyModel dependency, List<ServiceReference> matching, ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    public List<ServiceReference> onServiceModified(DependencyModel dependency, List<ServiceReference> matching, ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+}



Mime
View raw message