1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.asteriskjava.manager.internal;
18
19 import java.lang.reflect.Constructor;
20 import java.lang.reflect.Method;
21 import java.lang.reflect.Modifier;
22 import java.util.HashMap;
23 import java.util.Locale;
24 import java.util.Map;
25
26 import org.asteriskjava.manager.event.AgentCallbackLoginEvent;
27 import org.asteriskjava.manager.event.AgentCallbackLogoffEvent;
28 import org.asteriskjava.manager.event.AgentCalledEvent;
29 import org.asteriskjava.manager.event.AgentCompleteEvent;
30 import org.asteriskjava.manager.event.AgentConnectEvent;
31 import org.asteriskjava.manager.event.AgentDumpEvent;
32 import org.asteriskjava.manager.event.AgentLoginEvent;
33 import org.asteriskjava.manager.event.AgentLogoffEvent;
34 import org.asteriskjava.manager.event.AgentsCompleteEvent;
35 import org.asteriskjava.manager.event.AgentsEvent;
36 import org.asteriskjava.manager.event.AlarmClearEvent;
37 import org.asteriskjava.manager.event.AlarmEvent;
38 import org.asteriskjava.manager.event.CdrEvent;
39 import org.asteriskjava.manager.event.ChannelReloadEvent;
40 import org.asteriskjava.manager.event.DbGetResponseEvent;
41 import org.asteriskjava.manager.event.DialEvent;
42 import org.asteriskjava.manager.event.DndStateEvent;
43 import org.asteriskjava.manager.event.ExtensionStatusEvent;
44 import org.asteriskjava.manager.event.FaxReceivedEvent;
45 import org.asteriskjava.manager.event.HangupEvent;
46 import org.asteriskjava.manager.event.HoldEvent;
47 import org.asteriskjava.manager.event.HoldedCallEvent;
48 import org.asteriskjava.manager.event.JoinEvent;
49 import org.asteriskjava.manager.event.LeaveEvent;
50 import org.asteriskjava.manager.event.LinkEvent;
51 import org.asteriskjava.manager.event.LogChannelEvent;
52 import org.asteriskjava.manager.event.ManagerEvent;
53 import org.asteriskjava.manager.event.MeetMeJoinEvent;
54 import org.asteriskjava.manager.event.MeetMeLeaveEvent;
55 import org.asteriskjava.manager.event.MeetMeMuteEvent;
56 import org.asteriskjava.manager.event.MeetMeStopTalkingEvent;
57 import org.asteriskjava.manager.event.MeetMeTalkingEvent;
58 import org.asteriskjava.manager.event.MessageWaitingEvent;
59 import org.asteriskjava.manager.event.NewCallerIdEvent;
60 import org.asteriskjava.manager.event.NewChannelEvent;
61 import org.asteriskjava.manager.event.NewExtenEvent;
62 import org.asteriskjava.manager.event.NewStateEvent;
63 import org.asteriskjava.manager.event.OriginateFailureEvent;
64 import org.asteriskjava.manager.event.OriginateResponseEvent;
65 import org.asteriskjava.manager.event.OriginateSuccessEvent;
66 import org.asteriskjava.manager.event.ParkedCallEvent;
67 import org.asteriskjava.manager.event.ParkedCallGiveUpEvent;
68 import org.asteriskjava.manager.event.ParkedCallTimeOutEvent;
69 import org.asteriskjava.manager.event.ParkedCallsCompleteEvent;
70 import org.asteriskjava.manager.event.PeerEntryEvent;
71 import org.asteriskjava.manager.event.PeerStatusEvent;
72 import org.asteriskjava.manager.event.PeerlistCompleteEvent;
73 import org.asteriskjava.manager.event.QueueCallerAbandonEvent;
74 import org.asteriskjava.manager.event.QueueEntryEvent;
75 import org.asteriskjava.manager.event.QueueMemberAddedEvent;
76 import org.asteriskjava.manager.event.QueueMemberEvent;
77 import org.asteriskjava.manager.event.QueueMemberPausedEvent;
78 import org.asteriskjava.manager.event.QueueMemberRemovedEvent;
79 import org.asteriskjava.manager.event.QueueMemberStatusEvent;
80 import org.asteriskjava.manager.event.QueueParamsEvent;
81 import org.asteriskjava.manager.event.QueueStatusCompleteEvent;
82 import org.asteriskjava.manager.event.QueueSummaryCompleteEvent;
83 import org.asteriskjava.manager.event.QueueSummaryEvent;
84 import org.asteriskjava.manager.event.RegistryEvent;
85 import org.asteriskjava.manager.event.ReloadEvent;
86 import org.asteriskjava.manager.event.RenameEvent;
87 import org.asteriskjava.manager.event.ResponseEvent;
88 import org.asteriskjava.manager.event.ShutdownEvent;
89 import org.asteriskjava.manager.event.StatusCompleteEvent;
90 import org.asteriskjava.manager.event.StatusEvent;
91 import org.asteriskjava.manager.event.UnholdEvent;
92 import org.asteriskjava.manager.event.UnlinkEvent;
93 import org.asteriskjava.manager.event.UnparkedCallEvent;
94 import org.asteriskjava.manager.event.UserEvent;
95 import org.asteriskjava.manager.event.ZapShowChannelsCompleteEvent;
96 import org.asteriskjava.manager.event.ZapShowChannelsEvent;
97 import org.asteriskjava.util.AstUtil;
98 import org.asteriskjava.util.Log;
99 import org.asteriskjava.util.LogFactory;
100 import org.asteriskjava.util.ReflectionUtil;
101
102 /***
103 * Default implementation of the EventBuilder interface.
104 *
105 * @see org.asteriskjava.manager.event.ManagerEvent
106 * @author srt
107 * @version $Id: EventBuilderImpl.java 815 2007-07-01 20:30:31Z srt $
108 */
109 class EventBuilderImpl implements EventBuilder
110 {
111 private final Log logger = LogFactory.getLog(getClass());
112 private Map<String, Class> registeredEventClasses;
113
114 EventBuilderImpl()
115 {
116 this.registeredEventClasses = new HashMap<String, Class>();
117 registerBuiltinEventClasses();
118 }
119
120 @SuppressWarnings("deprecation")
121 private void registerBuiltinEventClasses()
122 {
123 registerEventClass(AgentCallbackLoginEvent.class);
124 registerEventClass(AgentCallbackLogoffEvent.class);
125 registerEventClass(AgentCalledEvent.class);
126 registerEventClass(AgentConnectEvent.class);
127 registerEventClass(AgentCompleteEvent.class);
128 registerEventClass(AgentDumpEvent.class);
129 registerEventClass(AgentLoginEvent.class);
130 registerEventClass(AgentLogoffEvent.class);
131 registerEventClass(AgentsEvent.class);
132 registerEventClass(AgentsCompleteEvent.class);
133 registerEventClass(AlarmEvent.class);
134 registerEventClass(AlarmClearEvent.class);
135 registerEventClass(CdrEvent.class);
136 registerEventClass(ChannelReloadEvent.class);
137 registerEventClass(DbGetResponseEvent.class);
138 registerEventClass(DialEvent.class);
139 registerEventClass(DndStateEvent.class);
140 registerEventClass(ExtensionStatusEvent.class);
141 registerEventClass(FaxReceivedEvent.class);
142 registerEventClass(HangupEvent.class);
143 registerEventClass(HoldedCallEvent.class);
144 registerEventClass(HoldEvent.class);
145 registerEventClass(JoinEvent.class);
146 registerEventClass(LeaveEvent.class);
147 registerEventClass(LinkEvent.class);
148 registerEventClass(LogChannelEvent.class);
149 registerEventClass(MeetMeJoinEvent.class);
150 registerEventClass(MeetMeLeaveEvent.class);
151 registerEventClass(MeetMeMuteEvent.class);
152 registerEventClass(MeetMeTalkingEvent.class);
153 registerEventClass(MeetMeStopTalkingEvent.class);
154 registerEventClass(MessageWaitingEvent.class);
155 registerEventClass(NewCallerIdEvent.class);
156 registerEventClass(NewChannelEvent.class);
157 registerEventClass(NewExtenEvent.class);
158 registerEventClass(NewStateEvent.class);
159 registerEventClass(OriginateFailureEvent.class);
160 registerEventClass(OriginateSuccessEvent.class);
161 registerEventClass(OriginateResponseEvent.class);
162 registerEventClass(ParkedCallGiveUpEvent.class);
163 registerEventClass(ParkedCallEvent.class);
164 registerEventClass(ParkedCallTimeOutEvent.class);
165 registerEventClass(ParkedCallsCompleteEvent.class);
166 registerEventClass(PeerEntryEvent.class);
167 registerEventClass(PeerlistCompleteEvent.class);
168 registerEventClass(PeerStatusEvent.class);
169 registerEventClass(QueueCallerAbandonEvent.class);
170 registerEventClass(QueueEntryEvent.class);
171 registerEventClass(QueueMemberAddedEvent.class);
172 registerEventClass(QueueMemberEvent.class);
173 registerEventClass(QueueMemberPausedEvent.class);
174 registerEventClass(QueueMemberRemovedEvent.class);
175 registerEventClass(QueueMemberStatusEvent.class);
176 registerEventClass(QueueParamsEvent.class);
177 registerEventClass(QueueStatusCompleteEvent.class);
178 registerEventClass(QueueSummaryCompleteEvent.class);
179 registerEventClass(QueueSummaryEvent.class);
180 registerEventClass(RegistryEvent.class);
181 registerEventClass(ReloadEvent.class);
182 registerEventClass(RenameEvent.class);
183 registerEventClass(ShutdownEvent.class);
184 registerEventClass(StatusEvent.class);
185 registerEventClass(StatusCompleteEvent.class);
186 registerEventClass(UnholdEvent.class);
187 registerEventClass(UnlinkEvent.class);
188 registerEventClass(UnparkedCallEvent.class);
189 registerEventClass(ZapShowChannelsEvent.class);
190 registerEventClass(ZapShowChannelsCompleteEvent.class);
191 }
192
193 public final void registerEventClass(Class clazz) throws IllegalArgumentException
194 {
195 String className;
196 String eventType;
197
198 className = clazz.getName();
199 eventType = className.substring(className.lastIndexOf('.') + 1).toLowerCase(Locale.ENGLISH);
200
201 if (eventType.endsWith("event"))
202 {
203 eventType = eventType.substring(0, eventType.length() - "event".length());
204 }
205
206 if (UserEvent.class.isAssignableFrom(clazz) && !eventType.startsWith("userevent"))
207 {
208 eventType = "userevent" + eventType;
209 }
210
211 registerEventClass(eventType, clazz);
212 }
213
214 /***
215 * Registers a new event class for the event given by eventType.
216 *
217 * @param eventType the name of the event to register the class for. For
218 * example "Join".
219 * @param clazz the event class to register, must extend
220 * {@link ManagerEvent}.
221 * @throws IllegalArgumentException if clazz is not a valid event class.
222 */
223 @SuppressWarnings("unchecked")
224 public final void registerEventClass(String eventType, Class clazz) throws IllegalArgumentException
225 {
226 Constructor defaultConstructor;
227
228 if (!ManagerEvent.class.isAssignableFrom(clazz))
229 {
230 throw new IllegalArgumentException(clazz + " is not a ManagerEvent");
231 }
232
233 if ((clazz.getModifiers() & Modifier.ABSTRACT) != 0)
234 {
235 throw new IllegalArgumentException(clazz + " is abstract");
236 }
237
238 try
239 {
240 defaultConstructor = clazz.getConstructor(new Class[]{Object.class});
241 }
242 catch (NoSuchMethodException ex)
243 {
244 throw new IllegalArgumentException(clazz + " has no usable constructor");
245 }
246
247 if ((defaultConstructor.getModifiers() & Modifier.PUBLIC) == 0)
248 {
249 throw new IllegalArgumentException(clazz + " has no public default constructor");
250 }
251
252 registeredEventClasses.put(eventType.toLowerCase(), clazz);
253
254 logger.debug("Registered event type '" + eventType + "' (" + clazz + ")");
255 }
256
257 @SuppressWarnings("unchecked")
258 public ManagerEvent buildEvent(Object source, Map<String, String> attributes)
259 {
260 ManagerEvent event;
261 String eventType;
262 Class eventClass;
263 Constructor constructor;
264
265 if (attributes.get("event") == null)
266 {
267 logger.error("No event event type in properties");
268 return null;
269 }
270
271 eventType = attributes.get("event").toLowerCase();
272
273
274
275 if ("userevent".equals(eventType))
276 {
277 String userEventType;
278
279 if (attributes.get("userevent") == null)
280 {
281 logger.error("No user event type in properties");
282 return null;
283 }
284
285 userEventType = attributes.get("userevent").toLowerCase();
286 eventType = eventType + userEventType;
287 }
288
289 eventClass = registeredEventClasses.get(eventType);
290 if (eventClass == null)
291 {
292 logger.info("No event class registered for event type '" + eventType + "', attributes: " + attributes);
293 return null;
294 }
295
296 try
297 {
298 constructor = eventClass.getConstructor(new Class[]{Object.class});
299 }
300 catch (NoSuchMethodException ex)
301 {
302 logger.error("Unable to get constructor of " + eventClass.getName(), ex);
303 return null;
304 }
305
306 try
307 {
308 event = (ManagerEvent) constructor.newInstance(source);
309 }
310 catch (Exception ex)
311 {
312 logger.error("Unable to create new instance of " + eventClass.getName(), ex);
313 return null;
314 }
315
316 setAttributes(event, attributes);
317
318
319
320
321 if (event instanceof ResponseEvent)
322 {
323 ResponseEvent responseEvent;
324 String actionId;
325
326 responseEvent = (ResponseEvent) event;
327 actionId = responseEvent.getActionId();
328 if (actionId != null)
329 {
330 responseEvent.setActionId(ManagerUtil.stripInternalActionId(actionId));
331 responseEvent.setInternalActionId(ManagerUtil.getInternalActionId(actionId));
332 }
333 }
334
335 return event;
336 }
337
338 @SuppressWarnings("unchecked")
339 private void setAttributes(ManagerEvent event, Map<String, String> attributes)
340 {
341 Map<String, Method> setters;
342
343 setters = ReflectionUtil.getSetters(event.getClass());
344 for (String name : attributes.keySet())
345 {
346 Object value;
347 Class dataType;
348 Method setter;
349
350 if ("event".equals(name))
351 {
352 continue;
353 }
354
355
356
357
358
359
360 if ("source".equals(name))
361 {
362 setter = setters.get("src");
363 }
364 else
365 {
366 setter = setters.get(stripIllegalCharacters(name));
367 }
368
369
370 if (setter == null && !(event instanceof UserEvent))
371 {
372 logger.error("Unable to set property '" + name + "' to '" + attributes.get(name) + "' on "
373 + event.getClass().getName() + ": no setter");
374 }
375
376 if(setter == null) {
377 continue;
378 }
379
380 dataType = setter.getParameterTypes()[0];
381
382 if (dataType == Boolean.class)
383 {
384 value = AstUtil.isTrue(attributes.get(name));
385 }
386 else if (dataType.isAssignableFrom(String.class))
387 {
388 value = attributes.get(name);
389 }
390 else
391 {
392 try
393 {
394 Constructor constructor = dataType.getConstructor(new Class[]{String.class});
395 value = constructor.newInstance(attributes.get(name));
396 }
397 catch (Exception e)
398 {
399 logger.error("Unable to convert value '" + attributes.get(name) + "' of property '" + name + "' on "
400 + event.getClass().getName() + " to required type " + dataType, e);
401 continue;
402 }
403 }
404
405 try
406 {
407 setter.invoke(event, value);
408 }
409 catch (Exception e)
410 {
411 logger.error("Unable to set property '" + name + "' to '" + attributes.get(name) + "' on "
412 + event.getClass().getName(), e);
413 }
414 }
415 }
416
417 /***
418 * Strips all illegal charaters from the given lower case string.
419 *
420 * @param s the original string
421 * @return the string with all illegal characters stripped
422 */
423 private String stripIllegalCharacters(String s)
424 {
425 char c;
426 boolean needsStrip = false;
427 StringBuffer sb;
428
429 if (s == null)
430 {
431 return null;
432 }
433
434 for (int i = 0; i < s.length(); i++)
435 {
436 c = s.charAt(i);
437 if (c >= '0' && c <= '9')
438 {
439
440 }
441 else if (c >= 'a' && c <= 'z')
442 {
443
444 }
445 else
446 {
447 needsStrip = true;
448 break;
449 }
450 }
451
452 if (!needsStrip)
453 {
454 return s;
455 }
456
457 sb = new StringBuffer(s.length());
458 for (int i = 0; i < s.length(); i++)
459 {
460 c = s.charAt(i);
461 if (c >= '0' && c <= '9')
462 {
463 sb.append(c);
464 }
465 else if (c >= 'a' && c <= 'z')
466 {
467 sb.append(c);
468 }
469 }
470
471 return sb.toString();
472 }
473 }