View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.context.notification;
8   
9   import org.mule.api.context.notification.ServerNotification;
10  import org.mule.api.context.notification.ServerNotificationListener;
11  import org.mule.config.i18n.CoreMessages;
12  
13  import java.util.Collection;
14  import java.util.Collections;
15  import java.util.HashMap;
16  import java.util.HashSet;
17  import java.util.Iterator;
18  import java.util.Map;
19  import java.util.Set;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  
24  import static org.mule.context.notification.ServerNotificationManager.toClass;
25  
26  /**
27   * This acts as a synchronized collection. No call blocks and all are synchronized.
28   */
29  class Configuration
30  {
31  
32      protected static Log logger = LogFactory.getLog(Configuration.class);
33      private Map<Class<? extends ServerNotificationListener>, Set<Class<? extends ServerNotification>>> interfaceToTypes =
34              new HashMap<Class<? extends ServerNotificationListener>, Set<Class<? extends ServerNotification>>>(); // map from interface to collection of events
35      private Set<ListenerSubscriptionPair> listenerSubscriptionPairs = new HashSet<ListenerSubscriptionPair>();
36      private Set<Class<? extends ServerNotificationListener>> disabledInterfaces = new HashSet<Class<? extends ServerNotificationListener>>();
37      private Set<Class<? extends ServerNotification>> disabledNotificationTypes = new HashSet<Class<? extends ServerNotification>>();
38      private volatile boolean dirty = true;
39      private Policy policy;
40  
41      synchronized void addInterfaceToType(Class<? extends ServerNotificationListener> iface, Class<? extends ServerNotification> type)
42      {
43          dirty = true;
44          if (!ServerNotification.class.isAssignableFrom(type))
45          {
46              throw new IllegalArgumentException(
47                      CoreMessages.propertyIsNotSupportedType("type",
48                              ServerNotification.class, type).getMessage());
49          }
50          if (!interfaceToTypes.containsKey(iface))
51          {
52              interfaceToTypes.put(iface, new HashSet<Class<? extends ServerNotification>>());
53          }
54          Set<Class<? extends ServerNotification>> events = interfaceToTypes.get(iface);
55          events.add(type);
56          if (logger.isDebugEnabled())
57          {
58              logger.debug("Registered event type: " + type);
59              logger.debug("Binding listener type '" + iface + "' to event type '" + type + "'");
60          }
61      }
62  
63      /**
64       * @param interfaceToTypes map from interace to a particular event
65       * @throws ClassNotFoundException if the interface is a key, but the corresponding class cannot be loaded
66       */
67      synchronized void addAllInterfaceToTypes(Map<Class<? extends ServerNotificationListener>, Set<Class<? extends ServerNotification>>> interfaceToTypes) throws ClassNotFoundException
68      {
69          dirty = true;
70  
71          for (Iterator ifaces = interfaceToTypes.keySet().iterator(); ifaces.hasNext();)
72          {
73              Object iface = ifaces.next();
74              addInterfaceToType(toClass(iface), toClass(interfaceToTypes.get(iface)));
75          }
76      }
77  
78      synchronized void addListenerSubscriptionPair(ListenerSubscriptionPair pair)
79      {
80          dirty = true;
81          if (!listenerSubscriptionPairs.add(pair))
82          {
83              logger.warn(CoreMessages.notificationListenerSubscriptionAlreadyRegistered(pair));
84          }
85      }
86  
87      synchronized void addAllListenerSubscriptionPairs(Collection pairs)
88      {
89          dirty = true;
90          for (Iterator listener = pairs.iterator(); listener.hasNext();)
91          {
92              addListenerSubscriptionPair((ListenerSubscriptionPair) listener.next());
93          }
94      }
95  
96      synchronized void removeListener(ServerNotificationListener listener)
97      {
98          dirty = true;
99          Set<ListenerSubscriptionPair> toRemove = new HashSet<ListenerSubscriptionPair>();
100         for (Iterator listeners = listenerSubscriptionPairs.iterator(); listeners.hasNext();)
101         {
102             ListenerSubscriptionPair pair = (ListenerSubscriptionPair) listeners.next();
103             if (pair.getListener().equals(listener))
104             {
105                 toRemove.add(pair);
106             }
107         }
108         listenerSubscriptionPairs.removeAll(toRemove);
109     }
110 
111     synchronized void removeAllListeners(Collection listeners)
112     {
113         dirty = true;
114         for (Iterator listener = listeners.iterator(); listener.hasNext();)
115         {
116             removeListener((ServerNotificationListener) listener.next());
117         }
118     }
119 
120     synchronized void disableInterface(Class<? extends ServerNotificationListener> iface)
121     {
122         dirty = true;
123         disabledInterfaces.add(iface);
124     }
125 
126     synchronized void disabledAllInterfaces(Collection<Class<? extends ServerNotificationListener>> interfaces) throws ClassNotFoundException
127     {
128         dirty = true;
129         for (Iterator iface = interfaces.iterator(); iface.hasNext();)
130         {
131             disableInterface(toClass(iface.next()));
132         }
133     }
134 
135     synchronized void disableType(Class<? extends ServerNotification> type)
136     {
137         dirty = true;
138         disabledNotificationTypes.add(type);
139     }
140 
141     synchronized void disableAllTypes(Collection types) throws ClassNotFoundException
142     {
143         dirty = true;
144         for (Iterator event = types.iterator(); event.hasNext();)
145         {
146             disableType(toClass(event.next()));
147         }
148     }
149 
150     protected Policy getPolicy()
151     {
152         if (dirty)
153         {
154             synchronized (this)
155             {
156                 if (dirty)
157                 {
158                     policy = new Policy(interfaceToTypes, listenerSubscriptionPairs, disabledInterfaces, disabledNotificationTypes);
159                     dirty = false;
160                 }
161             }
162         }
163         return policy;
164     }
165 
166     // for tests -------------------------------
167 
168     Map<Class<? extends ServerNotificationListener>, Set<Class<? extends ServerNotification>>> getInterfaceToTypes()
169     {
170         return Collections.unmodifiableMap(interfaceToTypes);
171     }
172 
173     Set<ListenerSubscriptionPair> getListeners()
174     {
175         return Collections.unmodifiableSet(listenerSubscriptionPairs);
176     }
177 
178 }