com.bt.aloha.eventing.EventDispatcher.java Source code

Java tutorial

Introduction

Here is the source code for com.bt.aloha.eventing.EventDispatcher.java

Source

/*
 * Aloha Open Source SIP Application Server- https://trac.osmosoft.com/Aloha
 *
 * Copyright (c) 2008, British Telecommunications plc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation; either version 3.0 of the License, or (at your option) any later
 * version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package com.bt.aloha.eventing;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.MDC;
import org.springframework.core.task.TaskExecutor;

public class EventDispatcher {
    private static final String LOCALE = "en";
    private static final String EVENT_SUFFIX = "event";
    private Log log = LogFactory.getLog(this.getClass());
    private TaskExecutor taskExecutor;

    public EventDispatcher() {
    }

    public TaskExecutor getTaskExecutor() {
        return this.taskExecutor;
    }

    public void setTaskExecutor(TaskExecutor aTaskExecutor) {
        this.taskExecutor = aTaskExecutor;
    }

    protected List<?> filterListeners(final List<?> rawListenerList, Object event) {
        if (rawListenerList == null || rawListenerList.size() == 0) {
            log.debug(String.format("NO listeners found for %s", event.getClass().getSimpleName()));
            return new ArrayList<Object>();
        }

        log.debug(String.format("Filtering %d listeners for event %s", rawListenerList.size(),
                event.getClass().getSimpleName()));
        List<Object> matchingListeners = new ArrayList<Object>();
        for (int i = 0; i < rawListenerList.size(); i++) {
            Object listener = null;
            try {
                listener = rawListenerList.get(i);
            } catch (IndexOutOfBoundsException e) {
                log.debug(String.format("%s: size changed whilst processing listener list",
                        e.getClass().getSimpleName()));
                continue;
            }
            if (listener instanceof EventFilter) {
                EventFilter filteringListener = (EventFilter) listener;
                if (filteringListener.shouldDeliverEvent(event)) {
                    matchingListeners.add(listener);
                } else {
                    log.info(String.format("Listener %s does NOT want event %s",
                            filteringListener.getClass().getSimpleName(), event.getClass().getSimpleName()));
                }
            } else {
                matchingListeners.add(listener);
            }
        }
        log.debug(String.format("Returning %d listeners found for %s", matchingListeners.size(),
                event.getClass().getSimpleName()));
        return matchingListeners;
    }

    public int dispatchEvent(List<?> rawListenerList, final Object event) {
        return dispatchEvent(rawListenerList, event, true, null);
    }

    public int dispatchEvent(List<?> rawListenerList, final Object event, boolean invokeAsynchronously,
            Integer maxNumberOfListenersToInvoke) {
        if (event == null)
            throw new UndefinedEventException("Cannot dispatch null event");

        List<?> filteredListenerArray = filterListeners(rawListenerList, event);
        final Locale locale = new Locale(LOCALE);
        String eventName = event.getClass().getSimpleName().toLowerCase(locale);
        if (eventName.toLowerCase(locale).endsWith(EVENT_SUFFIX))
            eventName = eventName.substring(0, eventName.length() - EVENT_SUFFIX.length());

        int numberOfListenersInvoked = 0;
        for (final Object listener : filteredListenerArray) {
            if (maxNumberOfListenersToInvoke != null
                    && numberOfListenersInvoked >= maxNumberOfListenersToInvoke.intValue()) {
                log.debug(String.format("Already invoked max number (%d) of listeners for event %s",
                        maxNumberOfListenersToInvoke.intValue(), eventName));
                break;
            }

            if (deliverEventToListener(listener, eventName, event, invokeAsynchronously)) {
                numberOfListenersInvoked++;
            } else {
                log.warn(String.format(
                        "Unable to deliver event %s to listener %s - check that the listeners have method names corresponding to event names",
                        eventName, listener.getClass().getName()));
            }
        }
        return numberOfListenersInvoked;
    }

    private boolean deliverEventToListener(final Object listener, final String eventName, final Object event,
            boolean invokeAsynchronously) {
        for (final Method method : listener.getClass().getMethods()) {
            final Locale locale = new Locale(LOCALE);
            if (method.getName().toLowerCase(locale).equals("on" + eventName)) {
                if (invokeAsynchronously) {
                    Runnable runnable = new EventDispatcherRunnable(method, event, listener,
                            (String) MDC.get("stackname"));
                    taskExecutor.execute(runnable);
                } else {
                    log.debug(String.format("Delivering synchronous event %s to %s",
                            event.getClass().getSimpleName(), listener.getClass().getName()));
                    try {
                        method.invoke(listener, new Object[] { event });
                    } catch (Throwable t) {
                        log.error(String.format("Exception whilst processing event %s",
                                event.getClass().getSimpleName()), t);
                    }
                }
                return true;
            }
        }
        return false;
    }
}