FELIX-4604 : Add a configuration to ignore certain events
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1617208 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/eventadmin/impl/changelog.txt b/eventadmin/impl/changelog.txt
index fe8532d..2fdf46e 100644
--- a/eventadmin/impl/changelog.txt
+++ b/eventadmin/impl/changelog.txt
@@ -1,6 +1,7 @@
Changes from 1.3.2 to 1.3.4
---------------------------
** Improvement
+ * [FELIX-4604] - Add a configuration to ignore certain events
* [FELIX-3511] - Use java.concurrent from Java 6
* [FELIX-4316] - Packages imported dynamically should also be imported statically with an optional flag
diff --git a/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/Configuration.java b/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/Configuration.java
index 8661aea..690ca3e 100644
--- a/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/Configuration.java
+++ b/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/Configuration.java
@@ -81,20 +81,43 @@
* <tt>org.apache.felix.eventadmin.IgnoreTimeout</tt> - Configure
* <tt>EventHandler</tt>s to be called without a timeout.
* </p>
+ * <p>
* If a timeout is configured by default all event handlers are called using the timeout.
* For performance optimization it is possible to configure event handlers where the
* timeout handling is not used - this reduces the thread usage from the thread pools
* as the timout handling requires an additional thread to call the event handler.
* However, the application should work without this configuration property. It is a
* pure optimization!
- * The value is a list of string (separated by comma). If the string ends with a dot,
+ * </p>
+ * <p>
+ * The value is a list of strings (separated by comma). If the string ends with a dot,
* all handlers in exactly this package are ignored. If the string ends with a star,
* all handlers in this package and all subpackages are ignored. If the string neither
* ends with a dot nor with a start, this is assumed to define an exact class name.
- *
+ * </p>
+ * <p>
+ * <p>
+ * <tt>org.apache.felix.eventadmin.IgnoreTopic</tt> - Configure
+ * topics to be ignore and not delivered to registered handlers.
+ * </p>
+ * <p>
+ * For performance optimization it is possible to configure topics which are ignored
+ * by the event admin implementation. In this case, a event is not delivered to
+ * registered event handlers.
+ * </p>
+ * <p>
+ * The value is a list of strings (separated by comma). If a single value ends with a dot,
+ * all topics in exactly this package are ignored. If a single value ends with a star,
+ * all topics in this package and all sub packages are ignored. If a single value neither
+ * ends with a dot nor with a start, this is assumed to define an exact topic. A single
+ * star can be used to disable delivery completely.
+ * </p>
+ * <p>
+ * <p>
* These properties are read at startup and serve as a default configuration.
* If a configuration admin is configured, the event admin can be configured
* through the config admin.
+ * </p>
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
@@ -107,6 +130,7 @@
static final String PROP_TIMEOUT = "org.apache.felix.eventadmin.Timeout";
static final String PROP_REQUIRE_TOPIC = "org.apache.felix.eventadmin.RequireTopic";
static final String PROP_IGNORE_TIMEOUT = "org.apache.felix.eventadmin.IgnoreTimeout";
+ static final String PROP_IGNORE_TOPIC = "org.apache.felix.eventadmin.IgnoreTopic";
static final String PROP_LOG_LEVEL = "org.apache.felix.eventadmin.LogLevel";
/** The bundle context. */
@@ -120,6 +144,8 @@
private String[] m_ignoreTimeout;
+ private String[] m_ignoreTopics;
+
private int m_logLevel;
// The thread pool used - this is a member because we need to close it on stop
@@ -244,6 +270,21 @@
m_ignoreTimeout[i] = st.nextToken();
}
}
+
+ final String valueIgnoreTopic = m_bundleContext.getProperty(PROP_IGNORE_TOPIC);
+ if ( valueIgnoreTopic == null )
+ {
+ m_ignoreTopics = null;
+ }
+ else
+ {
+ final StringTokenizer st = new StringTokenizer(valueIgnoreTopic, ",");
+ m_ignoreTopics = new String[st.countTokens()];
+ for(int i=0; i<m_ignoreTopics.length; i++)
+ {
+ m_ignoreTopics[i] = st.nextToken();
+ }
+ }
m_logLevel = getIntProperty(PROP_LOG_LEVEL,
m_bundleContext.getProperty(PROP_LOG_LEVEL),
LogWrapper.LOG_WARNING, // default log level is WARNING
@@ -269,6 +310,21 @@
LogWrapper.getLogger().log(LogWrapper.LOG_WARNING,
"Value for property: " + PROP_IGNORE_TIMEOUT + " is neither a string nor a string array - Using default");
}
+ m_ignoreTopics = null;
+ final Object valueIT = config.get(PROP_IGNORE_TOPIC);
+ if ( valueIT instanceof String )
+ {
+ m_ignoreTopics = new String[] {(String)valueIT};
+ }
+ else if ( valueIT instanceof String[] )
+ {
+ m_ignoreTopics = (String[])valueIT;
+ }
+ else
+ {
+ LogWrapper.getLogger().log(LogWrapper.LOG_WARNING,
+ "Value for property: " + PROP_IGNORE_TOPIC + " is neither a string nor a string array - Using default");
+ }
m_logLevel = getIntProperty(PROP_LOG_LEVEL,
config.get(PROP_LOG_LEVEL),
LogWrapper.LOG_WARNING, // default log level is WARNING
@@ -322,7 +378,8 @@
m_async_pool,
m_timeout,
m_ignoreTimeout,
- m_requireTopic);
+ m_requireTopic,
+ m_ignoreTopics);
// Finally, adapt the outside events to our kind of events as per spec
adaptEvents(m_admin);
@@ -335,7 +392,7 @@
}
else
{
- m_admin.update(m_timeout, m_ignoreTimeout, m_requireTopic);
+ m_admin.update(m_timeout, m_ignoreTimeout, m_requireTopic, m_ignoreTopics);
}
}
@@ -406,7 +463,7 @@
{
return new MetaTypeProviderImpl((ManagedService)managedService,
m_threadPoolSize, m_timeout, m_requireTopic,
- m_ignoreTimeout);
+ m_ignoreTimeout, m_ignoreTopics);
}
catch (final Throwable t)
{
diff --git a/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/MetaTypeProviderImpl.java b/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/MetaTypeProviderImpl.java
index 5b6f939..8212411 100644
--- a/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/MetaTypeProviderImpl.java
+++ b/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/MetaTypeProviderImpl.java
@@ -40,19 +40,22 @@
private final int m_timeout;
private final boolean m_requireTopic;
private final String[] m_ignoreTimeout;
+ private final String[] m_ignoreTopic;
private final ManagedService m_delegatee;
public MetaTypeProviderImpl(final ManagedService delegatee,
final int threadPoolSize,
final int timeout, final boolean requireTopic,
- final String[] ignoreTimeout)
+ final String[] ignoreTimeout,
+ final String[] ignoreTopic)
{
m_threadPoolSize = threadPoolSize;
m_timeout = timeout;
m_requireTopic = requireTopic;
m_delegatee = delegatee;
m_ignoreTimeout = ignoreTimeout;
+ m_ignoreTopic = ignoreTopic;
}
private ObjectClassDefinition ocd;
@@ -121,6 +124,15 @@
"all handlers in this package and all subpackages are ignored. If the string neither " +
"ends with a dot nor with a star, this is assumed to define an exact class name.",
AttributeDefinition.STRING, m_ignoreTimeout, Integer.MAX_VALUE, null, null));
+ adList.add( new AttributeDefinitionImpl( Configuration.PROP_IGNORE_TIMEOUT, "Ignore Topics",
+ "For performance optimization it is possible to configure topics which are ignored " +
+ "by the event admin implementation. In this case, a event is not delivered to " +
+ "registered event handlers. The value is a list of strings (separated by comma). " +
+ "If a single value ends with a dot, all topics in exactly this package are ignored. " +
+ "If a single value ends with a star, all topics in this package and all sub packages " +
+ "are ignored. If a single value neither ends with a dot nor with a start, this is assumed " +
+ "to define an exact topic. A single star can be used to disable delivery completely.",
+ AttributeDefinition.STRING, m_ignoreTopic, Integer.MAX_VALUE, null, null));
ocd = new ObjectClassDefinition()
{
diff --git a/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventAdminImpl.java b/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventAdminImpl.java
index 3b33bde..8750818 100644
--- a/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventAdminImpl.java
+++ b/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventAdminImpl.java
@@ -18,6 +18,7 @@
*/
package org.apache.felix.eventadmin.impl.handler;
+import org.apache.felix.eventadmin.impl.handler.EventHandlerTracker.Matcher;
import org.apache.felix.eventadmin.impl.tasks.AsyncDeliverTasks;
import org.apache.felix.eventadmin.impl.tasks.DefaultThreadPool;
import org.apache.felix.eventadmin.impl.tasks.SyncDeliverTasks;
@@ -49,6 +50,9 @@
// The synchronous event dispatcher
private final SyncDeliverTasks m_sendManager;
+ // matchers for ignore topics
+ private Matcher[] m_ignoreTopics;
+
/**
* The constructor of the <tt>EventAdmin</tt> implementation.
*
@@ -61,7 +65,8 @@
final DefaultThreadPool asyncPool,
final int timeout,
final String[] ignoreTimeout,
- final boolean requireTopic)
+ final boolean requireTopic,
+ final String[] ignoreTopics)
{
checkNull(syncPool, "syncPool");
checkNull(asyncPool, "asyncPool");
@@ -71,6 +76,7 @@
this.tracker.open();
m_sendManager = new SyncDeliverTasks(syncPool, timeout);
m_postManager = new AsyncDeliverTasks(asyncPool, m_sendManager);
+ m_ignoreTopics = EventHandlerTracker.createMatchers(ignoreTopics);
}
/**
@@ -87,6 +93,26 @@
}
/**
+ * Check whether the topic should be delivered at all
+ */
+ private boolean checkTopic( final Event event )
+ {
+ boolean result = true;
+ if ( this.m_ignoreTopics != null )
+ {
+ for(final Matcher m : this.m_ignoreTopics)
+ {
+ if ( m.match(event.getTopic()) )
+ {
+ result = false;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
* Post an asynchronous event.
*
* @param event The event to be posted by this service
@@ -95,9 +121,13 @@
*
* @see org.osgi.service.event.EventAdmin#postEvent(org.osgi.service.event.Event)
*/
+ @Override
public void postEvent(final Event event)
{
- m_postManager.execute(this.getTracker().getHandlers(event), event);
+ if ( checkTopic(event) )
+ {
+ m_postManager.execute(this.getTracker().getHandlers(event), event);
+ }
}
/**
@@ -109,9 +139,13 @@
*
* @see org.osgi.service.event.EventAdmin#sendEvent(org.osgi.service.event.Event)
*/
+ @Override
public void sendEvent(final Event event)
{
- m_sendManager.execute(this.getTracker().getHandlers(event), event, false);
+ if ( checkTopic(event) )
+ {
+ m_sendManager.execute(this.getTracker().getHandlers(event), event, false);
+ }
}
/**
@@ -128,12 +162,14 @@
*/
public void update(final int timeout,
final String[] ignoreTimeout,
- final boolean requireTopic)
+ final boolean requireTopic,
+ final String[] ignoreTopics)
{
this.tracker.close();
this.tracker.update(ignoreTimeout, requireTopic);
this.m_sendManager.update(timeout);
this.tracker.open();
+ this.m_ignoreTopics = EventHandlerTracker.createMatchers(ignoreTopics);
}
/**
diff --git a/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java b/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java
index cf76a7c..077f32c 100644
--- a/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java
+++ b/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java
@@ -274,6 +274,47 @@
}
}
+ static Matcher[] createMatchers(final String[] config)
+ {
+ final Matcher[] matchers;
+ if ( config == null || config.length == 0 )
+ {
+ matchers = null;
+ }
+ else
+ {
+ matchers = new Matcher[config.length];
+ for(int i=0;i<config.length;i++)
+ {
+ String value = config[i];
+ if ( value != null )
+ {
+ value = value.trim();
+ }
+ if ( value != null && value.length() > 0 )
+ {
+ if ( value.endsWith(".") )
+ {
+ matchers[i] = new PackageMatcher(value.substring(0, value.length() - 1));
+ }
+ else if ( value.endsWith("*") )
+ {
+ if ( value.equals("*") )
+ {
+ return new Matcher[] {new MatcherAll()};
+ }
+ matchers[i] = new SubPackageMatcher(value.substring(0, value.length() - 1));
+ }
+ else
+ {
+ matchers[i] = new ClassMatcher(value);
+ }
+ }
+ }
+ }
+ return matchers;
+ }
+
/**
* The matcher interface for checking if timeout handling
* is disabled for the handler.
@@ -284,6 +325,16 @@
boolean match(String className);
}
+ /** Match all. */
+ private static final class MatcherAll implements Matcher
+ {
+ @Override
+ public boolean match(final String className)
+ {
+ return true;
+ }
+ }
+
/** Match a package. */
private static final class PackageMatcher implements Matcher
{
@@ -294,7 +345,7 @@
m_packageName = name;
}
@Override
- public boolean match(String className)
+ public boolean match(final String className)
{
final int pos = className.lastIndexOf('.');
return pos > -1 && className.substring(0, pos).equals(m_packageName);
@@ -311,7 +362,7 @@
m_packageName = name + '.';
}
@Override
- public boolean match(String className)
+ public boolean match(final String className)
{
final int pos = className.lastIndexOf('.');
return pos > -1 && className.substring(0, pos + 1).startsWith(m_packageName);
@@ -328,7 +379,7 @@
m_className = name;
}
@Override
- public boolean match(String className)
+ public boolean match(final String className)
{
return m_className.equals(className);
}