Package org.mule.context.notification

Source Code of org.mule.context.notification.Policy

/*
* $Id: Policy.java 21939 2011-05-18 13:32:09Z aperepel $
* --------------------------------------------------------------------------------------
* Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
*
* The software in this package is published under the terms of the CPAL v1.0
* license, a copy of which has been included with this distribution in the
* LICENSE.txt file.
*/

package org.mule.context.notification;

import org.mule.api.context.notification.ServerNotification;
import org.mule.api.context.notification.ServerNotificationListener;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
* For a particular configuration, this describes what events should be delivered where.
* It is read-only and a lazy instance is cached by the
* {@link Configuration}
*/
class Policy
{

    // map from event to set of senders
    private Map<Class<? extends ServerNotification>, Collection<Sender>> eventToSenders = new HashMap<Class<? extends ServerNotification>, Collection<Sender>>();

    // these are cumulative - set values should never change, they are just a cache of known info
    // they are co and contra-variant wrt to exact event type (see code below).
    private ConcurrentMap knownEventsExact = new ConcurrentHashMap();
    private ConcurrentMap knownEventsSuper = new ConcurrentHashMap();

    /**
     * For each listener, we check each interface and see what events can be delivered.
     */
    Policy(Map<Class<? extends ServerNotificationListener>, Set<Class<? extends ServerNotification>>> interfaceToEvents,
        Set<ListenerSubscriptionPair> listenerSubscriptionPairs,
        Set<Class<? extends ServerNotificationListener>> disabledInterfaces,
        Set<Class<? extends ServerNotification>> disabledEvents)
    {
        for (ListenerSubscriptionPair pair : listenerSubscriptionPairs)
        {
            ServerNotificationListener listener = pair.getListener();
            for (Class<? extends ServerNotificationListener> iface : interfaceToEvents.keySet())
            {
                if (notASubclassOfAnyClassInSet(disabledInterfaces, iface))
                {
                    if (iface.isAssignableFrom(listener.getClass()))
                    {
                        Set<Class<? extends ServerNotification>> events = interfaceToEvents.get(iface);
                        for (Class<? extends ServerNotification> event : events)
                        {
                            if (notASubclassOfAnyClassInSet(disabledEvents, event))
                            {
                                knownEventsExact.put(event, Boolean.TRUE);
                                knownEventsSuper.put(event, Boolean.TRUE);
                                if (!eventToSenders.containsKey(event))
                                {
                                    // use a collection with predictable iteration order
                                    eventToSenders.put(event, new ArrayList<Sender>());
                                }
                                eventToSenders.get(event).add(new Sender(pair));
                            }
                        }
                    }
                }
            }
        }
    }

    protected static boolean notASubclassOfAnyClassInSet(Set set,  Class clazz)
    {
        for (Iterator iterator = set.iterator(); iterator.hasNext();)
        {
            Class disabled = (Class) iterator.next();
            if (disabled.isAssignableFrom(clazz))
            {
                return false;
            }
        }
        return true;
    }

    protected static boolean notASuperclassOfAnyClassInSet(Set set, Class clazz)
    {
        for (Iterator iterator = set.iterator(); iterator.hasNext();)
        {
            Class disabled = (Class) iterator.next();
            if (clazz.isAssignableFrom(disabled))
            {
                return false;
            }
        }
        return true;
    }

    void dispatch(ServerNotification notification)
    {
        if (null != notification)
        {
            Class notfnClass = notification.getClass();
            // search if we don't know about this event, or if we do know it is used
            if ((!knownEventsExact.containsKey(notfnClass))
                    || ((Boolean) knownEventsExact.get(notfnClass)).booleanValue())
            {
                boolean found = false;
                for (Class<? extends ServerNotification> event : eventToSenders.keySet())
                {
                    if (event.isAssignableFrom(notfnClass))
                    {
                        found = true;
                        for (Iterator senders = ((Collection) eventToSenders.get(event)).iterator(); senders.hasNext();)
                        {
                            ((Sender) senders.next()).dispatch(notification);
                        }
                    }
                }
                knownEventsExact.put(notfnClass, Boolean.valueOf(found));
            }
        }
    }

    /**
     * This returns a very "conservative" value - it is true if the notification or any subclass would be
     * accepted.  So if it returns false then you can be sure that there is no need to send the
     * notification.  On the other hand, if it returns true there is no guarantee that the notification
     * "really" will be dispatched to any listener.
     *
     * @param notfnClass Either the notification class being generated or some superclass
     * @return false if there is no need to dispatch the notification
     */
    boolean isNotificationEnabled(Class notfnClass)
    {
        if (!knownEventsSuper.containsKey(notfnClass))
        {
            boolean found = false;
            // this is exhaustive because we initialise to include all events handled.
            for (Iterator events = knownEventsSuper.keySet().iterator(); events.hasNext() && !found;)
            {
                Class event = (Class) events.next();
                found = ((Boolean) knownEventsSuper.get(event)).booleanValue() && notfnClass.isAssignableFrom(event);
            }
            knownEventsSuper.put(notfnClass, Boolean.valueOf(found));
        }
        if (!knownEventsExact.containsKey(notfnClass))
        {
            boolean found = false;
            for (Iterator events = eventToSenders.keySet().iterator(); events.hasNext() && !found;)
            {
                Class event = (Class) events.next();
                found = event.isAssignableFrom(notfnClass);
            }
            knownEventsExact.put(notfnClass, Boolean.valueOf(found));

        }
        return ((Boolean) knownEventsSuper.get(notfnClass)).booleanValue()
                || ((Boolean) knownEventsExact.get(notfnClass)).booleanValue();
    }

}
TOP

Related Classes of org.mule.context.notification.Policy

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.