1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sf.asterisk.fastagi.impl;
18
19 import java.io.Serializable;
20 import java.io.UnsupportedEncodingException;
21 import java.net.InetAddress;
22 import java.net.URLDecoder;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.StringTokenizer;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32
33 import net.sf.asterisk.fastagi.AGIRequest;
34 import net.sf.asterisk.util.Log;
35 import net.sf.asterisk.util.LogFactory;
36
37 /***
38 * Default implementation of the AGIRequest interface.
39 *
40 * @author srt
41 * @version $Id: AGIRequestImpl.java,v 1.11 2005/11/27 16:08:17 srt Exp $
42 */
43 public class AGIRequestImpl implements Serializable, AGIRequest
44 {
45 private final Log logger = LogFactory.getLog(getClass());
46 private static final Pattern SCRIPT_PATTERN = Pattern
47 .compile("^([^//?]*)//?(.*)$");
48 private static final Pattern PARAMETER_PATTERN = Pattern
49 .compile("^(.*)=(.*)$");
50
51 private String rawCallerId;
52
53 /***
54 * Serial version identifier.
55 */
56 private static final long serialVersionUID = 3257001047145789496L;
57
58 private Map request;
59
60 /***
61 * A map assigning the values of a parameter (an array of Strings) to the
62 * name of the parameter.
63 */
64 private Map parameterMap;
65
66 private String parameters;
67 private String script;
68 private boolean callerIdCreated;
69 private InetAddress localAddress;
70 private int localPort;
71 private InetAddress remoteAddress;
72 private int remotePort;
73
74 /***
75 * Creates a new AGIRequestImpl.
76 *
77 * @param environment the first lines as received from Asterisk containing
78 * the environment.
79 */
80 public AGIRequestImpl(final Collection environment)
81 {
82 if (environment == null)
83 {
84 throw new IllegalArgumentException("Environment must not be null.");
85 }
86 request = buildMap(environment);
87 }
88
89 /***
90 * Builds a map containing variable names as key (with the "agi_" prefix
91 * stripped) and the corresponding values.<br>
92 * Syntactically invalid and empty variables are skipped.
93 *
94 * @param lines the environment to transform.
95 * @return a map with the variables set corresponding to the given
96 * environment.
97 */
98 private Map buildMap(final Collection lines)
99 {
100 Map map;
101 Iterator lineIterator;
102
103 map = new HashMap();
104 lineIterator = lines.iterator();
105
106 while (lineIterator.hasNext())
107 {
108 String line;
109 int colonPosition;
110 String key;
111 String value;
112
113 line = (String) lineIterator.next();
114 colonPosition = line.indexOf(':');
115
116
117 if (colonPosition < 0)
118 {
119 continue;
120 }
121
122
123 if (!line.startsWith("agi_"))
124 {
125 continue;
126 }
127
128
129 if (line.length() < colonPosition + 2)
130 {
131 continue;
132 }
133
134 key = line.substring(4, colonPosition).toLowerCase();
135 value = line.substring(colonPosition + 2);
136
137 if (value.length() != 0)
138 {
139 map.put(key, value);
140 }
141 }
142
143 return map;
144 }
145
146 public Map getRequest()
147 {
148 return request;
149 }
150
151 /***
152 * Returns the name of the script to execute.
153 *
154 * @return the name of the script to execute.
155 */
156 public synchronized String getScript()
157 {
158 if (script != null)
159 {
160 return script;
161 }
162
163 script = (String) request.get("network_script");
164 if (script != null)
165 {
166 Matcher scriptMatcher = SCRIPT_PATTERN.matcher(script);
167 if (scriptMatcher.matches())
168 {
169 script = scriptMatcher.group(1);
170 parameters = scriptMatcher.group(2);
171 }
172 }
173
174 return script;
175 }
176
177 /***
178 * Returns the full URL of the request in the form
179 * agi://host[:port][/script].
180 *
181 * @return the full URL of the request in the form
182 * agi://host[:port][/script].
183 */
184 public String getRequestURL()
185 {
186 return (String) request.get("request");
187 }
188
189 /***
190 * Returns the name of the channel.
191 *
192 * @return the name of the channel.
193 */
194 public String getChannel()
195 {
196 return (String) request.get("channel");
197 }
198
199 /***
200 * Returns the unqiue id of the channel.
201 *
202 * @return the unqiue id of the channel.
203 */
204 public String getUniqueId()
205 {
206 return (String) request.get("uniqueid");
207 }
208
209 public String getType()
210 {
211 return (String) request.get("type");
212 }
213
214 public String getLanguage()
215 {
216 return (String) request.get("language");
217 }
218
219 public String getCallerId()
220 {
221 String callerIdName;
222 String callerId;
223
224 callerIdName = (String) request.get("calleridname");
225 callerId = (String) request.get("callerid");
226 if (callerIdName != null)
227 {
228
229 if (callerId == null || "unknown".equals(callerId))
230 {
231 return null;
232 }
233
234 return callerId;
235 }
236 else
237 {
238
239 return getCallerId10();
240 }
241 }
242
243 public String getCallerIdName()
244 {
245 String callerIdName;
246
247 callerIdName = (String) request.get("calleridname");
248 if (callerIdName != null)
249 {
250
251 if ("unknown".equals(callerIdName))
252 {
253 return null;
254 }
255
256 return callerIdName;
257 }
258 else
259 {
260
261 return getCallerIdName10();
262 }
263 }
264
265 /***
266 * Returns the Caller*ID using Asterisk 1.0 logic.
267 *
268 * @return the Caller*ID
269 */
270 private String getCallerId10()
271 {
272 int lbPosition;
273 int rbPosition;
274
275 if (!callerIdCreated)
276 {
277 rawCallerId = (String) request.get("callerid");
278 callerIdCreated = true;
279 }
280
281 if (rawCallerId == null)
282 {
283 return null;
284 }
285
286 lbPosition = rawCallerId.indexOf('<');
287 rbPosition = rawCallerId.indexOf('>');
288
289 if (lbPosition < 0 || rbPosition < 0)
290 {
291 return rawCallerId;
292 }
293
294 return rawCallerId.substring(lbPosition + 1, rbPosition);
295 }
296
297 /***
298 * Returns the Caller*ID using Asterisk 1.0 logic.
299 *
300 * @return the Caller*ID Name
301 */
302 private String getCallerIdName10()
303 {
304 int lbPosition;
305 String callerIdName;
306
307 if (!callerIdCreated)
308 {
309 rawCallerId = (String) request.get("callerid");
310 callerIdCreated = true;
311 }
312
313 if (rawCallerId == null)
314 {
315 return null;
316 }
317
318 lbPosition = rawCallerId.indexOf('<');
319
320 if (lbPosition < 0)
321 {
322 return null;
323 }
324
325 callerIdName = rawCallerId.substring(0, lbPosition).trim();
326 if (callerIdName.startsWith("\"") && callerIdName.endsWith("\""))
327 {
328 callerIdName = callerIdName.substring(1, callerIdName.length() - 1);
329 }
330
331 if (callerIdName.length() == 0)
332 {
333 return null;
334 }
335 else
336 {
337 return callerIdName;
338 }
339 }
340
341 public String getDnid()
342 {
343 String dnid;
344
345 dnid = (String) request.get("dnid");
346
347 if (dnid == null || "unknown".equals(dnid))
348 {
349 return null;
350 }
351
352 return dnid;
353 }
354
355 public String getRdnis()
356 {
357 String rdnis;
358
359 rdnis = (String) request.get("rdnis");
360
361 if (rdnis == null || "unknown".equals(rdnis))
362 {
363 return null;
364 }
365
366 return rdnis;
367 }
368
369 public String getContext()
370 {
371 return (String) request.get("context");
372 }
373
374 public String getExtension()
375 {
376 return (String) request.get("extension");
377 }
378
379 public Integer getPriority()
380 {
381 if (request.get("priority") != null)
382 {
383 return new Integer((String) request.get("priority"));
384 }
385 return null;
386 }
387
388 public Boolean getEnhanced()
389 {
390 if (request.get("enhanced") != null)
391 {
392 if ("1.0".equals((String) request.get("enhanced")))
393 {
394 return Boolean.TRUE;
395 }
396 else
397 {
398 return Boolean.FALSE;
399 }
400 }
401 return null;
402 }
403
404 public String getAccountCode()
405 {
406 return (String) request.get("accountCode");
407 }
408
409 public Integer getCallingAni2()
410 {
411 if (request.get("callingani2") == null)
412 {
413 return null;
414 }
415
416 try
417 {
418 return Integer.valueOf((String) request.get("callingani2"));
419 }
420 catch (NumberFormatException e)
421 {
422 return null;
423 }
424 }
425
426 public Integer getCallingPres()
427 {
428 if (request.get("callingpres") == null)
429 {
430 return null;
431 }
432
433 try
434 {
435 return Integer.valueOf((String) request.get("callingpres"));
436 }
437 catch (NumberFormatException e)
438 {
439 return null;
440 }
441 }
442
443 public Integer getCallingTns()
444 {
445 if (request.get("callingtns") == null)
446 {
447 return null;
448 }
449
450 try
451 {
452 return Integer.valueOf((String) request.get("callingtns"));
453 }
454 catch (NumberFormatException e)
455 {
456 return null;
457 }
458 }
459
460 public Integer getCallingTon()
461 {
462 if (request.get("callington") == null)
463 {
464 return null;
465 }
466
467 try
468 {
469 return Integer.valueOf((String) request.get("callington"));
470 }
471 catch (NumberFormatException e)
472 {
473 return null;
474 }
475 }
476
477 public String getParameter(String name)
478 {
479 String[] values;
480
481 values = getParameterValues(name);
482
483 if (values == null || values.length == 0)
484 {
485 return null;
486 }
487
488 return values[0];
489 }
490
491 public String[] getParameterValues(String name)
492 {
493 if (getParameterMap().isEmpty())
494 {
495 return null;
496 }
497
498 return (String[]) parameterMap.get(name);
499 }
500
501 public synchronized Map getParameterMap()
502 {
503 if (parameterMap == null)
504 {
505 parameterMap = parseParameters(parameters);
506 }
507 return parameterMap;
508 }
509
510 /***
511 * Parses the given parameter string and caches the result.
512 *
513 * @param s the parameter string to parse
514 * @return a Map made up of parameter names their values
515 */
516 private synchronized Map parseParameters(String s)
517 {
518 Map parameterMap;
519 Map result;
520 Iterator parameterIterator;
521 StringTokenizer st;
522
523 parameterMap = new HashMap();
524 if (s == null)
525 {
526 return parameterMap;
527 }
528
529 st = new StringTokenizer(s, "&");
530 while (st.hasMoreTokens())
531 {
532 String parameter;
533 Matcher parameterMatcher;
534 String name;
535 String value;
536 List values;
537
538 parameter = st.nextToken();
539 parameterMatcher = PARAMETER_PATTERN.matcher(parameter);
540 if (parameterMatcher.matches())
541 {
542 try
543 {
544 name = URLDecoder
545 .decode(parameterMatcher.group(1), "UTF-8");
546 value = URLDecoder.decode(parameterMatcher.group(2),
547 "UTF-8");
548 }
549 catch (UnsupportedEncodingException e)
550 {
551 logger.error("Unable to decode parameter '" + parameter
552 + "'", e);
553 continue;
554 }
555 }
556 else
557 {
558 try
559 {
560 name = URLDecoder.decode(parameter, "UTF-8");
561 value = "";
562 }
563 catch (UnsupportedEncodingException e)
564 {
565 logger.error("Unable to decode parameter '" + parameter
566 + "'", e);
567 continue;
568 }
569 }
570
571 if (parameterMap.get(name) == null)
572 {
573 values = new ArrayList();
574 values.add(value);
575 parameterMap.put(name, values);
576 }
577 else
578 {
579 values = (List) parameterMap.get(name);
580 values.add(value);
581 }
582 }
583
584 result = new HashMap();
585 parameterIterator = parameterMap.keySet().iterator();
586 while (parameterIterator.hasNext())
587 {
588 String name;
589 List values;
590 String[] valueArray;
591
592 name = (String) parameterIterator.next();
593 values = (List) parameterMap.get(name);
594
595 valueArray = new String[values.size()];
596 result.put(name, values.toArray(valueArray));
597 }
598
599 return result;
600 }
601
602 public InetAddress getLocalAddress()
603 {
604 return localAddress;
605 }
606
607 public void setLocalAddress(InetAddress localAddress)
608 {
609 this.localAddress = localAddress;
610 }
611
612 public int getLocalPort()
613 {
614 return localPort;
615 }
616
617 public void setLocalPort(int localPort)
618 {
619 this.localPort = localPort;
620 }
621
622 public InetAddress getRemoteAddress()
623 {
624 return remoteAddress;
625 }
626
627 public void setRemoteAddress(InetAddress remoteAddress)
628 {
629 this.remoteAddress = remoteAddress;
630 }
631
632 public int getRemotePort()
633 {
634 return remotePort;
635 }
636
637 public void setRemotePort(int remotePort)
638 {
639 this.remotePort = remotePort;
640 }
641
642 public String toString()
643 {
644 StringBuffer sb;
645
646 sb = new StringBuffer(getClass().getName() + ": ");
647 sb.append("script='" + getScript() + "'; ");
648 sb.append("requestURL='" + getRequestURL() + "'; ");
649 sb.append("channel='" + getChannel() + "'; ");
650 sb.append("uniqueId='" + getUniqueId() + "'; ");
651 sb.append("type='" + getType() + "'; ");
652 sb.append("language='" + getLanguage() + "'; ");
653 sb.append("callerId='" + getCallerId() + "'; ");
654 sb.append("callerIdName='" + getCallerIdName() + "'; ");
655 sb.append("dnid='" + getDnid() + "'; ");
656 sb.append("rdnis='" + getRdnis() + "'; ");
657 sb.append("context='" + getContext() + "'; ");
658 sb.append("extension='" + getExtension() + "'; ");
659 sb.append("priority='" + getPriority() + "'; ");
660 sb.append("enhanced='" + getEnhanced() + "'; ");
661 sb.append("accountCode='" + getAccountCode() + "'; ");
662 sb.append("systemHashcode=" + System.identityHashCode(this));
663
664 return sb.toString();
665 }
666 }