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/10/24 17:48:19 UTC
svn commit: r707659 [1/3] - in /felix/trunk/ipojo:
core/src/main/java/org/apache/felix/ipojo/util/
handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/
handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/publisher/...
Author: clement
Date: Fri Oct 24 08:48:18 2008
New Revision: 707659
URL: http://svn.apache.org/viewvc?rev=707659&view=rev
Log:
Fix the Felix-794 issue
The event admin handler now accepts to receive events on topics containing a '*' (at the end).
Modified:
felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java
felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/EventUtil.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/subscriber/EventAdminSubscriberMetadata.java
felix/trunk/ipojo/tests/handler/eventadmin/src/main/java/org/apache/felix/ipojo/test/BadTests.java
felix/trunk/ipojo/tests/handler/eventadmin/src/main/java/org/apache/felix/ipojo/test/GoodTests.java
felix/trunk/ipojo/tests/handler/eventadmin/src/main/resources/metadata.xml
Modified: felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java?rev=707659&r1=707658&r2=707659&view=diff
==============================================================================
--- felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java (original)
+++ felix/trunk/ipojo/core/src/main/java/org/apache/felix/ipojo/util/DependencyModel.java Fri Oct 24 08:48:18 2008
@@ -24,7 +24,6 @@
import java.util.List;
import org.apache.felix.ipojo.ConfigurationException;
-import org.apache.felix.ipojo.ServiceContext;
import org.apache.felix.ipojo.context.ServiceReferenceImpl;
import org.apache.felix.ipojo.metadata.Element;
import org.osgi.framework.BundleContext;
Modified: felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/EventUtil.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/EventUtil.java?rev=707659&r1=707658&r2=707659&view=diff
==============================================================================
--- felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/EventUtil.java (original)
+++ felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/EventUtil.java Fri Oct 24 08:48:18 2008
@@ -18,6 +18,8 @@
*/
package org.apache.felix.ipojo.handlers.event;
+import org.apache.felix.ipojo.parser.ParseUtils;
+
/**
* Utility methods.
*
@@ -25,40 +27,153 @@
*/
public class EventUtil {
- /**
- * Tests that the given topic match with the given topic pattern.
- *
- * @param topic the topic to test
- * @param topicPattern the topic pattern
- * @return true if it matches.
- */
- public static boolean matches(String topic, String topicPattern) {
- if (topicPattern.equals("*")) {
- return true;
- }
- int star;
- if ((star = topicPattern.indexOf("*")) > 0) {
- return topic.startsWith(topicPattern.substring(0, star - 1));
- } else {
- return topic.equals(topicPattern);
- }
- }
-
- /**
- * Tests that the given topic match with the given topic patterns.
- *
- * @param topic the topic to test
- * @param topicPatterns the topic patterns
- * @return true if it matches.
- */
- public static boolean matches(String topic, String[] topicPatterns) {
- int n = topicPatterns.length;
- for (int i = 0; i < n; i++) {
- if (matches(topic, topicPatterns[i])) {
- return true;
- }
- }
- return false;
- }
+ /**
+ * The separator between topics.
+ */
+ public static final String TOPIC_SEPARATOR = ",";
+
+ /**
+ * The separator between topics.
+ */
+ public static final String TOPIC_TOKEN_SEPARATOR = "/";
+
+ /**
+ * The topic token alphabet.
+ */
+ private static final String tokenAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
+
+ /**
+ * Tests that the given topic match with the given topic pattern.
+ *
+ * @param topic
+ * the topic to test
+ * @param topicPattern
+ * the topic pattern
+ * @return true if it matches.
+ */
+ public static final boolean matches(String topic, String topicPattern) {
+ if (topicPattern.equals("*")) {
+ return true;
+ }
+ int star;
+ if ((star = topicPattern.indexOf("*")) > 0) {
+ return topic.startsWith(topicPattern.substring(0, star - 1));
+ } else {
+ return topic.equals(topicPattern);
+ }
+ }
+
+ /**
+ * Tests that the given topic match with the given topic patterns.
+ *
+ * @param topic
+ * the topic to test
+ * @param topicPatterns
+ * the topic patterns
+ * @return true if it matches.
+ */
+ public static final boolean matches(String topic, String[] topicPatterns) {
+ int n = topicPatterns.length;
+ for (int i = 0; i < n; i++) {
+ if (matches(topic, topicPatterns[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check the given topic scope is valid.
+ *
+ * topicScope ::= "*" | ( topic "/*" ? )
+ *
+ * @param topicScope
+ * the topic scope to check.
+ *
+ * @return {@code true} if the given topic scope is valid, {@code false}
+ * otherwise.
+ */
+ public static final boolean isValidTopicScope(String topicScope) {
+ if (topicScope.equals("*")) {
+ // Wildcard character only accepted.
+ return true;
+ }
+
+ // Remove trailing "/*" if present, to check the topic radix.
+ String topicWithoutWildcard;
+ if (topicScope.endsWith("/*")) {
+ topicWithoutWildcard = topicScope.substring(0, topicScope.length() - 2);
+ } else {
+ topicWithoutWildcard = topicScope;
+ }
+
+ // Validate the topic radix.
+ return isValidTopic(topicWithoutWildcard);
+ }
+
+ /**
+ * Check the given topic is valid.
+ *
+ * topic ::= token ( / token ) *
+ *
+ * @param topic
+ * the topic to check.
+ *
+ * @return {@code true} if the given topic is valid, {@code false}
+ * otherwise.
+ */
+ public static final boolean isValidTopic(String topic) {
+ if (topic.startsWith(TOPIC_TOKEN_SEPARATOR)
+ || topic.endsWith(TOPIC_TOKEN_SEPARATOR)) {
+ // A topic cannot start nor end with '/'.
+ return false;
+ }
+
+ String[] tokens = ParseUtils.split(topic, TOPIC_TOKEN_SEPARATOR);
+ if (tokens.length < 1) {
+ // A topic must contain at least one token.
+ return false;
+ }
+
+ // Check each token is valid.
+ for (int i = 0; i < tokens.length; i++) {
+ String token = tokens[i];
+ if (!isValidToken(token)) {
+ return false;
+ }
+ }
+
+ // The topic is valid.
+ return true;
+ }
+
+ /**
+ * Check the given token is valid.
+ *
+ * token ::= ( alphanum | "_" | "-" )+
+ *
+ * @param token
+ * the token to check.
+ *
+ * @return {@code true} if the given topic token is valid, {@code false}
+ * otherwise.
+ */
+ private static boolean isValidToken(String token) {
+ int length = token.length();
+ if (length < 1) {
+ // Token must contain at least one character.
+ return false;
+ }
+
+ for (int i = 0; i < length; i++) {
+ // Each character in the token must belong to the token alphabet.
+ if (tokenAlphabet.indexOf(token.charAt(i)) == -1) {
+ return false;
+ }
+ }
+
+ // The token is valid.
+ return true;
+ }
}
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=707659&r1=707658&r2=707659&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 Fri Oct 24 08:48:18 2008
@@ -18,13 +18,10 @@
*/
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.handlers.event.EventUtil;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.parser.ParseUtils;
-import org.osgi.service.event.Event;
/**
* Represent a publisher.
@@ -33,221 +30,212 @@
*/
class EventAdminPublisherMetadata {
- // Names of metadata attributes
+ // 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;
-
- /**
- * Constructs a publisher from its metadata description.
- *
- * @param publisher the 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;
- }
- }
-
- /**
- * Sets 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);
- }
- }
-
- }
-
- /**
- * Checks 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);
- }
- }
-
- /**
- * Gets the name attribute of the publisher.
- *
- * @return the name
- */
- public String getName() {
- return m_name;
- }
-
- /**
- * Gets the field attribute of the publisher.
- *
- * @return the field
- */
- public String getField() {
- return m_field;
- }
-
- /**
- * Gets the topics attribute of the publisher.
- *
- * @return the topics
- */
- public String[] getTopics() {
- return m_topics;
- }
-
- /**
- * Gets the synchronous attribute of the publisher.
- *
- * @return the synchronous mode
- */
- public boolean isSynchronous() {
- return m_synchronous;
- }
-
- /**
- * Gets the dataKey attribute of the publisher.
- *
- * @return the data key
- */
- public String getDataKey() {
- return m_dataKey;
- }
+ /**
+ * 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;
+
+ /**
+ * Constructs a publisher from its metadata description.
+ *
+ * @param publisher
+ * the 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)) {
+ setTopics(publisher.getAttribute(TOPICS_ATTRIBUTE));
+ } 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;
+ }
+ }
+
+ /**
+ * Sets 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 {
+ String[] newTopics = ParseUtils.split(topicsString,
+ EventUtil.TOPIC_SEPARATOR);
+ // Check each topic is valid
+ for (int i = 0; i < newTopics.length; i++) {
+ String topic = newTopics[i];
+ if (!EventUtil.isValidTopic(topic)) {
+ throw new ConfigurationException("Invalid topic : \"" + topic
+ + "\".");
+ }
+ }
+ m_topics = newTopics;
+ }
+
+ /**
+ * Checks 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);
+ }
+ }
+
+ /**
+ * Gets the name attribute of the publisher.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+ /**
+ * Gets the field attribute of the publisher.
+ *
+ * @return the field
+ */
+ public String getField() {
+ return m_field;
+ }
+
+ /**
+ * Gets the topics attribute of the publisher.
+ *
+ * @return the topics
+ */
+ public String[] getTopics() {
+ return m_topics;
+ }
+
+ /**
+ * Gets the synchronous attribute of the publisher.
+ *
+ * @return the synchronous mode
+ */
+ public boolean isSynchronous() {
+ return m_synchronous;
+ }
+
+ /**
+ * Gets the dataKey attribute of the publisher.
+ *
+ * @return the data key
+ */
+ public String getDataKey() {
+ return m_dataKey;
+ }
}
Modified: felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberMetadata.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberMetadata.java?rev=707659&r1=707658&r2=707659&view=diff
==============================================================================
--- felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberMetadata.java (original)
+++ felix/trunk/ipojo/handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/subscriber/EventAdminSubscriberMetadata.java Fri Oct 24 08:48:18 2008
@@ -18,16 +18,13 @@
*/
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.handlers.event.EventUtil;
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.
@@ -36,269 +33,255 @@
*/
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 the bundle context of the managed instance.
- * @param subscriber the 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");
- }
- }
- }
-
- /**
- * Sets the topics attribute of the subscriber.
- *
- * @param topicsString the comma separated list of the topics to listen
- * @throws ConfigurationException if 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);
- }
- }
- }
-
- /**
- * Sets the filter attribute of the subscriber.
- *
- * @param filterString the string representation of the event filter
- * @throws ConfigurationException if 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");
- }
- }
-
- /**
- * Checks 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);
- }
- }
-
- /**
- * Gets the name attribute of the subscriber.
- *
- * @return the name
- */
- public String getName() {
- return m_name;
- }
-
- /**
- * Gets the topics attribute of the subscriber.
- *
- * @return the topics
- */
- public String[] getTopics() {
- return m_topics;
- }
-
- /**
- * Gets the callback attribute of the subscriber.
- *
- * @return the callback
- */
- public String getCallback() {
- return m_callback;
- }
-
- /**
- * Gets the data key attribute of the subscriber.
- *
- * @return the dataKey
- */
- public String getDataKey() {
- return m_dataKey;
- }
-
- /**
- * Gets the data type attribute of the subscriber.
- *
- * @return the dataType
- */
- public Class getDataType() {
- return m_dataType;
- }
-
- /**
- * Gets the filter attribute of the subscriber.
- *
- * @return the filter
- */
- public Filter getFilter() {
- return m_filter;
- }
+ // 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
+ * the bundle context of the managed instance.
+ * @param subscriber
+ * the 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)) {
+ setTopics(subscriber.getAttribute(TOPICS_ATTRIBUTE));
+ } 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)) {
+ setFilter(subscriber.getAttribute(FILTER_ATTRIBUTE));
+ }
+ }
+
+ /**
+ * Sets the topics attribute of the subscriber.
+ *
+ * @param topicsString
+ * the comma separated list of the topics to listen
+ * @throws ConfigurationException
+ * if the specified topic list is malformed
+ */
+ public void setTopics(String topicsString) throws ConfigurationException {
+ String[] newTopics = ParseUtils.split(topicsString,
+ EventUtil.TOPIC_SEPARATOR);
+ // Check each topic is valid
+ for (int i = 0; i < newTopics.length; i++) {
+ String topicScope = newTopics[i];
+ if (!EventUtil.isValidTopicScope(topicScope)) {
+ throw new ConfigurationException("Invalid topic scope : \""
+ + topicScope + "\".");
+ }
+ }
+ m_topics = newTopics;
+ }
+
+ /**
+ * Sets the filter attribute of the subscriber.
+ *
+ * @param filterString
+ * the string representation of the event filter
+ * @throws ConfigurationException
+ * if 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");
+ }
+ }
+
+ /**
+ * Checks 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);
+ }
+ }
+
+ /**
+ * Gets the name attribute of the subscriber.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return m_name;
+ }
+
+ /**
+ * Gets the topics attribute of the subscriber.
+ *
+ * @return the topics
+ */
+ public String[] getTopics() {
+ return m_topics;
+ }
+
+ /**
+ * Gets the callback attribute of the subscriber.
+ *
+ * @return the callback
+ */
+ public String getCallback() {
+ return m_callback;
+ }
+
+ /**
+ * Gets the data key attribute of the subscriber.
+ *
+ * @return the dataKey
+ */
+ public String getDataKey() {
+ return m_dataKey;
+ }
+
+ /**
+ * Gets the data type attribute of the subscriber.
+ *
+ * @return the dataType
+ */
+ public Class getDataType() {
+ return m_dataType;
+ }
+
+ /**
+ * Gets the filter attribute of the subscriber.
+ *
+ * @return the filter
+ */
+ public Filter getFilter() {
+ return m_filter;
+ }
}