felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1236655 - in /felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl: ./ adapter/ dispatch/ handler/ security/ tasks/ util/
Date Fri, 27 Jan 2012 12:33:32 GMT
Author: cziegeler
Date: Fri Jan 27 12:33:31 2012
New Revision: 1236655

URL: http://svn.apache.org/viewvc?rev=1236655&view=rev
Log:
FELIX-3321 : Improve implementation and reduce load on the service registry

Added:
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventAdminImpl.java   (contents, props changed)
      - copied, changed from r1230000, felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/EventAdminImpl.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerProxy.java   (with props)
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java   (with props)
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/DefaultThreadPool.java   (contents, props changed)
      - copied, changed from r1230000, felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/dispatch/DefaultThreadPool.java
Removed:
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/EventAdminImpl.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/dispatch/
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/BlackList.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/BlacklistingHandlerTasks.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/CacheFilters.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/CacheTopicHandlerFilters.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/CleanBlackList.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/Filters.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/HandlerTasks.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/TopicHandlerFilters.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/DeliverTask.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/HandlerTask.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/HandlerTaskImpl.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/util/CacheMap.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/util/LeastRecentlyUsedCacheMap.java
Modified:
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/Configuration.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/MetaTypeProviderImpl.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/adapter/AbstractAdapter.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/security/EventAdminSecurityDecorator.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/security/PermissionsUtil.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/AsyncDeliverTasks.java
    felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/SyncDeliverTasks.java

Modified: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/Configuration.java
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/Configuration.java?rev=1236655&r1=1236654&r2=1236655&view=diff
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/Configuration.java (original)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/Configuration.java Fri Jan 27 12:33:31 2012
@@ -22,10 +22,9 @@ package org.apache.felix.eventadmin.impl
 import java.util.*;
 
 import org.apache.felix.eventadmin.impl.adapter.*;
-import org.apache.felix.eventadmin.impl.dispatch.DefaultThreadPool;
-import org.apache.felix.eventadmin.impl.handler.*;
+import org.apache.felix.eventadmin.impl.handler.EventAdminImpl;
 import org.apache.felix.eventadmin.impl.security.SecureEventAdminFactory;
-import org.apache.felix.eventadmin.impl.util.LeastRecentlyUsedCacheMap;
+import org.apache.felix.eventadmin.impl.tasks.DefaultThreadPool;
 import org.apache.felix.eventadmin.impl.util.LogWrapper;
 import org.osgi.framework.*;
 import org.osgi.service.cm.ConfigurationException;
@@ -41,14 +40,6 @@ import org.osgi.service.metatype.MetaTyp
  * The service knows about the following properties which are read at bundle startup:
  * <p>
  * <p>
- *      <tt>org.apache.felix.eventadmin.CacheSize</tt> - The size of various internal
- *          caches.
- * </p>
- * The default value is 30. Increase in case of a large number (more then 100) of
- * <tt>EventHandler</tt> services. A value less then 10 triggers the default value.
- * </p>
- * <p>
- * <p>
  *      <tt>org.apache.felix.eventadmin.ThreadPoolSize</tt> - The size of the thread
  *          pool.
  * </p>
@@ -96,13 +87,14 @@ import org.osgi.service.metatype.MetaTyp
  * 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.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class Configuration
 {
     /** The PID for the event admin. */
     static final String PID = "org.apache.felix.eventadmin.impl.EventAdmin";
 
-    static final String PROP_CACHE_SIZE = "org.apache.felix.eventadmin.CacheSize";
     static final String PROP_THREAD_POOL_SIZE = "org.apache.felix.eventadmin.ThreadPoolSize";
     static final String PROP_TIMEOUT = "org.apache.felix.eventadmin.Timeout";
     static final String PROP_REQUIRE_TOPIC = "org.apache.felix.eventadmin.RequireTopic";
@@ -112,8 +104,6 @@ public class Configuration
     /** The bundle context. */
     private final BundleContext m_bundleContext;
 
-    private int m_cacheSize;
-
     private int m_threadPoolSize;
 
     private int m_timeout;
@@ -207,14 +197,6 @@ public class Configuration
     {
         if ( config == null )
         {
-            // The size of various internal caches. At the moment there are 4
-            // internal caches affected. Each will cache the determined amount of
-            // small but frequently used objects (i.e., in case of the default value
-            // we end-up with a total of 120 small objects being cached). A value of less
-            // then 10 triggers the default value.
-            m_cacheSize = getIntProperty(PROP_CACHE_SIZE,
-                m_bundleContext.getProperty(PROP_CACHE_SIZE), 30, 10);
-
             // The size of the internal thread pool. Note that we must execute
             // each synchronous event dispatch that happens in the synchronous event
             // dispatching thread in a new thread, hence a small thread pool is o.k.
@@ -260,7 +242,6 @@ public class Configuration
         }
         else
         {
-            m_cacheSize = getIntProperty(PROP_CACHE_SIZE, config.get(PROP_CACHE_SIZE), 30, 10);
             m_threadPoolSize = getIntProperty(PROP_THREAD_POOL_SIZE, config.get(PROP_THREAD_POOL_SIZE), 20, 2);
             m_timeout = getIntProperty(PROP_TIMEOUT, config.get(PROP_TIMEOUT), 5000, Integer.MIN_VALUE);
             m_requireTopic = getBooleanProperty(config.get(PROP_REQUIRE_TOPIC), true);
@@ -297,21 +278,12 @@ public class Configuration
         LogWrapper.getLogger().log(LogWrapper.LOG_DEBUG,
                 PROP_LOG_LEVEL + "=" + m_logLevel);
         LogWrapper.getLogger().log(LogWrapper.LOG_DEBUG,
-                PROP_CACHE_SIZE + "=" + m_cacheSize);
-        LogWrapper.getLogger().log(LogWrapper.LOG_DEBUG,
             PROP_THREAD_POOL_SIZE + "=" + m_threadPoolSize);
         LogWrapper.getLogger().log(LogWrapper.LOG_DEBUG,
             PROP_TIMEOUT + "=" + m_timeout);
         LogWrapper.getLogger().log(LogWrapper.LOG_DEBUG,
             PROP_REQUIRE_TOPIC + "=" + m_requireTopic);
 
-        final TopicHandlerFilters topicHandlerFilters =
-            new CacheTopicHandlerFilters(new LeastRecentlyUsedCacheMap(m_cacheSize),
-            m_requireTopic);
-
-        final Filters filters = new CacheFilters(
-            new LeastRecentlyUsedCacheMap(m_cacheSize), m_bundleContext);
-
         // Note that this uses a lazy thread pool that will create new threads on
         // demand - in case none of its cached threads is free - until threadPoolSize
         // is reached. Subsequently, a threadPoolSize of 2 effectively disables
@@ -334,16 +306,14 @@ public class Configuration
             m_async_pool.configure(asyncThreadPoolSize);
         }
 
-        // The handlerTasks object is responsible to determine concerned EventHandler
-        // for a given event. Additionally, it keeps a list of blacklisted handlers.
-        // Note that blacklisting is deactivated by selecting a different scheduler
-        // below (and not in this HandlerTasks object!)
-        final HandlerTasks handlerTasks = new BlacklistingHandlerTasks(m_bundleContext,
-            new CleanBlackList(), topicHandlerFilters, filters);
-
         if ( m_admin == null )
         {
-            m_admin = new EventAdminImpl(handlerTasks, m_sync_pool, m_async_pool, m_timeout, m_ignoreTimeout);
+            m_admin = new EventAdminImpl(m_bundleContext,
+                    m_sync_pool,
+                    m_async_pool,
+                    m_timeout,
+                    m_ignoreTimeout,
+                    m_requireTopic);
 
             // Finally, adapt the outside events to our kind of events as per spec
             adaptEvents(m_admin);
@@ -356,7 +326,7 @@ public class Configuration
         }
         else
         {
-            m_admin.update(handlerTasks, m_timeout, m_ignoreTimeout);
+            m_admin.update(m_timeout, m_ignoreTimeout, m_requireTopic);
         }
 
     }
@@ -426,10 +396,10 @@ public class Configuration
         try
         {
             return new MetaTypeProviderImpl((ManagedService)managedService,
-                    m_cacheSize, m_threadPoolSize, m_timeout, m_requireTopic,
+                    m_threadPoolSize, m_timeout, m_requireTopic,
                     m_ignoreTimeout);
         }
-        catch (Throwable t)
+        catch (final Throwable t)
         {
             // we simply ignore this
         }

Modified: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/MetaTypeProviderImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/MetaTypeProviderImpl.java?rev=1236655&r1=1236654&r2=1236655&view=diff
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/MetaTypeProviderImpl.java (original)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/MetaTypeProviderImpl.java Fri Jan 27 12:33:31 2012
@@ -28,11 +28,12 @@ import org.osgi.service.metatype.*;
 
 /**
  * The optional meta type provider for the event admin config.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public class MetaTypeProviderImpl
     implements MetaTypeProvider, ManagedService
 {
-    private final int m_cacheSize;
     private final int m_threadPoolSize;
     private final int m_timeout;
     private final boolean m_requireTopic;
@@ -41,11 +42,10 @@ public class MetaTypeProviderImpl
     private final ManagedService m_delegatee;
 
     public MetaTypeProviderImpl(final ManagedService delegatee,
-            final int cacheSize, final int threadPoolSize,
+            final int threadPoolSize,
             final int timeout, final boolean requireTopic,
             final String[] ignoreTimeout)
     {
-        m_cacheSize = cacheSize;
         m_threadPoolSize = threadPoolSize;
         m_timeout = timeout;
         m_requireTopic = requireTopic;
@@ -85,11 +85,6 @@ public class MetaTypeProviderImpl
         {
             final ArrayList adList = new ArrayList();
 
-            adList.add( new AttributeDefinitionImpl( Configuration.PROP_CACHE_SIZE, "Cache Size",
-                    "The size of various internal caches. The default value is 30. Increase in case " +
-                    "of a large number (more then 100) of services. A value less then 10 triggers the " +
-                    "default value.", m_cacheSize) );
-
             adList.add( new AttributeDefinitionImpl( Configuration.PROP_THREAD_POOL_SIZE, "Thread Pool Size",
                 "The size of the thread pool. The default value is 10. Increase in case of a large amount " +
                 "of synchronous events where the event handler services in turn send new synchronous events in " +

Modified: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/adapter/AbstractAdapter.java
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/adapter/AbstractAdapter.java?rev=1236655&r1=1236654&r2=1236655&view=diff
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/adapter/AbstractAdapter.java (original)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/adapter/AbstractAdapter.java Fri Jan 27 12:33:31 2012
@@ -24,6 +24,7 @@ import org.osgi.service.event.EventAdmin
 /**
  * Abstract base class for all adapters.
  * This class allows to exchange the event admin at runtime
+ *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
 public abstract class AbstractAdapter

Copied: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventAdminImpl.java (from r1230000, felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/EventAdminImpl.java)
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventAdminImpl.java?p2=felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventAdminImpl.java&p1=felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/EventAdminImpl.java&r1=1230000&r2=1236655&rev=1236655&view=diff
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/EventAdminImpl.java (original)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventAdminImpl.java Fri Jan 27 12:33:31 2012
@@ -16,13 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.eventadmin.impl;
+package org.apache.felix.eventadmin.impl.handler;
 
-import java.util.List;
-
-import org.apache.felix.eventadmin.impl.dispatch.DefaultThreadPool;
-import org.apache.felix.eventadmin.impl.handler.HandlerTasks;
 import org.apache.felix.eventadmin.impl.tasks.*;
+import org.osgi.framework.BundleContext;
 import org.osgi.service.event.Event;
 import org.osgi.service.event.EventAdmin;
 
@@ -41,46 +38,53 @@ import org.osgi.service.event.EventAdmin
  */
 public class EventAdminImpl implements EventAdmin
 {
-    // The factory used to determine applicable EventHandlers - this will be replaced
-    // by a null object in stop() that subsequently throws an IllegalStateException
-    private volatile HandlerTasks m_managers;
+    /** The tracker for the event handlers. */
+    private volatile EventHandlerTracker tracker;
 
     // The asynchronous event dispatcher
-    private final DeliverTask m_postManager;
+    private final AsyncDeliverTasks m_postManager;
 
     // The synchronous event dispatcher
     private final SyncDeliverTasks m_sendManager;
 
     /**
-     * The constructor of the <tt>EventAdmin</tt> implementation. The
-     * <tt>HandlerTasks</tt> factory is used to determine applicable
-     * <tt>EventHandler</tt> for a given event. Additionally, the two
-     * <tt>DeliverTasks</tt> are used to dispatch the event.
+     * The constructor of the <tt>EventAdmin</tt> implementation.
      *
-     * @param managers The factory used to determine applicable <tt>EventHandler</tt>
      * @param syncPool The synchronous thread pool
      * @param asyncPool The asynchronous thread pool
      */
-    public EventAdminImpl(final HandlerTasks managers,
+    public EventAdminImpl(
+            final BundleContext bundleContext,
             final DefaultThreadPool syncPool,
             final DefaultThreadPool asyncPool,
             final int timeout,
-            final String[] ignoreTimeout)
+            final String[] ignoreTimeout,
+            final boolean requireTopic)
     {
-        checkNull(managers, "Managers");
         checkNull(syncPool, "syncPool");
         checkNull(asyncPool, "asyncPool");
 
-        m_managers = managers;
-
-        m_sendManager = new SyncDeliverTasks(syncPool,
-                (timeout > 100 ? timeout : 0),
-                ignoreTimeout);
-
+        this.tracker = new EventHandlerTracker(bundleContext);
+        this.tracker.update(ignoreTimeout, requireTopic);
+        this.tracker.open();
+        m_sendManager = new SyncDeliverTasks(syncPool, timeout);
         m_postManager = new AsyncDeliverTasks(asyncPool, m_sendManager);
     }
 
     /**
+     * Check if the event admin is active and return the tracker
+     * @return The tracker
+     * @throws IllegalArgumentException if the event admin has been stopped
+     */
+    private EventHandlerTracker getTracker() {
+        final EventHandlerTracker localTracker = tracker;
+        if ( localTracker == null ) {
+            throw new IllegalStateException("The EventAdmin is stopped");
+        }
+        return localTracker;
+    }
+
+    /**
      * Post an asynchronous event.
      *
      * @param event The event to be posted by this service
@@ -91,7 +95,7 @@ public class EventAdminImpl implements E
      */
     public void postEvent(final Event event)
     {
-        handleEvent(m_managers.createHandlerTasks(event), m_postManager);
+        m_postManager.execute(this.getTracker().getHandlers(event), event);
     }
 
     /**
@@ -105,65 +109,29 @@ public class EventAdminImpl implements E
      */
     public void sendEvent(final Event event)
     {
-        handleEvent(m_managers.createHandlerTasks(event), m_sendManager);
+        m_sendManager.execute(this.getTracker().getHandlers(event), event);
     }
 
     /**
-     * This method can be used to stop the delivery of events. The m_managers is
-     * replaced with a null object that throws an IllegalStateException on a call
-     * to <tt>createHandlerTasks()</tt>.
+     * This method can be used to stop the delivery of events.
      */
     public void stop()
     {
-        // replace the HandlerTasks with a null object that will throw an
-        // IllegalStateException on a call to createHandlerTasks
-        m_managers = new HandlerTasks()
-        {
-            /**
-             * This is a null object and this method will throw an
-             * IllegalStateException due to the bundle being stopped.
-             *
-             * @param event An event that is not used.
-             *
-             * @return This method does not return normally
-             *
-             * @throws IllegalStateException - This is a null object and this method
-             *          will always throw an IllegalStateException
-             */
-            public List createHandlerTasks(final Event event)
-            {
-                throw new IllegalStateException("The EventAdmin is stopped");
-            }
-        };
+        this.tracker.close();
+        this.tracker = null;
     }
 
     /**
      * Update the event admin with new configuration.
      */
-    public void update(final HandlerTasks managers, final int timeout,
-            final String[] ignoreTimeout)
-    {
-        m_managers = managers;
-        m_sendManager.update(timeout, ignoreTimeout);
-    }
-
-    /**
-     * This is a utility method that uses the given DeliverTasks to create a
-     * dispatch tasks that subsequently is used to dispatch the given HandlerTasks.
-     */
-    private void handleEvent(List managers,
-        final DeliverTask manager)
-    {
-        if (managers != null && managers.size() > 0 )
-        {
-            // This might throw an IllegalStateException in case that we are stopped
-            // and the null object for m_managers was not fast enough established
-            // This is needed in the adapter/* classes due to them sending
-            // events whenever they receive an event from their source.
-            // Service importers that call us regardless of the fact that we are
-            // stopped deserve an exception anyways
-            manager.execute(managers);
-        }
+    public void update(final int timeout,
+            final String[] ignoreTimeout,
+            final boolean requireTopic)
+    {
+        this.tracker.close();
+        this.tracker.update(ignoreTimeout, requireTopic);
+        this.m_sendManager.update(timeout);
+        this.tracker.open();
     }
 
     /**
@@ -173,7 +141,7 @@ public class EventAdminImpl implements E
      */
     private void checkNull(final Object object, final String name)
     {
-        if(null == object)
+        if (null == object)
         {
             throw new NullPointerException(name + " may not be null");
         }

Propchange: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventAdminImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerProxy.java
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerProxy.java?rev=1236655&view=auto
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerProxy.java (added)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerProxy.java Fri Jan 27 12:33:31 2012
@@ -0,0 +1,342 @@
+/*
+ * 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.eventadmin.impl.handler;
+
+import org.apache.felix.eventadmin.impl.security.PermissionsUtil;
+import org.apache.felix.eventadmin.impl.util.LogWrapper;
+import org.osgi.framework.*;
+import org.osgi.service.event.*;
+
+/**
+ * This is a proxy for event handlers. It gets the real event handler
+ * on demand and prepares some information for faster processing.
+ *
+ * It checks the timeout handling for the implementation as well as
+ * blacklisting the handler.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class EventHandlerProxy {
+
+    /** The service reference for the event handler. */
+    private final ServiceReference reference;
+
+    /** The handler context. */
+    private final EventHandlerTracker.HandlerContext handlerContext;
+
+    /** The event topics. */
+    private volatile String[] topics;
+
+    /** Optional filter. */
+    private volatile Filter filter;
+
+    /** Lazy fetched event handler. */
+    private volatile EventHandler handler;
+
+    /** Is this handler blacklisted? */
+    private volatile boolean blacklisted;
+
+    /** Use timeout. */
+    private boolean useTimeout;
+
+	/**
+	 * Create an EventHandlerProxy.
+     *
+     * @param context The handler context
+	 * @param reference Reference to the EventHandler
+	 */
+	public EventHandlerProxy(final EventHandlerTracker.HandlerContext context,
+	        final ServiceReference reference)
+	{
+	    this.handlerContext = context;
+		this.reference = reference;
+	}
+
+	/**
+	 * Update the state with current properties from the service
+	 * @return <code>true</code> if the handler configuration is valid.
+	 */
+	public boolean update()
+	{
+	    this.blacklisted = false;
+		boolean valid = true;
+		// First check, topic
+        final Object topicObj = reference.getProperty(EventConstants.EVENT_TOPIC);
+        if (topicObj instanceof String)
+        {
+            if ( topicObj.toString().equals("*") )
+            {
+                this.topics = null;
+            }
+            else
+            {
+                this.topics = new String[] {topicObj.toString()};
+            }
+        }
+        else if (topicObj instanceof String[])
+        {
+            // check if one value matches '*'
+            final String[] values = (String[])topicObj;
+            boolean matchAll = false;
+            for(int i=0;i<values.length;i++)
+            {
+                if ( "*".equals(values[i]) )
+                {
+                    matchAll = true;
+                }
+            }
+            if ( matchAll )
+            {
+                this.topics = null;
+            }
+            else
+            {
+                this.topics = values;
+            }
+        }
+        else if ( topicObj == null && !this.handlerContext.requireTopic )
+        {
+            this.topics = null;
+        }
+        else
+        {
+            final String reason;
+            if ( topicObj == null )
+            {
+                reason = "Missing";
+            }
+            else
+            {
+                reason = "Neither of type String nor String[] : " + topicObj.getClass().getName();
+            }
+            LogWrapper.getLogger().log(
+                    this.reference,
+                    LogWrapper.LOG_WARNING,
+                    "Invalid EVENT_TOPICS : " + reason + " - Ignoring ServiceReference ["
+                        + this.reference + " | Bundle("
+                        + this.reference.getBundle() + ")]");
+            this.topics = null;
+            valid = false;
+        }
+        // Second check filter (but only if topics is valid)
+        Filter handlerFilter = null;
+        if ( this.topics != null )
+        {
+            final Object filterObj = reference.getProperty(EventConstants.EVENT_FILTER);
+            if (filterObj instanceof String)
+            {
+                try
+                {
+                    handlerFilter = this.handlerContext.bundleContext.createFilter(filterObj.toString());
+                }
+                catch (final InvalidSyntaxException e)
+                {
+                    valid = false;
+                    LogWrapper.getLogger().log(
+                            this.reference,
+                            LogWrapper.LOG_WARNING,
+                            "Invalid EVENT_FILTER - Ignoring ServiceReference ["
+                                + this.reference + " | Bundle("
+                                + this.reference.getBundle() + ")]", e);
+                }
+            }
+            else if ( filterObj != null )
+            {
+                valid = false;
+                LogWrapper.getLogger().log(
+                        this.reference,
+                        LogWrapper.LOG_WARNING,
+                        "Invalid EVENT_FILTER - Ignoring ServiceReference ["
+                            + this.reference + " | Bundle("
+                            + this.reference.getBundle() + ")]");
+            }
+        }
+        this.filter = handlerFilter;
+
+        // make sure to release the handler
+        this.release();
+
+        return valid;
+	}
+
+	/**
+	 * Dispose the proxy and release the handler
+	 */
+	public void dispose()
+	{
+	    this.release();
+	}
+
+    /**
+     * Get the event handler.
+     */
+    private synchronized EventHandler obtain() {
+        if (this.handler == null)
+        {
+            try
+            {
+                this.handler = (EventHandler)this.handlerContext.bundleContext.getService(this.reference);
+                if ( this.handler != null )
+                {
+                    this.checkTimeout(this.handler.getClass().getName());
+                }
+            }
+            catch (final IllegalStateException ignore)
+            {
+                // event handler might be stopped - ignore
+            }
+        }
+        return this.handler;
+    }
+
+    /**
+	 * Release the handler
+	 */
+	private synchronized void release()
+	{
+		if ( this.handler != null )
+		{
+            try
+            {
+                this.handlerContext.bundleContext.ungetService(this.reference);
+            }
+            catch (final IllegalStateException ignore)
+            {
+                // event handler might be stopped - ignore
+            }
+            this.handler = null;
+		}
+	}
+
+	/**
+	 * Get the topics of this handler.
+	 * If this handler matches all topics <code>null</code> is returned
+	 */
+	public String[] getTopics()
+	{
+	    return this.topics;
+	}
+
+    /**
+     * Check if this handler is allowed to receive the event
+     * - blacklisted
+     * - check filter
+     * - check permission
+     */
+    public boolean canDeliver(final Event event)
+    {
+        if ( this.blacklisted )
+        {
+            return false;
+        }
+        final Bundle bundle = reference.getBundle();
+        // is service unregistered?
+        if (bundle == null)
+        {
+            return false;
+        }
+
+        // filter match
+        final Filter eventFilter = this.filter;
+        if ( eventFilter != null && !event.matches(eventFilter) )
+        {
+            return false;
+        }
+
+        // permission check
+        final Object p = PermissionsUtil.createSubscribePermission(event.getTopic());
+        if (p != null && !bundle.hasPermission(p) )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Should a timeout be used for this handler?
+     */
+    public boolean useTimeout()
+    {
+        return this.useTimeout;
+    }
+
+    /**
+     * Check the timeout configuration for this handler.
+     */
+    private void checkTimeout(final String className)
+    {
+        if ( this.handlerContext.ignoreTimeoutMatcher != null )
+        {
+            for(int i=0;i<this.handlerContext.ignoreTimeoutMatcher.length;i++)
+            {
+                if ( this.handlerContext.ignoreTimeoutMatcher[i] != null)
+                {
+                    if ( this.handlerContext.ignoreTimeoutMatcher[i].match(className) )
+                    {
+                        this.useTimeout = false;
+                        return;
+                    }
+                }
+            }
+        }
+        this.useTimeout = true;
+    }
+
+    /**
+	 * Send the event.
+	 */
+	public void sendEvent(final Event event)
+	{
+		final EventHandler handlerService = this.obtain();
+		if (handlerService == null)
+		{
+			return;
+		}
+
+		try
+		{
+			handlerService.handleEvent(event);
+		}
+		catch (final Throwable e)
+		{
+            // The spec says that we must catch exceptions and log them:
+            LogWrapper.getLogger().log(
+                this.reference,
+                LogWrapper.LOG_WARNING,
+                "Exception during event dispatch [" + event + " | "
+                    + this.reference + " | Bundle("
+                    + this.reference.getBundle() + ")]", e);
+		}
+	}
+
+	/**
+	 * Blacklist the handler.
+	 */
+	public void blackListHandler()
+	{
+        LogWrapper.getLogger().log(
+                LogWrapper.LOG_WARNING,
+                "Blacklisting ServiceReference [" + this.reference + " | Bundle("
+                    + this.reference.getBundle() + ")] due to timeout!");
+        this.blacklisted = true;
+        // we can free the handler now.
+        this.release();
+	}
+}

Propchange: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerProxy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerProxy.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerProxy.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java?rev=1236655&view=auto
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java (added)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java Fri Jan 27 12:33:31 2012
@@ -0,0 +1,396 @@
+/*
+ * 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.eventadmin.impl.handler;
+
+import java.util.*;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * The event handler tracker keeps track of all event handler services.
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class EventHandlerTracker extends ServiceTracker {
+
+    /** The proxies in this list match all events. */
+	private volatile List matchingAllEvents;
+
+    /** This is a map for exact topic matches. The key is the topic,
+     * the value is a list of proxies.
+     */
+    private volatile Map matchingTopic;
+
+	/** This is a map for wildcard topics. The key is the prefix of the topic,
+	 * the value is a list of proxies
+	 */
+	private volatile Map matchingPrefixTopic;
+
+
+	/** The context for the proxies. */
+	private HandlerContext handlerContext;
+
+    public EventHandlerTracker(final BundleContext context) {
+		super(context, EventHandler.class.getName(), null);
+
+		// we start with empty collections
+		this.matchingAllEvents = new ArrayList();
+		this.matchingTopic = new HashMap();
+		this.matchingPrefixTopic = new HashMap();
+	}
+
+    /**
+     * Update the timeout configuration.
+     * @param ignoreTimeout
+     */
+    public void update(final String[] ignoreTimeout, final boolean requireTopic) {
+        final Matcher[] ignoreTimeoutMatcher;
+        if ( ignoreTimeout == null || ignoreTimeout.length == 0 )
+        {
+            ignoreTimeoutMatcher = null;
+        }
+        else
+        {
+            ignoreTimeoutMatcher = new Matcher[ignoreTimeout.length];
+            for(int i=0;i<ignoreTimeout.length;i++)
+            {
+                String value = ignoreTimeout[i];
+                if ( value != null )
+                {
+                    value = value.trim();
+                }
+                if ( value != null && value.length() > 0 )
+                {
+                    if ( value.endsWith(".") )
+                    {
+                        ignoreTimeoutMatcher[i] = new PackageMatcher(value.substring(0, value.length() - 1));
+                    }
+                    else if ( value.endsWith("*") )
+                    {
+                        ignoreTimeoutMatcher[i] = new SubPackageMatcher(value.substring(0, value.length() - 1));
+                    }
+                    else
+                    {
+                        ignoreTimeoutMatcher[i] = new ClassMatcher(value);
+                    }
+                }
+            }
+        }
+        this.handlerContext = new HandlerContext(this.context, ignoreTimeoutMatcher, requireTopic);
+    }
+
+    /**
+	 * @see org.osgi.util.tracker.ServiceTracker#addingService(org.osgi.framework.ServiceReference)
+	 */
+	public Object addingService(final ServiceReference reference) {
+		final EventHandlerProxy proxy = new EventHandlerProxy(this.handlerContext, reference);
+		if ( proxy.update() ) {
+			this.put(proxy);
+		}
+		return proxy;
+	}
+
+	/**
+	 * @see org.osgi.util.tracker.ServiceTracker#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
+	 */
+	public void modifiedService(final ServiceReference reference, final Object service) {
+	    final EventHandlerProxy proxy = (EventHandlerProxy)service;
+	    this.remove(proxy);
+	    if ( proxy.update() ) {
+            this.put(proxy);
+	    }
+	}
+
+	/**
+	 * @see org.osgi.util.tracker.ServiceTracker#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
+	 */
+	public void removedService(ServiceReference reference, Object service) {
+        final EventHandlerProxy proxy = (EventHandlerProxy)service;
+        this.remove(proxy);
+        proxy.dispose();
+	}
+
+	private void updateMap(final Map proxyListMap, final String key, final EventHandlerProxy proxy, final boolean add) {
+        List proxies = (List)proxyListMap.get(key);
+        if (proxies == null) {
+            if ( !add )
+            {
+                return;
+            }
+            proxies = new ArrayList();
+        } else {
+            proxies = new ArrayList(proxies);
+        }
+        if ( add )
+        {
+            proxies.add(proxy);
+        }
+        else
+        {
+            proxies.remove(proxy);
+        }
+        if ( proxies.size() == 0 )
+        {
+            proxyListMap.remove(key);
+        }
+        else
+        {
+            proxyListMap.put(key, proxies);
+        }
+	}
+
+	/**
+	 * Check the topics of the event handler and put it into the
+	 * corresponding collections.
+	 * We always create new collections - while this is "expensive"
+	 * it allows us to read from them unsynced
+	 */
+	private synchronized void put(final EventHandlerProxy proxy) {
+		final String[] topics = proxy.getTopics();
+		if ( topics == null )
+		{
+		    final List newMatchingAllEvents = new ArrayList(this.matchingAllEvents);
+		    newMatchingAllEvents.add(proxy);
+		    this.matchingAllEvents = newMatchingAllEvents;
+		}
+		else
+		{
+		    Map newMatchingTopic = null;
+		    Map newMatchingPrefixTopic = null;
+    		for(int i = 0; i < topics.length; i++) {
+    			final String topic = topics[i];
+
+    			if ( topic.endsWith("/*") )
+    			{
+                    // prefix topic: we remove the /*
+    			    if ( newMatchingPrefixTopic == null )
+    			    {
+    			        newMatchingPrefixTopic = new HashMap(this.matchingPrefixTopic);
+    			    }
+
+    				final String prefix = topic.substring(0, topic.length() - 2);
+                    this.updateMap(newMatchingPrefixTopic, prefix, proxy, true);
+    			}
+    			else
+    			{
+    			    // exact match
+                    if ( newMatchingTopic == null )
+                    {
+                        newMatchingTopic = new HashMap(this.matchingTopic);
+                    }
+
+                    this.updateMap(newMatchingTopic, topic, proxy, true);
+    			}
+    		}
+    		if ( newMatchingTopic != null )
+    		{
+    		    this.matchingTopic = newMatchingTopic;
+    		}
+    		if ( newMatchingPrefixTopic != null )
+    		{
+    		    this.matchingPrefixTopic = newMatchingPrefixTopic;
+    		}
+		}
+	}
+
+    /**
+     * Check the topics of the event handler and remove it from the
+     * corresponding collections.
+     * We always create new collections - while this is "expensive"
+     * it allows us to read from them unsynced
+     */
+	private synchronized void remove(final EventHandlerProxy proxy) {
+        final String[] topics = proxy.getTopics();
+        if ( topics == null )
+        {
+            final List newMatchingAllEvents = new ArrayList(this.matchingAllEvents);
+            newMatchingAllEvents.remove(proxy);
+            this.matchingAllEvents = newMatchingAllEvents;
+        } else {
+            Map newMatchingTopic = null;
+            Map newMatchingPrefixTopic = null;
+            for(int i = 0; i < topics.length; i++) {
+                final String topic = topics[i];
+
+                if ( topic.endsWith("/*") )
+                {
+                    // prefix topic: we remove the /*
+                    if ( newMatchingPrefixTopic == null )
+                    {
+                        newMatchingPrefixTopic = new HashMap(this.matchingPrefixTopic);
+                    }
+
+                    final String prefix = topic.substring(0, topic.length() - 2);
+                    this.updateMap(newMatchingPrefixTopic, prefix, proxy, false);
+                }
+                else
+                {
+                    // exact match
+                    if ( newMatchingTopic == null )
+                    {
+                        newMatchingTopic = new HashMap(this.matchingTopic);
+                    }
+
+                    this.updateMap(newMatchingTopic, topic, proxy, false);
+                }
+            }
+            if ( newMatchingTopic != null )
+            {
+                this.matchingTopic = newMatchingTopic;
+            }
+            if ( newMatchingPrefixTopic != null )
+            {
+                this.matchingPrefixTopic = newMatchingPrefixTopic;
+            }
+        }
+	}
+
+	/**
+	 * Get all handlers for this event
+	 *
+	 * @param event The event topic
+	 * @return All handlers for the event
+	 */
+	public Collection getHandlers(final Event event) {
+	    final String topic = event.getTopic();
+
+		final Set handlers = new HashSet();
+
+		// Add all handlers matching everything
+		handlers.addAll(this.matchingAllEvents);
+
+		// Now check for prefix matches
+		if ( !this.matchingPrefixTopic.isEmpty() )
+		{
+		    int pos = topic.lastIndexOf('/');
+			while (pos != -1)
+			{
+			    final String prefix = topic.substring(0, pos);
+				List proxies = (List)this.matchingPrefixTopic.get(prefix);
+				if (proxies != null)
+				{
+					handlers.addAll(proxies);
+				}
+
+				pos = prefix.lastIndexOf('/');
+			}
+		}
+
+		// Add the handlers for matching topic names
+		List proxies = (List)this.matchingTopic.get(topic);
+		if (proxies != null) {
+			handlers.addAll(proxies);
+		}
+
+		// now check permission and filters
+		final Iterator i = handlers.iterator();
+		while ( i.hasNext() ) {
+		    final EventHandlerProxy proxy = (EventHandlerProxy) i.next();
+		    if ( !proxy.canDeliver(event) ) {
+		        i.remove();
+		    }
+		}
+		return handlers;
+	}
+
+    /**
+     * The matcher interface for checking if timeout handling
+     * is disabled for the handler.
+     * Matching is based on the class name of the event handler.
+     */
+    static interface Matcher
+    {
+        boolean match(String className);
+    }
+
+    /** Match a package. */
+    private static final class PackageMatcher implements Matcher
+    {
+        private final String m_packageName;
+
+        public PackageMatcher(final String name)
+        {
+            m_packageName = name;
+        }
+        public boolean match(String className)
+        {
+            final int pos = className.lastIndexOf('.');
+            return pos > -1 && className.substring(0, pos).equals(m_packageName);
+        }
+    }
+
+    /** Match a package or sub package. */
+    private static final class SubPackageMatcher implements Matcher
+    {
+        private final String m_packageName;
+
+        public SubPackageMatcher(final String name)
+        {
+            m_packageName = name + '.';
+        }
+        public boolean match(String className)
+        {
+            final int pos = className.lastIndexOf('.');
+            return pos > -1 && className.substring(0, pos + 1).startsWith(m_packageName);
+        }
+    }
+
+    /** Match a class name. */
+    private static final class ClassMatcher implements Matcher
+    {
+        private final String m_className;
+
+        public ClassMatcher(final String name)
+        {
+            m_className = name;
+        }
+        public boolean match(String className)
+        {
+            return m_className.equals(className);
+        }
+    }
+
+    /**
+     * The context object passed to the proxies.
+     */
+    static final class HandlerContext
+    {
+        /** The bundle context. */
+        public final BundleContext bundleContext;
+
+        /** The matchers for ignore timeout handling. */
+        public final Matcher[] ignoreTimeoutMatcher;
+
+        /** Is a topic required. */
+        public final boolean requireTopic;
+
+        public HandlerContext(final BundleContext bundleContext,
+                final Matcher[] ignoreTimeoutMatcher,
+                final boolean   requireTopic)
+        {
+            this.bundleContext = bundleContext;
+            this.ignoreTimeoutMatcher = ignoreTimeoutMatcher;
+            this.requireTopic = requireTopic;
+        }
+    }
+}

Propchange: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/handler/EventHandlerTracker.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/security/EventAdminSecurityDecorator.java
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/security/EventAdminSecurityDecorator.java?rev=1236655&r1=1236654&r2=1236655&view=diff
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/security/EventAdminSecurityDecorator.java (original)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/security/EventAdminSecurityDecorator.java Fri Jan 27 12:33:31 2012
@@ -18,6 +18,8 @@
  */
 package org.apache.felix.eventadmin.impl.security;
 
+import java.security.Permission;
+
 import org.osgi.framework.Bundle;
 import org.osgi.service.event.Event;
 import org.osgi.service.event.EventAdmin;
@@ -128,7 +130,7 @@ public class EventAdminSecurityDecorator
         return m_admin.equals(o);
     }
 
-    /*
+    /**
      * This is a utility method that will throw a <tt>SecurityExcepiton</tt> in case
      * that the given bundle (i.e, the caller) has not appropriate permissions to
      * publish to this topic. This method uses Bundle.hasPermission() and the given
@@ -136,7 +138,8 @@ public class EventAdminSecurityDecorator
      */
     private void checkPermission(final String topic)
     {
-        if(!m_bundle.hasPermission(PermissionsUtil.createPublishPermission(topic)))
+        final Permission p = PermissionsUtil.createPublishPermission(topic);
+        if(p != null && !m_bundle.hasPermission(p))
         {
             throw new SecurityException("Bundle[" + m_bundle +
                 "] has no PUBLISH permission for topic [" + topic + "]");

Modified: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/security/PermissionsUtil.java
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/security/PermissionsUtil.java?rev=1236655&r1=1236654&r2=1236655&view=diff
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/security/PermissionsUtil.java (original)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/security/PermissionsUtil.java Fri Jan 27 12:33:31 2012
@@ -18,6 +18,8 @@
  */
 package org.apache.felix.eventadmin.impl.security;
 
+import java.security.Permission;
+
 import org.osgi.service.event.TopicPermission;
 
 /**
@@ -27,74 +29,61 @@ import org.osgi.service.event.TopicPermi
  */
 public abstract class PermissionsUtil
 {
+    /** Marker if permission created failed. */
+    private static volatile boolean createPermissions = true;
+
     /**
      * Creates a <tt>TopicPermission</tt> for the given topic and the type PUBLISH
-     * Note that a
-     * <tt>java.lang.Object</tt> is returned in case creating a new TopicPermission
-     * fails. This assumes that Bundle.hasPermission is used in order to evaluate the
-     * created Permission which in turn will return true if security is not supported
-     * by the framework. Otherwise, it will return false due to receiving something
-     * that is not a subclass of <tt>java.lang.SecurityPermission</tt> hence, this
-     * combination ensures that access is granted in case a topic permission could
-     * not be created due to missing security support by the framework.
      *
      * @param topic The target topic
      *
-     * @return The created permission or a <tt>java.lang.Object</tt> in case the
-     *      permission could not be created.
+     * @return The created permission or <tt>null</tt> in case the
+     *         permission could not be created.
      *
      * @see org.osgi.service.event.TopicPermission
      */
-    public static Object createPublishPermission(final String topic)
+    public static Permission createPublishPermission(final String topic)
     {
-        Object result;
-        try
-        {
-            result = new org.osgi.service.event.TopicPermission(topic, TopicPermission.PUBLISH);
-        } catch (Throwable t)
+        if ( createPermissions )
         {
-            // This might happen in case security is not supported
-            // Bundle.hasPermission will return true in this case
-            // hence topicPermission = new Object() is o.k.
-
-            result = new Object();
+            try
+            {
+                return new org.osgi.service.event.TopicPermission(topic, TopicPermission.PUBLISH);
+            }
+            catch (Throwable t)
+            {
+                // This might happen in case security is not supported
+                createPermissions = false;
+            }
         }
-        return result;
+        return null;
     }
 
     /**
      * Creates a <tt>TopicPermission</tt> for the given topic and the type SUBSCRIBE
      * Note that a
-     * <tt>java.lang.Object</tt> is returned in case creating a new TopicPermission
-     * fails. This assumes that Bundle.hasPermission is used in order to evaluate the
-     * created Permission which in turn will return true if security is not supported
-     * by the framework. Otherwise, it will return false due to receiving something
-     * that is not a subclass of <tt>java.lang.SecurityPermission</tt> hence, this
-     * combination ensures that access is granted in case a topic permission could
-     * not be created due to missing security support by the framework.
      *
      * @param topic The target topic
      *
-     * @return The created permission or a <tt>java.lang.Object</tt> in case the
+     * @return The created permission or a <tt>null</tt> in case the
      *      permission could not be created.
      *
      * @see org.osgi.service.event.TopicPermission
      */
-    public static Object createSubscribePermission(final String topic)
+    public static Permission createSubscribePermission(final String topic)
     {
-        Object result;
-        try
-        {
-            result = new org.osgi.service.event.TopicPermission(topic, TopicPermission.SUBSCRIBE);
-        } catch (Throwable t)
+        if ( createPermissions )
         {
-            // This might happen in case security is not supported
-            // Bundle.hasPermission will return true in this case
-            // hence topicPermission = new Object() is o.k.
-
-            result = new Object();
+            try
+            {
+                return new org.osgi.service.event.TopicPermission(topic, TopicPermission.SUBSCRIBE);
+            }
+            catch (Throwable t)
+            {
+                // This might happen in case security is not supported
+                createPermissions = false;
+            }
         }
-        return result;
+        return null;
     }
-
 }

Modified: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/AsyncDeliverTasks.java
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/AsyncDeliverTasks.java?rev=1236655&r1=1236654&r2=1236655&view=diff
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/AsyncDeliverTasks.java (original)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/AsyncDeliverTasks.java Fri Jan 27 12:33:31 2012
@@ -20,14 +20,14 @@ package org.apache.felix.eventadmin.impl
 
 import java.util.*;
 
-import org.apache.felix.eventadmin.impl.dispatch.DefaultThreadPool;
+import org.osgi.service.event.Event;
 
 /**
  * This class does the actual work of the asynchronous event dispatch.
  *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class AsyncDeliverTasks implements DeliverTask
+public class AsyncDeliverTasks
 {
     /** The thread pool to use to spin-off new threads. */
     private final DefaultThreadPool m_pool;
@@ -36,7 +36,7 @@ public class AsyncDeliverTasks implement
      * is the sync deliver tasks as this has all the code for timeout
      * handling etc.
      */
-    private final DeliverTask m_deliver_task;
+    private final SyncDeliverTasks m_deliver_task;
 
     /** A map of running threads currently delivering async events. */
     private final Map m_running_threads = new HashMap();
@@ -49,7 +49,7 @@ public class AsyncDeliverTasks implement
      *      dispatching thread is used to send a synchronous event
      * @param deliverTask The deliver tasks for dispatching the event.
      */
-    public AsyncDeliverTasks(final DefaultThreadPool pool, final DeliverTask deliverTask)
+    public AsyncDeliverTasks(final DefaultThreadPool pool, final SyncDeliverTasks deliverTask)
     {
         m_pool = pool;
         m_deliver_task = deliverTask;
@@ -60,9 +60,8 @@ public class AsyncDeliverTasks implement
      *
      * @param tasks The event handler dispatch tasks to execute
      *
-     * @see org.apache.felix.eventadmin.impl.tasks.DeliverTask#execute(org.apache.felix.eventadmin.impl.tasks.HandlerTask[])
      */
-    public void execute(final List tasks)
+    public void execute(final Collection tasks, final Event event)
     {
         final Thread currentThread = Thread.currentThread();
         TaskExecuter executer = null;
@@ -71,11 +70,11 @@ public class AsyncDeliverTasks implement
             TaskExecuter runningExecutor = (TaskExecuter)m_running_threads.get(currentThread);
             if ( runningExecutor != null )
             {
-                runningExecutor.add(tasks);
+                runningExecutor.add(tasks, event);
             }
             else
             {
-                executer = new TaskExecuter( tasks, currentThread );
+                executer = new TaskExecuter( tasks, event, currentThread );
                 m_running_threads.put(currentThread, executer);
             }
         }
@@ -91,10 +90,10 @@ public class AsyncDeliverTasks implement
 
         private final Object m_key;
 
-        public TaskExecuter(final List tasks, final Object key)
+        public TaskExecuter(final Collection tasks, final Event event, final Object key)
         {
             m_key = key;
-            m_tasks.add(tasks);
+            m_tasks.add(new Object[] {tasks, event});
         }
 
         public void run()
@@ -102,12 +101,12 @@ public class AsyncDeliverTasks implement
             boolean running;
             do
             {
-                List tasks = null;
+                Object[] tasks = null;
                 synchronized ( m_tasks )
                 {
-                    tasks = (List) m_tasks.remove(0);
+                    tasks = (Object[]) m_tasks.remove(0);
                 }
-                m_deliver_task.execute(tasks);
+                m_deliver_task.execute((Collection)tasks[0], (Event)tasks[1]);
                 synchronized ( m_running_threads )
                 {
                     running = m_tasks.size() > 0;
@@ -119,11 +118,11 @@ public class AsyncDeliverTasks implement
             } while ( running );
         }
 
-        public void add(final List tasks)
+        public void add(final Collection tasks, final Event event)
         {
             synchronized ( m_tasks )
             {
-                m_tasks.add(tasks);
+                m_tasks.add(new Object[] {tasks, event});
             }
         }
     }

Copied: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/DefaultThreadPool.java (from r1230000, felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/dispatch/DefaultThreadPool.java)
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/DefaultThreadPool.java?p2=felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/DefaultThreadPool.java&p1=felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/dispatch/DefaultThreadPool.java&r1=1230000&r2=1236655&rev=1236655&view=diff
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/dispatch/DefaultThreadPool.java (original)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/DefaultThreadPool.java Fri Jan 27 12:33:31 2012
@@ -14,9 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.felix.eventadmin.impl.dispatch;
+package org.apache.felix.eventadmin.impl.tasks;
 
-import org.apache.felix.eventadmin.impl.tasks.SyncThread;
 import org.apache.felix.eventadmin.impl.util.LogWrapper;
 
 import EDU.oswego.cs.dl.util.concurrent.*;
@@ -95,13 +94,13 @@ public class DefaultThreadPool
      * Execute the task in a free thread or create a new one.
      * @param task The task to execute
      */
-    public void executeTask(Runnable task)
+    public void executeTask(final Runnable task)
     {
         try
         {
             super.execute(task);
         }
-        catch (Throwable t)
+        catch (final Throwable t)
         {
             LogWrapper.getLogger().log(
                     LogWrapper.LOG_WARNING,

Propchange: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/DefaultThreadPool.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/DefaultThreadPool.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/DefaultThreadPool.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/SyncDeliverTasks.java
URL: http://svn.apache.org/viewvc/felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/SyncDeliverTasks.java?rev=1236655&r1=1236654&r2=1236655&view=diff
==============================================================================
--- felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/SyncDeliverTasks.java (original)
+++ felix/trunk/eventadmin/impl/src/main/java/org/apache/felix/eventadmin/impl/tasks/SyncDeliverTasks.java Fri Jan 27 12:33:31 2012
@@ -18,10 +18,11 @@
  */
 package org.apache.felix.eventadmin.impl.tasks;
 
+import java.util.Collection;
 import java.util.Iterator;
-import java.util.List;
 
-import org.apache.felix.eventadmin.impl.dispatch.DefaultThreadPool;
+import org.apache.felix.eventadmin.impl.handler.EventHandlerProxy;
+import org.osgi.service.event.Event;
 
 import EDU.oswego.cs.dl.util.concurrent.TimeoutException;
 
@@ -52,119 +53,30 @@ import EDU.oswego.cs.dl.util.concurrent.
  *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public class SyncDeliverTasks implements DeliverTask
+public class SyncDeliverTasks
 {
+
     /** The thread pool used to spin-off new threads. */
-    final DefaultThreadPool m_pool;
+    private final DefaultThreadPool pool;
 
-    /** The timeout for event handlers, 0 = disabled. */
-    long m_timeout;
+    private long timeout;
 
     /**
-     * The matcher interface for checking if timeout handling
-     * is disabled for the handler.
-     * Matching is based on the class name of the event handler.
+     * Construct a new sync deliver tasks.
+     * @param pool The thread pool used to spin-off new threads.
      */
-    private static interface Matcher
-    {
-        boolean match(String className);
-    }
-
-    /** Match a package. */
-    private static final class PackageMatcher implements Matcher
-    {
-        private final String m_packageName;
-
-        public PackageMatcher(final String name)
-        {
-            m_packageName = name;
-        }
-        public boolean match(String className)
-        {
-            final int pos = className.lastIndexOf('.');
-            return pos > -1 && className.substring(0, pos).equals(m_packageName);
-        }
-    }
-
-    /** Match a package or sub package. */
-    private static final class SubPackageMatcher implements Matcher
+    public SyncDeliverTasks(final DefaultThreadPool pool, final long timeout)
     {
-        private final String m_packageName;
-
-        public SubPackageMatcher(final String name)
-        {
-            m_packageName = name + '.';
-        }
-        public boolean match(String className)
-        {
-            final int pos = className.lastIndexOf('.');
-            return pos > -1 && className.substring(0, pos + 1).startsWith(m_packageName);
-        }
-    }
-
-    /** Match a class name. */
-    private static final class ClassMatcher implements Matcher
-    {
-        private final String m_className;
-
-        public ClassMatcher(final String name)
-        {
-            m_className = name;
-        }
-        public boolean match(String className)
-        {
-            return m_className.equals(className);
-        }
+        this.pool = pool;
+        this.update(timeout);
     }
 
-    /** The matchers for ignore timeout handling. */
-    private Matcher[] m_ignoreTimeoutMatcher;
-
     /**
-     * Construct a new sync deliver tasks.
-     * @param pool The thread pool used to spin-off new threads.
-     * @param timeout The timeout for an event handler, 0 = disabled
+     * Update the timeout configuration
      */
-    public SyncDeliverTasks(final DefaultThreadPool pool, final long timeout, final String[] ignoreTimeout)
+    public void update(final long timeout)
     {
-        m_pool = pool;
-        update(timeout, ignoreTimeout);
-    }
-
-    public void update(final long timeout, final String[] ignoreTimeout) {
-        m_timeout = timeout;
-        if ( ignoreTimeout == null || ignoreTimeout.length == 0 )
-        {
-            m_ignoreTimeoutMatcher = null;
-        }
-        else
-        {
-            Matcher[] ignoreTimeoutMatcher = new Matcher[ignoreTimeout.length];
-            for(int i=0;i<ignoreTimeout.length;i++)
-            {
-                String value = ignoreTimeout[i];
-                if ( value != null )
-                {
-                    value = value.trim();
-                }
-                if ( value != null && value.length() > 0 )
-                {
-                    if ( value.endsWith(".") )
-                    {
-                        ignoreTimeoutMatcher[i] = new PackageMatcher(value.substring(0, value.length() - 1));
-                    }
-                    else if ( value.endsWith("*") )
-                    {
-                        ignoreTimeoutMatcher[i] = new SubPackageMatcher(value.substring(0, value.length() - 1));
-                    }
-                    else
-                    {
-                        ignoreTimeoutMatcher[i] = new ClassMatcher(value);
-                    }
-                }
-            }
-            m_ignoreTimeoutMatcher = ignoreTimeoutMatcher;
-        }
+        this.timeout = timeout;
     }
 
     /**
@@ -172,27 +84,12 @@ public class SyncDeliverTasks implements
      * task.
      * @param tasks The event handler dispatch tasks to execute
      */
-    private boolean useTimeout(final HandlerTask task)
+    private boolean useTimeout(final EventHandlerProxy proxy)
     {
-        // we only check the classname if a timeout is configured
-        if ( m_timeout > 0)
+        // we only check the proxy if a timeout is configured
+        if ( this.timeout > 0)
         {
-            final Matcher[] ignoreTimeoutMatcher = m_ignoreTimeoutMatcher;
-            if ( ignoreTimeoutMatcher != null )
-            {
-                final String className = task.getHandlerClassName();
-                for(int i=0;i<ignoreTimeoutMatcher.length;i++)
-                {
-                    if ( ignoreTimeoutMatcher[i] != null)
-                    {
-                        if ( ignoreTimeoutMatcher[i].match(className) )
-                        {
-                            return false;
-                        }
-                    }
-                }
-            }
-            return true;
+            return proxy.useTimeout();
         }
         return false;
     }
@@ -203,9 +100,8 @@ public class SyncDeliverTasks implements
      *
      * @param tasks The event handler dispatch tasks to execute
      *
-     * @see org.apache.felix.eventadmin.impl.tasks.DeliverTask#execute(List)
      */
-    public void execute(final List tasks)
+    public void execute(final Collection tasks, final Event event)
     {
         final Thread sleepingThread = Thread.currentThread();
         final SyncThread syncThread = sleepingThread instanceof SyncThread ? (SyncThread)sleepingThread : null;
@@ -213,20 +109,20 @@ public class SyncDeliverTasks implements
         final Iterator i = tasks.iterator();
         while ( i.hasNext() )
         {
-            final HandlerTask task = (HandlerTask)i.next();
+            final EventHandlerProxy task = (EventHandlerProxy)i.next();
 
             if ( !useTimeout(task) )
             {
                 // no timeout, we can directly execute
-                task.execute();
+                task.sendEvent(event);
             }
             else if ( syncThread != null )
             {
                 // if this is a cascaded event, we directly use this thread
                 // otherwise we could end up in a starvation
                 final long startTime = System.currentTimeMillis();
-                task.execute();
-                if ( System.currentTimeMillis() - startTime > m_timeout )
+                task.sendEvent(event);
+                if ( System.currentTimeMillis() - startTime > this.timeout )
                 {
                     task.blackListHandler();
                 }
@@ -235,7 +131,7 @@ public class SyncDeliverTasks implements
             {
                 final Rendezvous startBarrier = new Rendezvous();
                 final Rendezvous timerBarrier = new Rendezvous();
-                m_pool.executeTask(new Runnable()
+                this.pool.executeTask(new Runnable()
                 {
                     public void run()
                     {
@@ -244,7 +140,7 @@ public class SyncDeliverTasks implements
                             // notify the outer thread to start the timer
                             startBarrier.waitForRendezvous();
                             // execute the task
-                            task.execute();
+                            task.sendEvent(event);
                             // stop the timer
                             timerBarrier.waitForRendezvous();
                         }
@@ -262,7 +158,7 @@ public class SyncDeliverTasks implements
                 // if someone wakes us up it's the finished inner task
                 try
                 {
-                    timerBarrier.waitAttemptForRendezvous(m_timeout);
+                    timerBarrier.waitAttemptForRendezvous(this.timeout);
                 }
                 catch (final TimeoutException ie)
                 {



Mime
View raw message