1
2
3
4
5
6
7
8
9
10
11 package org.mule.context.notification;
12
13 import org.mule.api.context.WorkManager;
14 import org.mule.api.context.notification.BlockingServerEvent;
15 import org.mule.api.context.notification.ServerNotification;
16 import org.mule.api.context.notification.ServerNotificationHandler;
17 import org.mule.api.context.notification.ServerNotificationListener;
18 import org.mule.api.lifecycle.Disposable;
19 import org.mule.api.lifecycle.LifecycleException;
20 import org.mule.util.ClassUtils;
21
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Map;
25
26 import javax.resource.spi.work.Work;
27 import javax.resource.spi.work.WorkException;
28 import javax.resource.spi.work.WorkListener;
29
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.atomic.AtomicBoolean;
33
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
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
73 public boolean isNotificationDynamic()
74 {
75 return dynamic;
76 }
77
78 public void setNotificationDynamic(boolean dynamic)
79 {
80 this.dynamic = dynamic;
81 }
82
83 public void start(WorkManager workManager, WorkListener workListener) throws LifecycleException
84 {
85 try
86 {
87 workManager.scheduleWork(this, WorkManager.INDEFINITE, null, workListener);
88 }
89 catch (WorkException e)
90 {
91 throw new LifecycleException(e, this);
92 }
93 }
94
95 public void addInterfaceToType(Class iface, Class event)
96 {
97 configuration.addInterfaceToType(iface, event);
98 }
99
100 public void setInterfaceToTypes(Map interfaceToEvents) throws ClassNotFoundException
101 {
102 configuration.addAllInterfaceToTypes(interfaceToEvents);
103 }
104
105 public void addListenerSubscriptionPair(ListenerSubscriptionPair pair)
106 {
107 configuration.addListenerSubscriptionPair(pair);
108 }
109
110 public void addListener(ServerNotificationListener listener)
111 {
112 configuration.addListenerSubscriptionPair(new ListenerSubscriptionPair(listener));
113 }
114
115 public void addListenerSubscription(ServerNotificationListener listener, String subscription)
116 {
117 configuration.addListenerSubscriptionPair(new ListenerSubscriptionPair(listener, subscription));
118 }
119
120 public void setAllListenerSubscriptionPairs(Collection pairs)
121 {
122 configuration.addAllListenerSubscriptionPairs(pairs);
123 }
124
125
126
127
128 public void removeListener(ServerNotificationListener listener)
129 {
130 configuration.removeListener(listener);
131 }
132
133 public void removeAllListeners(Collection listeners)
134 {
135 configuration.removeAllListeners(listeners);
136 }
137
138 public void disableInterface(Class iface) throws ClassNotFoundException
139 {
140 configuration.disableInterface(iface);
141 }
142
143 public void setDisabledInterfaces(Collection interfaces) throws ClassNotFoundException
144 {
145 configuration.disabledAllInterfaces(interfaces);
146 }
147
148 public void disableType(Class type) throws ClassNotFoundException
149 {
150 configuration.disableType(type);
151 }
152
153 public void setDisabledTypes(Collection types) throws ClassNotFoundException
154 {
155 configuration.disableAllTypes(types);
156 }
157
158 public void fireNotification(ServerNotification notification)
159 {
160 if (!disposed.get())
161 {
162 if (notification instanceof BlockingServerEvent)
163 {
164 notifyListeners(notification);
165 }
166 else
167 {
168 try
169 {
170 eventQueue.put(notification);
171 }
172 catch (InterruptedException e)
173 {
174 if (!disposed.get())
175 {
176 logger.error("Failed to queue notification: " + notification, e);
177 }
178 }
179 }
180 }
181 else
182 {
183 logger.warn("Notification not enqueued after ServerNotificationManager disposal: " + notification);
184 }
185 }
186
187 public boolean isNotificationEnabled(Class type)
188 {
189 return configuration.getPolicy().isNotificationEnabled(type);
190 }
191
192 public void dispose()
193 {
194 disposed.set(true);
195 configuration = null;
196 }
197
198 protected void notifyListeners(ServerNotification notification)
199 {
200 if (!disposed.get())
201 {
202 configuration.getPolicy().dispatch(notification);
203 }
204 else
205 {
206 logger.warn("Notification not delivered after ServerNotificationManager disposal: " + notification);
207 }
208 }
209
210 public void release()
211 {
212 dispose();
213 }
214
215 public void run()
216 {
217 while (!disposed.get())
218 {
219 try
220 {
221 ServerNotification notification = (ServerNotification) eventQueue.take();
222 notifyListeners(notification);
223 }
224 catch (InterruptedException e)
225 {
226
227 }
228 }
229 }
230
231
232
233
234 public static Class toClass(Object value) throws ClassNotFoundException
235 {
236 Class clazz;
237 if (value instanceof String)
238 {
239 clazz = ClassUtils.loadClass(value.toString(), value.getClass());
240 }
241 else if(value instanceof Class)
242 {
243 clazz = (Class)value;
244 }
245 else
246 {
247 throw new IllegalArgumentException("Notification types and listeners must be a Class with fully qualified class name. Value is: " + value);
248 }
249 return clazz;
250 }
251
252
253
254 Policy getPolicy()
255 {
256 return configuration.getPolicy();
257 }
258
259 public Map getInterfaceToTypes()
260 {
261 return Collections.unmodifiableMap(configuration.getInterfaceToTypes());
262 }
263
264 public Collection getListeners()
265 {
266 return Collections.unmodifiableCollection(configuration.getListeners());
267 }
268
269 }