You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2008/07/30 19:50:39 UTC

svn commit: r681144 [1/2] - in /felix/trunk/ipojo/handler/eventadmin: ./ src/main/java/org/apache/felix/ipojo/handlers/event/publisher/ src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/

Author: clement
Date: Wed Jul 30 10:50:39 2008
New Revision: 681144

URL: http://svn.apache.org/viewvc?rev=681144&view=rev
Log:
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

Modified:
    felix/trunk/ipojo/handler/eventadmin/metadata.xml
    felix/trunk/ipojo/handler/eventadmin/pom.xml
    felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherHandler.java
    felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherMetadata.java
    felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/PublisherImpl.java
    felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberHandler.java
    felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberMetadata.java

Modified: felix/trunk/ipojo/handler/eventadmin/metadata.xml
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/eventadmin/metadata.xml?rev=681144&r1=681143&r2=681144&view=diff
==============================================================================
--- felix/trunk/ipojo/handler/eventadmin/metadata.xml (original)
+++ felix/trunk/ipojo/handler/eventadmin/metadata.xml Wed Jul 30 10:50:39 2008
@@ -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

Modified: felix/trunk/ipojo/handler/eventadmin/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/eventadmin/pom.xml?rev=681144&r1=681143&r2=681144&view=diff
==============================================================================
--- felix/trunk/ipojo/handler/eventadmin/pom.xml (original)
+++ felix/trunk/ipojo/handler/eventadmin/pom.xml Wed Jul 30 10:50:39 2008
@@ -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>
 	

Modified: felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherHandler.java?rev=681144&r1=681143&r2=681144&view=diff
==============================================================================
--- felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherHandler.java (original)
+++ felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherHandler.java Wed Jul 30 10:50:39 2008
@@ -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;
+    }
+}

Modified: felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherMetadata.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherMetadata.java?rev=681144&r1=681143&r2=681144&view=diff
==============================================================================
--- felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherMetadata.java (original)
+++ felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/EventAdminPublisherMetadata.java Wed Jul 30 10:50:39 2008
@@ -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;
+    }
+}

Modified: felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/PublisherImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/PublisherImpl.java?rev=681144&r1=681143&r2=681144&view=diff
==============================================================================
--- felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/PublisherImpl.java (original)
+++ felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/PublisherImpl.java Wed Jul 30 10:50:39 2008
@@ -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);
+    }
+}

Modified: felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberHandler.java?rev=681144&r1=681143&r2=681144&view=diff
==============================================================================
--- felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberHandler.java (original)
+++ felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberHandler.java Wed Jul 30 10:50:39 2008
@@ -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);
+                    }
+                }
+            }
+        }
+    }
+}