Test interceptor combination

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1559506 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/runtime/core-it/ipojo-core-service-dependency-interceptor-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/AdvancedFooConsumer.java b/ipojo/runtime/core-it/ipojo-core-service-dependency-interceptor-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/AdvancedFooConsumer.java
new file mode 100644
index 0000000..7858711
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-service-dependency-interceptor-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/components/AdvancedFooConsumer.java
@@ -0,0 +1,82 @@
+/*
+ * 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.runtime.core.test.components;
+
+import org.apache.felix.ipojo.annotations.*;
+import org.apache.felix.ipojo.runtime.core.test.services.CheckService;
+import org.apache.felix.ipojo.runtime.core.test.services.Enhanced;
+import org.apache.felix.ipojo.runtime.core.test.services.FooService;
+import org.apache.felix.ipojo.runtime.core.test.services.Setter;
+
+import java.util.Dictionary;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * A component consuming FooService with a filter requiring interception, and impacting the ranking.
+ */
+@Component(immediate = true)
+@Provides
+public class AdvancedFooConsumer implements CheckService, Setter {
+
+    @Requires(id= "foo", policy = BindingPolicy.DYNAMIC_PRIORITY, proxy = false, filter= "(intercepted=true)",
+            optional = true, nullable = false)
+    private FooService foo;
+
+    private Map<String, Object> props;
+
+    // Will be read by the interceptor to inject only matching provider.
+    @Property(value = "0")
+    private int grade = 0;
+
+    @Override
+    public boolean check() {
+        return foo.foo();
+    }
+
+    @Override
+    public Dictionary getProps() {
+        Properties properties =  new Properties();
+        properties.put("props", props);
+        if (foo != null) {
+            properties.put("grade", foo.getGrade());
+            if (foo instanceof Enhanced) {
+                properties.put("enhanced", ((Enhanced) foo).enhance());
+            }
+        }
+        return properties;
+    }
+
+    @Bind(id="foo")
+    public void bind(FooService foo, Map<String, Object> properties) {
+        props = properties;
+    }
+
+    @Modified(id = "foo")
+    public void modified(FooService foo, Map<String, Object> properties) {
+        props = properties;
+    }
+
+    @Override
+    public void set(String newValue) {
+        System.out.println("Setting grade to " + newValue);
+        grade = Integer.parseInt(newValue);
+    }
+}
diff --git a/ipojo/runtime/core-it/ipojo-core-service-dependency-interceptor-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/interceptors/AdvancedTrackerAndRankerInterceptor.java b/ipojo/runtime/core-it/ipojo-core-service-dependency-interceptor-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/interceptors/AdvancedTrackerAndRankerInterceptor.java
new file mode 100644
index 0000000..0537aa3
--- /dev/null
+++ b/ipojo/runtime/core-it/ipojo-core-service-dependency-interceptor-test/src/main/java/org/apache/felix/ipojo/runtime/core/test/interceptors/AdvancedTrackerAndRankerInterceptor.java
@@ -0,0 +1,126 @@
+/*
+ * 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.runtime.core.test.interceptors;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Provides;
+import org.apache.felix.ipojo.annotations.ServiceProperty;
+import org.apache.felix.ipojo.dependency.interceptors.DefaultDependencyInterceptor;
+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.handlers.configuration.ConfigurationHandlerDescription;
+import org.apache.felix.ipojo.handlers.configuration.ConfigurationListener;
+import org.apache.felix.ipojo.runtime.core.test.services.Setter;
+import org.apache.felix.ipojo.util.DependencyModel;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An interceptor implements both ranking and tracking interfaces.
+ * It first adds the 'intercepted' property to the services, and then select only the provider having a grade
+ * matching the instance's 'grade' property.
+ */
+@Component(immediate = true)
+@Provides
+public class AdvancedTrackerAndRankerInterceptor extends DefaultDependencyInterceptor implements
+        ServiceTrackingInterceptor, ServiceRankingInterceptor, ConfigurationListener {
+
+    @ServiceProperty
+    private String target;
+
+    @Override
+    public void close(DependencyModel dependency) {
+        super.close(dependency);
+        ConfigurationHandlerDescription handler = (ConfigurationHandlerDescription) dependency.getComponentInstance().getInstanceDescription()
+                .getHandlerDescription("org.apache.felix.ipojo:properties");
+        handler.removeListener(this);
+    }
+
+    @Override
+    public void open(DependencyModel dependency) {
+        super.open(dependency);
+        ConfigurationHandlerDescription handler = (ConfigurationHandlerDescription) dependency.getComponentInstance().getInstanceDescription()
+                .getHandlerDescription("org.apache.felix.ipojo:properties");
+        handler.addListener(this);
+    }
+
+    @Override
+    public List<ServiceReference> getServiceReferences(DependencyModel dependency, List<ServiceReference> matching) {
+       List<ServiceReference> list = new ArrayList<ServiceReference>();
+       Integer grade = getInstanceGrade(dependency);
+       for (ServiceReference ref : matching) {
+           if (grade.equals(ref.getProperty("grade"))) {
+               list.add(ref);
+           }
+       }
+        return list;
+    }
+
+    private Integer getInstanceGrade(DependencyModel dependency) {
+        ConfigurationHandlerDescription handler = (ConfigurationHandlerDescription) dependency.getComponentInstance().getInstanceDescription()
+                .getHandlerDescription("org.apache.felix.ipojo:properties");
+        return (Integer) handler.getPropertyByName("grade").getCurrentValue();
+    }
+
+    @Override
+    public List<ServiceReference> onServiceArrival(DependencyModel dependency, List<ServiceReference> matching, ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    @Override
+    public List<ServiceReference> onServiceDeparture(DependencyModel dependency, List<ServiceReference> matching, ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    @Override
+    public List<ServiceReference> onServiceModified(DependencyModel dependency, List<ServiceReference> matching, ServiceReference<?> reference) {
+        return getServiceReferences(dependency, matching);
+    }
+
+    @Override
+    public <S> TransformedServiceReference<S> accept(DependencyModel dependency, BundleContext context, TransformedServiceReference<S> ref) {
+       return ref.addProperty("intercepted", true);
+    }
+
+    /**
+     * 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();
+        }
+    }
+
+    @Override
+    public void configurationChanged(ComponentInstance instance, Map<String, Object> configuration) {
+        invalidateSelectedServices();
+    }
+}
diff --git a/ipojo/runtime/core-it/ipojo-core-service-dependency-interceptor-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/TestCombinationOfInterceptors.java b/ipojo/runtime/core-it/ipojo-core-service-dependency-interceptor-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/TestCombinationOfInterceptors.java
index 36108c5..df9f9fe 100644
--- a/ipojo/runtime/core-it/ipojo-core-service-dependency-interceptor-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/TestCombinationOfInterceptors.java
+++ b/ipojo/runtime/core-it/ipojo-core-service-dependency-interceptor-test/src/test/java/org/apache/felix/ipojo/runtime/core/test/dependencies/TestCombinationOfInterceptors.java
@@ -46,7 +46,7 @@
     private ComponentInstance provider6;
 
     @Test
-    public void test() {
+    public void testCombination() {
 
         provider1 = provider(0);
         provider2 = provider(1);
@@ -76,15 +76,49 @@
         // Change range
         Setter setter = osgiHelper.getServiceObject(Setter.class);
         setter.set("LOW REVERSE");
-
-//        check = osgiHelper.getServiceObject(CheckService.class);
-//        assertThat(check.getProps().get("grade")).isEqualTo(3);
-//
-//        setter.set("REVERSE");
-//        check = osgiHelper.getServiceObject(CheckService.class);
         assertThat(check.getProps().get("grade")).isEqualTo(0);
     }
 
+    @Test
+    public void testAdvanced() {
+
+        provider1 = provider(0);
+        provider2 = provider(0);
+        provider3 = provider(1);
+        provider4 = provider(1);
+        provider5 = provider(2);
+        provider6 = provider(2);
+
+        // Create the interceptor
+        Properties configuration = new Properties();
+        configuration.put("target", "(dependency.id=foo)");
+        ipojoHelper.createComponentInstance("org.apache.felix.ipojo.runtime.core.test.interceptors" +
+                ".AdvancedTrackerAndRankerInterceptor", configuration);
+
+        // Create the FooConsumer
+        ComponentInstance instance = ipojoHelper.createComponentInstance("org.apache.felix.ipojo.runtime.core.test" +
+                ".components.AdvancedFooConsumer");
+
+        // Check we are using provider 0
+        osgiHelper.waitForService(CheckService.class.getName(), null, 1000, true);
+        CheckService check = osgiHelper.getServiceObject(CheckService.class);
+        assertThat(check.getProps().get("grade")).isEqualTo(0);
+
+        Dictionary conf = new Hashtable();
+        conf.put("grade", "1");
+        instance.reconfigure(conf);
+
+        assertThat(check.getProps().get("grade")).isEqualTo(1);
+
+        conf.put("grade", "2");
+        instance.reconfigure(conf);
+        assertThat(check.getProps().get("grade")).isEqualTo(2);
+
+        conf.put("grade", "3");
+        instance.reconfigure(conf);
+        assertThat(check.getProps().get("grade")).isNull();
+    }
+
 
     private ComponentInstance provider(int i) {
         Dictionary<String, String> configuration = new Hashtable<String, String>();