You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pd...@apache.org on 2014/11/03 00:49:11 UTC
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...
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<Dictionary></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>
* /**
* * All component instances will be created/updated/removed by the "Y" component
* */
- * @Component(factorySet="MyComponentFactory", factoryConfigure="configure")
+ * @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;
* */
* @Component
* class Y {
- * @ServiceDependency(filter="(dm.factory.name=MyComponentFactory)")
- * Set<Dictionary> _XFactory; // This Set acts as a Factory API for creating X component instances.
+ * @ServiceDependency(filter="(" + ComponentFactory.FACTORY_NAME + "=MyComponentFactory)")
+ * ComponentFactory _XFactory;
*
* @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;