1
2
3
4
5
6
7 package org.mule.context.notification;
8
9 import org.mule.api.MuleContext;
10 import org.mule.api.context.MuleContextAware;
11 import org.mule.api.context.WorkManager;
12 import org.mule.api.context.notification.BlockingServerEvent;
13 import org.mule.api.context.notification.ServerNotification;
14 import org.mule.api.context.notification.ServerNotificationHandler;
15 import org.mule.api.context.notification.ServerNotificationListener;
16 import org.mule.api.lifecycle.Disposable;
17 import org.mule.api.lifecycle.LifecycleException;
18 import org.mule.util.ClassUtils;
19
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.Map;
23 import java.util.Set;
24
25 import javax.resource.spi.work.Work;
26 import javax.resource.spi.work.WorkException;
27 import javax.resource.spi.work.WorkListener;
28
29 import edu.emory.mathcs.backport.java.util.Queue;
30 import edu.emory.mathcs.backport.java.util.concurrent.BlockingDeque;
31 import edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingDeque;
32 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
33 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public class ServerNotificationManager implements Work, Disposable, ServerNotificationHandler, MuleContextAware
64 {
65
66 public static final String NULL_SUBSCRIPTION = "NULL";
67 protected Log logger = LogFactory.getLog(getClass());
68 private boolean dynamic = false;
69 private Configuration configuration = new Configuration();
70 private AtomicBoolean disposed = new AtomicBoolean(false);
71 private BlockingDeque eventQueue = new LinkedBlockingDeque();
72 private MuleContext muleContext;
73
74 public boolean isNotificationDynamic()
75 {
76 return dynamic;
77 }
78
79 public void setMuleContext(MuleContext context)
80 {
81 muleContext = context;
82 }
83
84 public void setNotificationDynamic(boolean dynamic)
85 {
86 this.dynamic = dynamic;
87 }
88
89 public void start(WorkManager workManager, WorkListener workListener) throws LifecycleException
90 {
91 try
92 {
93 workManager.scheduleWork(this, WorkManager.INDEFINITE, null, workListener);
94 }
95 catch (WorkException e)
96 {
97 throw new LifecycleException(e, this);
98 }
99 }
100
101 public void addInterfaceToType(Class<? extends ServerNotificationListener> iface, Class<? extends ServerNotification> event)
102 {
103 configuration.addInterfaceToType(iface, event);
104 }
105
106 public void setInterfaceToTypes(Map<Class<? extends ServerNotificationListener>, Set<Class<? extends ServerNotification>>> interfaceToEvents) throws ClassNotFoundException
107 {
108 configuration.addAllInterfaceToTypes(interfaceToEvents);
109 }
110
111 public void addListenerSubscriptionPair(ListenerSubscriptionPair pair)
112 {
113 configuration.addListenerSubscriptionPair(pair);
114 }
115
116 public void addListener(ServerNotificationListener<?> listener)
117 {
118 configuration.addListenerSubscriptionPair(new ListenerSubscriptionPair(listener));
119 }
120
121 public void addListenerSubscription(ServerNotificationListener<?> listener, String subscription)
122 {
123 configuration.addListenerSubscriptionPair(new ListenerSubscriptionPair(listener, subscription));
124 }
125
126 public void addAllListenerSubscriptionPairs(Collection<?> pairs)
127 {
128 configuration.addAllListenerSubscriptionPairs(pairs);
129 }
130
131
132
133
134
135 @Deprecated
136 public void setAllListenerSubscriptionPairs(Collection<?> pairs)
137 {
138 configuration.addAllListenerSubscriptionPairs(pairs);
139 }
140
141
142
143
144 public void removeListener(ServerNotificationListener<?> listener)
145 {
146 configuration.removeListener(listener);
147 }
148
149 public void removeAllListeners(Collection<ServerNotificationListener> listeners)
150 {
151 configuration.removeAllListeners(listeners);
152 }
153
154 public void disableInterface(Class<? extends ServerNotificationListener> iface) throws ClassNotFoundException
155 {
156 configuration.disableInterface(iface);
157 }
158
159 public void setDisabledInterfaces(Collection<Class<? extends ServerNotificationListener>> interfaces) throws ClassNotFoundException
160 {
161 configuration.disabledAllInterfaces(interfaces);
162 }
163
164 public void disableType(Class<? extends ServerNotification> type) throws ClassNotFoundException
165 {
166 configuration.disableType(type);
167 }
168
169 public void setDisabledTypes(Collection<Class<? extends ServerNotificationListener>> types) throws ClassNotFoundException
170 {
171 configuration.disableAllTypes(types);
172 }
173
174 public boolean isListenerRegistered(ServerNotificationListener listener)
175 {
176 for (ListenerSubscriptionPair pair : configuration.getListeners())
177 {
178 if (pair.getListener().equals(listener))
179 {
180 return true;
181 }
182 }
183 return false;
184 }
185
186 public void fireNotification(ServerNotification notification)
187 {
188 if (!disposed.get())
189 {
190 notification.setMuleContext(muleContext);
191 if (notification instanceof BlockingServerEvent)
192 {
193 notifyListeners(notification);
194 }
195 else
196 {
197 try
198 {
199 eventQueue.put(notification);
200 }
201 catch (InterruptedException e)
202 {
203 if (!disposed.get())
204 {
205 logger.error("Failed to queue notification: " + notification, e);
206 }
207 }
208 }
209 }
210 else
211 {
212 logger.warn("Notification not enqueued after ServerNotificationManager disposal: " + notification);
213 }
214 }
215
216 public boolean isNotificationEnabled(Class<? extends ServerNotification> type)
217 {
218 boolean enabled = false;
219 if (configuration != null)
220 {
221 Policy policy = configuration.getPolicy();
222 if (policy != null)
223 {
224 enabled = policy.isNotificationEnabled(type);
225 }
226 }
227 return enabled;
228 }
229
230 public void dispose()
231 {
232 disposed.set(true);
233 configuration = null;
234 }
235
236 protected void notifyListeners(ServerNotification notification)
237 {
238 if (!disposed.get())
239 {
240 configuration.getPolicy().dispatch(notification);
241 }
242 else
243 {
244 logger.warn("Notification not delivered after ServerNotificationManager disposal: " + notification);
245 }
246 }
247
248 public void release()
249 {
250 dispose();
251 }
252
253 public void run()
254 {
255 while (!disposed.get())
256 {
257 try
258 {
259 ServerNotification notification = (ServerNotification) eventQueue.poll(
260 muleContext.getConfiguration().getDefaultQueueTimeout(),
261 TimeUnit.MILLISECONDS);
262 if (notification != null)
263 {
264 notifyListeners(notification);
265 }
266 }
267 catch (InterruptedException e)
268 {
269 Thread.currentThread().interrupt();
270 }
271 }
272 }
273
274
275
276
277 public Queue getEventQueue() {
278 return eventQueue;
279 }
280
281
282
283
284 static Class toClass(Object value) throws ClassNotFoundException
285 {
286 Class clazz;
287 if (value instanceof String)
288 {
289 clazz = ClassUtils.loadClass(value.toString(), value.getClass());
290 }
291 else if(value instanceof Class)
292 {
293 clazz = (Class)value;
294 }
295 else
296 {
297 throw new IllegalArgumentException("Notification types and listeners must be a Class with fully qualified class name. Value is: " + value);
298 }
299 return clazz;
300 }
301
302
303
304 Policy getPolicy()
305 {
306 return configuration.getPolicy();
307 }
308
309 public Map<Class<? extends ServerNotificationListener>, Set<Class<? extends ServerNotification>>> getInterfaceToTypes()
310 {
311 return Collections.unmodifiableMap(configuration.getInterfaceToTypes());
312 }
313
314 public Set<ListenerSubscriptionPair> getListeners()
315 {
316 return Collections.unmodifiableSet(configuration.getListeners());
317 }
318
319 }