/* * 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.HandlerDescription; 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 { /** * The handler Namespace. */ public static final String NAMESPACE = "org.apache.felix.ipojo.handlers.event"; /** * The names of instance configuration properties. */ public static final String TOPICS_PROPERTY = "event.topics"; /** * The prefix for logged messages. */ private static final String LOG_PREFIX = "EVENT ADMIN PUBLISHER HANDLER : "; /** * The instance manager. */ private InstanceManager m_manager; /** * The current EventAdmin service. */ private EventAdmin m_ea; /** * The publishers accessible by their fields. */ private Map m_publishersByField = new Hashtable(); /** * The handler description */ private EventAdminPublisherHandlerDescription m_description; /** * Initializes the component type. * * @param cd the component type description to populate * @param metadata the component type metadata * @throws ConfigurationException if the given metadata is incorrect. * @see org.apache.felix.ipojo.Handler#initializeComponentFactory( * org.apache.felix.ipojo.architecture.ComponentTypeDescription, org.apache.felix.ipojo.metadata.Element) */ public void initializeComponentFactory(ComponentTypeDescription cd, Element metadata) throws ConfigurationException { // Update the current component description Dictionary dict = new Properties(); PropertyDescription pd = new PropertyDescription(TOPICS_PROPERTY, Dictionary.class.getName(), dict.toString()); cd.addProperty(pd); // Get Metadata publishers Element[] publishers = metadata.getElements("publisher", NAMESPACE); // if publisher is null, look for 'publishes' elements if (publishers == null || publishers.length == 0) { publishers = metadata.getElements("publishes", 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 the component type metadata * @param conf the instance configuration * @throws ConfigurationException if one event publication is not correct * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.metadata.Element, java.util.Dictionary) */ 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 publisher is null, look for 'publishes' elements if (publishers == null || publishers.length == 0) { publishers = metadata.getElements("publishes", 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"); } setValidity(true); debug(LOG_PREFIX+ "Setup description...."); m_description = new EventAdminPublisherHandlerDescription(this, m_publishersByField.values()); // Initialize the description. } /** * Starts the handler instance. * * This method does nothing. */ public void start() { } /** * Stops the handler instance. * * This method does nothing. */ 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 */ 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; } /** * Gets the handler description * @see org.apache.felix.ipojo.Handler#getDescription() */ public HandlerDescription getDescription() { return m_description; } }