felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pde...@apache.org
Subject svn commit: r1636212 - in /felix/sandbox/pderop/dependencymanager-prototype: org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/ org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/b...
Date Sun, 02 Nov 2014 23:49:11 GMT
Author: pderop
Date: Sun Nov  2 23:49:10 2014
New Revision: 1636212

URL: http://svn.apache.org/r1636212
Log:
FELIX-4684: Replace DependencyManager Runtime "factorySet" by a cleaner API.


Added:
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ComponentFactoryAnnotation.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ComponentFactoryServiceTestWthPublisher.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ExtraComponentFactoryServiceProperties.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/ComponentFactoryAnnotationTest.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentFactoryImpl.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentInstanceImpl.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentException.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentFactory.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentInstance.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/packageinfo
Modified:
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Component.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/EntryParam.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/ExtraServicePropertiesTest.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/PublisherAnnotationTest.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/bnd.bnd
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentBuilder.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Params.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/bnd.bnd
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceAndParameterFactory.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceImpl.java
    felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceParameterImpl.java

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Component.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Component.java?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Component.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/api/Component.java Sun Nov  2 23:49:10 2014
@@ -31,15 +31,13 @@ import java.lang.annotation.Target;
  * By default, all directly implemented interfaces are registered into the OSGi registry,
  * and the component is instantiated automatically, when the component bundle is started and 
  * when the component dependencies are available. If you need to take control of when and how 
- * much component instances must be created, then you can use the <code>factorySet</code> 
+ * much component instances must be created, then you can use the <code>factoryName</code> 
  * annotation attribute.<p> 
- * If a <code>factorySet</code> attribute is set, the component is not started automatically 
- * during bundle startup, and a <code>java.util.Set&lt;Dictionary&gt;</code> 
- * object is registered into the OSGi registry on behalf of the component. This Set will act 
- * as a Factory API, and another component may use this Set and add some configuration 
- * dictionaries in it, in order to fire some component activations (there is one component 
- * instantiated per dictionary, which is passed to component instances via a configurable 
- * callback method).
+ * If a <code>factoryName</code> attribute is set, the component is not started automatically 
+ * during bundle startup, and a <code>org.apache.felix.dm.runtime.api.ComponentFactory</code> 
+ * object is registered into the OSGi registry on behalf of the component. This ComponentFactory
+ * can then be used by another component in order to instantiate multiple instances of the component 
+ * (DM ComponentFactory are really similar to DS ComponentFactory).
  *
  * <h3>Usage Examples</h3>
  * 
@@ -71,14 +69,14 @@ import java.lang.annotation.Target;
  * </blockquote>
  * 
  * Here is a sample showing how a Y component may dynamically instantiate several X component instances, 
- * using the {@link #factorySet()} attribute:<p>
+ * using the {@link #factoryName()} attribute:<p>
  * <blockquote>
  * 
  * <pre>
  *  &#47;**
  *    * All component instances will be created/updated/removed by the "Y" component
  *    *&#47;
- *  &#64;Component(factorySet="MyComponentFactory", factoryConfigure="configure")
+ *  &#64;Component(factoryName="MyComponentFactory", factoryConfigure="configure")
  *  class X implements Z {                 
  *      void configure(Dictionary conf) {
  *          // Configure or reconfigure our component. The conf is provided by the factory,
@@ -106,31 +104,31 @@ import java.lang.annotation.Target;
  *    *&#47;
  *  &#64;Component 
  *  class Y {
- *      &#64;ServiceDependency(filter="(dm.factory.name=MyComponentFactory)")
- *      Set&lt;Dictionary&gt; _XFactory; // This Set acts as a Factory API for creating X component instances.
+ *      &#64;ServiceDependency(filter="(" + ComponentFactory.FACTORY_NAME + "=MyComponentFactory)")
+ *      ComponentFactory _XFactory;
  *    
  *      &#64;Start
  *      void start() {
  *          // Instantiate a X component instance
- *          Dictionary x1 = new Hashtable() {{ put("foo", "bar1"); }};
- *          _XFactory.add(x1);
+ *          Dictionary instance1Conf = new Hashtable() {{ put("foo", "bar1"); }};
+ *          ComponentInstance instance1 = _XFactory.newInstance(instance1Conf);
  *      
  *          // Instantiate another X component instance
- *          Dictionary x2 = new Hashtable() {{ put("foo", "bar2"); }};
- *          _XFactory.add(x2);
+ *          Dictionary instance2Conf = new Hashtable() {{ put("foo2", "bar2"); }};
+ *          ComponentInstance instance2 = _XFactory.newInstance(instance2Conf);
  *      
  *          // Update the first X component instance
- *          x1.put("foo", "bar1_modified");
- *          _XFactory.add(x1);
+ *          instance1Conf = new Hashtable() {{ put("foo", "bar1 modified"); }};
+ *          instance1.update(instance1Conf);
  *          
  *          // Instantiate a third X instance, by explicitly providing the implementation object
- *          Dictionary x3 = new Hashtable() {{ put(Component.FACTORY_INSTANCE, new X()); }};
- *          _XFactory.add(x3);
+ *          Dictionary instance3Conf = new Hashtable() {{ put(ComponentFactory.FACTORY_INSTANCE, new X()); }};
+ *          ComponentInstance instance3 = _XFactory.newInstance(instance3Conf);
  *      
- *          // Destroy x1/x2/x3 components (Notice that invoking XFactory.clear() will destroy all X component  instances).
- *          _XFactory.remove(x1);
- *          _XFactory.remove(x2); 
- *          _XFactory.remove(x3); 
+ *          // Destroy x1/x2/x3 components
+ *          instance1.dispose();
+ *          instance2.dispose();
+ *          instance3.dispose();
  *      }
  *  }
  * </pre>
@@ -172,12 +170,32 @@ public @interface Component
      * 
      * <p>Optionally, the dictionary registered into the factory set may provide an implementation instance for the component to be created,
      * using the {@value #FACTORY_INSTANCE} key. 
+     * 
+     * @deprecated use {@link #factoryName()} instead of a factorySet.
      */
     String factorySet() default "";
+    
+    /**
+     * Returns the name of the <code>ComponentFactory</code> used to dynamically instantiate this component.
+     * When you set this attribute, a <code>org.apache.felix.dm.runtime.api.ComponentFactory</code> OSGi Service will 
+     * be provided with a <code>dm.runtime.factory.name</code> service property matching 
+     * your specified <code>factoryName</code> attribute.
+     * The ComponentFactory will be provided once the component bundle is started, even if required dependencies are not available, and the
+     * ComponentFactory will be unregistered from the OSGi registry once the component bundle is stopped or being updated.<p>
+     * So, another component may then be injected with this ComponentFactory in order to dynamically instantiate some component instances:
+     * 
+     * <p>The dictionary passed to the ComponentFactory.newInstance method will be provided to the created component instance using a callback 
+     * method that you can optionally specify in the {@link Component#factoryConfigure()} attribute. Each public properties from that dictionary 
+     * (which don't start with a dot) will be propagated along with the annotated component service properties.
+     * 
+     * <p>Optionally, the dictionary registered into the factory set may provide an implementation instance for the component to be created,
+     * using a "dm.runtime.factory.instance" key.
+     */
+    String factoryName() default "";
 
     /**
      * Sets "configure" callback method name to be called with the factory configuration. This attribute only makes sense if the 
-     * {@link #factorySet()} attribute is used. If specified, then this attribute references a callback method, which is called 
+     * {@link #factoryName()} attribute is used. If specified, then this attribute references a callback method, which is called 
      * for providing the configuration supplied by the factory that instantiated this component. The current component service properties will be 
      * also updated with all public properties (which don't start with a dot).
      */
@@ -191,12 +209,18 @@ public @interface Component
     /**
      * Service property name used to match a given Factory Set.
      * @see #factorySet() for more information about factory sets.
+     * @deprecated This constant was used by a {@link #factorySet()} annotation which is deprecated. Now a {@link #factoryName()}
+     * and the org.apache.felix.dm.runtime.api.ComponentFactory service can be filtered using the 
+     * org.apache.felix.dm.runtime.api.ComponentFactory.FACTORY_NAME constant.
      */
     final static String FACTORY_NAME = "dm.factory.name";
     
     /**
      * Key used when providing an implementation in a factory Set dictionary configuration.
      * @see #factorySet()
+     * @deprecated This constant was used by a {@link #factorySet()} annotation which is deprecated. Now a {@link #factoryName()}
+     * should be used instead, and a component instance can be stored in the dictionary passed to the ComponentFactory.newInstance() method
+     * using the org.apache.felix.dm.runtime.api.ComponentFactory.FACTORY_INSTANCE key.
      */
     final static String FACTORY_INSTANCE = "dm.factory.instance";
 }

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java Sun Nov  2 23:49:10 2014
@@ -350,7 +350,7 @@ public class AnnotationCollector extends
             checkRegisteredUnregisteredNotPresent();
         }
 
-        // factorySet attribute
+        // factorySet attribute (deprecated, replaced by factoryName)
         String factorySetName = writer.putString(annotation, EntryParam.factorySet, null);
         if (factorySetName != null)
         {
@@ -362,6 +362,17 @@ public class AnnotationCollector extends
             m_exportService.add("java.util.Set");
         }
 
+        // factoryName attribute
+        String factoryName = writer.putString(annotation, EntryParam.factoryName, null);
+        if (factoryName != null)
+        {
+            // When a component defines a factoryName, it means that a ComponentFactory will 
+            // be provided into the OSGi registry, in order to let another component create some component instances.
+            // So, we have to indicate that the ComponentFactory is provided as a service, in the Export-Serviec
+            // header.
+            m_exportService.add("org.apache.felix.dependencymanager.runtime.api.ComponentFactory");
+        }
+
         // factoryConfigure attribute
         writer.putString(annotation, EntryParam.factoryConfigure, null);
         

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/EntryParam.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/EntryParam.java?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/EntryParam.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.annotation/src/org/apache/felix/dm/annotation/plugin/bnd/EntryParam.java Sun Nov  2 23:49:10 2014
@@ -52,6 +52,7 @@ public enum EntryParam
     stateMask,
     ranking,
     factorySet,
+    factoryName,
     factoryConfigure,
     factoryMethod,
     field,

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/bnd.bnd Sun Nov  2 23:49:10 2014
@@ -4,7 +4,8 @@
 	org.apache.felix.dependencymanager.itest.api;version=latest,\
 	org.apache.felix.dependencymanager.annotation;version=latest,\
 	osgi.cmpn;version=4.2,\
-	junit.osgi;version=3.8
+	junit.osgi;version=3.8,\
+	org.apache.felix.dependencymanager.runtime;version=latest
 -runbundles:  \
 	org.apache.felix.configadmin;version=1.8.0,\
 	org.apache.felix.dependencymanager;version=latest,\

Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ComponentFactoryAnnotation.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ComponentFactoryAnnotation.java?rev=1636212&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ComponentFactoryAnnotation.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ComponentFactoryAnnotation.java Sun Nov  2 23:49:10 2014
@@ -0,0 +1,179 @@
+/*
+* 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.runtime.itest.components;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.felix.dm.annotation.api.Component;
+import org.apache.felix.dm.annotation.api.Init;
+import org.apache.felix.dm.annotation.api.Property;
+import org.apache.felix.dm.annotation.api.ServiceDependency;
+import org.apache.felix.dm.annotation.api.Start;
+import org.apache.felix.dm.annotation.api.Stop;
+import org.apache.felix.dm.itest.Ensure;
+
+import junit.framework.Assert;
+
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class ComponentFactoryAnnotation {
+    public final static String FACTORY = "ComponentFactoryAnnotation.Factory";
+    public final static String ENSURE = "ComponentFactoryAnnotation.Ensure";
+
+    public interface MyServiceInterface {
+        public void added(String instanceId);
+
+        public void changed(String modified);
+
+        public void removed();
+    }
+
+    @Component(properties = @Property(name = "foo", value = "bar"))
+    public static class ExtraDependency1 implements Runnable {
+        public void run() {
+        }
+    }
+
+    @Component(properties = @Property(name = "foo", value = "bar2"))
+    public static class ExtraDependency2 implements Runnable {
+        public void run() {
+            System.out.println("ExtraDependency2.run()");
+        }
+    }
+
+    /**
+     * This service is instantiated using a "factory set" from the
+     * ServiceFactoryAnnotationTest class.
+     * 
+     * @see org.apache.felix.dm.test.annotation.ServiceFactoryAnnotationTest
+     */
+    @Component(factoryName = FACTORY, factoryConfigure = "configure", properties = {@Property(name = "foo", value = "bar")})
+    public static class MyService implements MyServiceInterface {
+        /**
+         * The configuration provided by MyServiceFactory
+         */
+        volatile Dictionary m_configuration;
+
+        /**
+         * Our sequencer.
+         */
+        @ServiceDependency(filter = "(name=" + ENSURE + ")")
+        volatile Ensure m_sequencer;
+
+        /**
+         * An extra dependency (we'll dynamically configure the filter from our
+         * init() method).
+         */
+        @ServiceDependency(name = "extra")
+        Runnable m_extra;
+
+        /**
+         * This is the first method called: we are provided with the
+         * MyServiceFactory configuration.
+         */
+        public void configure(Dictionary<?, ?> configuration) {
+            if (m_configuration == null) {
+                m_configuration = configuration;
+            } else {
+                m_sequencer.step(5);
+                m_configuration = configuration;
+            }
+        }
+
+        /**
+         * Initialize our Service: we'll dynamically configure our dependency whose
+         * name is "extra".
+         */
+        @SuppressWarnings("serial")
+        @Init
+        Map init() {
+            return new HashMap() {
+                {
+                    put("extra.filter", "(foo=bar2)");
+                    put("extra.required", "true");
+                }
+            };
+        }
+
+        /**
+         * our Service is starting: at this point, all required dependencies have
+         * been injected.
+         */
+        @Start
+        public void start() {
+            Assert.assertNotNull("Extra dependency not injected", m_extra);
+            m_extra.run();
+            m_sequencer.step(2);
+        }
+
+        /**
+         * Our service is stopping.
+         */
+        @Stop
+        public void stop() {
+            m_sequencer.step(10);
+        }
+
+        public void added(String instanceId) {
+            if (instanceId.equals(m_configuration.get("instance.id"))) {
+                m_sequencer.step(4);
+            }
+        }
+
+        public void changed(String modified) {
+            if (modified.equals(m_configuration.get("instance.modified"))) {
+                m_sequencer.step(7);
+            }
+        }
+
+        public void removed() {
+            m_sequencer.step(9);
+        }
+    }
+
+    @Component
+    public static class MyServiceClient {
+        @ServiceDependency(filter = "(name=" + ENSURE + ")")
+        volatile Ensure m_sequencer;
+
+        @Start
+        void start() {
+            m_sequencer.step(1);
+        }
+        
+        @ServiceDependency(required = false, changed = "update", removed = "removed")
+        void bind(Map serviceProperties, MyServiceInterface service) {
+            m_sequencer.step(3);
+            Assert.assertEquals("bar", serviceProperties.get("foo"));
+            Assert.assertNull(serviceProperties.get(".private.param"));
+            service.added((String) serviceProperties.get("instance.id"));
+        }
+
+        void update(Map serviceProperties, MyServiceInterface service) {
+            m_sequencer.step(6);
+            service.changed((String) serviceProperties.get("instance.modified"));
+        }
+
+        void removed(MyServiceInterface service) {
+            m_sequencer.step(8);
+            service.removed();
+        }
+    }
+}

Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ComponentFactoryServiceTestWthPublisher.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ComponentFactoryServiceTestWthPublisher.java?rev=1636212&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ComponentFactoryServiceTestWthPublisher.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ComponentFactoryServiceTestWthPublisher.java Sun Nov  2 23:49:10 2014
@@ -0,0 +1,115 @@
+/*
+ * 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.runtime.itest.components;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.dm.annotation.api.Component;
+import org.apache.felix.dm.annotation.api.Init;
+import org.apache.felix.dm.annotation.api.LifecycleController;
+import org.apache.felix.dm.annotation.api.Property;
+import org.apache.felix.dm.annotation.api.ServiceDependency;
+import org.apache.felix.dm.annotation.api.Start;
+import org.apache.felix.dm.itest.Ensure;
+import org.apache.felix.dm.runtime.api.ComponentFactory;
+
+/**
+ * A Service instantiated from a DM ComponentFactory, and which registers/unregisters its service,
+ * using the @ServiceLifecycle annotation.
+ */
+@SuppressWarnings({"unchecked", "rawtypes", "serial"})
+public class ComponentFactoryServiceTestWthPublisher {
+    public final static String FACTORY = "ComponentFactoryServiceTestWthPublisher.FACTORYSET";
+    public final static String ENSURE = "ComponentFactoryServiceTestWthPublisher";
+    
+    public interface Provider {
+    }
+
+    @Component
+    public static class Consumer {
+        @ServiceDependency(filter = "(name=" + ENSURE + ")")
+        volatile Ensure m_sequencer;
+
+        @ServiceDependency(required = false, removed = "unbind")
+        void bind(Map properties, Provider provider) {
+            System.out.println("BIND: " + provider + ", map=" + properties);
+            m_sequencer.step(1);
+            if ("bar".equals(properties.get("foo"))) {
+                m_sequencer.step(2);
+            }
+            if ("bar2".equals(properties.get("foo2"))) {
+                m_sequencer.step(3);
+            }
+            if ("bar3".equals(properties.get("foo3"))) {
+                m_sequencer.step(4);
+            }
+        }
+
+        void unbind(Provider provider) {
+            m_sequencer.step(5);
+        }
+    }
+
+    @Component(factoryName = FACTORY, properties = {@Property(name = "foo", value = "bar")})
+    public static class ProviderImpl implements Provider {
+        @LifecycleController
+        volatile Runnable m_publisher; // injected and used to register our service
+
+        @LifecycleController(start = false)
+        volatile Runnable m_unpublisher; // injected and used to unregister our service
+
+        @ServiceDependency(filter = "(name=" + ENSURE + ")")
+        volatile Ensure m_sequencer;
+
+        @Init
+        void init() {
+            // register service in 1 second
+            Utils.schedule(m_publisher, 1000);
+            // unregister the service in 2 seconds
+            Utils.schedule(m_unpublisher, 2000);
+        }
+
+        @Start
+        Map start() {
+            // At this point, our service properties are the one specified in our @Service annotation + the one specified by our Factory.
+            // We also append an extra service property here:
+            return new HashMap() {
+                {
+                    put("foo3", "bar3");
+                }
+            };
+        }
+    }
+
+    @Component
+    public static class ProviderImplFactory {
+        @ServiceDependency(filter = "(" + ComponentFactory.FACTORY_NAME + "=" + FACTORY + ")")
+        void bind(ComponentFactory providerImplFactory) {
+            providerImplFactory.newInstance(new Hashtable() {
+                {
+                    put("foo2", "bar2");
+                }
+            });
+        }
+    }
+}

Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ExtraComponentFactoryServiceProperties.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ExtraComponentFactoryServiceProperties.java?rev=1636212&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ExtraComponentFactoryServiceProperties.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/components/ExtraComponentFactoryServiceProperties.java Sun Nov  2 23:49:10 2014
@@ -0,0 +1,95 @@
+/*
+ * 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.runtime.itest.components;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.felix.dm.annotation.api.Component;
+import org.apache.felix.dm.annotation.api.Property;
+import org.apache.felix.dm.annotation.api.ServiceDependency;
+import org.apache.felix.dm.annotation.api.Start;
+import org.apache.felix.dm.itest.Ensure;
+import org.apache.felix.dm.runtime.api.ComponentFactory;
+
+@SuppressWarnings({"unchecked", "rawtypes", "serial"})
+public class ExtraComponentFactoryServiceProperties {
+    public final static String FACTORYNAME = "ExtraComponentFactoryServiceProperties.FACTORYSET";
+    public final static String ENSURE = "ExtraComponentFactoryServiceProperties";
+
+    public interface Provider {
+    }
+
+    @Component(properties = {@Property(name = "foo", value = "bar")}, factoryName = FACTORYNAME)
+    public static class ProviderImpl implements Provider {
+        @Start
+        Map<String, String> start() {
+            return new HashMap<String, String>() {
+                {
+                    put("foo2", "bar2");
+                }
+            };
+        }
+    }
+
+    @Component
+    public static class ProviderImplFactory {
+        @ServiceDependency(filter = "(" + ComponentFactory.FACTORY_NAME + "=" + FACTORYNAME + ")")
+        volatile ComponentFactory m_factory;
+
+        @Start
+        void start() {
+            m_factory.newInstance(new Hashtable() {
+                {
+                    put("foo3", "bar3");
+                }
+            });
+        }
+    }
+
+    @Component
+    public static class Consumer {
+        @ServiceDependency(filter = "(name=" + ENSURE + ")")
+        volatile Ensure m_sequencer;
+
+        private volatile Map m_properties;
+
+        @ServiceDependency
+        void bindProvider(Map properties, Provider m_provider) {
+            m_properties = properties;
+        }
+
+        @Start
+        void start() {
+            System.out.println("provider service properties: " + m_properties);
+            if ("bar".equals(m_properties.get("foo"))) {
+                m_sequencer.step(1);
+            }
+
+            if ("bar2".equals(m_properties.get("foo2"))) {
+                m_sequencer.step(2);
+            }
+
+            if ("bar3".equals(m_properties.get("foo3"))) {
+                m_sequencer.step(3);
+            }
+        }
+    }
+}

Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/ComponentFactoryAnnotationTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/ComponentFactoryAnnotationTest.java?rev=1636212&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/ComponentFactoryAnnotationTest.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/ComponentFactoryAnnotationTest.java Sun Nov  2 23:49:10 2014
@@ -0,0 +1,74 @@
+/*
+ * 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.runtime.itest.tests;
+
+import java.util.Hashtable;
+
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.itest.Ensure;
+import org.apache.felix.dm.itest.TestBase;
+import org.apache.felix.dm.runtime.api.ComponentFactory;
+import org.apache.felix.dm.runtime.api.ComponentInstance;
+import org.apache.felix.dm.runtime.itest.components.ComponentFactoryAnnotation;
+import org.osgi.framework.ServiceRegistration;
+
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class ComponentFactoryAnnotationTest extends TestBase {
+    
+    private final Ensure m_ensure = new Ensure();
+
+    public void testServiceFactory() {
+        ServiceRegistration sr = register(m_ensure, ComponentFactoryAnnotation.ENSURE);
+
+        DependencyManager m = new DependencyManager(context);
+        // Wait for the factory.
+        m.add(m.createComponent()
+                .setImplementation(this)
+                .add(m.createServiceDependency()
+                        .setService(ComponentFactory.class,
+                                "(" + ComponentFactory.FACTORY_NAME + "=" + ComponentFactoryAnnotation.FACTORY + ")")
+                        .setRequired(true).setCallbacks("bindFactory", null)));
+
+        // Check if the test.annotation components have been initialized orderly
+        m_ensure.waitForStep(10, 5000);
+        m.clear();
+        sr.unregister();
+    }
+
+    void bindFactory(ComponentFactory factory) {
+        // create a service instance with this configuration
+        Hashtable conf = new Hashtable();
+        conf.put("instance.id", "instance");
+        conf.put(".private.param", "private");
+        ComponentInstance instance = factory.newInstance(conf);
+        m_ensure.waitForStep(4, 5000);
+
+        // update the service instance
+        conf = new Hashtable();
+        conf.put("instance.id", "instance");
+        conf.put(".private.param", "private");
+        conf.put("instance.modified", "true");
+        instance.update(conf);
+        m_ensure.waitForStep(7, 5000);
+
+        // remove instance
+        instance.dispose();
+        m_ensure.waitForStep(10, 5000);        
+    }
+}

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/ExtraServicePropertiesTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/ExtraServicePropertiesTest.java?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/ExtraServicePropertiesTest.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/ExtraServicePropertiesTest.java Sun Nov  2 23:49:10 2014
@@ -21,6 +21,7 @@ package org.apache.felix.dm.runtime.ites
 import org.apache.felix.dm.itest.Ensure;
 import org.apache.felix.dm.itest.TestBase;
 import org.apache.felix.dm.runtime.itest.components.ExtraAdapterServiceProperties;
+import org.apache.felix.dm.runtime.itest.components.ExtraComponentFactoryServiceProperties;
 import org.apache.felix.dm.runtime.itest.components.ExtraFactoryServiceProperties;
 import org.apache.felix.dm.runtime.itest.components.ExtraServiceProperties;
 import org.osgi.framework.ServiceRegistration;
@@ -41,7 +42,7 @@ public class ExtraServicePropertiesTest 
     }
 
     /**
-     * Tests if a Service instantiated by a Factory can provide its service properties from its start method.
+     * Tests if a Service instantiated by a Factory set can provide its service properties from its start method.
      */
     public void testExtraFactoryServiceProperties() {
         Ensure e = new Ensure();
@@ -49,6 +50,16 @@ public class ExtraServicePropertiesTest 
         e.waitForStep(3, 10000);
         sr.unregister();
     }
+    
+    /**
+     * Tests if a Service instantiated by a DM ComponentFactory can provide its service properties from its start method.
+     */
+    public void testExtraComponentFactoryServiceProperties() {
+        Ensure e = new Ensure();
+        ServiceRegistration sr = register(e, ExtraComponentFactoryServiceProperties.ENSURE);
+        e.waitForStep(3, 10000);
+        sr.unregister();
+    }
 
     /**
      * Tests if an AdapterService can provide its service properties from its start method.

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/PublisherAnnotationTest.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/PublisherAnnotationTest.java?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/PublisherAnnotationTest.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime.itest/src/org/apache/felix/dm/runtime/itest/tests/PublisherAnnotationTest.java Sun Nov  2 23:49:10 2014
@@ -22,6 +22,7 @@ import org.apache.felix.dm.itest.Ensure;
 import org.apache.felix.dm.itest.TestBase;
 import org.apache.felix.dm.runtime.itest.components.AdapterServiceTestWithPublisher;
 import org.apache.felix.dm.runtime.itest.components.BundleAdapterServiceTestWithPublisher;
+import org.apache.felix.dm.runtime.itest.components.ComponentFactoryServiceTestWthPublisher;
 import org.apache.felix.dm.runtime.itest.components.FactoryConfigurationAdapterServiceTestWithPublisher;
 import org.apache.felix.dm.runtime.itest.components.FactoryServiceTestWthPublisher;
 import org.apache.felix.dm.runtime.itest.components.ResourceAdapterServiceTestWithPublisher;
@@ -52,6 +53,17 @@ public class PublisherAnnotationTest ext
     }
 
     /**
+     * A Service instantiated from a DM ComponentFactory, and which registers/unregisters its service,
+     * using the @ServiceLifecycle annotation.
+     */
+    public void testComponentFactoryServiceWithPublisher() {
+        Ensure e = new Ensure();
+        ServiceRegistration sr = register(e, ComponentFactoryServiceTestWthPublisher.ENSURE);
+        e.waitForStep(5, 10000);
+        sr.unregister();
+    }
+
+    /**
      * Test an AdapterService which provides its interface using a @ServiceLifecycle.
      */
     public void testAdapterServiceWithPublisher() {

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/bnd.bnd
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/bnd.bnd?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/bnd.bnd (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/bnd.bnd Sun Nov  2 23:49:10 2014
@@ -8,5 +8,7 @@ Private-Package: \
 	org.apache.felix.dependencymanager;version=latest,\
 	de.twentyeleven.skysail.org.json-osgi;version=20080701.0
 Bundle-Activator:org.apache.felix.dm.runtime.Activator
+Export-Package:  \
+	org.apache.felix.dm.runtime.api
 Provide-Capability: osgi.extender; osgi.extender="org.apache.felix.dependencymanager.runtime";\
 	uses:="org.apache.felix.dm";version:Version="4.0.0"
\ No newline at end of file

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentBuilder.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentBuilder.java?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentBuilder.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentBuilder.java Sun Nov  2 23:49:10 2014
@@ -25,6 +25,7 @@ import java.util.Set;
 
 import org.apache.felix.dm.Component;
 import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.runtime.api.ComponentFactory;
 import org.osgi.framework.Bundle;
 
 /**
@@ -49,12 +50,13 @@ public class ComponentBuilder extends Ab
     {
         Component c = dm.createComponent();
         String factory = srvMeta.getString(Params.factorySet, null);
+        String factoryName = srvMeta.getString(Params.factoryName, null);
 
         // Setup Component auto config fields
         setCommonServiceParams(c, srvMeta);
         
-        // Check if we must provide a Component factory set.
-        if (factory == null)
+        // Check if we must provide a Component factory set (deprecated), or a ComponentFactory.
+        if (factory == null && factoryName == null)
         {
             Log.instance().info("ComponentBuilder: building service %s with dependencies %s",
                                 srvMeta,
@@ -86,7 +88,7 @@ public class ComponentBuilder extends Ab
             String[] services = srvMeta.getStrings(Params.provides, null);
             c.setInterface(services, properties);
         }
-        else
+        else if (factory != null) /* deprecated */ 
         {
             Log.instance()
                     .info("ComponentBuilder: providing factory set for service %s with dependencies %s",
@@ -102,6 +104,21 @@ public class ComponentBuilder extends Ab
             Hashtable<String, String> props = new Hashtable<String, String>();
             props.put(DM_FACTORY_NAME, factory);
             c.setInterface(Set.class.getName(), props);
+        } 
+        else if (factoryName != null) {
+            Log.instance()
+            .info("ComponentBuilder: providing component factory for service %s with dependencies %s",
+                  srvMeta,
+                  depsMeta);
+
+            // We don't instantiate the service, but instead we provide a ComponentFactory in the registry.
+            // (similar to DS ComponentFactory).
+            ComponentFactoryImpl compFactory = new ComponentFactoryImpl(b, srvMeta, depsMeta);
+            c.setImplementation(compFactory);
+            c.setCallbacks(null, "start", "stop", null);
+            Hashtable<String, String> props = new Hashtable<String, String>();
+            props.put(ComponentFactory.FACTORY_NAME, factoryName);
+            c.setInterface(ComponentFactory.class.getName(), props);
         }
 
         dm.add(c);

Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentFactoryImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentFactoryImpl.java?rev=1636212&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentFactoryImpl.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentFactoryImpl.java Sun Nov  2 23:49:10 2014
@@ -0,0 +1,103 @@
+package org.apache.felix.dm.runtime;
+
+import java.util.Dictionary;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.runtime.api.ComponentException;
+import org.apache.felix.dm.runtime.api.ComponentFactory;
+import org.apache.felix.dm.runtime.api.ComponentInstance;
+import org.osgi.framework.Bundle;
+
+/**
+ * This class implements a DM Component factory service.
+ * When a <code>Component</annotation> contains a <code>factoryName</code> attribute, this class is provided
+ * into the OSGi registry with a <code>org.apache.felix.dependencymanager.factory.name</code> service property. 
+ * 
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ComponentFactoryImpl implements ComponentFactory {
+    /**
+     * The list of Dependencies which are applied in the Service.
+     */
+    private MetaData m_srvMeta;
+
+    /**
+     * The list of Dependencies which are applied in the Service.
+     */
+    private List<MetaData> m_depsMeta;
+
+    /**
+     * The DependencyManager which is used to create Service instances.
+     */
+    private DependencyManager m_dm;
+
+    /**
+     * Flag used to check if our service is Active.
+     */
+    private volatile boolean m_active;
+
+    /**
+     * The bundle containing the Service annotated with the factory attribute.
+     */
+    private final Bundle m_bundle;
+
+    /**
+     * Sole constructor.
+     * @param b the bundle containing the Service annotated with the factory attribute
+     * @param srvMeta the component service metadata
+     * @param depsMeta teh component dependencies metadata
+     */
+    public ComponentFactoryImpl(Bundle b, MetaData srvMeta, List<MetaData> depsMeta) {
+        m_bundle = b;
+        m_srvMeta = srvMeta;
+        m_depsMeta = depsMeta;
+    }
+
+    /**
+     * Our Service is starting. 
+     */
+    public void start(Component c) {
+        m_active = true;
+        m_dm = c.getDependencyManager();
+    }
+
+    /**
+     * Our Service is stopping.
+     */
+    public void stop() {
+        m_active = false;
+    }
+
+    /**
+     * Create or Update a Service.
+     */
+    public ComponentInstance newInstance(Dictionary<String, ?> conf) {
+        // Check parameter validity
+        if (conf == null) {
+            throw new NullPointerException("configuration parameter can't be null");
+        }
+
+        // Check if our service is running.
+        checkServiceAvailable();
+
+        try {
+            ComponentInstanceImpl instance = new ComponentInstanceImpl(m_dm,m_bundle, m_srvMeta, m_depsMeta, conf);
+            return instance;
+            
+        } catch (Throwable t) {
+            Log.instance().error("ServiceFactory: could not instantiate service %s", t, m_srvMeta);
+            throw new ComponentException("could not instantiate factory component", t);
+        }   
+    }
+
+    /**
+     * Checks if our Service is available (we are not stopped").
+     */
+    private void checkServiceAvailable() {
+        if (!m_active) {
+            throw new IllegalStateException("Service not available");
+        }
+    }
+}

Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentInstanceImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentInstanceImpl.java?rev=1636212&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentInstanceImpl.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/ComponentInstanceImpl.java Sun Nov  2 23:49:10 2014
@@ -0,0 +1,190 @@
+package org.apache.felix.dm.runtime;
+
+import java.lang.reflect.Method;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.Dependency;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.runtime.api.ComponentFactory;
+import org.apache.felix.dm.runtime.api.ComponentInstance;
+import org.osgi.framework.Bundle;
+
+/**
+ * 
+ * @author nxuser
+ *
+ */
+public class ComponentInstanceImpl implements ComponentInstance {
+    /**
+     * The list of Dependencies which are applied in the Service.
+     */
+    private final MetaData m_srvMeta;
+
+    /**
+     * The list of Dependencies which are applied in the Service.
+     */
+    private final List<MetaData> m_depsMeta;
+
+    /**
+     * The DependencyManager which is used to create Service instances.
+     */
+    private final DependencyManager m_dm;
+
+    /**
+     * The bundle containing the Service annotated with the factory attribute.
+     */
+    private final Bundle m_bundle;
+    
+    /**
+     * The component 
+     */
+    private final Object m_impl;
+    
+    /**
+     * The DM Component used to define the component
+     */
+    private final Component m_component;
+
+    public ComponentInstanceImpl(DependencyManager dm, Bundle b, MetaData srvMeta, List<MetaData> depsMeta, Dictionary<String, ?> conf) throws Exception
+    {
+        m_bundle = b;
+        m_dm = dm;
+        m_srvMeta = srvMeta;
+        m_depsMeta = depsMeta;
+        m_component = m_dm.createComponent();
+        
+        Class<?> implClass = m_bundle.loadClass(m_srvMeta.getString(Params.impl));
+        Object impl = conf.get(ComponentFactory.FACTORY_INSTANCE);
+        if (impl == null) {
+            String factoryMethod = m_srvMeta.getString(Params.factoryMethod, null);
+            if (factoryMethod == null) {
+                impl = implClass.newInstance();
+            } else {
+                Method m = implClass.getDeclaredMethod(factoryMethod);
+                m.setAccessible(true);
+                impl = m.invoke(null);
+            }
+        }
+        m_impl = impl;
+
+        // Invoke "configure" callback
+        String configure = m_srvMeta.getString(Params.factoryConfigure, null);
+
+        if (configure != null) {
+            invokeConfigure(impl, configure, conf);
+        }
+
+        // Create Service
+        m_component.setImplementation(impl);
+        String[] provides = m_srvMeta.getStrings(Params.provides, null);
+        if (provides != null) {
+            // Merge service properties with the configuration provided by the factory.
+            Dictionary<String, ?> serviceProperties = m_srvMeta.getDictionary(Params.properties, null);
+            serviceProperties = mergeSettings(serviceProperties, conf);
+            m_component.setInterface(provides, serviceProperties);
+        }
+
+        m_component.setComposition(m_srvMeta.getString(Params.composition, null));
+        ServiceLifecycleHandler lfcleHandler = new ServiceLifecycleHandler(m_component, m_bundle, m_dm, m_srvMeta, m_depsMeta);
+        // The dependencies will be plugged by our lifecycle handler.
+        m_component.setCallbacks(lfcleHandler, "init", "start", "stop", "destroy");
+
+        // Adds dependencies (except named dependencies, which are managed by the lifecycle handler).
+        for (MetaData dependency : m_depsMeta) {
+            String name = dependency.getString(Params.name, null);
+            if (name == null) {
+                DependencyBuilder depBuilder = new DependencyBuilder(dependency);
+                Log.instance().info("ServiceLifecycleHandler.init: adding dependency %s into service %s", dependency,
+                    m_srvMeta);
+                Dependency d = depBuilder.build(m_bundle, m_dm);
+                m_component.add(d);
+            }
+        }
+
+        // Register the Service instance, and keep track of it.
+        Log.instance().info("ServiceFactory: created service %s", m_srvMeta);
+        m_dm.add(m_component);
+    }
+
+    @Override
+    public void dispose() {
+        m_dm.remove(m_component);
+    }
+
+    @Override
+    public void update(Dictionary<String, ?> conf) {
+        // Reconfigure an already existing Service.
+        String configure = m_srvMeta.getString(Params.factoryConfigure, null);
+        if (configure != null) {
+            Log.instance().info("ServiceFactory: updating service %s", m_impl);
+            invokeConfigure(m_impl, configure, conf);
+        }
+
+        // Update service properties
+        String[] provides = m_srvMeta.getStrings(Params.provides, null);
+        if (provides != null) {
+            Dictionary<String, ?> serviceProperties = m_srvMeta.getDictionary(Params.properties, null);
+            serviceProperties = mergeSettings(serviceProperties, conf);
+            m_component.setServiceProperties(serviceProperties);
+        }
+    }
+
+    /**
+     * Invokes the configure callback method on the service instance implemenatation.
+     * @param impl
+     * @param configure
+     * @param config
+     */
+    private void invokeConfigure(Object impl, String configure, Dictionary<String, ?> config) {
+        try {
+            InvocationUtil.invokeCallbackMethod(impl, configure, new Class[][] { { Dictionary.class } },
+                new Object[][] { { config } });
+        }
+
+        catch (Throwable t) {
+            if (t instanceof RuntimeException) {
+                throw (RuntimeException) t;
+            } else {
+                throw new RuntimeException("Could not invoke method " + configure + " on object " + impl, t);
+            }
+        }
+    }
+
+    /**
+     * Merge factory configuration settings with the service properties. The private factory configuration 
+     * settings are ignored. A factory configuration property is private if its name starts with a dot (".").
+     * 
+     * @param serviceProperties
+     * @param factoryConfiguration
+     * @return
+     */
+    private Dictionary<String, Object> mergeSettings(Dictionary<String, ?> serviceProperties,
+        Dictionary<String, ?> factoryConfiguration)
+    {
+        Dictionary<String, Object> props = new Hashtable<>();
+
+        if (serviceProperties != null) {
+            Enumeration<String> keys = serviceProperties.keys();
+            while (keys.hasMoreElements()) {
+                String key = keys.nextElement();
+                Object val = serviceProperties.get(key);
+                props.put(key, val);
+            }
+        }
+
+        Enumeration<String> keys = factoryConfiguration.keys();
+        while (keys.hasMoreElements()) {
+            String key = keys.nextElement();
+            if (!key.toString().startsWith(".")) {
+                // public properties are propagated
+                Object val = factoryConfiguration.get(key);
+                props.put(key, val);
+            }
+        }
+        return props;
+    }
+}

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Params.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Params.java?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Params.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/Params.java Sun Nov  2 23:49:10 2014
@@ -53,6 +53,7 @@ public enum Params
     ranking,
     factoryPid,    
     factorySet,
+    factoryName,
     factoryConfigure,
     factoryMethod,
     name,

Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentException.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentException.java?rev=1636212&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentException.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentException.java Sun Nov  2 23:49:10 2014
@@ -0,0 +1,13 @@
+package org.apache.felix.dm.runtime.api;
+
+/**
+ * Exception thrown when a Component can't be instantiated using a {@link ComponentFactory#newInstance(java.util.Dictionary)} 
+ * service.
+ *
+ */
+@SuppressWarnings("serial")
+public class ComponentException extends RuntimeException {
+    public ComponentException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}

Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentFactory.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentFactory.java?rev=1636212&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentFactory.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentFactory.java Sun Nov  2 23:49:10 2014
@@ -0,0 +1,31 @@
+package org.apache.felix.dm.runtime.api;
+
+import java.util.Dictionary;
+
+/**
+ * When a Component is annotated with a DM "Component" annotation with a "factoryName" attribute, a corresponding
+ * ComponentFactory is registered in the OSGi service registry with a @link {@link ComponentFactory#FACTORY_NAME} 
+ * servie property with the Component "factoryName" value.
+ */
+public interface ComponentFactory {
+    /**
+     * A ComponentFactory is registered in the OSGI service registry with a FACTORY_NAME matching the "factoryName" attribute
+     * value used in the DM Component annotation.
+     */
+    public final static String FACTORY_NAME = "dm.runtime.factory.name";
+    
+    /**
+     * When instantiating a Component, you can specify the component instance in the dictionary passed to the {@link #newInstance(Dictionary)}
+     * method using this key.
+     */
+    public final static String FACTORY_INSTANCE = "dm.runtime.factory.instance";
+
+    /**
+     * Instantiates a Component instance. Any properties starts with a "." are considered as private. Other properties will be
+     * published as the component instance service properties (if the component provides a services).
+     * @param conf the properties passed to the component "configure" method which is specified with the "configure" attribute
+     * of the @Component annotation.  
+     * @return the component instance.
+     */
+    ComponentInstance newInstance(Dictionary<String, ?> conf);
+}

Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentInstance.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentInstance.java?rev=1636212&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentInstance.java (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/ComponentInstance.java Sun Nov  2 23:49:10 2014
@@ -0,0 +1,19 @@
+package org.apache.felix.dm.runtime.api;
+
+import java.util.Dictionary;
+
+/**
+ * A Component instance created using a {@link ComponentFactory} service
+ */
+public interface ComponentInstance {
+    /**
+     * Destroy the component instance.
+     */
+    void dispose();
+    
+    /**
+     * Updates the component instance.
+     * @param conf the properties used to update the component.
+     */
+    void update(Dictionary<String, ?> conf);
+}

Added: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/packageinfo
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/packageinfo?rev=1636212&view=auto
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/packageinfo (added)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.runtime/src/org/apache/felix/dm/runtime/api/packageinfo Sun Nov  2 23:49:10 2014
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/bnd.bnd
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/bnd.bnd?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/bnd.bnd (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/bnd.bnd Sun Nov  2 23:49:10 2014
@@ -5,7 +5,8 @@ Bundle-Version: 1.0.0.${tstamp}
 	org.apache.felix.dependencymanager.annotation;version=latest,\
 	osgi.cmpn;version=4.2,\
 	org.apache.felix.gogo.runtime;version=latest,\
-	biz.aQute.bnd.annotation;version=2.3
+	biz.aQute.bnd.annotation;version=2.3,\
+	org.apache.felix.dependencymanager.runtime;version=latest
 -runfw: org.apache.felix.framework;version='[4.4.0,4.4.0]'
 -runee: OSGi/Minimum-1.1
 -runbundles:  \

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceAndParameterFactory.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceAndParameterFactory.java?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceAndParameterFactory.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceAndParameterFactory.java Sun Nov  2 23:49:10 2014
@@ -7,6 +7,7 @@ import java.util.Set;
 import org.apache.felix.dm.annotation.api.Component;
 import org.apache.felix.dm.annotation.api.ServiceDependency;
 import org.apache.felix.dm.annotation.api.Start;
+import org.apache.felix.dm.runtime.api.ComponentFactory;
 import org.osgi.service.log.LogService;
 
 /**
@@ -15,11 +16,11 @@ import org.osgi.service.log.LogService;
  */
 @Component
 public class DeviceAndParameterFactory {
-    @ServiceDependency(filter = "(" + Component.FACTORY_NAME + "=Device)")
-    volatile Set<Dictionary<?,?>> m_deviceFactory;
+    @ServiceDependency(filter = "(" + ComponentFactory.FACTORY_NAME + "=Device)")
+    volatile ComponentFactory m_deviceFactory;
     
-    @ServiceDependency(filter = "(" + Component.FACTORY_NAME + "=DeviceParameter)")
-    volatile Set<Dictionary<?,?>> m_deviceParameterFactory;
+    @ServiceDependency(filter = "(" + ComponentFactory.FACTORY_NAME + "=DeviceParameter)")
+    volatile ComponentFactory m_deviceParameterFactory;
 
     @ServiceDependency
     volatile LogService log;
@@ -37,10 +38,10 @@ public class DeviceAndParameterFactory {
 
         Dictionary<String,Object> device = new Hashtable<>();
         device.put("device.id", new Integer(id));
-        m_deviceFactory.add(device);
+        m_deviceFactory.newInstance(device);
         
         Dictionary<String, Object> param = new Hashtable<>();
         param.put("device.id", new Integer(id));
-        m_deviceParameterFactory.add(param);
+        m_deviceParameterFactory.newInstance(param);
     }
 }

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceImpl.java?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceImpl.java Sun Nov  2 23:49:10 2014
@@ -4,7 +4,7 @@ import java.util.Dictionary;
 
 import org.apache.felix.dm.annotation.api.Component;
 
-@Component(factorySet = "Device", factoryConfigure = "configure")
+@Component(factoryName = "Device", factoryConfigure = "configure")
 public class DeviceImpl implements Device {
     int id;
 

Modified: felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceParameterImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceParameterImpl.java?rev=1636212&r1=1636211&r2=1636212&view=diff
==============================================================================
--- felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceParameterImpl.java (original)
+++ felix/sandbox/pderop/dependencymanager-prototype/org.apache.felix.dependencymanager.samples/src/org/apache/felix/dependencymanager/samples/device/annot/DeviceParameterImpl.java Sun Nov  2 23:49:10 2014
@@ -4,7 +4,7 @@ import java.util.Dictionary;
 
 import org.apache.felix.dm.annotation.api.Component;
 
-@Component(factorySet="DeviceParameter", factoryConfigure="configure")
+@Component(factoryName="DeviceParameter", factoryConfigure="configure")
 public class DeviceParameterImpl implements DeviceParameter {
     int id;
         



Mime
View raw message