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 2010/04/28 23:03:48 UTC

svn commit: r939089 - in /felix/trunk/dependencymanager: annotation/src/main/java/org/apache/felix/dm/annotation/api/ annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/ runtime/src/main/java/org/apache/felix/dm/runtime/ test/src/main/j...

Author: pderop
Date: Wed Apr 28 21:03:47 2010
New Revision: 939089

URL: http://svn.apache.org/viewvc?rev=939089&view=rev
Log:
added annotation support for factory configuration adapter service

Added:
    felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java
    felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/
    felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceClient.java
    felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceInterface.java
    felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceProvider.java
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/FactoryConfigurationAdapterAnnotationTest.java
Modified:
    felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
    felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/MetaType.java
    felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ComponentManager.java
    felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorEntry.java
    felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParam.java
    felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/sequencer/Sequencer.java
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/AnnotationBase.java

Added: felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java?rev=939089&view=auto
==============================================================================
--- felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java (added)
+++ felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/api/FactoryConfigurationAdapterService.java Wed Apr 28 21:03:47 2010
@@ -0,0 +1,84 @@
+/*
+ * 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.annotation.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates a class that acts as a Configuration Factory Adapter Service. For each new Config Admin factory configuration matching
+ * the specified factoryPid, an instance of this service will be created.
+ * The adapter will be registered with the specified interface, and with the specified adapter service properties.
+ * Depending on the <code>propagate</code> parameter, every public factory configuration properties 
+ * (which don't start with ".") will be propagated along with the adapter service properties. 
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.TYPE)
+public @interface FactoryConfigurationAdapterService
+{
+    /**
+     * Returns the factory pid whose configurations will instantiate the annotated service class. (By default, the pid is the 
+     * service class name).
+     */
+    String factoryPid() default "";
+
+    /**
+     * The Update method to invoke (defaulting to "updated"), when a factory configuration is created or updated
+     */
+    String updated() default "updated";
+
+    /**
+     * Returns true if the configuration properties must be published along with the service. 
+     * Any additional service properties specified directly are merged with these.
+     * @return true if configuration must be published along with the service, false if not.
+     */
+    boolean propagate() default false;
+
+    /**
+     * The interface(s) to use when registering adapters. By default, directly implemented 
+     * interfaces will be registered in the OSGi registry.
+     */
+    Class<?>[] service() default {};
+
+    /**
+     * Adapter Service properties. Notice that public factory configuration is also registered in service properties,
+     * (only if propagate is true). Public factory configuration properties are those which don't starts with a dot (".").
+     */
+    Property[] properties() default {};
+
+    /**
+     * The label used to display the tab name (or section) where the properties are displayed. Example: "Printer Service".
+     * @return The label used to display the tab name where the properties are displayed.
+     */
+    String heading() default "";
+
+    /**
+     * A human readable description of the PID this annotation is associated with. Example: "Configuration for the PrinterService bundle".
+     * @return A human readable description of the PID this annotation is associated with.
+     */
+    String description() default "";
+
+    /**
+     * The list of properties types used to expose properties in web console. 
+     * @return The list of properties types used to expose properties in web console. 
+     */
+    PropertyMetaData[] metadata() default {};
+}

Modified: felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java?rev=939089&r1=939088&r2=939089&view=diff
==============================================================================
--- felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java (original)
+++ felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/AnnotationCollector.java Wed Apr 28 21:03:47 2010
@@ -36,6 +36,7 @@ import org.apache.felix.dm.annotation.ap
 import org.apache.felix.dm.annotation.api.Composition;
 import org.apache.felix.dm.annotation.api.ConfigurationDependency;
 import org.apache.felix.dm.annotation.api.Destroy;
+import org.apache.felix.dm.annotation.api.FactoryConfigurationAdapterService;
 import org.apache.felix.dm.annotation.api.Init;
 import org.apache.felix.dm.annotation.api.ResourceAdapterService;
 import org.apache.felix.dm.annotation.api.ResourceDependency;
@@ -83,6 +84,8 @@ public class AnnotationCollector extends
         + BundleAdapterService.class.getName().replace('.', '/') + ";";
     private final static String A_RESOURCE_ADAPTER_SERVICE = "L"
         + ResourceAdapterService.class.getName().replace('.', '/') + ";";
+    private final static String A_FACTORYCONFIG_ADAPTER_SERVICE = "L"
+        + FactoryConfigurationAdapterService.class.getName().replace('.', '/') + ";";
 
     private Reporter m_reporter;
     private String m_className;
@@ -124,7 +127,8 @@ public class AnnotationCollector extends
         TemporalServiceDependency, 
         ConfigurationDependency,
         BundleDependency,
-        ResourceDependency
+        ResourceDependency,
+        FactoryConfigurationAdapterService
     };
 
     // List of component descriptor parameters
@@ -149,6 +153,7 @@ public class AnnotationCollector extends
         removed,
         autoConfig, 
         pid, 
+        factoryPid,
         propagate, 
         updated, 
         timeout,
@@ -384,6 +389,10 @@ public class AnnotationCollector extends
         {
             parseResourceAdapterService(annotation);
         }
+        else if (annotation.getName().equals(A_FACTORYCONFIG_ADAPTER_SERVICE))
+        {
+            parseFactoryConfigurationAdapterService(annotation);
+        }
         else if (annotation.getName().equals(A_INIT))
         {
             checkMethod(m_voidMethodPattern);
@@ -566,45 +575,8 @@ public class AnnotationCollector extends
         info.addParam(annotation, Params.propagate, null);
 
         // Property Meta Types
-        if (annotation.get("metadata") != null)
-        {
-            String propertiesPid = get(annotation, "pid", m_className);
-            String propertiesHeading = annotation.get("heading");
-            String propertiesDesc = annotation.get("description");
-
-            MetaType.OCD ocd = new MetaType.OCD(propertiesPid, propertiesHeading, propertiesDesc);
-            for (Object p : (Object[]) annotation.get("metadata"))
-            {
-                Annotation property = (Annotation) p;
-                String heading = property.get("heading");
-                String id = property.get("id");
-                String type = (String) property.get("type");
-                type = (type != null) ? parseClass(type, m_classPattern, 1) : null;
-                Object[] defaults = (Object[]) property.get("defaults");
-                String description = property.get("description");
-                Integer cardinality = property.get("cardinality");
-                Boolean required = property.get("required");
-
-                MetaType.AD ad = new MetaType.AD(id, type, defaults, heading, description,
-                    cardinality, required);
-                Object[] options = property.get("options");
-                if (options != null)
-                {
-                    for (Object o : (Object[]) property.get("options"))
-                    {
-                        Annotation option = (Annotation) o;
-                        ad.add(new MetaType.Option((String) option.get("name"),
-                            (String) option.get("value")));
-                    }
-                }
-                ocd.add(ad);
-            }
-
-            m_metaType.add(ocd);
-            MetaType.Designate designate = new MetaType.Designate(propertiesPid);
-            m_metaType.add(designate);
-            m_reporter.warning("Parsed MetaType Properties from class " + m_className);
-        }
+        String pid = get(annotation, Params.pid.toString(), m_className);
+        parseMetaTypes(annotation, pid, false);
     }
 
     /**
@@ -765,6 +737,42 @@ public class AnnotationCollector extends
         info.addParam(annotation, Params.propagate, Boolean.FALSE);
     }
 
+    /**
+     * Parses a Factory Configuration Adapter annotation.
+     * @param annotation
+     */
+    private void parseFactoryConfigurationAdapterService(Annotation annotation)
+    {
+        Info info = new Info(EntryTypes.FactoryConfigurationAdapterService);
+        m_infos.add(info);
+        
+        // Register previously parsed Init/Start/Stop/Destroy/Composition annotations
+        addCommonServiceParams(info);
+
+        // Generate Adapter Implementation
+        info.addParam(Params.impl, m_className);
+
+        // Parse factory Pid
+        info.addParam(annotation, Params.factoryPid, m_className);
+        
+        // Parse updated callback
+        info.addParam(annotation, Params.updated, "updated");
+        
+        // propagate attribute
+        info.addParam(annotation, Params.propagate, Boolean.FALSE);
+        
+        // Parse the optional adapter service (use directly implemented interface by default).
+        info.addClassParam(annotation, Params.service, m_interfaces);
+
+        // Parse Adapter properties.
+        parseParameters(annotation, Params.properties, info);
+
+        // Parse optional meta types for configuration description.
+        String factoryPid = get(annotation, Params.factoryPid.toString(), m_className);
+        parseMetaTypes(annotation, factoryPid, true);        
+    }
+
+
     private void parseBundleDependencyAnnotation(Annotation annotation)
     {
         Info info = new Info(EntryTypes.BundleDependency);
@@ -805,6 +813,52 @@ public class AnnotationCollector extends
     }
 
     /**
+     * Parse optional meta types annotation attributes
+     * @param annotation
+     */
+    private void parseMetaTypes(Annotation annotation, String pid, boolean factory)
+    {
+        if (annotation.get("metadata") != null)
+        {
+            String propertiesHeading = annotation.get("heading");
+            String propertiesDesc = annotation.get("description");
+
+            MetaType.OCD ocd = new MetaType.OCD(pid, propertiesHeading, propertiesDesc);
+            for (Object p : (Object[]) annotation.get("metadata"))
+            {
+                Annotation property = (Annotation) p;
+                String heading = property.get("heading");
+                String id = property.get("id");
+                String type = (String) property.get("type");
+                type = (type != null) ? parseClass(type, m_classPattern, 1) : null;
+                Object[] defaults = (Object[]) property.get("defaults");
+                String description = property.get("description");
+                Integer cardinality = property.get("cardinality");
+                Boolean required = property.get("required");
+
+                MetaType.AD ad = new MetaType.AD(id, type, defaults, heading, description,
+                    cardinality, required);
+                Object[] options = property.get("options");
+                if (options != null)
+                {
+                    for (Object o : (Object[]) property.get("options"))
+                    {
+                        Annotation option = (Annotation) o;
+                        ad.add(new MetaType.Option((String) option.get("name"),
+                            (String) option.get("value")));
+                    }
+                }
+                ocd.add(ad);
+            }
+
+            m_metaType.add(ocd);
+            MetaType.Designate designate = new MetaType.Designate(pid, factory);
+            m_metaType.add(designate);
+            m_reporter.warning("Parsed MetaType Properties from class " + m_className);
+        }          
+    }
+
+    /**
      * Parses a Param annotation (which represents a list of key-value pari).
      * @param annotation the annotation where the Param annotation is defined
      * @param attribute the attribute name which is of Param type
@@ -915,7 +969,7 @@ public class AnnotationCollector extends
 
         // We must have at least a Service or an AspectService annotation.
         checkServiceDeclared(EntryTypes.Service, EntryTypes.AspectService, EntryTypes.AdapterService, EntryTypes.BundleAdapterService,
-            EntryTypes.ResourceAdapterService);
+            EntryTypes.ResourceAdapterService, EntryTypes.FactoryConfigurationAdapterService);
 
         StringBuilder sb = new StringBuilder();
         sb.append("Parsed annotation for class ");

Modified: felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/MetaType.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/MetaType.java?rev=939089&r1=939088&r2=939089&view=diff
==============================================================================
--- felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/MetaType.java (original)
+++ felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/MetaType.java Wed Apr 28 21:03:47 2010
@@ -278,11 +278,13 @@ public class MetaType
     public static class Designate
     {
         String m_pid;
+        boolean m_factory;
         OBject m_object;
 
-        public Designate(String pid)
+        public Designate(String pid, boolean factory)
         {
             this.m_pid = pid;
+            this.m_factory = factory;
             this.m_object = new OBject(pid);
         }
 
@@ -290,6 +292,10 @@ public class MetaType
         {
             pw.print("   <Designate");
             writeAttribute("pid", m_pid, pw);
+            if (m_factory) 
+            {
+                writeAttribute("factoryPid", m_pid, pw);
+            }
             pw.println(">");
             m_object.writeTo(pw);
             pw.println("   </Designate>");

Modified: felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ComponentManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ComponentManager.java?rev=939089&r1=939088&r2=939089&view=diff
==============================================================================
--- felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ComponentManager.java (original)
+++ felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/ComponentManager.java Wed Apr 28 21:03:47 2010
@@ -168,6 +168,10 @@ public class ComponentManager implements
                     case ResourceAdapterService:
                         service = createResourceAdapterService(b, dm, parser);
                         break;
+                        
+                    case FactoryConfigurationAdapterService:
+                        service = createFactoryConfigurationAdapterService(b, dm, parser);
+                        break;
 
                     case ServiceDependency:
                         checkServiceParsed(service);
@@ -416,6 +420,28 @@ public class ComponentManager implements
     }
 
     /**
+     * Creates a Factory Configuration Adapter Service
+     * @param b
+     * @param dm
+     * @param parser
+     * @return
+     */
+    private Service createFactoryConfigurationAdapterService(Bundle b, DependencyManager dm, DescriptorParser parser)
+        throws ClassNotFoundException
+    {
+        Class<?> impl = b.loadClass(parser.getString(DescriptorParam.impl));
+        String factoryPid = parser.getString(DescriptorParam.factoryPid);
+        String updated = parser.getString(DescriptorParam.updated);
+        String[] services = parser.getStrings(DescriptorParam.service, null);
+        Dictionary<String, String> properties = parser.getDictionary(DescriptorParam.properties, null);
+        boolean propagate = "true".equals(parser.getString(DescriptorParam.propagate, "false"));
+        Service srv = dm.createFactoryConfigurationAdapterService(factoryPid, updated, impl, services, properties, propagate);
+        setCommonServiceParams(srv, parser);
+        return srv;
+    }
+
+
+    /**
      * Creates a ServiceDependency that we parsed from a component descriptor "ServiceDependency" entry.
      * @param b
      * @param dm

Modified: felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorEntry.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorEntry.java?rev=939089&r1=939088&r2=939089&view=diff
==============================================================================
--- felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorEntry.java (original)
+++ felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorEntry.java Wed Apr 28 21:03:47 2010
@@ -29,6 +29,7 @@ public enum DescriptorEntry
     AdapterService,
     BundleAdapterService,
     ResourceAdapterService,
+    FactoryConfigurationAdapterService,
     ServiceDependency,
     TemporalServiceDependency,
     ConfigurationDependency,

Modified: felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParam.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParam.java?rev=939089&r1=939088&r2=939089&view=diff
==============================================================================
--- felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParam.java (original)
+++ felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/DescriptorParam.java Wed Apr 28 21:03:47 2010
@@ -108,7 +108,10 @@ public enum DescriptorParam
     stateMask,
     
     /* The ranking of an aspect (the parsed value is an int) */
-    ranking;
+    ranking,
+    
+    /* The factory pid of an FactoryConfigurationAdapterService annotation (the parsed value is a string) */
+    factoryPid;
     
     /**
      * Indicates if a given attribute is a Service attribute.

Added: felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceClient.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceClient.java?rev=939089&view=auto
==============================================================================
--- felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceClient.java (added)
+++ felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceClient.java Wed Apr 28 21:03:47 2010
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.test.bundle.annotation.factoryconfadapter;
+
+import java.util.Map;
+
+import org.apache.felix.dm.annotation.api.Service;
+import org.apache.felix.dm.annotation.api.ServiceDependency;
+
+@Service
+public class ServiceClient
+{
+    @ServiceDependency(changed="changeServiceProvider")
+    void addServiceProvider(ServiceInterface si) {
+        si.doService();
+    }
+    
+    void changeServiceProvider(Map serviceProperties, ServiceInterface si) 
+    {
+        si.doService();
+    }
+}

Added: felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceInterface.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceInterface.java?rev=939089&view=auto
==============================================================================
--- felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceInterface.java (added)
+++ felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceInterface.java Wed Apr 28 21:03:47 2010
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.test.bundle.annotation.factoryconfadapter;
+
+public interface ServiceInterface
+{
+    public void doService();
+}

Added: felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceProvider.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceProvider.java?rev=939089&view=auto
==============================================================================
--- felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceProvider.java (added)
+++ felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/factoryconfadapter/ServiceProvider.java Wed Apr 28 21:03:47 2010
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.dm.test.bundle.annotation.factoryconfadapter;
+
+import java.util.Dictionary;
+
+import org.apache.felix.dm.annotation.api.FactoryConfigurationAdapterService;
+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.test.bundle.annotation.sequencer.Sequencer;
+
+/**
+ * This service is instantiated when a factory configuration is created from ConfigAdmin
+ */
+@FactoryConfigurationAdapterService(factoryPid = "FactoryPidTest", properties = { @Property(name = "foo", value = "bar") }, propagate = true)
+public class ServiceProvider implements ServiceInterface
+{
+    @ServiceDependency
+    private Sequencer m_sequencer;
+    
+    private volatile boolean m_started;
+
+    // Either initial config, or an updated config
+    protected void updated(Dictionary conf)
+    {
+        if (m_started)
+        {
+            m_sequencer.step(3);
+        }
+    }
+
+    @Start
+    void start()
+    {
+        m_started = true;
+        m_sequencer.step(1);
+    }    
+
+    // The ServiceClient is invoking our service
+    public void doService()
+    {
+       m_sequencer.step();
+    }
+
+    @Stop
+    void stop() 
+    {
+        m_sequencer.step(5);
+    }
+}

Modified: felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/sequencer/Sequencer.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/sequencer/Sequencer.java?rev=939089&r1=939088&r2=939089&view=diff
==============================================================================
--- felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/sequencer/Sequencer.java (original)
+++ felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/sequencer/Sequencer.java Wed Apr 28 21:03:47 2010
@@ -24,6 +24,11 @@ package org.apache.felix.dm.test.bundle.
 public interface Sequencer
 {
     /**
+     * Proceed with the next step.
+     */
+    void step();
+    
+    /**
      * Crosses a given step.
      * @param step the step we are crossing
      */

Modified: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/AnnotationBase.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/AnnotationBase.java?rev=939089&r1=939088&r2=939089&view=diff
==============================================================================
--- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/AnnotationBase.java (original)
+++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/AnnotationBase.java Wed Apr 28 21:03:47 2010
@@ -85,6 +85,14 @@ public class AnnotationBase extends Base
     // ----------------------- Sequencer interface ------------------------------------------
 
     /**
+     * Goes to the next step.
+     */
+    public void step()
+    {
+        m_ensure.step();
+    }
+    
+    /**
      * Crosses a given step number.
      */
     public void step(int step)

Added: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/FactoryConfigurationAdapterAnnotationTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/FactoryConfigurationAdapterAnnotationTest.java?rev=939089&view=auto
==============================================================================
--- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/FactoryConfigurationAdapterAnnotationTest.java (added)
+++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/FactoryConfigurationAdapterAnnotationTest.java Wed Apr 28 21:03:47 2010
@@ -0,0 +1,103 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+package org.apache.felix.dm.test.annotation;
+
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.options;
+import static org.ops4j.pax.exam.CoreOptions.provision;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import junit.framework.Assert;
+
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.dm.test.BundleGenerator;
+import org.apache.felix.dm.test.bundle.annotation.sequencer.Sequencer;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.Configuration;
+import org.ops4j.pax.exam.junit.JUnit4TestRunner;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * Use case: Verify that an annotated Configuration Factory Adapter Service is properly created when a factory configuration
+ * is created from Config Admin.
+ */
+@RunWith(JUnit4TestRunner.class)
+public class FactoryConfigurationAdapterAnnotationTest extends AnnotationBase
+{
+    @Configuration
+    public static Option[] configuration()
+    {
+        return options(
+            systemProperty("dm.log").value( "true" ),
+            provision(
+                mavenBundle().groupId("org.osgi").artifactId("org.osgi.compendium").version("4.1.0"),
+                mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.configadmin").version("1.2.4"),
+                mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.dependencymanager").versionAsInProject(),
+                mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.dependencymanager.runtime").versionAsInProject()),
+            provision(
+                new BundleGenerator()
+                    .set(Constants.BUNDLE_SYMBOLICNAME, "FactoryConfigurationAdapterTest")
+                    .set("Export-Package", "org.apache.felix.dm.test.bundle.annotation.sequencer")
+                    .set("Private-Package", "org.apache.felix.dm.test.bundle.annotation.factoryconfadapter")
+                    .set("Import-Package", "*")
+                    .set("-plugin", "org.apache.felix.dm.annotation.plugin.bnd.AnnotationPlugin")
+                    .build()));           
+    }
+
+    @Test
+    public void testFactoryConfigurationAdapterAnnotation(BundleContext context)
+    {
+        DependencyManager m = new DependencyManager(context);
+        // Provide the Sequencer to the adapter bundle service (see main/src/.../factoryconfadapter/*.java). 
+        m.add(m.createService().setImplementation(this).setInterface(Sequencer.class.getName(), null));
+        ConfigurationAdmin cm = (ConfigurationAdmin) context.getService(context.getServiceReference(ConfigurationAdmin.class.getName()));
+        try
+        {
+            // Create a factory configuration in order to instantiate the ServiceProvider
+            org.osgi.service.cm.Configuration cf = cm.createFactoryConfiguration("FactoryPidTest", null);
+            cf.update(new Hashtable() {{ put("foo", "bar"); }});
+            // Wait for the ServiceProvider activation.
+            m_ensure.waitForStep(2, 10000);
+            // Avoid bug in CM, which may miss some updates
+            sleep(1); 
+            // Update conf
+            cf.update(new Hashtable() {{ put("foo", "bar2"); }});            
+            // Wait for effective update
+            m_ensure.waitForStep(4, 10000);
+            // Avoid bug in CM, which may miss some updates
+            sleep(1);
+            // Remove configuration.
+            cf.delete();
+            // Check if ServiceProvider has been stopped.
+            m_ensure.waitForStep(5, 1000);
+        }
+        catch (IOException e)
+        {
+            e.printStackTrace();
+            Assert.fail("can't create factory configuration");
+        }
+    }
+}