| /* |
| * 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; |
| |
| 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.service.event.Event; |
| import org.osgi.service.event.EventAdmin; |
| |
| /** |
| * This is the actual implementation of the OSGi R4 Event Admin Service (see the |
| * Compendium 113 for details). The implementation uses a <tt>HandlerTasks</tt> |
| * in order to determine applicable <tt>EventHandler</tt> for a specific event and |
| * subsequently dispatches the event to the handlers via <tt>DeliverTasks</tt>. |
| * To do this, it uses two different <tt>DeliverTasks</tt> one for asynchronous and |
| * one for synchronous event delivery depending on whether its <tt>post()</tt> or |
| * its <tt>send()</tt> method is called. Note that the actual work is done in the |
| * implementations of the <tt>DeliverTasks</tt>. Additionally, a stop method is |
| * provided that prevents subsequent events to be delivered. |
| * |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| 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 asynchronous event dispatcher |
| private final DeliverTask 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. |
| * |
| * @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, |
| final DefaultThreadPool syncPool, |
| final DefaultThreadPool asyncPool, |
| final int timeout, |
| final String[] ignoreTimeout) |
| { |
| checkNull(managers, "Managers"); |
| checkNull(syncPool, "syncPool"); |
| checkNull(asyncPool, "asyncPool"); |
| |
| m_managers = managers; |
| |
| m_sendManager = new SyncDeliverTasks(syncPool, |
| (timeout > 100 ? timeout : 0), |
| ignoreTimeout); |
| |
| m_postManager = new AsyncDeliverTasks(asyncPool, m_sendManager); |
| } |
| |
| /** |
| * Post an asynchronous event. |
| * |
| * @param event The event to be posted by this service |
| * |
| * @throws IllegalStateException - In case we are stopped |
| * |
| * @see org.osgi.service.event.EventAdmin#postEvent(org.osgi.service.event.Event) |
| */ |
| public void postEvent(final Event event) |
| { |
| handleEvent(m_managers.createHandlerTasks(event), m_postManager); |
| } |
| |
| /** |
| * Send a synchronous event. |
| * |
| * @param event The event to be send by this service |
| * |
| * @throws IllegalStateException - In case we are stopped |
| * |
| * @see org.osgi.service.event.EventAdmin#sendEvent(org.osgi.service.event.Event) |
| */ |
| public void sendEvent(final Event event) |
| { |
| handleEvent(m_managers.createHandlerTasks(event), m_sendManager); |
| } |
| |
| /** |
| * 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>. |
| */ |
| 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 HandlerTask[] createHandlerTasks(final Event event) |
| { |
| throw new IllegalStateException("The EventAdmin is stopped"); |
| } |
| }; |
| } |
| |
| /** |
| * 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(final HandlerTask[] managers, |
| final DeliverTask manager) |
| { |
| if (0 < managers.length) |
| { |
| // 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); |
| } |
| } |
| |
| /** |
| * This is a utility method that will throw a <tt>NullPointerException</tt> |
| * in case that the given object is null. The message will be of the form |
| * "${name} + may not be null". |
| */ |
| private void checkNull(final Object object, final String name) |
| { |
| if(null == object) |
| { |
| throw new NullPointerException(name + " may not be null"); |
| } |
| } |
| } |