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