Fix FELIX-2624 Support multiple whiteboards using annotations

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1032253 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/annotations/src/main/java/org/apache/felix/ipojo/whiteboard/Whiteboards.java b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/whiteboard/Whiteboards.java
new file mode 100644
index 0000000..d00f1b5
--- /dev/null
+++ b/ipojo/annotations/src/main/java/org/apache/felix/ipojo/whiteboard/Whiteboards.java
@@ -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.ipojo.whiteboard;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Whiteboard pattern Handler annotation.
+ * Allows configuring several whiteboard patterns.
+ * Be aware that despite is it provided in the annotations jar,
+ * it refers to an external handler.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Target(ElementType.TYPE)
+public @interface Whiteboards {
+
+    /**
+     * Whiteboards list.
+     */
+    Wbp[] whiteboards() default {};
+}
diff --git a/ipojo/handler/whiteboard/metadata.xml b/ipojo/handler/whiteboard/metadata.xml
index d9c1c53..88eec46 100644
--- a/ipojo/handler/whiteboard/metadata.xml
+++ b/ipojo/handler/whiteboard/metadata.xml
@@ -6,9 +6,9 @@
 	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

@@ -21,4 +21,10 @@
 		classname="org.apache.felix.ipojo.handler.wbp.WhiteBoardPatternHandler"

 		name="wbp" namespace="org.apache.felix.ipojo.whiteboard">

 	</handler>

+

+	<!-- Alternative handler for component using the @Whiteboards annotation -->

+	<handler

+		classname="org.apache.felix.ipojo.handler.wbp.WhiteBoardPatternHandler"

+		name="whiteboards" namespace="org.apache.felix.ipojo.whiteboard">

+	</handler>

 </ipojo>
\ No newline at end of file
diff --git a/ipojo/handler/whiteboard/src/main/java/org/apache/felix/ipojo/handler/wbp/WhiteBoardPatternHandler.java b/ipojo/handler/whiteboard/src/main/java/org/apache/felix/ipojo/handler/wbp/WhiteBoardPatternHandler.java
index 778eae7..70a880e 100644
--- a/ipojo/handler/whiteboard/src/main/java/org/apache/felix/ipojo/handler/wbp/WhiteBoardPatternHandler.java
+++ b/ipojo/handler/whiteboard/src/main/java/org/apache/felix/ipojo/handler/wbp/WhiteBoardPatternHandler.java
@@ -53,7 +53,27 @@
      * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
      */
     public void configure(Element elem, Dictionary dict) throws ConfigurationException {
+
+    	// There is two way to configure the handler :
+    	// - the wbp elements
+    	// - the whiteboards elements
         Element[] elems = elem.getElements("wbp", NAMESPACE);
+
+        if (elems == null  || elems.length == 0) {
+        	// Alternative way
+        	Element[] whiteboards = elem.getElements("whiteboards", NAMESPACE);
+        	if (whiteboards == null) {
+        		throw new ConfigurationException("Cannot configure the whiteboard pattern handler - no suitable configuration found");
+        	} else {
+        		elems = whiteboards[0].getElements("wbp", NAMESPACE);
+        	}
+        }
+
+        // Last check.
+        if (elems == null) {
+        	throw new ConfigurationException("Cannot configure the whiteboard pattern handler - no suitable configuration found");
+        }
+
         for (int i = 0; i < elems.length; i++) {
             String filter = elems[i].getAttribute("filter");
             String onArrival = elems[i].getAttribute("onArrival");
diff --git a/ipojo/tests/core/annotations/src/main/java/org/apache/felix/ipojo/test/scenarios/annotations/WhiteBoard.java b/ipojo/tests/core/annotations/src/main/java/org/apache/felix/ipojo/test/scenarios/annotations/WhiteBoard.java
index b2e38d0..418364f 100644
--- a/ipojo/tests/core/annotations/src/main/java/org/apache/felix/ipojo/test/scenarios/annotations/WhiteBoard.java
+++ b/ipojo/tests/core/annotations/src/main/java/org/apache/felix/ipojo/test/scenarios/annotations/WhiteBoard.java
@@ -5,17 +5,18 @@
 import org.apache.felix.ipojo.metadata.Element;
 
 public class WhiteBoard extends OSGiTestCase {
-    
+
     String typeWI = "org.apache.felix.ipojo.test.scenarios.component.whiteboard.WhiteBoardWIModification";
     String typeWO = "org.apache.felix.ipojo.test.scenarios.component.whiteboard.WhiteBoardWOModification";
+    String typeWhiteboards = "org.apache.felix.ipojo.test.scenarios.component.whiteboard.WhiteBoards";
     String namespace = "org.apache.felix.ipojo.whiteboard";
-    
+
     private IPOJOHelper helper;
-    
+
     public void setUp() {
         helper = new IPOJOHelper(this);
     }
-    
+
     public void testMetadataWithOnModification() {
         Element meta = helper.getMetadata(typeWI);
         assertNotNull("Check meta", meta);
@@ -26,14 +27,14 @@
         String onDep = ext[0].getAttribute("onDeparture");
         String onMod = ext[0].getAttribute("onModification");
 
-        
+
         assertEquals("Check filter", "(foo=true)", filter);
         assertEquals("Check onArrival", "onArrival", onArr);
         assertEquals("Check onDeparture", "onDeparture", onDep);
         assertEquals("Check onModification", "onModification", onMod);
 
     }
-    
+
     public void testMetadataWithoutOnModification() {
         Element meta = helper.getMetadata(typeWO);
         assertNotNull("Check meta", meta);
@@ -44,7 +45,7 @@
         String onDep = ext[0].getAttribute("onDeparture");
         String onMod = ext[0].getAttribute("onModification");
 
-        
+
         assertEquals("Check filter", "(foo=true)", filter);
         assertEquals("Check onArrival", "onArrival", onArr);
         assertEquals("Check onDeparture", "onDeparture", onDep);
@@ -52,4 +53,36 @@
 
     }
 
+    public void testWhiteboards() {
+        Element meta = helper.getMetadata(typeWhiteboards);
+        assertNotNull("Check meta", meta);
+        Element[] ext = meta.getElements("whiteboards", namespace);
+        assertEquals("Check size", 1, ext.length);
+
+        // Two sub-element
+        Element[] wbps = ext[0].getElements("wbp", namespace);
+        assertEquals("Check size", 2, wbps.length);
+
+        String filter = wbps[0].getAttribute("filter");
+        String onArr = wbps[0].getAttribute("onArrival");
+        String onDep = wbps[0].getAttribute("onDeparture");
+        String onMod = wbps[0].getAttribute("onModification");
+
+        assertEquals("Check filter", "(foo=true)", filter);
+        assertEquals("Check onArrival", "onArrival", onArr);
+        assertEquals("Check onDeparture", "onDeparture", onDep);
+        assertNull("Check onModification", onMod);
+
+        filter = wbps[1].getAttribute("filter");
+        onArr = wbps[1].getAttribute("onArrival");
+        onDep = wbps[1].getAttribute("onDeparture");
+        onMod = wbps[1].getAttribute("onModification");
+
+        assertEquals("Check filter", "(foo=true)", filter);
+        assertEquals("Check onArrival", "onArrival", onArr);
+        assertEquals("Check onDeparture", "onDeparture", onDep);
+        assertEquals("Check onModification", "onModification", onMod);
+    }
+
+
 }
diff --git a/ipojo/tests/core/annotations/src/main/java/org/apache/felix/ipojo/test/scenarios/component/whiteboard/WhiteBoards.java b/ipojo/tests/core/annotations/src/main/java/org/apache/felix/ipojo/test/scenarios/component/whiteboard/WhiteBoards.java
new file mode 100644
index 0000000..540837f
--- /dev/null
+++ b/ipojo/tests/core/annotations/src/main/java/org/apache/felix/ipojo/test/scenarios/component/whiteboard/WhiteBoards.java
@@ -0,0 +1,27 @@
+package org.apache.felix.ipojo.test.scenarios.component.whiteboard;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.whiteboard.Whiteboards;
+import org.apache.felix.ipojo.whiteboard.Wbp;
+import org.osgi.framework.ServiceReference;
+
+@Component
+@Whiteboards(whiteboards={
+		@Wbp(filter="(foo=true)", onArrival="onArrival", onDeparture="onDeparture"),
+		@Wbp(filter="(foo=true)", onArrival="onArrival", onDeparture="onDeparture", onModification="onModification")
+	})
+public class WhiteBoards {
+
+    public void onArrival(ServiceReference ref) {
+        // nothing
+    }
+
+    public void onDeparture(ServiceReference ref) {
+        // nothing
+    }
+
+    public void onModification(ServiceReference ref) {
+        // nothing
+    }
+
+}
diff --git a/ipojo/tests/handler/whiteboard/pom.xml b/ipojo/tests/handler/whiteboard/pom.xml
index 1c56f54..88c7f35 100644
--- a/ipojo/tests/handler/whiteboard/pom.xml
+++ b/ipojo/tests/handler/whiteboard/pom.xml
@@ -86,8 +86,7 @@
    					<![CDATA[

    					<ipojo

     					xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

-						xsi:schemaLocation="org.apache.felix.ipojo http://felix.apache.org/ipojo/schemas/SNAPSHOT/core.xsd

-	 					org.apache.felix.ipojo.whiteboard http://felix.apache.org/ipojo/schemas/SNAPSHOT/whiteboard-pattern.xsd"

+						xsi:schemaLocation="org.apache.felix.ipojo http://felix.apache.org/ipojo/schemas/SNAPSHOT/core.xsd"

 						xmlns="org.apache.felix.ipojo"

 						xmlns:wbp="org.apache.felix.ipojo.whiteboard">

 						<component classname="org.apache.felix.ipojo.test.FooProvider" name="fooprovider">

@@ -111,6 +110,16 @@
 								<provides/>

 						</component>

 

+						<component classname="org.apache.felix.ipojo.test.FooWhiteBoardPattern" name="under-providers-2">

+								<wbp:whiteboards>

+									<wbp:wbp

+										filter="(objectclass=org.apache.felix.ipojo.test.FooService)"

+										onArrival="onArrival" onDeparture="onDeparture" onModification="onModification"

+									/>

+								</wbp:whiteboards>

+								<provides/>

+						</component>

+

 						<component classname="org.apache.felix.ipojo.test.FooWhiteBoardPattern" name="under-providers-lifecycle">

 								<wbp:wbp

 									filter="(objectclass=org.apache.felix.ipojo.test.FooService)"

diff --git a/ipojo/tests/handler/whiteboard/src/main/java/org/apache/felix/ipojo/test/WbpTests.java b/ipojo/tests/handler/whiteboard/src/main/java/org/apache/felix/ipojo/test/WbpTests.java
index e791e40..0206900 100644
--- a/ipojo/tests/handler/whiteboard/src/main/java/org/apache/felix/ipojo/test/WbpTests.java
+++ b/ipojo/tests/handler/whiteboard/src/main/java/org/apache/felix/ipojo/test/WbpTests.java
@@ -16,13 +16,14 @@
 public class WbpTests extends OSGiTestCase {

 

     Factory provFactory;

-    Factory factory, factory2, factory3;

+    Factory factory, factory2, factory3, factory4;

 

     public void setUp() {

         provFactory = Utils.getFactoryByName(context, "fooprovider");

         factory = Utils.getFactoryByName(context, "under-providers");

         factory2 = Utils.getFactoryByName(context, "under-properties");

         factory3 = Utils.getFactoryByName(context, "under-providers-lifecycle");

+        factory4 = Utils.getFactoryByName(context, "under-providers-2");

     }

 

     public void tearDown() {

@@ -219,4 +220,62 @@
         ci.dispose();

 

     }

+

+    public void testServiceProvidersWhiteWhiteboards() throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {

+        ComponentInstance ci = factory4.createComponentInstance(new Properties());

+

+        ServiceReference ref = Utils.getServiceReferenceByName(context, Observable.class.getName(), ci.getInstanceName());

+        assertNotNull("Check Observable availability", ref);

+        Observable obs = (Observable) context.getService(ref);

+

+        Map map = obs.getObservations();

+        assertEquals("Check empty list" , ((List) map.get("list")).size(), 0);

+

+        Properties p1 = new Properties();

+        p1.put("foo", "foo");

+        ComponentInstance prov1 = provFactory.createComponentInstance(p1);

+

+        map = obs.getObservations();

+        assertEquals("Check list #1" , ((List) map.get("list")).size(), 1);

+

+        Properties p2 = new Properties();

+        p2.put("foo", "foo");

+        ComponentInstance prov2 = provFactory.createComponentInstance(p2);

+

+        map = obs.getObservations();

+        assertEquals("Check list #2" , ((List) map.get("list")).size(), 2);

+

+        prov1.stop();

+

+        map = obs.getObservations();

+        assertEquals("(1) Check list #1" , ((List) map.get("list")).size(), 1);

+

+        prov2.stop();

+

+        map = obs.getObservations();

+        assertEquals("(2) Check list #0" , ((List) map.get("list")).size(), 0);

+

+        prov2.start();

+

+        map = obs.getObservations();

+        assertEquals("(3) Check list #1" , ((List) map.get("list")).size(), 1);

+

+        prov1.start();

+

+        map = obs.getObservations();

+        assertEquals("(4) Check list #2" , ((List) map.get("list")).size(), 2);

+

+        prov1.dispose();

+

+        map = obs.getObservations();

+        assertEquals("(5) Check list #1" , ((List) map.get("list")).size(), 1);

+

+        prov2.dispose();

+

+        map = obs.getObservations();

+        assertEquals("(6) Check list #0" , ((List) map.get("list")).size(), 0);

+

+        context.ungetService(ref);

+        ci.dispose();

+    }

 }