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 2011/05/23 10:42:48 UTC

svn commit: r1126383 - in /felix/trunk/dependencymanager: annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/ runtime/src/main/java/org/apache/felix/dm/runtime/ test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/ te...

Author: pderop
Date: Mon May 23 08:42:48 2011
New Revision: 1126383

URL: http://svn.apache.org/viewvc?rev=1126383&view=rev
Log:
[FELIX-2965] - Apply @Registered/@Unregistered annotation on composition instances.


Added:
    felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C1.java
    felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C1Service.java
    felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C2.java
Removed:
    felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/Composite.java
    felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/CompositeService.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/EntryWriter.java
    felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AbstractBuilder.java
    felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/CompositeAnnotationsTest.java

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=1126383&r1=1126382&r2=1126383&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 Mon May 23 08:42:48 2011
@@ -335,8 +335,13 @@ public class AnnotationCollector extends
         // properties attribute
         parseProperties(annotation, EntryParam.properties, writer);
 
-        // provides attribute
-        writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService);
+        // provides attribute.
+        if (writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService) == 0)
+        {
+            // no service provided: check if @Registered/@Unregistered annotation are used
+            // and raise an error if true.
+            checkRegisteredUnregisteredNotPresent();
+        }
 
         // factorySet attribute
         String factorySetName = writer.putString(annotation, EntryParam.factorySet, null);
@@ -644,7 +649,10 @@ public class AnnotationCollector extends
         parseProperties(annotation, EntryParam.properties, writer);
 
         // Parse the provided adapter service (use directly implemented interface by default).
-        writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService);
+        if (writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService) == 0)
+        {
+            checkRegisteredUnregisteredNotPresent();
+        }
         
         // Parse factoryMethod attribute
         writer.putString(annotation, EntryParam.factoryMethod, null);
@@ -684,7 +692,10 @@ public class AnnotationCollector extends
         parseProperties(annotation, EntryParam.properties, writer);
 
         // Parse the optional adapter service (use directly implemented interface by default).
-        writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService);
+        if (writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService) == 0)
+        {
+            checkRegisteredUnregisteredNotPresent();
+        }
 
         // Parse propagate attribute
         writer.putString(annotation, EntryParam.propagate, Boolean.FALSE.toString());
@@ -720,7 +731,10 @@ public class AnnotationCollector extends
         parseProperties(annotation, EntryParam.properties, writer);
 
         // Parse the provided adapter service (use directly implemented interface by default).
-        writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService);
+        if (writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService) == 0)
+        {
+            checkRegisteredUnregisteredNotPresent();
+        }
 
         // Parse propagate attribute
         writer.putString(annotation, EntryParam.propagate, Boolean.FALSE.toString());
@@ -754,7 +768,10 @@ public class AnnotationCollector extends
         writer.putString(annotation, EntryParam.propagate, Boolean.FALSE.toString());
 
         // Parse the provided adapter service (use directly implemented interface by default).
-        writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService);
+        if (writer.putClassArray(annotation, EntryParam.provides, m_interfaces, m_exportService) == 0)
+        {
+            checkRegisteredUnregisteredNotPresent();
+        }
 
         // Parse Adapter properties.
         parseProperties(annotation, EntryParam.properties, writer);
@@ -1008,6 +1025,27 @@ public class AnnotationCollector extends
     }
 
     /**
+     * This method checks if the @Registered and/or @Unregistered annotations have been defined
+     * while they should not, because the component does not provide a service.
+     */
+    private void checkRegisteredUnregisteredNotPresent()
+    {
+        if (m_registeredMethod != null)
+        {
+            throw new IllegalStateException("@Registered annotation can't be used on a Component " +
+                                            " which does not provide a service (class=" + m_className + ")");
+
+        }
+        
+        if (m_unregisteredMethod != null)
+        {
+            throw new IllegalStateException("@Unregistered annotation can't be used on a Component " +
+                                            " which does not provide a service (class=" + m_className + ")");
+
+        }
+    }
+
+    /**
      * Get an annotation attribute, and return a default value if its not present.
      * @param <T> the type of the variable which is assigned to the return value of this method.
      * @param annotation The annotation we are parsing

Modified: felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java?rev=1126383&r1=1126382&r2=1126383&view=diff
==============================================================================
--- felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java (original)
+++ felix/trunk/dependencymanager/annotation/src/main/java/org/apache/felix/dm/annotation/plugin/bnd/EntryWriter.java Mon May 23 08:42:48 2011
@@ -221,8 +221,9 @@ public class EntryWriter
     /**
      * Get a class array attribute value from an annotation and write it into this descriptor entry.
      * Also collect classes found from the array into a given Set.
+     * @return the class array size.
      */
-    public void putClassArray(Annotation annotation, EntryParam param, Object def, Set<String> collect)
+    public int putClassArray(Annotation annotation, EntryParam param, Object def, Set<String> collect)
     {
         checkType(param.toString());
 
@@ -258,7 +259,11 @@ public class EntryWriter
                             + value.toString(), e);
                 }
             }
+            
+            return ((Object[]) value).length;
         }
+        
+        return 0;
     }
 
     /**

Modified: felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AbstractBuilder.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AbstractBuilder.java?rev=1126383&r1=1126382&r2=1126383&view=diff
==============================================================================
--- felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AbstractBuilder.java (original)
+++ felix/trunk/dependencymanager/runtime/src/main/java/org/apache/felix/dm/runtime/AbstractBuilder.java Mon May 23 08:42:48 2011
@@ -144,18 +144,23 @@ public abstract class AbstractBuilder
         {
             if (m_registered != null)
             {
-                Object instance = c.getService();
-                try
-                {
-                    InvocationUtil
-                        .invokeCallbackMethod(instance,
-                                              m_registered, 
-                                              new Class[][]  {{ ServiceRegistration.class },  {}},
-                                              new Object[][] {{ c.getServiceRegistration() }, {}});
-                }
-                catch (Throwable t)
+                // The component has registered a service: notify all component instances
+                Object[] componentInstances = c.getCompositionInstances();
+                for (Object instance : componentInstances)
                 {
-                    Log.instance().error("Exception caught while invoking method %s on component %s", t, m_registered, instance);
+                    try
+                    {
+                        Class[][] signatures = new Class[][] { { ServiceRegistration.class }, {} };
+                        Object[][] params = new Object[][] { { c.getServiceRegistration() }, {} };
+                        InvocationUtil.invokeCallbackMethod(instance, m_registered, signatures, params);
+                    }
+                    catch (Throwable t)
+                    {
+                        Log.instance().error("Exception caught while invoking method %s on component %s",
+                                             t,
+                                             m_registered,
+                                             instance);
+                    }
                 }
             }
         }

Added: felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C1.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C1.java?rev=1126383&view=auto
==============================================================================
--- felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C1.java (added)
+++ felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C1.java Mon May 23 08:42:48 2011
@@ -0,0 +1,108 @@
+/*
+ * 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.composite;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.felix.dm.annotation.api.Component;
+import org.apache.felix.dm.annotation.api.Composition;
+import org.apache.felix.dm.annotation.api.Destroy;
+import org.apache.felix.dm.annotation.api.Init;
+import org.apache.felix.dm.annotation.api.Registered;
+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;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * This service is also composed of the Component object.
+ */
+@Component
+public class C1 implements C1Service
+{
+    /* We are composed of this object, which will also be injected with our dependencies */
+    private C2 m_c2 = new C2();
+
+    /* This dependency filter will be configured from our init method */
+    @ServiceDependency(name = "D")
+    public volatile Runnable m_runnable;
+    
+    /* Object used to check that methods are called in the proper sequence */
+    @ServiceDependency(filter="(name=C1)")
+    private volatile Sequencer m_sequencer;
+
+    /**
+     *  Dynamically configure our "D" dependency, using a dependency customization map 
+     */
+    @Init
+    Map<String, String> init()
+    {
+        m_sequencer.step(1);
+        // Configure a filter for our dependency whose name is "D"
+        Map<String, String> customization = new HashMap<String, String>();
+        customization.put("D.filter", "(foo=bar2)");
+        customization.put("D.required", "true");
+        return customization;
+    }
+
+    /**
+     * Return the list of object our service is composed of
+     */
+    @Composition
+    Object[] getComposition()
+    {
+        return new Object[] { this, m_c2 };
+    }
+
+    /** 
+     * Our Service is starting, and our Composites will also be 
+     */
+    @Start
+    void start()
+    {
+        System.out.println("start: m_runnable=" + m_runnable);
+        m_sequencer.step(3);
+        m_runnable.run(); /* step 4 */
+        // Our Component.start() method should be called once this method returns.
+    }
+
+    /**
+     * Our provided service has been registered into the OSGi service registry.
+     */
+    @Registered
+    void registered(ServiceRegistration sr)
+    {
+        m_sequencer.step(7);
+    }
+    
+    /**
+     *  Our Service is stopping, and our Composites will also be 
+     */
+    @Stop
+    void stop()
+    {
+        m_sequencer.step(9);
+        // Our Component.stop() method should be called once this method returns.
+    }
+
+    /**
+     * Our Service is destroying, and our Composites will also be.
+     */
+    @Destroy
+    void destroy()
+    {
+        m_sequencer.step(11);
+        // Our Component.destroy() method should be called once this method returns.
+    }
+}

Added: felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C1Service.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C1Service.java?rev=1126383&view=auto
==============================================================================
--- felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C1Service.java (added)
+++ felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C1Service.java Mon May 23 08:42:48 2011
@@ -0,0 +1,5 @@
+package org.apache.felix.dm.test.bundle.annotation.composite;
+
+public interface C1Service
+{
+}

Added: felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C2.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C2.java?rev=1126383&view=auto
==============================================================================
--- felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C2.java (added)
+++ felix/trunk/dependencymanager/test/src/main/java/org/apache/felix/dm/test/bundle/annotation/composite/C2.java Mon May 23 08:42:48 2011
@@ -0,0 +1,61 @@
+/*
+ * 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.composite;
+
+import org.apache.felix.dm.test.bundle.annotation.sequencer.Sequencer;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * The CompositeService is also made up of this Class.
+ */
+public class C2
+{
+    // Injected dependency (from CompositeService)
+    private volatile Sequencer m_sequencer;
+
+    // Injected dependency (from CompositeService)
+    public volatile Runnable m_runnable;
+    
+    // lifecycle callback (same method as the one from CompositeService)
+    void init()
+    {
+        m_sequencer.step(2);
+    }
+
+    // lifecycle callback (same method as the one from CompositeService)
+    void start()
+    {
+        m_sequencer.step(5);
+        m_runnable.run(); /* step 6 */
+    }
+
+    void registered(ServiceRegistration sr)
+    {
+        if (sr == null)
+        {
+            m_sequencer.throwable(new Exception("null service registration"));
+        }
+        m_sequencer.step(8);
+    }
+
+    // lifecycle callback (same method as the one from CompositeService)
+    void stop()
+    {
+        m_sequencer.step(10);
+    }
+
+    // lifecycle callback (same method as the one from CompositeService)
+    void destroy()
+    {
+        m_sequencer.step(12);
+    }
+}

Modified: felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/CompositeAnnotationsTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/CompositeAnnotationsTest.java?rev=1126383&r1=1126382&r2=1126383&view=diff
==============================================================================
--- felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/CompositeAnnotationsTest.java (original)
+++ felix/trunk/dependencymanager/test/src/test/java/org/apache/felix/dm/test/annotation/CompositeAnnotationsTest.java Mon May 23 08:42:48 2011
@@ -64,7 +64,7 @@ public class CompositeAnnotationsTest ex
     {
         DependencyManager m = new DependencyManager(context);
         // Provide the Sequencer service to the "Component" service.
-        m.add(makeSequencer(m, "CompositeService"));
+        m.add(makeSequencer(m, "C1"));
         m.add(makeSequencer(m, "Dependency1"));
         m.add(makeSequencer(m, "Dependency2"));
         // Check if the components have been initialized orderly
@@ -72,6 +72,6 @@ public class CompositeAnnotationsTest ex
         // Stop the bundle
         stopBundle("CompositeAnnotationsTest", context);
         // And check if the components lifecycle callbacks are called orderly
-        m_ensure.waitForStep(10, 10000);
+        m_ensure.waitForStep(12, 10000);
     }
 }