All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.felix.useradmin.impl.EventDispatcher Maven / Gradle / Ivy

There is a newer version: 1.0.4
Show newest version
/**
 *  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.useradmin.impl;

import java.util.Properties;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.UserAdminEvent;
import org.osgi.service.useradmin.UserAdminListener;

/**
 * Provides an event dispatcher for delivering {@link UserAdminEvent}s asynchronously. 
 */
public final class EventDispatcher implements Runnable {
    
    private static final String TOPIC_BASE = "org/osgi/service/useradmin/UserAdmin/";

    private final EventAdmin m_eventAdmin;
    private final UserAdminListenerList m_listenerList;
    private final BlockingQueue m_eventQueue;
    private final Thread m_backgroundThread;

    /**
     * Creates a new {@link EventDispatcher} instance, and starts a background thread to deliver all events.
     * 
     * @param eventAdmin the event admin to use, cannot be null;
     * @param listenerList the list with {@link UserAdminListener}s, cannot be null.
     * @throws IllegalArgumentException in case one of the given parameters was null.
     */
    public EventDispatcher(EventAdmin eventAdmin, UserAdminListenerList listenerList) {
        if (eventAdmin == null) {
            throw new IllegalArgumentException("EventAdmin cannot be null!");
        }
        if (listenerList == null) {
            throw new IllegalArgumentException("ListenerList cannot be null!");
        }

        m_eventAdmin = eventAdmin;
        m_listenerList = listenerList;
        m_eventQueue = new LinkedBlockingQueue();

        m_backgroundThread = new Thread(this, "UserAdmin event dispatcher");
    }

    /**
     * Dispatches a given event for asynchronous delivery to all interested listeners, 
     * including those using the {@link EventAdmin} service.
     * 

* This method will perform a best-effort to dispatch the event to all listeners, i.e., * there is no guarantee that the listeners will actually obtain the event, nor any * notification is given in case delivery fails. *

* * @param event the event to dispatch, cannot be null. * @throws IllegalStateException in case this dispatcher is already stopped. */ public void dispatch(UserAdminEvent event) { if (!isRunning()) { return; } try { m_eventQueue.put(event); } catch (InterruptedException e) { // Restore interrupt flag... Thread.currentThread().interrupt(); } } /** * Starts this event dispatcher, allowing it to pick up events and deliver them. */ public void start() { if (!isRunning()) { m_backgroundThread.start(); } } /** * Signals this event dispatcher to stop its work and clean up all running threads. */ public void stop() { if (!isRunning()) { return; } // Add poison object to queue to let the background thread terminate... m_eventQueue.add(EventDispatcher.this); try { m_backgroundThread.join(); } catch (InterruptedException e) { // We're already stopping; so don't bother... } } /** * Returns whether or not the background thread is running. * * @return true if the background thread is running (alive), false otherwise. */ final boolean isRunning() { return m_backgroundThread.isAlive(); } /** * Provides the main event loop, which waits until an event is enqueued in order * to deliver it to any interested listener. */ public void run() { try { while (true) { // Blocks until a event is dispatched... Object event = m_eventQueue.take(); if (event instanceof UserAdminEvent) { // Got a "normal" user admin event; lets dispatch it further... deliverEventSynchronously((UserAdminEvent) event); } else { // Got a "poison" object; this means we must stop running... return; } } } catch (InterruptedException e) { // Restore interrupt flag, and terminate thread... Thread.currentThread().interrupt(); } } /** * Converts a given {@link UserAdminEvent} to a {@link Event} that can be * dispatched through the {@link EventAdmin} service. * * @param event * the event to convert, cannot be null. * @return a new {@link Event} instance containing the same set of * information as the given event, never null. */ private Event convertEvent(UserAdminEvent event) { String topic = getTopicName(event.getType()); Role role = event.getRole(); ServiceReference serviceRef = event.getServiceReference(); Properties props = new Properties(); props.put(EventConstants.EVENT_TOPIC, TOPIC_BASE.concat(topic)); props.put(EventConstants.EVENT, event); props.put("role", role); props.put("role.name", role.getName()); props.put("role.type", new Integer(role.getType())); if (serviceRef != null) { props.put(EventConstants.SERVICE, serviceRef); Object property; property = serviceRef.getProperty(Constants.SERVICE_ID); if (property != null) { props.put(EventConstants.SERVICE_ID, property); } property = serviceRef.getProperty(Constants.OBJECTCLASS); if (property != null) { props.put(EventConstants.SERVICE_OBJECTCLASS, property); } property = serviceRef.getProperty(Constants.SERVICE_PID); if (property != null) { props.put(EventConstants.SERVICE_PID, property); } } return new Event(topic, props); } /** * Delivers the given event synchronously to all interested listeners. * * @param event the event to deliver, cannot be null. */ private void deliverEventSynchronously(UserAdminEvent event) { // Asynchronously deliver an event to the EventAdmin service... m_eventAdmin.postEvent(convertEvent(event)); // Synchronously call all UserAdminListeners to deliver the event... UserAdminListener[] listeners = m_listenerList.getListeners(); for (int i = 0; i < listeners.length; i++) { listeners[i].roleChanged(event); } } /** * Converts a topic name for the given event-type. * * @param type the type of event to get the topic name for. * @return a topic name, never null. */ private String getTopicName(int type) { switch (type) { case UserAdminEvent.ROLE_CREATED: return "ROLE_CREATED"; case UserAdminEvent.ROLE_CHANGED: return "ROLE_CHANGED"; case UserAdminEvent.ROLE_REMOVED: return "ROLE_REMOVED"; default: return null; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy