Package org.apache.felix.useradmin.impl

Source Code of org.apache.felix.useradmin.impl.EventDispatcher

/**
*  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 <code>null</code>;
     * @param listenerList the list with {@link UserAdminListener}s, cannot be <code>null</code>.
     * @throws IllegalArgumentException in case one of the given parameters was <code>null</code>.
     */
    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.
     * <p>
     * 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.
     * </p>
     *
     * @param event the event to dispatch, cannot be <code>null</code>.
     * @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 <code>true</code> if the background thread is running (alive), <code>false</code> 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 <code>null</code>.
     * @return a new {@link Event} instance containing the same set of
     *         information as the given event, never <code>null</code>.
     */
    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 <code>null</code>.
     */
    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 <code>null</code>.
     */
    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;
        }
    }
}
TOP

Related Classes of org.apache.felix.useradmin.impl.EventDispatcher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.