added propagate attribute in ServiceDependency annotation. Also added corresponding testcase.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@990650 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ServiceDependency.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ServiceDependency.java
index 4f51357..14da19e 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ServiceDependency.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/ServiceDependency.java
@@ -164,4 +164,11 @@
      *  </pre></blockquote>
      */
     String name() default "";
+    
+    /**
+     * Returns true if the dependency service properties must be published along with the service. 
+     * Any additional service properties specified directly are merged with these.
+     * @return true if dependency service properties must be published along with the service, false if not.
+     */
+    boolean propagate() default false;
 }
diff --git a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
index bdcb4e5..897f26f 100644
--- a/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
+++ b/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
@@ -388,6 +388,9 @@
         if (name != null && ! m_dependencyNames.add(name)) {
             throw new IllegalArgumentException("Duplicate dependency name " + name + " in ServiceDependency annotation from class " + m_className);
         }
+        
+        // propagate attribute
+        writer.putString(annotation, EntryParam.propagate, null);
     }
 
     /**
diff --git a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
index 344e92f..993500f 100644
--- a/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
+++ b/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DependencyBuilder.java
@@ -108,17 +108,18 @@
         String removed = timeout != -1 ? null : m_metaData.getString(Params.removed, null);
         String autoConfigField = m_metaData.getString(Params.autoConfig, null);
         boolean required = "true".equals(m_metaData.getString(Params.required, "true"));
+        boolean propagate = "true".equals(m_metaData.getString(Params.propagate, "false"));
 
         Dependency dp = createServiceDependency(dm, serviceClass,
             serviceFilter, defaultServiceImplClass, added, changed,
-            removed, autoConfigField, timeout, required, instanceBound);
+            removed, autoConfigField, timeout, required, instanceBound, propagate);
         return dp;
     }
 
     private Dependency createServiceDependency(DependencyManager dm, Class<?> serviceClass, 
         String serviceFilter, Class<?> defaultServiceImplClass, String added,
         String changed, String removed, String autoConfigField, long timeout, boolean required,
-        boolean instanceBound)
+        boolean instanceBound, boolean propagate)
     {
         ServiceDependency sd = timeout != -1 ? dm.createTemporalServiceDependency()
             : dm.createServiceDependency();
@@ -145,6 +146,7 @@
         }
         
         sd.setInstanceBound(instanceBound);
+        sd.setPropagate(propagate);
         return sd;
     }
 
diff --git a/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/propagate/ServiceDependencyPropagateTest.java b/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/propagate/ServiceDependencyPropagateTest.java
new file mode 100644
index 0000000..64e1383
--- /dev/null
+++ b/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/propagate/ServiceDependencyPropagateTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.dm.test.bundle.annotation.propagate;
+
+import java.util.Map;
+
+import org.apache.felix.dm.annotation.api.Property;
+import org.apache.felix.dm.annotation.api.Service;
+import org.apache.felix.dm.annotation.api.ServiceDependency;
+import org.apache.felix.dm.annotation.api.Start;
+import org.apache.felix.dm.test.bundle.annotation.sequencer.Sequencer;
+
+/**
+ * Verifies ServiceDependencyservice properties propagation.
+ */
+public class ServiceDependencyPropagateTest
+{
+    @Service
+    public static class Consumer {
+        private Map m_producerProps;
+
+        @ServiceDependency
+        void bind(Map props, Producer producer) {
+            m_producerProps = props;
+        }
+        
+        @ServiceDependency(filter="(test=ServiceDependencyPropagateTest)")
+        Sequencer m_sequencer;
+        
+        @Start
+        void start() {
+            m_sequencer.step(1);
+            if ("bar".equals(m_producerProps.get("foo"))) {
+                m_sequencer.step(2);
+            }
+            if ("bar2".equals(m_producerProps.get("foo2"))) {
+                m_sequencer.step(3);
+            }
+        }
+    }
+    
+    @Service(provides={Producer.class}, properties={@Property(name="foo", value="bar")})
+    public static class Producer {
+        @ServiceDependency(propagate=true)
+        Producer2 m_producer;
+    }
+    
+
+    @Service(provides={Producer2.class}, properties={@Property(name="foo2", value="bar2")})
+    public static class Producer2 {
+    }
+}
diff --git a/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/AnnotationBase.java b/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/AnnotationBase.java
index 1b923e3..c9786c9 100644
--- a/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/AnnotationBase.java
+++ b/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/AnnotationBase.java
@@ -18,6 +18,9 @@
 */
 package org.apache.felix.dm.test.annotation;
 
+import java.util.Hashtable;
+
+import org.apache.felix.dm.DependencyManager;
 import org.apache.felix.dm.test.Base;
 import org.apache.felix.dm.test.Ensure;
 import org.apache.felix.dm.test.bundle.annotation.sequencer.Sequencer;
@@ -74,6 +77,18 @@
         }
     }
 
+    /**
+     * Registers the Sequencer interface, for activating a given testcase
+     */
+    protected void registerSequencer(DependencyManager m, final String testName) 
+    {
+        m.add(m.createService()
+              .setImplementation(this)
+              .setInterface(Sequencer.class.getName(),new Hashtable() {{
+                  put("test", testName);
+              }}));
+    }
+    
     // ----------------------- Sequencer interface ------------------------------------------
 
     /**
diff --git a/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/PropagateAnnotationTest.java b/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/PropagateAnnotationTest.java
new file mode 100644
index 0000000..ee52219
--- /dev/null
+++ b/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/PropagateAnnotationTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.dm.test.annotation;
+
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.provision;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.test.BundleGenerator;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+/**
+ * Use case: Verify that dependency "propagate" option is properly propagating properties to provided service.
+ */
+@RunWith(JUnit4TestRunner.class)
+public class PropagateAnnotationTest extends AnnotationBase
+{
+    @Configuration
+    public static Option[] configuration()
+    {
+        return options(
+            systemProperty(DMLOG_PROPERTY).value( "true" ),
+            provision(
+                mavenBundle().groupId("org.osgi").artifactId("org.osgi.compendium").version("4.1.0"),
+                mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.dependencymanager").versionAsInProject(),
+                mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.configadmin").version("1.2.4"),
+                mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.dependencymanager.runtime").versionAsInProject()),
+            provision(
+                new BundleGenerator()
+                    .set(Constants.BUNDLE_SYMBOLICNAME, "PropagateAnnotationTest")
+                    .set("Export-Package", "org.apache.felix.dm.test.bundle.annotation.sequencer")
+                    .set("Private-Package", "org.apache.felix.dm.test.bundle.annotation.propagate")
+                    .set("Import-Package", "*")
+                    .set("-plugin", "org.apache.felix.dm.annotation.plugin.bnd.AnnotationPlugin")
+                    .build()));            
+    }
+
+    /**
+     * A Service that just registers/unregisters its service, using the @ServiceLifecycle annotation.
+     */
+    @Test
+    public void testServiceDependencyPropagate(BundleContext context)
+    {
+        DependencyManager m = new DependencyManager(context);
+        registerSequencer(m, "ServiceDependencyPropagateTest"); 
+        m_ensure.waitForStep(3, 10000);
+    }    
+}
diff --git a/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/PublisherAnnotationTest.java b/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/PublisherAnnotationTest.java
index 137b326..c722074 100644
--- a/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/PublisherAnnotationTest.java
+++ b/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/PublisherAnnotationTest.java
@@ -61,18 +61,6 @@
                     .set("-plugin", "org.apache.felix.dm.annotation.plugin.bnd.AnnotationPlugin")
                     .build()));            
     }
-
-    /**
-     * Registers the Sequencer interface, for activating a given testcase
-     */
-    private void registerSequencer(DependencyManager m, final String testName) 
-    {
-        m.add(m.createService()
-              .setImplementation(this)
-              .setInterface(Sequencer.class.getName(),new Hashtable() {{
-                  put("test", testName);
-              }}));
-    }
     
     /**
      * A Service that just registers/unregisters its service, using the @ServiceLifecycle annotation.