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