The iPOJO API now supports external handlers. To use them, the handler provider has to implements HandlerConfiguration that returns the Element-Attribute structure representing the handler configuration.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@766037 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/ComponentType.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/ComponentType.java
index b45d0b4..ef4cd06 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/ComponentType.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/ComponentType.java
@@ -43,6 +43,7 @@
* current component type.
*/
private List m_instances = new ArrayList();
+
/**
* Gets the factory attached to the current
@@ -64,7 +65,7 @@
* component type.
*/
public abstract void stop();
-
+
/**
* Creates a component instance from the current type
@@ -189,9 +190,6 @@
}
}
}
-
-
-
}
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Dependency.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Dependency.java
index a2dbe29..ba04f09 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Dependency.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Dependency.java
@@ -28,7 +28,7 @@
* Allows configuring a service dependencies.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class Dependency {
+public class Dependency implements HandlerConfiguration {
/**
* The dynamic binding policy.
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/HandlerConfiguration.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/HandlerConfiguration.java
new file mode 100644
index 0000000..6e0958c
--- /dev/null
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/HandlerConfiguration.java
@@ -0,0 +1,36 @@
+/*
+ * 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.api;
+
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Common interfaces for all contributions.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface HandlerConfiguration {
+
+ /**
+ * Gets the Handler description.
+ * @return the Element-Attribute structure containing the handler
+ * configuration.
+ */
+ public Element getElement();
+
+}
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java
index 09d1a93..93bdb54 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java
@@ -125,6 +125,12 @@
private ArrayList m_temporals = new ArrayList();
/**
+ * List of Handler representing external
+ * handler configuration
+ */
+ private List m_handlers = new ArrayList();
+
+ /**
* Checks that the component type is not already
* started.
*/
@@ -356,9 +362,28 @@
element.addElement(properties);
}
+ // External handlers
+ for (int i = 0; i < m_handlers.size(); i++) {
+ HandlerConfiguration hc = (HandlerConfiguration) m_handlers.get(i);
+ element.addElement(hc.getElement());
+ }
+
return element;
}
+
+ /**
+ * Adds an HandlerConfiguration to the component type. Each component type
+ * implementation must uses the populated list (m_handlers) when generating
+ * the component metadata.
+ * @param handler the handler configuration to add
+ * @return the current component type
+ */
+ public PrimitiveComponentType addHandler(HandlerConfiguration handler) {
+ m_handlers.add(handler);
+ return this;
+ }
+
/**
* Creates the component factory.
*/
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Service.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Service.java
index b70057f..3ce062e 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Service.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Service.java
@@ -33,7 +33,7 @@
* Allows configuring a provided service.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class Service {
+public class Service implements HandlerConfiguration {
/**
* Creation strategy : singleton (default).
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/TemporalDependency.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/TemporalDependency.java
index 4f89295..713bf0a 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/TemporalDependency.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/TemporalDependency.java
@@ -25,7 +25,7 @@
* Allows configuring a service dependencies.
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
-public class TemporalDependency {
+public class TemporalDependency implements HandlerConfiguration {
/**
* OnTimeout policy: nullable object.
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/CompositeComponentType.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/CompositeComponentType.java
index 7186f26..3da590e 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/CompositeComponentType.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/CompositeComponentType.java
@@ -25,6 +25,7 @@
import org.apache.felix.ipojo.ConfigurationException;
import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.api.ComponentType;
+import org.apache.felix.ipojo.api.HandlerConfiguration;
import org.apache.felix.ipojo.composite.CompositeFactory;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
@@ -82,7 +83,16 @@
*/
private boolean m_public = true;
+ /**
+ * Component type name.
+ */
private String m_name;
+
+ /**
+ * List of Handler representing external
+ * handler configuration
+ */
+ private List m_handlers = new ArrayList();
/**
* Checks that the component type is not already
@@ -199,6 +209,17 @@
}
/**
+ * Adds an HandlerConfiguration to the component type. Each component type
+ * implementation must uses the populated list (m_handlers) when generating
+ * the component metadata.
+ * @param handler the handler configuration to add
+ * @return the current component type.
+ */
+ public void CompositeComponentType(HandlerConfiguration handler) {
+ m_handlers.add(handler);
+ }
+
+ /**
* Generates the component description.
* @return the component type description of
* the current component type
@@ -231,6 +252,13 @@
ProvidedService inst = (ProvidedService) m_provided.get(i);
element.addElement(inst.getElement());
}
+
+ // External handlers
+ for (int i = 0; i < m_handlers.size(); i++) {
+ HandlerConfiguration hc = (HandlerConfiguration) m_handlers.get(i);
+ element.addElement(hc.getElement());
+ }
+
return element;
}
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ExportedService.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ExportedService.java
index 981fae8..c7cb423 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ExportedService.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ExportedService.java
@@ -18,11 +18,12 @@
*/
package org.apache.felix.ipojo.api.composite;
+import org.apache.felix.ipojo.api.HandlerConfiguration;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.util.DependencyModel;
-public class ExportedService {
+public class ExportedService implements HandlerConfiguration {
/**
* The required specification.
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ImportedService.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ImportedService.java
index be91287..d7aff45 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ImportedService.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ImportedService.java
@@ -18,11 +18,12 @@
*/
package org.apache.felix.ipojo.api.composite;
+import org.apache.felix.ipojo.api.HandlerConfiguration;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.util.DependencyModel;
-public class ImportedService {
+public class ImportedService implements HandlerConfiguration {
public static final String COMPOSITE_SCOPE = "composite";
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/Instance.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/Instance.java
index 68d0dd6..ae66997 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/Instance.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/Instance.java
@@ -28,10 +28,11 @@
import java.util.Vector;
import java.util.Map.Entry;
+import org.apache.felix.ipojo.api.HandlerConfiguration;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
-public class Instance {
+public class Instance implements HandlerConfiguration {
private String m_type;
private List m_conf = new ArrayList();
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/InstantiatedService.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/InstantiatedService.java
index 5751cd9..b53c636 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/InstantiatedService.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/InstantiatedService.java
@@ -28,11 +28,12 @@
import java.util.Vector;
import java.util.Map.Entry;
+import org.apache.felix.ipojo.api.HandlerConfiguration;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.util.DependencyModel;
-public class InstantiatedService {
+public class InstantiatedService implements HandlerConfiguration {
/**
* The required specification.
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ProvidedService.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ProvidedService.java
index 1b2bd0c..136419e 100644
--- a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ProvidedService.java
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/composite/ProvidedService.java
@@ -21,10 +21,11 @@
import java.util.ArrayList;
import java.util.List;
+import org.apache.felix.ipojo.api.HandlerConfiguration;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;
-public class ProvidedService {
+public class ProvidedService implements HandlerConfiguration {
public static final String ALL_POLICY = "all";
public static final String ONE_POLICY = "one";
diff --git a/ipojo/tests/api/pom.xml b/ipojo/tests/api/pom.xml
index 4d8faed..2417d4e 100644
--- a/ipojo/tests/api/pom.xml
+++ b/ipojo/tests/api/pom.xml
@@ -72,6 +72,12 @@
<version>1.3.0-SNAPSHOT</version>
</dependency>
+ <!-- For external handlermanagement -->
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.handler.whiteboard</artifactId>
+ <version>1.3.0-SNAPSHOT</version>
+ </dependency>
<!--
Pax Exam API:
@@ -108,7 +114,7 @@
<version>4.5</version>
<type>jar</type>
<scope>test</scope>
- </dependency>
+ </dependency>
</dependencies>
<repositories>
diff --git a/ipojo/tests/api/src/test/java/org/apache/felix/ipojo/tests/api/ExternalHandlerTest.java b/ipojo/tests/api/src/test/java/org/apache/felix/ipojo/tests/api/ExternalHandlerTest.java
new file mode 100644
index 0000000..59f4e0d
--- /dev/null
+++ b/ipojo/tests/api/src/test/java/org/apache/felix/ipojo/tests/api/ExternalHandlerTest.java
@@ -0,0 +1,107 @@
+package org.apache.felix.ipojo.tests.api;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+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.MavenUtils.asInProject;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.api.PrimitiveComponentType;
+import org.apache.felix.ipojo.architecture.HandlerDescription;
+import org.example.service.impl.HostImpl;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Inject;
+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;
+
+
+
+@RunWith( JUnit4TestRunner.class )
+public class ExternalHandlerTest {
+
+ @Inject
+ private BundleContext context;
+
+ private OSGiHelper osgi;
+
+ private IPOJOHelper ipojo;
+
+ @Before
+ public void init() {
+ osgi = new OSGiHelper(context);
+ ipojo = new IPOJOHelper(context);
+ }
+
+ @After
+ public void stop() {
+ ipojo.dispose();
+ osgi.dispose();
+ }
+
+ @Configuration
+ public static Option[] configure() {
+ Option[] opt = options(
+ provision(
+ mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.ipojo").version(asInProject()),
+ mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.ipojo.api").version(asInProject()),
+ mavenBundle().groupId("org.apache.felix").artifactId("org.apache.felix.ipojo.handler.whiteboard").version(asInProject())
+ )
+ );
+ return opt;
+ }
+
+ @Test
+ public void createAHost() throws Exception {
+ PrimitiveComponentType type = createAWhiteboardHost();
+ ComponentInstance ci = type.createInstance();
+ assertThat (ci.getState(), is (ComponentInstance.VALID));
+ HandlerDescription hd = ci.getInstanceDescription().getHandlerDescription(Whiteboard.NAMESPACE + ":" + Whiteboard.NAME);
+ assertThat (hd, is (notNullValue()));
+ }
+
+ @Test
+ public void createDoubleHost() throws Exception {
+ PrimitiveComponentType type = createASecondWhiteboardHost();
+ ComponentInstance ci = type.createInstance();
+ assertThat (ci.getState(), is (ComponentInstance.VALID));
+ HandlerDescription hd = ci.getInstanceDescription().getHandlerDescription(Whiteboard.NAMESPACE + ":" + Whiteboard.NAME);
+ assertThat (hd, is (notNullValue()));
+ }
+
+ private PrimitiveComponentType createAWhiteboardHost() {
+ return new PrimitiveComponentType()
+ .setBundleContext(context)
+ .setClassName(HostImpl.class.getName())
+ .addHandler(new Whiteboard()
+ .onArrival("arrival")
+ .onDeparture("departure")
+ .setFilter("(foo=foo)")
+ );
+ }
+
+ private PrimitiveComponentType createASecondWhiteboardHost() {
+ return new PrimitiveComponentType()
+ .setBundleContext(context)
+ .setClassName(HostImpl.class.getName())
+ .addHandler(new Whiteboard()
+ .onArrival("arrival")
+ .onDeparture("departure")
+ .setFilter("(foo=foo)")
+ )
+ .addHandler(new Whiteboard()
+ .onArrival("arrival")
+ .onDeparture("departure")
+ .setFilter("(foo=bar)")
+ .onModification("modification")
+ );
+ }
+
+}
diff --git a/ipojo/tests/api/src/test/java/org/apache/felix/ipojo/tests/api/Whiteboard.java b/ipojo/tests/api/src/test/java/org/apache/felix/ipojo/tests/api/Whiteboard.java
new file mode 100644
index 0000000..17bce48
--- /dev/null
+++ b/ipojo/tests/api/src/test/java/org/apache/felix/ipojo/tests/api/Whiteboard.java
@@ -0,0 +1,71 @@
+package org.apache.felix.ipojo.tests.api;
+
+import org.apache.felix.ipojo.api.HandlerConfiguration;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+
+public class Whiteboard implements HandlerConfiguration {
+
+ public static final String NAME = "wbp";
+
+ public static final String NAMESPACE = "org.apache.felix.ipojo.whiteboard";
+
+ private String arrival;
+
+ private String departure;
+
+ private String modification;
+
+ private String filter;
+
+ public Whiteboard onArrival(String method) {
+ arrival = method;
+ return this;
+ }
+
+ public Whiteboard onDeparture(String method) {
+ departure = method;
+ return this;
+ }
+
+ public Whiteboard onModification(String method) {
+ modification = method;
+ return this;
+ }
+
+ public Whiteboard setFilter(String fil) {
+ filter = fil;
+ return this;
+ }
+
+ public Element getElement() {
+ ensureValidity();
+ // Create the root element.
+ Element element = new Element(NAME, NAMESPACE);
+ // Mandatory attributes
+ element.addAttribute(new Attribute("onArrival", arrival));
+ element.addAttribute(new Attribute("onDeparture", departure));
+ element.addAttribute(new Attribute("filter", filter));
+
+ // Optional attribute
+ if (modification != null) {
+ element.addAttribute(new Attribute("onModification", modification));
+ }
+
+ return element;
+ }
+
+ private void ensureValidity() {
+ if (arrival == null) {
+ throw new IllegalStateException("The whiteboard pattern configuration must have a onArrival method");
+ }
+ if (departure == null) {
+ throw new IllegalStateException("The whiteboard pattern configuration must have a onDeparture method");
+ }
+ if (filter == null) {
+ throw new IllegalStateException("The whiteboard pattern configuration must have a filter");
+ }
+
+ }
+
+}
diff --git a/ipojo/tests/api/src/test/java/org/example/service/impl/HostImpl.java b/ipojo/tests/api/src/test/java/org/example/service/impl/HostImpl.java
new file mode 100644
index 0000000..1be1a70
--- /dev/null
+++ b/ipojo/tests/api/src/test/java/org/example/service/impl/HostImpl.java
@@ -0,0 +1,19 @@
+package org.example.service.impl;
+
+import org.osgi.framework.ServiceReference;
+
+public class HostImpl {
+
+ public void arrival(ServiceReference ref) {
+
+ }
+
+ public void departure(ServiceReference ref) {
+
+ }
+
+ public void modification(ServiceReference ref) {
+
+ }
+
+}