Several improvements in the event admin handler:
- add checking when the factory is initializing instead of during the instance creation
- subscribers are no more ignored when an error occurs
- improve error messages
- fix a mistake (eventadmins instead of eventadmin) in the artifactid
- the handler now requires the event admin as an iPOJO dependency, this avoids tracking the service
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@681144 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/handler/eventadmin/metadata.xml b/ipojo/handler/eventadmin/metadata.xml
index db43296..9bf4cb6 100644
--- a/ipojo/handler/eventadmin/metadata.xml
+++ b/ipojo/handler/eventadmin/metadata.xml
@@ -1,15 +1,16 @@
-<ipojo>
- <handler
- classname="org.apache.felix.ipojo.handlers.event.subscriber.EventAdminSubscriberHandler"
- name="subscriber"
- namespace="org.apache.felix.ipojo.handlers.event.EventAdminHandler">
- <provides>
- <property field="m_topics" name="event.topics" value=""/>
- </provides>
- </handler>
-
- <handler classname="org.apache.felix.ipojo.handlers.event.publisher.EventAdminPublisherHandler"
- name="publisher"
- namespace="org.apache.felix.ipojo.handlers.event.EventAdminHandler">
- </handler>
+<ipojo>
+ <handler
+ classname="org.apache.felix.ipojo.handlers.event.subscriber.EventAdminSubscriberHandler"
+ name="subscriber"
+ namespace="org.apache.felix.ipojo.handlers.event.EventAdminHandler">
+ <provides>
+ <property field="m_topics" name="event.topics" value=""/>
+ </provides>
+ </handler>
+
+ <handler classname="org.apache.felix.ipojo.handlers.event.publisher.EventAdminPublisherHandler"
+ name="publisher"
+ namespace="org.apache.felix.ipojo.handlers.event.EventAdminHandler">
+ <requires field="m_ea"/>
+ </handler>
</ipojo>
\ No newline at end of file
diff --git a/ipojo/handler/eventadmin/pom.xml b/ipojo/handler/eventadmin/pom.xml
index ca80272..039b1f2 100644
--- a/ipojo/handler/eventadmin/pom.xml
+++ b/ipojo/handler/eventadmin/pom.xml
@@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<packaging>bundle</packaging>
<name>Apache Felix iPOJO Event Admin Handler</name>
- <artifactId>org.apache.felix.ipojo.handler.eventadmins</artifactId>
+ <artifactId>org.apache.felix.ipojo.handler.eventadmin</artifactId>
<groupId>org.apache.felix</groupId>
<version>0.9.0-SNAPSHOT</version>
diff --git a/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherHandler.java b/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherHandler.java
index e77924d..8a0f973 100644
--- a/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherHandler.java
+++ b/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherHandler.java
@@ -1,323 +1,262 @@
-/*
- * 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.handlers.event.publisher;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.InstanceManager;
-import org.apache.felix.ipojo.PrimitiveHandler;
-import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
-import org.apache.felix.ipojo.architecture.PropertyDescription;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.parser.FieldMetadata;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.event.EventAdmin;
-
-/**
- * Event Publisher Handler.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class EventAdminPublisherHandler extends PrimitiveHandler implements
- ServiceListener {
-
- /**
- * Handler Namespace.
- */
- public static final String NAMESPACE = "org.apache.felix.ipojo.handlers.event.EventAdminHandler";
-
- /**
- * Names of instance configuration properties.
- */
- public static final String TOPICS_PROPERTY = "event.topics";
-
- /**
- * Prefix for logged messages.
- */
- private static final String LOG_PREFIX = "EVENT ADMIN PUBLISHER HANDLER : ";
-
- /**
- * The Instance Manager.
- */
- private InstanceManager m_manager;
-
- /**
- * The bundle context.
- */
- private BundleContext m_context;
-
- /**
- * The current Event Admin service reference.
- */
- private ServiceReference m_eaReference;
-
- /**
- * The current Event Admin service.
- */
- private EventAdmin m_ea;
-
- /**
- * The publishers accessible by their names.
- */
- private Map m_publishersByName = new Hashtable();
-
- /**
- * The publishers accessible by their fields.
- */
- private Map m_publishersByField = new Hashtable();
-
- /**
- * Initialize the component type.
- *
- * @param cd :
- * component type description to populate.
- * @param metadata :
- * component type metadata.
- * @throws ConfigurationException :
- * metadata are incorrect.
- * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentDescription,
- * org.apache.felix.ipojo.metadata.Element)
- */
- // @Override
- public void initializeComponentFactory(ComponentTypeDescription cd,
- Element metadata)
- throws ConfigurationException {
-
- // Update the current component description
- Dictionary dict = new Properties();
- cd.addProperty(new PropertyDescription(TOPICS_PROPERTY,
- Dictionary.class.getName(), dict.toString()));
- }
-
- /**
- * Constructor.
- *
- * @param metadata :
- * component type metadata
- * @param conf :
- * instance configuration
- * @throws ConfigurationException :
- * one event publication is not correct
- * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.InstanceManager,
- * org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
- */
- // @Override
- public void configure(Element metadata, Dictionary conf)
- throws ConfigurationException {
-
- // Store the component manager
- m_manager = getInstanceManager();
-
- // Get Metadata publishers
- Element[] publishers = metadata.getElements("publisher", NAMESPACE);
-
- if (publishers != null) {
- // then check publishers are well formed and fill the publishers'
- // map
- for (int i = 0; i < publishers.length; i++) {
-
- try {
- // Extract the publisher configuration
- EventAdminPublisherMetadata publisherMetadata = new EventAdminPublisherMetadata(
- publishers[i], conf);
- String name = publisherMetadata.getName();
- info(LOG_PREFIX + "configuring publisher " + name);
-
- // Create the associated Publisher
- Publisher publisher = new PublisherImpl(this,
- publisherMetadata.getTopics(), publisherMetadata
- .isSynchronous(), publisherMetadata
- .getDataKey(), m_manager.getInstanceName());
-
- // Check field existence and type
- String field = publisherMetadata.getField();
- FieldMetadata fieldMetadata = getPojoMetadata().getField(
- publisherMetadata.getField(),
- Publisher.class.getName());
- if (fieldMetadata == null) {
- throw new ConfigurationException(
- "Field not found in the component : "
- + Publisher.class.getName() + " "
- + field);
- }
-
- // Insert in the publisher tables.
- Object old;
- if ((old = m_publishersByName.put(name, publisher)) != null) {
- m_publishersByName.put(name, old);
- throw new ConfigurationException("The publisher "
- + name + "already exists");
- }
- if ((old = m_publishersByField.put(field, publisher)) != null) {
- m_publishersByField.put(field, old);
- m_publishersByName.remove(name);
- throw new ConfigurationException("The field " + field
- + " is already associated to a publisher");
- }
-
- // Register the callback that return the publisher
- // reference when the specified field is read by the
- // POJO.
- m_manager.register(fieldMetadata, this);
-
- } catch (Exception e) {
- // Ignore invalid publishers
- warn(LOG_PREFIX
- + "Ignoring publisher : Error in configuration", e);
- }
- }
- } else {
- info(LOG_PREFIX + "no publisher detected !");
- }
- }
-
- /**
- * Start the handler instance. This method tries to get an initial reference
- * of the EventAdmin service.
- */
- // @Override
- public void start() {
- info(LOG_PREFIX + "STARTING");
-
- // Look for the EventAdmin service at startup
- m_context = m_manager.getContext();
- m_eaReference = m_context.getServiceReference(EventAdmin.class
- .getName());
- if (m_eaReference != null) {
- m_ea = (EventAdmin) m_context.getService(m_eaReference);
- if (m_ea != null) {
- info(LOG_PREFIX + "EventAdmin service caught");
- }
- }
-
- // Update handler validity
- setValidity(m_ea != null);
-
- // Register service listener for EventAdmin services
- try {
- m_context.addServiceListener(this, "(OBJECTCLASS="
- + EventAdmin.class.getName() + ")");
- } catch (InvalidSyntaxException e) {
- error(LOG_PREFIX + "Cannot register ServiceListener", e);
- }
- info(LOG_PREFIX + "STARTED");
- }
-
- /**
- * Stop the handler instance. This method release the used EventAdmin
- * service (if any).
- */
- // @Override
- public void stop() {
- info(LOG_PREFIX + "STOPPING");
-
- // Unregister service
- if (m_ea != null) {
- m_ea = null;
- m_context.ungetService(m_eaReference);
- info(LOG_PREFIX + "EventAdmin service released");
- }
-
- info(LOG_PREFIX + "STOPPED");
- }
-
- /***************************************************************************
- * OSGi ServiceListener callback
- **************************************************************************/
-
- /**
- * Service listener callback. This method check the
- * registration/unregistration of EventAdmin services and update the
- * valididy of the handler.
- *
- * @param event
- * the concerned service reference
- */
- // @Override
- public void serviceChanged(ServiceEvent event) {
- warn(LOG_PREFIX + "serviceChanged()");
-
- if (m_eaReference == null && event.getType() == ServiceEvent.REGISTERED) {
- // An EventAdmin service appeared and was expected
- m_eaReference = event.getServiceReference();
- m_ea = (EventAdmin) m_context.getService(m_eaReference);
- info(LOG_PREFIX + "EventAdmin service caught");
- } else if (m_eaReference != null
- && event.getType() == ServiceEvent.UNREGISTERING
- && m_eaReference == event.getServiceReference()) {
- // The used EventAdmin service disappeared
- m_ea = null;
- m_context.ungetService(m_eaReference);
- info(LOG_PREFIX + "EventAdmin service released");
-
- // Find another EventAdmin service if available
- m_eaReference = m_context.getServiceReference(EventAdmin.class
- .getName());
- if (m_eaReference != null) {
- m_ea = (EventAdmin) m_context.getService(m_eaReference);
- info(LOG_PREFIX + "EventAdmin service caught");
- }
- }
-
- // Update handler validity
- setValidity(m_ea != null);
- }
-
- /**
- * Field interceptor callback. This method is called when the component
- * attempt to one of its Publisher field.
- *
- * @param pojo
- * the accessed field
- * @param fieldName
- * the name of the accessed field
- * @param value
- * the value of the field (useless here)
- *
- * @return the Publisher associated with the accessed field's name
- */
- // @Override
- public Object onGet(Object pojo, String fieldName, Object value) {
- // Retrieve the publisher associated to the given field name
- Publisher pub = (Publisher) m_publishersByField.get(fieldName);
- if (pub == null) {
- error(LOG_PREFIX + "No publisher associated to the field "
- + fieldName);
- }
- return pub;
- }
-
- /**
- * This method is called by managed publishers to obtain the current
- * EventAdmin service.
- *
- * @return the current EventAdmin service or {@code null} if unavailable.
- */
- public EventAdmin getEventAdminService() {
- return m_ea;
- }
-}
+/*
+ * 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.handlers.event.publisher;
+
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.PrimitiveHandler;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.architecture.PropertyDescription;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.FieldMetadata;
+import org.osgi.service.event.EventAdmin;
+
+/**
+ * Event Publisher Handler.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class EventAdminPublisherHandler extends PrimitiveHandler {
+
+ /**
+ * Handler Namespace.
+ */
+ public static final String NAMESPACE = "org.apache.felix.ipojo.handlers.event.EventAdminHandler";
+
+ /**
+ * Names of instance configuration properties.
+ */
+ public static final String TOPICS_PROPERTY = "event.topics";
+
+ /**
+ * Prefix for logged messages.
+ */
+ private static final String LOG_PREFIX = "EVENT ADMIN PUBLISHER HANDLER : ";
+
+ /**
+ * The Instance Manager.
+ */
+ private InstanceManager m_manager;
+
+ /**
+ * The current Event Admin service.
+ */
+ private EventAdmin m_ea;
+
+ /**
+ * The publishers accessible by their fields.
+ */
+ private Map m_publishersByField = new Hashtable();
+
+ /**
+ * Initialize the component type.
+ *
+ * @param cd :
+ * component type description to populate.
+ * @param metadata :
+ * component type metadata.
+ * @throws ConfigurationException :
+ * metadata are incorrect.
+ * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentDescription,
+ * org.apache.felix.ipojo.metadata.Element)
+ */
+ // @Override
+ public void initializeComponentFactory(ComponentTypeDescription cd,
+ Element metadata)
+ throws ConfigurationException {
+
+ // Update the current component description
+ Dictionary dict = new Properties();
+ cd.addProperty(new PropertyDescription(TOPICS_PROPERTY,
+ Dictionary.class.getName(), dict.toString()));
+
+ // Get Metadata publishers
+ Element[] publishers = metadata.getElements("publisher", NAMESPACE);
+ if (publishers != null) {
+
+ // Maps used to check name and field are unique
+ Set nameSet = new HashSet();
+ Set fieldSet = new HashSet();
+
+ // Check all publishers are well formed
+ for (int i = 0; i < publishers.length; i++) {
+
+ // Check the publisher configuration is correct by creating an
+ // unused publisher metadata
+ EventAdminPublisherMetadata publisherMetadata = new EventAdminPublisherMetadata(
+ publishers[i]);
+ String name = publisherMetadata.getName();
+ info(LOG_PREFIX + "checking publisher " + name);
+
+ // Check field existence and type
+ String field = publisherMetadata.getField();
+ FieldMetadata fieldMetadata = getPojoMetadata()
+ .getField(publisherMetadata.getField(),
+ Publisher.class.getName());
+ if (fieldMetadata == null) {
+ throw new ConfigurationException(
+ "Field not found in the component : "
+ + Publisher.class.getName() + " " + field);
+ }
+
+ // Check name and field are unique
+ if (nameSet.contains(name)) {
+ throw new ConfigurationException(
+ "A publisher with the same name already exists : "
+ + name);
+ } else if (fieldSet.contains(field)) {
+ throw new ConfigurationException("The field " + field
+ + " is already associated to a publisher");
+ }
+ nameSet.add(name);
+ fieldSet.add(field);
+ }
+ } else {
+ info(LOG_PREFIX + "no publisher to check");
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param metadata :
+ * component type metadata
+ * @param conf :
+ * instance configuration
+ * @throws ConfigurationException :
+ * one event publication is not correct
+ * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.InstanceManager,
+ * org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
+ */
+ // @Override
+ public void configure(Element metadata, Dictionary conf)
+ throws ConfigurationException {
+
+ // Store the component manager
+ m_manager = getInstanceManager();
+
+ // Get the topics instance configuration
+ Dictionary instanceTopics = (Dictionary) conf.get(TOPICS_PROPERTY);
+
+ // Get Metadata publishers
+ Element[] publishers = metadata.getElements("publisher", NAMESPACE);
+
+ if (publishers != null) {
+ // then check publishers are well formed and fill the publishers'
+ // map
+ for (int i = 0; i < publishers.length; i++) {
+
+ // Extract the publisher configuration
+ EventAdminPublisherMetadata publisherMetadata = new EventAdminPublisherMetadata(
+ publishers[i]);
+ String name = publisherMetadata.getName();
+ info(LOG_PREFIX + "configuring publisher " + name);
+
+ // Get the topic instance configuration if redefined
+ String topicsString = (instanceTopics != null) ? (String) instanceTopics
+ .get(name)
+ : null;
+ if (topicsString != null) {
+ publisherMetadata.setTopics(topicsString);
+ }
+
+ // Check the publisher is correctly configured
+ publisherMetadata.check();
+
+ // Create the associated Publisher and insert it in the
+ // publisher map
+ Publisher publisher = new PublisherImpl(this, publisherMetadata
+ .getTopics(), publisherMetadata.isSynchronous(),
+ publisherMetadata.getDataKey(), m_manager
+ .getInstanceName());
+ m_publishersByField
+ .put(publisherMetadata.getField(), publisher);
+
+ // Register the callback that return the publisher
+ // reference when the specified field is read by the
+ // POJO.
+ FieldMetadata fieldMetadata = getPojoMetadata()
+ .getField(publisherMetadata.getField(),
+ Publisher.class.getName());
+ m_manager.register(fieldMetadata, this);
+ }
+ } else {
+ info(LOG_PREFIX + "no publisher to configure");
+ }
+ }
+
+ /**
+ * Start the handler instance.
+ *
+ * This method does nothing.
+ */
+ // @Override
+ public void start() {
+ }
+
+ /**
+ * Stop the handler instance.
+ *
+ * This method does nothing.
+ */
+ // @Override
+ public void stop() {
+ }
+
+ /**
+ * Field interceptor callback. This method is called when the component
+ * attempt to one of its Publisher field.
+ *
+ * @param pojo
+ * the accessed field
+ * @param fieldName
+ * the name of the accessed field
+ * @param value
+ * the value of the field (useless here)
+ *
+ * @return the Publisher associated with the accessed field's name
+ */
+ // @Override
+ public Object onGet(Object pojo, String fieldName, Object value) {
+ // Retrieve the publisher associated to the given field name
+ Publisher pub = (Publisher) m_publishersByField.get(fieldName);
+ if (pub == null) {
+ error(LOG_PREFIX + "No publisher associated to the field "
+ + fieldName);
+ }
+ return pub;
+ }
+
+ /**
+ * This method is called by managed publishers to obtain the current
+ * EventAdmin service.
+ *
+ * @return the current EventAdmin service.
+ */
+ public EventAdmin getEventAdminService() {
+ return m_ea;
+ }
+}
diff --git a/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherMetadata.java b/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherMetadata.java
index 0408abf..620bf20 100644
--- a/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherMetadata.java
+++ b/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherMetadata.java
@@ -1,225 +1,260 @@
-/*
- * 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.handlers.event.publisher;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.handlers.event.subscriber.EventAdminSubscriberHandler;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.parser.ParseUtils;
-
-/**
- * Represent a publisher.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-class EventAdminPublisherMetadata {
-
- // Names of metadata attributes
-
- /**
- * The name attribute in the component metadata.
- */
- public static final String NAME_ATTRIBUTE = "name";
-
- /**
- * The field attribute in the component metadata.
- */
- public static final String FIELD_ATTRIBUTE = "field";
-
- /**
- * The topics attribute in the component metadata.
- */
- public static final String TOPICS_ATTRIBUTE = "topics";
-
- /**
- * The synchronous attribute in the component metadata.
- */
- public static final String SYNCHRONOUS_ATTRIBUTE = "synchronous";
-
- /**
- * The data key attribute in the component metadata.
- */
- public static final String DATA_KEY_ATTRIBUTE = "data-key";
-
- // Default values
-
- /**
- * The data key attribute's default value.
- */
- public static final String DEFAULT_DATA_KEY_VALUE = "user.data";
-
- /**
- * The synchronous attribute's default value.
- */
- public static final boolean DEFAULT_SYNCHRONOUS_VALUE = false;
-
- /**
- * The name which acts as an identifier.
- */
- private final String m_name;
-
- /**
- * The name of the field representing the publisher in the component.
- */
- private final String m_field;
-
- /**
- * Topics to which events are sent.
- */
- private final String[] m_topics;
-
- /**
- * Events sending mode.
- */
- private final boolean m_synchronous;
-
- /**
- * The key where user data are stored in the event dictionary.
- */
- private final String m_dataKey;
-
- /**
- * Construct a publisher from its metadata description.
- *
- * @param publisher :
- * publisher metadata description.
- * @param instanceConf :
- * the configuration of the component instance
- * @throws ConfigurationException
- * if the configuration of the component or the instance is
- * invalid.
- */
- public EventAdminPublisherMetadata(Element publisher,
- Dictionary instanceConf) throws ConfigurationException {
-
- /**
- * Setup required attributes
- */
-
- // NAME_ATTRIBUTE
- if (publisher.containsAttribute(NAME_ATTRIBUTE)) {
- m_name = publisher.getAttribute(NAME_ATTRIBUTE);
- } else {
- throw new ConfigurationException(
- "Missing required attribute in component configuration : "
- + NAME_ATTRIBUTE);
- }
-
- // FIELD_ATTRIBUTE
- if (publisher.containsAttribute(FIELD_ATTRIBUTE)) {
- m_field = publisher.getAttribute(FIELD_ATTRIBUTE);
- } else {
- throw new ConfigurationException(
- "Missing required attribute in component configuration : "
- + FIELD_ATTRIBUTE);
- }
-
- // TOPICS_ATTRIBUTE
- String topicsString = null;
- if (publisher.containsAttribute(TOPICS_ATTRIBUTE)) {
- topicsString = publisher.getAttribute(TOPICS_ATTRIBUTE);
- }
- // Check TOPICS_PROPERTY in the instance configuration
- Dictionary instanceTopics = (Dictionary) instanceConf
- .get(EventAdminSubscriberHandler.TOPICS_PROPERTY);
- if (instanceTopics != null) {
- Enumeration e = instanceTopics.keys();
- while (e.hasMoreElements()) {
- String myName = (String) e.nextElement(); // name
- if (m_name.equals(myName)) {
- topicsString = (String) instanceTopics.get(myName);
- break;
- }
- }
- }
- if (topicsString != null) {
- m_topics = ParseUtils.split(topicsString, ",");
- } else {
- throw new ConfigurationException(
- "Missing required attribute in component or instance configuration : "
- + TOPICS_ATTRIBUTE);
- }
-
- /**
- * Setup optional attributes
- */
- // SYNCHRONOUS_ATTRIBUTE
- if (publisher.containsAttribute(SYNCHRONOUS_ATTRIBUTE)) {
- m_synchronous = "true".equalsIgnoreCase(publisher
- .getAttribute(SYNCHRONOUS_ATTRIBUTE));
- } else {
- m_synchronous = DEFAULT_SYNCHRONOUS_VALUE;
- }
-
- // DATA_KEY_ATTRIBUTE
- if (publisher.containsAttribute(DATA_KEY_ATTRIBUTE)) {
- m_dataKey = publisher.getAttribute(DATA_KEY_ATTRIBUTE);
- } else {
- m_dataKey = DEFAULT_DATA_KEY_VALUE;
- }
- }
-
- /**
- * Get the name attribute of the publisher.
- *
- * @return the name
- */
- public String getName() {
- return m_name;
- }
-
- /**
- * Get the field attribute of the publisher.
- *
- * @return the field
- */
- public String getField() {
- return m_field;
- }
-
- /**
- * Get the topics attribute of the publisher.
- *
- * @return the topics
- */
- public String[] getTopics() {
- return m_topics;
- }
-
- /**
- * Get the synchronous attribute of the publisher.
- *
- * @return the synchronous
- */
- public boolean isSynchronous() {
- return m_synchronous;
- }
-
- /**
- * Get the dataKey attribute of the publisher.
- *
- * @return the dataKey
- */
- public String getDataKey() {
- return m_dataKey;
- }
-}
+/*
+ * 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.handlers.event.publisher;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.ParseUtils;
+import org.osgi.service.event.Event;
+
+/**
+ * Represent a publisher.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+class EventAdminPublisherMetadata {
+
+ // Names of metadata attributes
+
+ /**
+ * The name attribute in the component metadata.
+ */
+ public static final String NAME_ATTRIBUTE = "name";
+
+ /**
+ * The field attribute in the component metadata.
+ */
+ public static final String FIELD_ATTRIBUTE = "field";
+
+ /**
+ * The topics attribute in the component metadata.
+ */
+ public static final String TOPICS_ATTRIBUTE = "topics";
+
+ /**
+ * The synchronous attribute in the component metadata.
+ */
+ public static final String SYNCHRONOUS_ATTRIBUTE = "synchronous";
+
+ /**
+ * The data key attribute in the component metadata.
+ */
+ public static final String DATA_KEY_ATTRIBUTE = "data-key";
+
+ // Default values
+
+ /**
+ * The data key attribute's default value.
+ */
+ public static final String DEFAULT_DATA_KEY_VALUE = "user.data";
+
+ /**
+ * The synchronous attribute's default value.
+ */
+ public static final boolean DEFAULT_SYNCHRONOUS_VALUE = false;
+
+ /**
+ * The name which acts as an identifier.
+ */
+ private final String m_name;
+
+ /**
+ * The name of the field representing the publisher in the component.
+ */
+ private final String m_field;
+
+ /**
+ * Topics to which events are sent.
+ */
+ private String[] m_topics;
+
+ /**
+ * Events sending mode.
+ */
+ private final boolean m_synchronous;
+
+ /**
+ * The key where user data are stored in the event dictionary.
+ */
+ private final String m_dataKey;
+
+ /**
+ * Construct a publisher from its metadata description.
+ *
+ * @param publisher :
+ * publisher metadata description.
+ * @throws ConfigurationException
+ * if the configuration of the component or the instance is
+ * invalid.
+ */
+ public EventAdminPublisherMetadata(Element publisher)
+ throws ConfigurationException {
+
+ /**
+ * Setup required attributes
+ */
+
+ // NAME_ATTRIBUTE
+ if (publisher.containsAttribute(NAME_ATTRIBUTE)) {
+ m_name = publisher.getAttribute(NAME_ATTRIBUTE);
+ } else {
+ throw new ConfigurationException(
+ "Missing required attribute in component configuration : "
+ + NAME_ATTRIBUTE);
+ }
+
+ // FIELD_ATTRIBUTE
+ if (publisher.containsAttribute(FIELD_ATTRIBUTE)) {
+ m_field = publisher.getAttribute(FIELD_ATTRIBUTE);
+ } else {
+ throw new ConfigurationException(
+ "Missing required attribute in component configuration : "
+ + FIELD_ATTRIBUTE);
+ }
+
+ // TOPICS_ATTRIBUTE
+ if (publisher.containsAttribute(TOPICS_ATTRIBUTE)) {
+ m_topics = ParseUtils.split(publisher
+ .getAttribute(TOPICS_ATTRIBUTE), ",");
+ // Check each topic is valid
+ Dictionary empty = new Hashtable();
+ for (int i = 0; i < m_topics.length; i++) {
+ String topic = m_topics[i];
+ try {
+ new Event(topic, empty);
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException("Malformed topic : "
+ + topic);
+ }
+ }
+
+ } else {
+ m_topics = null;
+ // Nothing to do if TOPICS_ATTRIBUTE is not present as it can be
+ // overridden in the instance configuration.
+ }
+
+ /**
+ * Setup optional attributes
+ */
+
+ // SYNCHRONOUS_ATTRIBUTE
+ if (publisher.containsAttribute(SYNCHRONOUS_ATTRIBUTE)) {
+ m_synchronous = "true".equalsIgnoreCase(publisher
+ .getAttribute(SYNCHRONOUS_ATTRIBUTE));
+ } else {
+ m_synchronous = DEFAULT_SYNCHRONOUS_VALUE;
+ }
+
+ // DATA_KEY_ATTRIBUTE
+ if (publisher.containsAttribute(DATA_KEY_ATTRIBUTE)) {
+ m_dataKey = publisher.getAttribute(DATA_KEY_ATTRIBUTE);
+ } else {
+ m_dataKey = DEFAULT_DATA_KEY_VALUE;
+ }
+ }
+
+ /**
+ * Set the topics attribute of the publisher.
+ *
+ * @param topicsString
+ * the comma separated list of the topics on which events are
+ * sent
+ * @throws ConfigurationException
+ * the specified topic string is malformed
+ */
+ public void setTopics(String topicsString)
+ throws ConfigurationException {
+ m_topics = ParseUtils.split(topicsString, ",");
+ // Check each topic is valid
+ Dictionary empty = new Hashtable();
+ for (int i = 0; i < m_topics.length; i++) {
+ String topic = m_topics[i];
+ try {
+ new Event(topic, empty);
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException("Malformed topic : " + topic);
+ }
+ }
+
+ }
+
+ /**
+ * Check that the required instance configurable attributes are all set.
+ *
+ * @throws ConfigurationException
+ * if a required attribute is missing
+ */
+ public void check()
+ throws ConfigurationException {
+ if (m_topics == null || m_topics.length == 0) {
+ throw new ConfigurationException(
+ "Missing required attribute in component or instance configuration : "
+ + TOPICS_ATTRIBUTE);
+ }
+ }
+
+ /**
+ * Get the name attribute of the publisher.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+ /**
+ * Get the field attribute of the publisher.
+ *
+ * @return the field
+ */
+ public String getField() {
+ return m_field;
+ }
+
+ /**
+ * Get the topics attribute of the publisher.
+ *
+ * @return the topics
+ */
+ public String[] getTopics() {
+ return m_topics;
+ }
+
+ /**
+ * Get the synchronous attribute of the publisher.
+ *
+ * @return the synchronous
+ */
+ public boolean isSynchronous() {
+ return m_synchronous;
+ }
+
+ /**
+ * Get the dataKey attribute of the publisher.
+ *
+ * @return the dataKey
+ */
+ public String getDataKey() {
+ return m_dataKey;
+ }
+}
diff --git a/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/PublisherImpl.java b/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/PublisherImpl.java
index 265c0a5..17c068f 100644
--- a/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/PublisherImpl.java
+++ b/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/PublisherImpl.java
@@ -1,139 +1,124 @@
-/*
- * 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.handlers.event.publisher;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.osgi.service.event.Event;
-
-/**
- * The PublisherImpl class is the implementation of the Publisher object used by
- * components to send events.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class PublisherImpl implements Publisher {
-
- /**
- * The key where the component instance name is stored.
- */
- public static final String INSTANCE_NAME_PROPERTY = "publisher.instance.name";
-
- /**
- * The managing handler.
- */
- private EventAdminPublisherHandler m_handler;
-
- /**
- * The topics of sent events.
- */
- private final String[] m_topics;
-
- /**
- * The sending mode of events.
- */
- private final boolean m_synchronous;
-
- /**
- * The key, in the content of the event, where user data are stored.
- */
- private final String m_dataKey;
-
- /**
- * The name of the component instance using this publisher.
- */
- private final String m_instanceName;
-
- /**
- * Construct an Publisher with given parameters.
- *
- * @param handler
- * the handler that will manage this publisher
- * @param topics
- * the topics on which events are sent
- * @param synchronous
- * the sending mode of events
- * @param dataKey
- * The key, in the content of the event, where user data are
- * stored (may be {@code null})
- * @param instanceName
- * the name of the instance creating this publisher.
- */
- public PublisherImpl(EventAdminPublisherHandler handler, String[] topics,
- boolean synchronous, String dataKey, String instanceName) {
-
- // Check parameters
- if (topics.length == 0) {
- throw new IllegalArgumentException(
- "At least one topic must be specified");
- }
- // Test validity of each topic
- for (int i = 0; i < topics.length; i++) {
- try {
- new Event(topics[i], null);
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("Malformed topic : "
- + e.getMessage());
- }
- }
-
- // Initialize the publisher's fields
- m_handler = handler;
- m_topics = topics;
- m_synchronous = synchronous;
- m_dataKey = dataKey;
- m_instanceName = instanceName;
- }
-
- /**
- * Send an event with the specified content.
- *
- * @param content
- * the content of the event
- */
- public void send(Dictionary content) {
- // Add instance information in the event
- content.put(INSTANCE_NAME_PROPERTY, m_instanceName);
- // We sent the event on each topic
- for (int i = 0; i < m_topics.length; i++) {
- // Create an event with the given topic and content
- Event e = new Event(m_topics[i], content);
- // Send the event, depending on the sending mode
- if (!m_synchronous) {
- m_handler.getEventAdminService().postEvent(e); // Asynchronous
- } else {
- m_handler.getEventAdminService().sendEvent(e); // Synchronous
- }
- }
- }
-
- /**
- * Send a data event.
- *
- * @param object
- * the data to send
- */
- public void sendData(Object object) {
- // Construct the content of the event with the given object
- Dictionary content = new Hashtable();
- content.put(m_dataKey, object);
- send(content);
- }
-}
+/*
+ * 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.handlers.event.publisher;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.service.event.Event;
+
+/**
+ * The PublisherImpl class is the implementation of the Publisher object used by
+ * components to send events.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class PublisherImpl implements Publisher {
+
+ /**
+ * The key where the component instance name is stored.
+ */
+ public static final String INSTANCE_NAME_PROPERTY = "publisher.instance.name";
+
+ /**
+ * The managing handler.
+ */
+ private EventAdminPublisherHandler m_handler;
+
+ /**
+ * The topics of sent events.
+ */
+ private final String[] m_topics;
+
+ /**
+ * The sending mode of events.
+ */
+ private final boolean m_synchronous;
+
+ /**
+ * The key, in the content of the event, where user data are stored.
+ */
+ private final String m_dataKey;
+
+ /**
+ * The name of the component instance using this publisher.
+ */
+ private final String m_instanceName;
+
+ /**
+ * Construct an Publisher with given parameters.
+ *
+ * @param handler
+ * the handler that will manage this publisher
+ * @param topics
+ * the topics on which events are sent
+ * @param synchronous
+ * the sending mode of events
+ * @param dataKey
+ * The key, in the content of the event, where user data are
+ * stored (may be {@code null})
+ * @param instanceName
+ * the name of the instance creating this publisher.
+ */
+ public PublisherImpl(EventAdminPublisherHandler handler, String[] topics,
+ boolean synchronous, String dataKey, String instanceName) {
+
+ // Initialize the publisher's fields
+ m_handler = handler;
+ m_topics = topics;
+ m_synchronous = synchronous;
+ m_dataKey = dataKey;
+ m_instanceName = instanceName;
+ }
+
+ /**
+ * Send an event with the specified content.
+ *
+ * @param content
+ * the content of the event
+ */
+ public void send(Dictionary content) {
+ // Add instance information in the event
+ content.put(INSTANCE_NAME_PROPERTY, m_instanceName);
+ // We sent the event on each topic
+ for (int i = 0; i < m_topics.length; i++) {
+ // Create an event with the given topic and content
+ Event e = new Event(m_topics[i], content);
+ // Send the event, depending on the sending mode
+ if (!m_synchronous) {
+ m_handler.getEventAdminService().postEvent(e); // Asynchronous
+ } else {
+ m_handler.getEventAdminService().sendEvent(e); // Synchronous
+ }
+ }
+ }
+
+ /**
+ * Send a data event.
+ *
+ * @param object
+ * the data to send
+ */
+ public void sendData(Object object) {
+ // Construct the content of the event with the given object
+ Dictionary content = new Hashtable();
+ content.put(m_dataKey, object);
+ send(content);
+ }
+}
diff --git a/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberHandler.java b/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberHandler.java
index d9e6cdc..ba81c2a 100644
--- a/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberHandler.java
+++ b/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberHandler.java
@@ -1,343 +1,409 @@
-/*
- * 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.handlers.event.subscriber;
-
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.InstanceManager;
-import org.apache.felix.ipojo.PrimitiveHandler;
-import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
-import org.apache.felix.ipojo.architecture.PropertyDescription;
-import org.apache.felix.ipojo.handlers.event.EventUtil;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.parser.MethodMetadata;
-import org.apache.felix.ipojo.parser.PojoMetadata;
-import org.apache.felix.ipojo.util.Callback;
-import org.osgi.framework.Filter;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventHandler;
-
-/**
- * Event Subscriber Handler.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class EventAdminSubscriberHandler extends PrimitiveHandler implements
- EventHandler {
-
- /**
- * Handler Namespace.
- */
- public static final String NAMESPACE = "org.apache.felix.ipojo.handlers.event.EventAdminHandler";
-
- // Names of instance configuration properties.
-
- /**
- * The event's topics instance configuration property.
- */
- public static final String TOPICS_PROPERTY = "event.topics";
-
- /**
- * The event's filter instance configuration property.
- */
- public static final String FILTER_PROPERTY = "event.filter";
-
- /**
- * Prefix for logged messages.
- */
- private static final String LOG_PREFIX = "EVENT ADMIN SUBSCRIBER HANDLER : ";
-
- /**
- * Instance Manager.
- */
- private InstanceManager m_manager;
-
- /**
- * List of subscriber accessible by name.
- */
- private Map m_subscribersByName = new HashMap();
-
- /**
- * List of callbacks accessible by subscribers' names.
- */
- private Map m_callbacks = new Hashtable();
-
- /**
- * iPOJO Properties representing all the topics.
- */
- private String[] m_topics;
-
- /**
- * Initialize the component type.
- *
- * @param cd :
- * component type description to populate.
- * @param metadata :
- * component type metadata.
- * @throws ConfigurationException :
- * metadata are incorrect.
- * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentDescription,
- * org.apache.felix.ipojo.metadata.Element)
- */
- // @Override
- public void initializeComponentFactory(ComponentTypeDescription cd,
- Element metadata)
- throws ConfigurationException {
-
- // Update the current component description
- Dictionary dict = new Properties();
- cd.addProperty(new PropertyDescription(TOPICS_PROPERTY,
- Dictionary.class.getName(), dict.toString()));
- dict = new Properties();
- cd.addProperty(new PropertyDescription(FILTER_PROPERTY,
- Dictionary.class.getName(), dict.toString()));
- }
-
- /**
- * Constructor.
- *
- * @param metadata :
- * component type metadata
- * @param conf :
- * instance configuration
- * @throws ConfigurationException :
- * one event subscription is not correct
- * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.InstanceManager,
- * org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
- */
- // @Override
- public void configure(Element metadata, Dictionary conf)
- throws ConfigurationException {
-
- // Store the component manager
- m_manager = getInstanceManager();
-
- // Get Metadata subscribers
- Element[] subscribers = metadata.getElements("subscriber", NAMESPACE);
-
- if (subscribers != null) {
-
- // then check subscribers are well formed and fill the subscriber'
- // map
- for (int i = 0; i < subscribers.length; i++) {
-
- try {
- // Extract the subscriber configuration
- EventAdminSubscriberMetadata subscriberMetadata = new EventAdminSubscriberMetadata(
- m_manager, subscribers[i], conf);
- String subscriberName = subscriberMetadata.getName();
- info(LOG_PREFIX + "configuring subscriber "
- + subscriberName);
-
- // Determine the callback prototype
- PojoMetadata pojoMetadata = getFactory().getPojoMetadata();
- String callbackType;
- if (subscriberMetadata.getDataKey() == null) {
- callbackType = Event.class.getName();
- } else {
- callbackType = subscriberMetadata.getDataType()
- .getName();
- }
-
- // Find the specified callback
- MethodMetadata methodMetadata = pojoMetadata.getMethod(
- subscriberMetadata.getCallback(),
- new String[] { callbackType });
- if (methodMetadata == null) {
- throw new ConfigurationException(
- "Unable to find callback "
- + subscriberMetadata.getCallback()
- + "(" + callbackType + ")");
- }
- Callback callback = new Callback(methodMetadata, m_manager);
-
- // Add the subscriber to the subscriber list and
- // register callback
- Object old;
- if ((old = m_subscribersByName.put(subscriberName,
- subscriberMetadata)) != null) {
- m_subscribersByName.put(subscriberName, old);
- throw new ConfigurationException("The subscriber "
- + subscriberName + "already exists");
- }
- m_callbacks.put(subscriberName, callback);
-
- } catch (Exception e) {
- // Ignore invalid subscribers
- warn(LOG_PREFIX
- + "Ignoring subscriber : Error in configuration", e);
- }
- }
- } else {
- info(LOG_PREFIX + "no subscriber detected !");
- }
- }
-
- /**
- * Handler start method.
- *
- * @see org.apache.felix.ipojo.Handler#start()
- */
- // @Override
- public void start() {
-
- Set topics = new TreeSet();
-
- // Build the topic to listen
- // Topics is a merge of all required topics by subscribers
- if (!m_subscribersByName.isEmpty()) {
- Collection subscribers = m_subscribersByName.values();
- for (Iterator i = subscribers.iterator(); i.hasNext();) {
- String[] subTopics = ((EventAdminSubscriberMetadata) i.next())
- .getTopics();
- for (int j = 0; j < subTopics.length; j++) {
- topics.add(subTopics[j]);
- }
- }
- }
-
- m_topics = new String[topics.size()];
- int i = 0;
- for (Iterator iterator = topics.iterator(); iterator.hasNext();) {
- String tmp = (String) iterator.next();
- m_topics[i++] = tmp;
- }
- }
-
- /**
- * Handler stop method.
- *
- * @see org.apache.felix.ipojo.Handler#stop()
- */
- // @Override
- public void stop() {
- }
-
- /***************************************************************************
- * OSGi EventHandler callback
- **************************************************************************/
-
- /**
- * Receive an event. The event is dispatch to attached subscribers.
- *
- * @param event :
- * the received event.
- * @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
- */
- public void handleEvent(Event event) {
-
- // Retrieve the event's topic
- String topic = event.getTopic();
-
- // For each subscribers
- Collection subscribers = m_subscribersByName.values();
- for (Iterator i = subscribers.iterator(); i.hasNext();) {
- EventAdminSubscriberMetadata subscriberMetadata = (EventAdminSubscriberMetadata) i
- .next();
-
- synchronized (this) {
- // Check if the subscriber's topic and filter match
- Filter filter = subscriberMetadata.getFilter();
-
- if (EventUtil.matches(topic, subscriberMetadata.getTopics())
- && (filter == null || event.matches(filter))) {
-
- String name = subscriberMetadata.getName();
- String dataKey = subscriberMetadata.getDataKey();
- Callback callback = (Callback) m_callbacks.get(name);
- Object callbackParam;
-
- try {
- // Depending on the subscriber type...
- if (dataKey == null) {
-
- // Generic event subscriber : pass the event to the
- // registered
- // callback
- callbackParam = event;
-
- } else {
-
- // Check for a data key in the event
- boolean dataKeyPresent = false;
- String[] properties = event.getPropertyNames();
- for (int j = 0; j < properties.length
- && !dataKeyPresent; j++) {
- if (dataKey.equals(properties[j])) {
- dataKeyPresent = true;
- }
- }
-
- if (dataKeyPresent) {
- // Data event : check type compatibility and
- // pass the given object to the registered
- // callback
- Object data = event.getProperty(dataKey);
- Class dataType = subscriberMetadata
- .getDataType();
- Class dataClazz = data.getClass();
- if (dataType.isAssignableFrom(dataClazz)) {
- callbackParam = data;
- } else {
- throw new ClassCastException(
- "Cannot convert "
- + dataClazz.getName()
- + " to "
- + dataType.getName());
- }
-
- } else {
- throw new java.lang.NoSuchFieldException(
- dataKey);
- }
- }
-
- // Run the callback
- callback.call(new Object[] { callbackParam });
-
- } catch (ClassCastException e) {
- // Ignore the data event if type doesn't match
- warn(
- LOG_PREFIX
- + "Ignoring data event : Bad data type",
- e);
- } catch (NoSuchFieldException e) {
- // Ignore events without data field for data events
- // subscriber
- warn(LOG_PREFIX + "Ignoring data event : No data", e);
- } catch (Exception e) {
- // Unexpected exception
- error(LOG_PREFIX
- + "Unexpected exception when calling callback",
- e);
- }
- }
- }
- }
- }
-}
+/*
+ * 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.handlers.event.subscriber;
+
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.PrimitiveHandler;
+import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
+import org.apache.felix.ipojo.architecture.PropertyDescription;
+import org.apache.felix.ipojo.handlers.event.EventUtil;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.MethodMetadata;
+import org.apache.felix.ipojo.parser.PojoMetadata;
+import org.apache.felix.ipojo.util.Callback;
+import org.osgi.framework.Filter;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * Event Subscriber Handler.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class EventAdminSubscriberHandler extends PrimitiveHandler implements
+ EventHandler {
+
+ /**
+ * Handler Namespace.
+ */
+ public static final String NAMESPACE = "org.apache.felix.ipojo.handlers.event.EventAdminHandler";
+
+ // Names of instance configuration properties.
+
+ /**
+ * The event's topics instance configuration property.
+ */
+ public static final String TOPICS_PROPERTY = "event.topics";
+
+ /**
+ * The event's filter instance configuration property.
+ */
+ public static final String FILTER_PROPERTY = "event.filter";
+
+ /**
+ * Prefix for logged messages.
+ */
+ private static final String LOG_PREFIX = "EVENT ADMIN SUBSCRIBER HANDLER : ";
+
+ /**
+ * Instance Manager.
+ */
+ private InstanceManager m_manager;
+
+ /**
+ * List of subscriber accessible by name.
+ */
+ private Map m_subscribersByName = new HashMap();
+
+ /**
+ * List of callbacks accessible by subscribers' names.
+ */
+ private Map m_callbacksByName = new Hashtable();
+
+ /**
+ * iPOJO Properties representing all the topics.
+ */
+ private String[] m_topics;
+
+ /**
+ * Listen received events ?
+ */
+ private boolean m_isListening;
+
+ /**
+ * Initialize the component type.
+ *
+ * @param cd :
+ * component type description to populate.
+ * @param metadata :
+ * component type metadata.
+ * @throws ConfigurationException :
+ * metadata are incorrect.
+ * @see org.apache.felix.ipojo.Handler#initializeComponentFactory(org.apache.felix.ipojo.architecture.ComponentDescription,
+ * org.apache.felix.ipojo.metadata.Element)
+ */
+ // @Override
+ public void initializeComponentFactory(ComponentTypeDescription cd,
+ Element metadata)
+ throws ConfigurationException {
+
+ // Update the current component description
+ Dictionary dict = new Properties();
+ cd.addProperty(new PropertyDescription(TOPICS_PROPERTY,
+ Dictionary.class.getName(), dict.toString()));
+ dict = new Properties();
+ cd.addProperty(new PropertyDescription(FILTER_PROPERTY,
+ Dictionary.class.getName(), dict.toString()));
+
+ // Get Metadata subscribers
+ Element[] subscribers = metadata.getElements("subscriber", NAMESPACE);
+ if (subscribers != null) {
+
+ // Maps used to check name and field are unique
+ Set nameSet = new HashSet();
+ Set callbackSet = new HashSet();
+
+ // Check all subscribers are well formed
+ for (int i = 0; i < subscribers.length; i++) {
+
+ // Check the subscriber configuration is correct by creating an
+ // unused subscriber metadata
+ EventAdminSubscriberMetadata subscriberMetadata = new EventAdminSubscriberMetadata(
+ getFactory().getBundleContext(), subscribers[i]);
+
+ String name = subscriberMetadata.getName();
+ info(LOG_PREFIX + "checking subscriber " + name);
+
+ // Determine the event callback prototype
+ PojoMetadata pojoMetadata = getPojoMetadata();
+ String callbackType;
+ if (subscriberMetadata.getDataKey() == null) {
+ callbackType = Event.class.getName();
+ } else {
+ callbackType = subscriberMetadata.getDataType().getName();
+ }
+
+ // Check the event callback method is present
+ MethodMetadata methodMetadata = pojoMetadata.getMethod(
+ subscriberMetadata.getCallback(),
+ new String[] { callbackType });
+ String callbackSignature = subscriberMetadata.getCallback()
+ + "(" + callbackType + ")";
+ if (methodMetadata == null) {
+ throw new ConfigurationException(
+ "Cannot find callback method " + callbackSignature);
+ }
+
+ // Warn if the same callback is used by several subscribers
+ if (callbackSet.contains(callbackSignature)) {
+ warn("The callback method is already used by another subscriber : "
+ + callbackSignature);
+ } else {
+ callbackSet.add(callbackSignature);
+ }
+
+ // Check name is unique
+ if (nameSet.contains(name)) {
+ throw new ConfigurationException(
+ "A subscriber with the same name already exists : "
+ + name);
+ }
+ nameSet.add(name);
+ }
+ } else {
+ info(LOG_PREFIX + "no subscriber to check");
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param metadata :
+ * component type metadata
+ * @param conf :
+ * instance configuration
+ * @throws ConfigurationException :
+ * one event subscription is not correct
+ * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.InstanceManager,
+ * org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
+ */
+ // @Override
+ public void configure(Element metadata, Dictionary conf)
+ throws ConfigurationException {
+
+ // Store the component manager
+ m_manager = getInstanceManager();
+
+ // Get the topics and filter instance configuration
+ Dictionary instanceTopics = (Dictionary) conf.get(TOPICS_PROPERTY);
+ Dictionary instanceFilter = (Dictionary) conf.get(FILTER_PROPERTY);
+
+ // Get Metadata subscribers
+ Element[] subscribers = metadata.getElements("subscriber", NAMESPACE);
+
+ // The topics to listen
+ Set topics = new TreeSet();
+
+ if (subscribers != null) {
+
+ // Configure all subscribers
+ for (int i = 0; i < subscribers.length; i++) {
+
+ // Extract the subscriber configuration
+ EventAdminSubscriberMetadata subscriberMetadata = new EventAdminSubscriberMetadata(
+ m_manager.getContext(), subscribers[i]);
+ String name = subscriberMetadata.getName();
+ info(LOG_PREFIX + "configuring subscriber " + name);
+
+ // Get the topics instance configuration if redefined
+ String topicsString = (instanceTopics != null) ? (String) instanceTopics
+ .get(name)
+ : null;
+ if (topicsString != null) {
+ subscriberMetadata.setTopics(topicsString);
+ }
+
+ // Get the filter instance configuration if redefined
+ String filterString = (instanceFilter != null) ? (String) instanceFilter
+ .get(name)
+ : null;
+ if (filterString != null) {
+ subscriberMetadata.setFilter(filterString);
+ }
+
+ // Check the publisher is correctly configured
+ subscriberMetadata.check();
+
+ // Add this subscriber's topics to the global list
+ String[] subscriberTopics = subscriberMetadata.getTopics();
+ for (int j = 0; j < subscriberTopics.length; j++) {
+ topics.add(subscriberTopics[j]);
+ }
+
+ // Determine the event callback prototype
+ PojoMetadata pojoMetadata = getPojoMetadata();
+ String callbackType;
+ if (subscriberMetadata.getDataKey() == null) {
+ callbackType = Event.class.getName();
+ } else {
+ callbackType = subscriberMetadata.getDataType().getName();
+ }
+
+ // Create the specified callback and register it
+ MethodMetadata methodMetadata = pojoMetadata.getMethod(
+ subscriberMetadata.getCallback(),
+ new String[] { callbackType });
+ Callback callback = new Callback(methodMetadata, m_manager);
+ m_callbacksByName.put(name, callback);
+
+ // Add the subscriber list gloal map
+ m_subscribersByName.put(name, subscriberMetadata);
+ }
+
+ // Construct the global topic list
+ m_topics = new String[topics.size()];
+ int i = 0;
+ for (Iterator iterator = topics.iterator(); iterator.hasNext();) {
+ String tmp = (String) iterator.next();
+ m_topics[i++] = tmp;
+ }
+
+ } else {
+ info(LOG_PREFIX + "no subscriber to configure");
+ }
+ }
+
+ /**
+ * Handler start method.
+ *
+ * @see org.apache.felix.ipojo.Handler#start()
+ */
+ // @Override
+ public synchronized void start() {
+ m_isListening = true;
+ }
+
+ /**
+ * Handler stop method.
+ *
+ * @see org.apache.felix.ipojo.Handler#stop()
+ */
+ // @Override
+ public synchronized void stop() {
+ m_isListening = false;
+ }
+
+ /***************************************************************************
+ * OSGi EventHandler callback
+ **************************************************************************/
+
+ /**
+ * Receive an event. The event is dispatch to attached subscribers.
+ *
+ * @param event :
+ * the received event.
+ * @see org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
+ */
+ public void handleEvent(Event event) {
+
+ // Retrieve the event's topic
+ String topic = event.getTopic();
+
+ // For each subscribers
+ Collection subscribers = m_subscribersByName.values();
+ for (Iterator i = subscribers.iterator(); i.hasNext();) {
+ EventAdminSubscriberMetadata subscriberMetadata = (EventAdminSubscriberMetadata) i
+ .next();
+
+ synchronized (this) {
+ // Check if the subscriber's topic and filter match
+ Filter filter = subscriberMetadata.getFilter();
+
+ if (EventUtil.matches(topic, subscriberMetadata.getTopics())
+ && (filter == null || event.matches(filter))) {
+
+ String name = subscriberMetadata.getName();
+ String dataKey = subscriberMetadata.getDataKey();
+ Callback callback = (Callback) m_callbacksByName.get(name);
+ Object callbackParam;
+
+ try {
+ // Depending on the subscriber type...
+ if (dataKey == null) {
+
+ // Generic event subscriber : pass the event to the
+ // registered
+ // callback
+ callbackParam = event;
+
+ } else {
+
+ // Check for a data key in the event
+ boolean dataKeyPresent = false;
+ String[] properties = event.getPropertyNames();
+ for (int j = 0; j < properties.length
+ && !dataKeyPresent; j++) {
+ if (dataKey.equals(properties[j])) {
+ dataKeyPresent = true;
+ }
+ }
+
+ if (dataKeyPresent) {
+ // Data event : check type compatibility and
+ // pass the given object to the registered
+ // callback
+ Object data = event.getProperty(dataKey);
+ Class dataType = subscriberMetadata
+ .getDataType();
+ Class dataClazz = data.getClass();
+ if (dataType.isAssignableFrom(dataClazz)) {
+ callbackParam = data;
+ } else {
+ throw new ClassCastException(
+ "Cannot convert "
+ + dataClazz.getName()
+ + " to "
+ + dataType.getName());
+ }
+
+ } else {
+ throw new java.lang.NoSuchFieldException(
+ dataKey);
+ }
+ }
+
+ // Run the callback (final check to avoid
+ // NullPointerExceptions)
+ if (m_isListening) {
+ callback.call(new Object[] { callbackParam });
+ }
+
+ } catch (ClassCastException e) {
+ // Ignore the data event if type doesn't match
+ warn(
+ LOG_PREFIX
+ + "Ignoring data event : Bad data type",
+ e);
+ } catch (NoSuchFieldException e) {
+ // Ignore events without data field for data events
+ // subscriber
+ warn(LOG_PREFIX + "Ignoring data event : No data", e);
+ } catch (Exception e) {
+ // Unexpected exception
+ error(LOG_PREFIX
+ + "Unexpected exception when calling callback",
+ e);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberMetadata.java b/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberMetadata.java
index de221f4..01567e3 100644
--- a/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberMetadata.java
+++ b/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberMetadata.java
@@ -1,295 +1,310 @@
-/*
- * 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.handlers.event.subscriber;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-
-import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.InstanceManager;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.parser.ParseUtils;
-import org.apache.felix.ipojo.util.Logger;
-import org.osgi.framework.Filter;
-import org.osgi.framework.InvalidSyntaxException;
-
-/**
- * Represent an subscriber.
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-class EventAdminSubscriberMetadata {
-
- // Names of metadata attributes
-
- /**
- * The name attribute in the component metadata.
- */
- public static final String NAME_ATTRIBUTE = "name";
-
- /**
- * The callback attribute in the component metadata.
- */
- public static final String CALLBACK_ATTRIBUTE = "callback";
-
- /**
- * The topics attribute in the component metadata.
- */
- public static final String TOPICS_ATTRIBUTE = "topics";
-
- /**
- * The data key attribute in the component metadata.
- */
- public static final String DATA_KEY_ATTRIBUTE = "data-key";
-
- /**
- * The data type attribute in the component metadata.
- */
- public static final String DATA_TYPE_ATTRIBUTE = "data-type";
-
- /**
- * The filter attribute in the component metadata.
- */
- public static final String FILTER_ATTRIBUTE = "filter";
-
- // Default values
-
- /**
- * The data type atttribute's default value.
- */
- public static final Class DEFAULT_DATA_TYPE_VALUE = java.lang.Object.class;
-
- /**
- * The name which acts as an identifier.
- */
- private final String m_name;
-
- /**
- * Name of the callback method.
- */
- private final String m_callback;
-
- /**
- * Listened topics.
- */
- private final String[] m_topics;
-
- /**
- * The key where user data are stored in the event dictionary.
- */
- private final String m_dataKey;
-
- /**
- * The type of received data.
- */
- private final Class m_dataType;
-
- /**
- * Event filter.
- */
- private final Filter m_filter;
-
- /**
- * The Instance Manager.
- */
- private final InstanceManager m_instanceManager;
-
- /**
- * Constructor.
- *
- * @param instanceManager :
- * instance manager.
- * @param subscriber :
- * subscriber metadata.
- * @param instanceConf :
- * the configuration of the component instance
- * @throws ConfigurationException
- * if the configuration of the component or the instance is
- * invalid.
- */
- public EventAdminSubscriberMetadata(InstanceManager instanceManager,
- Element subscriber, Dictionary instanceConf)
- throws ConfigurationException {
-
- m_instanceManager = instanceManager;
-
- /**
- * Setup required attributes
- */
-
- // NAME_ATTRIBUTE
- if (subscriber.containsAttribute(NAME_ATTRIBUTE)) {
- m_name = subscriber.getAttribute(NAME_ATTRIBUTE);
- } else {
- throw new ConfigurationException(
- "Missing required attribute in component configuration : "
- + NAME_ATTRIBUTE);
- }
-
- // CALLBACK_ATTRIBUTE
- if (subscriber.containsAttribute(CALLBACK_ATTRIBUTE)) {
- m_callback = subscriber.getAttribute(CALLBACK_ATTRIBUTE);
- } else {
- throw new ConfigurationException(
- "Missing required attribute in component configuration : "
- + CALLBACK_ATTRIBUTE);
- }
-
- // TOPICS_ATTRIBUTE
- String topicsString = null;
- if (subscriber.containsAttribute(TOPICS_ATTRIBUTE)) {
- topicsString = subscriber.getAttribute(TOPICS_ATTRIBUTE);
- }
- // Check TOPICS_PROPERTY in the instance configuration
- Dictionary instanceTopics = (Dictionary) instanceConf
- .get(EventAdminSubscriberHandler.TOPICS_PROPERTY);
- if (instanceTopics != null) {
- Enumeration e = instanceTopics.keys();
- while (e.hasMoreElements()) {
- String myName = (String) e.nextElement(); // name
- if (m_name.equals(myName)) {
- topicsString = (String) instanceTopics.get(myName);
- break;
- }
- }
- }
- if (topicsString != null) {
- m_topics = ParseUtils.split(topicsString, ",");
- } else {
- throw new ConfigurationException(
- "Missing required attribute in component or instance configuration : "
- + TOPICS_ATTRIBUTE);
- }
-
- /**
- * Setup optional attributes
- */
-
- // DATA_KEY_ATTRIBUTE
- m_dataKey = subscriber.getAttribute(DATA_KEY_ATTRIBUTE);
- if (subscriber.containsAttribute(DATA_TYPE_ATTRIBUTE)) {
- Class type;
- try {
- type = m_instanceManager.getContext().getBundle().loadClass(
- subscriber.getAttribute(DATA_TYPE_ATTRIBUTE));
- } catch (ClassNotFoundException e) {
- m_instanceManager
- .getFactory()
- .getLogger()
- .log(
- Logger.WARNING,
- "Ignoring data-type (using default) : Malformed attribute in metadata",
- e);
- type = DEFAULT_DATA_TYPE_VALUE;
- }
- m_dataType = type;
- } else {
- m_dataType = DEFAULT_DATA_TYPE_VALUE;
- }
-
- // FILTER_ATTRIBUTE
- String filterString = null;
- if (subscriber.containsAttribute(FILTER_ATTRIBUTE)) {
- filterString = subscriber.getAttribute(FILTER_ATTRIBUTE);
- }
- // Check FILTER_PROPERTY in the instance configuration
- Dictionary instanceFilter = (Dictionary) instanceConf
- .get(EventAdminSubscriberHandler.FILTER_PROPERTY);
- if (instanceFilter != null) {
- Enumeration e = instanceFilter.keys();
- while (e.hasMoreElements()) {
- String myName = (String) e.nextElement(); // name
- if (m_name.equals(myName)) {
- filterString = (String) instanceFilter.get(myName);
- break;
- }
- }
- }
- Filter filter;
- if (filterString != null) {
- try {
- filter = m_instanceManager.getContext().createFilter(
- filterString);
- } catch (InvalidSyntaxException e) {
- // Ignore filter if malformed
- m_instanceManager.getFactory().getLogger().log(Logger.WARNING,
- "Ignoring filter : Malformed attribute in metadata", e);
- filter = null;
- }
- } else {
- filter = null;
- }
- m_filter = filter;
- }
-
- /**
- * Get the name attribute of the subscriber.
- *
- * @return the name
- */
- public String getName() {
- return m_name;
- }
-
- /**
- * Get the topics attribute of the subscriber.
- *
- * @return the topics
- */
- public String[] getTopics() {
- return m_topics;
- }
-
- /**
- * Get the callback attribute of the subscriber.
- *
- * @return the callback
- */
- public String getCallback() {
- return m_callback;
- }
-
- /**
- * Get the data key attribute of the subscriber.
- *
- * @return the dataKey
- */
- public String getDataKey() {
- return m_dataKey;
- }
-
- /**
- * Get the data type attribute of the subscriber.
- *
- * @return the dataType
- */
- public Class getDataType() {
- return m_dataType;
- }
-
- /**
- * Get the filter attribute of the subscriber.
- *
- * @return the filter
- */
- public Filter getFilter() {
- return m_filter;
- }
-
-}
+/*
+ * 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.handlers.event.subscriber;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.ParseUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.event.Event;
+
+/**
+ * Represent an subscriber.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+class EventAdminSubscriberMetadata {
+
+ // Names of metadata attributes
+
+ /**
+ * The name attribute in the component metadata.
+ */
+ public static final String NAME_ATTRIBUTE = "name";
+
+ /**
+ * The callback attribute in the component metadata.
+ */
+ public static final String CALLBACK_ATTRIBUTE = "callback";
+
+ /**
+ * The topics attribute in the component metadata.
+ */
+ public static final String TOPICS_ATTRIBUTE = "topics";
+
+ /**
+ * The data key attribute in the component metadata.
+ */
+ public static final String DATA_KEY_ATTRIBUTE = "data-key";
+
+ /**
+ * The data type attribute in the component metadata.
+ */
+ public static final String DATA_TYPE_ATTRIBUTE = "data-type";
+
+ /**
+ * The filter attribute in the component metadata.
+ */
+ public static final String FILTER_ATTRIBUTE = "filter";
+
+ // Default values
+
+ /**
+ * The data type atttribute's default value.
+ */
+ public static final Class DEFAULT_DATA_TYPE_VALUE = java.lang.Object.class;
+
+ /**
+ * The name which acts as an identifier.
+ */
+ private final String m_name;
+
+ /**
+ * Name of the callback method.
+ */
+ private final String m_callback;
+
+ /**
+ * Listened topics.
+ */
+ private String[] m_topics;
+
+ /**
+ * The key where user data are stored in the event dictionary.
+ */
+ private final String m_dataKey;
+
+ /**
+ * The type of received data.
+ */
+ private final Class m_dataType;
+
+ /**
+ * Event filter.
+ */
+ private Filter m_filter;
+
+ /**
+ * The context of the bundle.
+ */
+ private final BundleContext m_bundleContext;
+
+ /**
+ * Constructor.
+ *
+ * @param bundleContext : bundle context of the managed instance.
+ * @param subscriber : subscriber metadata.
+ * @throws ConfigurationException
+ * if the configuration of the component or the instance is
+ * invalid.
+ */
+ public EventAdminSubscriberMetadata(BundleContext bundleContext,
+ Element subscriber)
+ throws ConfigurationException {
+
+ m_bundleContext = bundleContext;
+
+ /**
+ * Setup required attributes
+ */
+
+ // NAME_ATTRIBUTE
+ if (subscriber.containsAttribute(NAME_ATTRIBUTE)) {
+ m_name = subscriber.getAttribute(NAME_ATTRIBUTE);
+ } else {
+ throw new ConfigurationException(
+ "Missing required attribute in component configuration : "
+ + NAME_ATTRIBUTE);
+ }
+
+ // CALLBACK_ATTRIBUTE
+ if (subscriber.containsAttribute(CALLBACK_ATTRIBUTE)) {
+ m_callback = subscriber.getAttribute(CALLBACK_ATTRIBUTE);
+ } else {
+ throw new ConfigurationException(
+ "Missing required attribute in component configuration : "
+ + CALLBACK_ATTRIBUTE);
+ }
+
+ // TOPICS_ATTRIBUTE
+ if (subscriber.containsAttribute(TOPICS_ATTRIBUTE)) {
+ m_topics = ParseUtils.split(subscriber
+ .getAttribute(TOPICS_ATTRIBUTE), ",");
+ // Check each topic is valid
+ Dictionary empty = new Hashtable();
+ for (int i = 0; i < m_topics.length; i++) {
+ String topic = m_topics[i];
+ try {
+ new Event(topic, empty);
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException("Malformed topic : "
+ + topic);
+ }
+ }
+ } else {
+ m_topics = null;
+ // Nothing to do if TOPICS_ATTRIBUTE is not present as it can be
+ // overridden in the instance configuration.
+ }
+
+ /**
+ * Setup optional attributes
+ */
+
+ // DATA_KEY_ATTRIBUTE
+ m_dataKey = subscriber.getAttribute(DATA_KEY_ATTRIBUTE);
+ if (subscriber.containsAttribute(DATA_TYPE_ATTRIBUTE)) {
+ Class type;
+ String typeName = subscriber.getAttribute(DATA_TYPE_ATTRIBUTE);
+ try {
+ type = m_bundleContext.getBundle().loadClass(typeName);
+ } catch (ClassNotFoundException e) {
+ throw new ConfigurationException("Data type class not found : "
+ + typeName);
+ }
+ m_dataType = type;
+ } else {
+ m_dataType = DEFAULT_DATA_TYPE_VALUE;
+ }
+
+ // FILTER_ATTRIBUTE
+ if (subscriber.containsAttribute(FILTER_ATTRIBUTE)) {
+ try {
+ m_filter = m_bundleContext.createFilter(subscriber
+ .getAttribute(FILTER_ATTRIBUTE));
+ } catch (InvalidSyntaxException e) {
+ throw new ConfigurationException("Invalid filter syntax");
+ }
+ }
+ }
+
+ /**
+ * Set the topics attribute of the subscriber.
+ *
+ * @param topicsString
+ * the comma separated list of the topics to listen
+ * @throws ConfigurationException
+ * the specified topic list is malformed
+ */
+ public void setTopics(String topicsString)
+ throws ConfigurationException {
+ m_topics = ParseUtils.split(topicsString, ",");
+ // Check each topic is valid
+ Dictionary empty = new Hashtable();
+ for (int i = 0; i < m_topics.length; i++) {
+ String topic = m_topics[i];
+ try {
+ new Event(topic, empty);
+ } catch (IllegalArgumentException e) {
+ throw new ConfigurationException("Malformed topic : " + topic);
+ }
+ }
+ }
+
+ /**
+ * Set the filter attribute of the subscriber.
+ *
+ * @param filterString
+ * the string representation of the event filter
+ * @throws ConfigurationException : the LDAP filter is malformed
+ */
+ public void setFilter(String filterString)
+ throws ConfigurationException {
+ try {
+ m_filter = m_bundleContext.createFilter(filterString);
+ } catch (InvalidSyntaxException e) {
+ throw new ConfigurationException("Invalid filter syntax");
+ }
+ }
+
+ /**
+ * Check that the required instance configurable attributes are all set.
+ *
+ * @throws ConfigurationException
+ * if a required attribute is missing
+ */
+ public void check()
+ throws ConfigurationException {
+ if (m_topics == null || m_topics.length == 0) {
+ throw new ConfigurationException(
+ "Missing required attribute in component or instance configuration : "
+ + TOPICS_ATTRIBUTE);
+ }
+ }
+
+ /**
+ * Get the name attribute of the subscriber.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+ /**
+ * Get the topics attribute of the subscriber.
+ *
+ * @return the topics
+ */
+ public String[] getTopics() {
+ return m_topics;
+ }
+
+ /**
+ * Get the callback attribute of the subscriber.
+ *
+ * @return the callback
+ */
+ public String getCallback() {
+ return m_callback;
+ }
+
+ /**
+ * Get the data key attribute of the subscriber.
+ *
+ * @return the dataKey
+ */
+ public String getDataKey() {
+ return m_dataKey;
+ }
+
+ /**
+ * Get the data type attribute of the subscriber.
+ *
+ * @return the dataType
+ */
+ public Class getDataType() {
+ return m_dataType;
+ }
+
+ /**
+ * Get the filter attribute of the subscriber.
+ *
+ * @return the filter
+ */
+ public Filter getFilter() {
+ return m_filter;
+ }
+
+}