Coverage Report - org.mule.context.notification.Policy
 
Classes in this File Line Coverage Branch Coverage Complexity
Policy
90%
57/63
91%
49/54
5.4
 
 1  
 /*
 2  
  * $Id: Policy.java 10489 2008-01-23 17:53:38Z dfeist $
 3  
  * --------------------------------------------------------------------------------------
 4  
  * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
 5  
  *
 6  
  * The software in this package is published under the terms of the CPAL v1.0
 7  
  * license, a copy of which has been included with this distribution in the
 8  
  * LICENSE.txt file.
 9  
  */
 10  
 
 11  
 package org.mule.context.notification;
 12  
 
 13  
 import org.mule.api.context.notification.ServerNotification;
 14  
 import org.mule.api.context.notification.ServerNotificationListener;
 15  
 
 16  
 import java.util.Collection;
 17  
 import java.util.HashMap;
 18  
 import java.util.HashSet;
 19  
 import java.util.Iterator;
 20  
 import java.util.Map;
 21  
 import java.util.Set;
 22  
 
 23  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
 24  
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentMap;
 25  
 
 26  
 /**
 27  
  * For a particular configuration, this describes what events should be delivered where.
 28  
  * It is read-only and a lazy instance is cached by the
 29  
  * {@link Configuration}
 30  
  */
 31  
 class Policy
 32  
 {
 33  
 
 34  
     // map from event to set of senders
 35  1206
     private Map eventToSenders = new HashMap();
 36  
 
 37  
     // these are cumulative - set values should never change, they are just a cache of known info
 38  
     // they are co and contra-variant wrt to exact event type (see code below).
 39  1206
     private ConcurrentMap knownEventsExact = new ConcurrentHashMap();
 40  1206
     private ConcurrentMap knownEventsSuper = new ConcurrentHashMap();
 41  
 
 42  
     /**
 43  
      * For each listener, we check each interface and see what events can be delivered.
 44  
      *
 45  
      * @param interfaceToEvents
 46  
      * @param listenerSubscriptionPairs
 47  
      * @param disabledInterfaces
 48  
      * @param disabledEvents
 49  
      */
 50  
     Policy(Map interfaceToEvents, Set listenerSubscriptionPairs, Set disabledInterfaces, Set disabledEvents)
 51  1206
     {
 52  1206
         for (Iterator pairs = listenerSubscriptionPairs.iterator(); pairs.hasNext();)
 53  
         {
 54  68
             ListenerSubscriptionPair pair = (ListenerSubscriptionPair) pairs.next();
 55  68
             ServerNotificationListener listener = pair.getListener();
 56  68
             for (Iterator interfaces = interfaceToEvents.keySet().iterator(); interfaces.hasNext();)
 57  
             {
 58  316
                 Class iface = (Class) interfaces.next();
 59  316
                 if (notASubclassOfAnyClassInSet(disabledInterfaces, iface))
 60  
                 {
 61  312
                     if (iface.isAssignableFrom(listener.getClass()))
 62  
                     {
 63  74
                         for (Iterator events = ((Collection) interfaceToEvents.get(iface)).iterator(); events.hasNext();)
 64  
                         {
 65  76
                             Class event = (Class) events.next();
 66  76
                             if (notASubclassOfAnyClassInSet(disabledEvents, event))
 67  
                             {
 68  66
                                 knownEventsExact.put(event, Boolean.TRUE);
 69  66
                                 knownEventsSuper.put(event, Boolean.TRUE);
 70  66
                                 if (!eventToSenders.containsKey(event))
 71  
                                 {
 72  62
                                     eventToSenders.put(event, new HashSet());
 73  
                                 }
 74  66
                                 ((Collection) eventToSenders.get(event)).add(new Sender(pair));
 75  
                             }
 76  76
                         }
 77  
                     }
 78  
                 }
 79  316
             }
 80  68
         }
 81  1206
     }
 82  
 
 83  
     protected static boolean notASubclassOfAnyClassInSet(Set set, Class clazz)
 84  
     {
 85  392
         for (Iterator iterator = set.iterator(); iterator.hasNext();)
 86  
         {
 87  26
             Class disabled = (Class) iterator.next();
 88  26
             if (disabled.isAssignableFrom(clazz))
 89  
             {
 90  14
                 return false;
 91  
             }
 92  12
         }
 93  378
         return true;
 94  
     }
 95  
 
 96  
     protected static boolean notASuperclassOfAnyClassInSet(Set set, Class clazz)
 97  
     {
 98  0
         for (Iterator iterator = set.iterator(); iterator.hasNext();)
 99  
         {
 100  0
             Class disabled = (Class) iterator.next();
 101  0
             if (clazz.isAssignableFrom(disabled))
 102  
             {
 103  0
                 return false;
 104  
             }
 105  0
         }
 106  0
         return true;
 107  
     }
 108  
 
 109  
     void dispatch(ServerNotification notification)
 110  
     {
 111  10887
         if (null != notification)
 112  
         {
 113  10887
             Class notfnClass = notification.getClass();
 114  
             // search if we don't know about this event, or if we do know it is used
 115  10887
             if ((!knownEventsExact.containsKey(notfnClass))
 116  
                     || ((Boolean) knownEventsExact.get(notfnClass)).booleanValue())
 117  
             {
 118  2826
                 boolean found = false;
 119  2826
                 for (Iterator events = eventToSenders.keySet().iterator(); events.hasNext();)
 120  
                 {
 121  218
                     Class event = (Class) events.next();
 122  218
                     if (event.isAssignableFrom(notfnClass))
 123  
                     {
 124  124
                         found = true;
 125  124
                         for (Iterator senders = ((Collection) eventToSenders.get(event)).iterator(); senders.hasNext();)
 126  
                         {
 127  144
                             ((Sender) senders.next()).dispatch(notification);
 128  
                         }
 129  
                     }
 130  218
                 }
 131  2826
                 knownEventsExact.put(notfnClass, Boolean.valueOf(found));
 132  
             }
 133  
         }
 134  10887
     }
 135  
 
 136  
     /**
 137  
      * This returns a very "conservative" value - it is true if the notification or any subclass would be
 138  
      * accepted.  So if it returns false then you can be sure that there is no need to send the
 139  
      * notification.  On the other hand, if it returns true there is no guarantee that the notification
 140  
      * "really" will be dispatched to any listener.
 141  
      *
 142  
      * @param notfnClass Either the notification class being generated or some superclass
 143  
      * @return false if there is no need to dispatch the notification
 144  
      */
 145  
     boolean isNotificationEnabled(Class notfnClass)
 146  
     {
 147  654
         if (!knownEventsSuper.containsKey(notfnClass))
 148  
         {
 149  510
             boolean found = false;
 150  
             // this is exhaustive because we initialise to include all events handled.
 151  510
             for (Iterator events = knownEventsSuper.keySet().iterator(); events.hasNext() && !found;)
 152  
             {
 153  224
                 Class event = (Class) events.next();
 154  224
                 found = ((Boolean) knownEventsSuper.get(event)).booleanValue() && notfnClass.isAssignableFrom(event);
 155  224
             }
 156  510
             knownEventsSuper.put(notfnClass, Boolean.valueOf(found));
 157  
         }
 158  654
         if (!knownEventsExact.containsKey(notfnClass))
 159  
         {
 160  510
             boolean found = false;
 161  510
             for (Iterator events = eventToSenders.keySet().iterator(); events.hasNext() && !found;)
 162  
             {
 163  88
                 Class event = (Class) events.next();
 164  88
                 found = event.isAssignableFrom(notfnClass);
 165  88
             }
 166  510
             knownEventsExact.put(notfnClass, Boolean.valueOf(found));
 167  
 
 168  
         }
 169  654
         return ((Boolean) knownEventsSuper.get(notfnClass)).booleanValue()
 170  
                 || ((Boolean) knownEventsExact.get(notfnClass)).booleanValue();
 171  
     }
 172  
 
 173  
 }