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);
     }
 }


Reply via email to