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