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.io.IOException;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import net.sf.asterisk.io.SocketConnectionFacade;
26 import net.sf.asterisk.manager.AsteriskServer;
27 import net.sf.asterisk.manager.Dispatcher;
28 import net.sf.asterisk.manager.EventBuilder;
29 import net.sf.asterisk.manager.ManagerReader;
30 import net.sf.asterisk.manager.ResponseBuilder;
31 import net.sf.asterisk.manager.event.ConnectEvent;
32 import net.sf.asterisk.manager.event.DisconnectEvent;
33 import net.sf.asterisk.manager.event.ManagerEvent;
34 import net.sf.asterisk.manager.response.CommandResponse;
35 import net.sf.asterisk.manager.response.ManagerResponse;
36 import net.sf.asterisk.util.DateUtil;
37
38 import net.sf.asterisk.util.Log;
39 import net.sf.asterisk.util.LogFactory;
40
41 /***
42 * Default implementation of the ManagerReader interface.
43 *
44 * @author srt
45 * @version $Id: ManagerReaderImpl.java,v 1.9 2005/09/13 19:59:58 srt Exp $
46 */
47 public class ManagerReaderImpl implements ManagerReader
48 {
49 /***
50 * Instance logger.
51 */
52 private final Log logger = LogFactory.getLog(getClass());
53
54 /***
55 * The event builder utility to convert a map of attributes reveived from asterisk to instances
56 * of registered event classes.
57 */
58 private final EventBuilder eventBuilder;
59
60 /***
61 * The response builder utility to convert a map of attributes reveived from asterisk to
62 * instances of well known response classes.
63 */
64 private final ResponseBuilder responseBuilder;
65
66 /***
67 * The dispatcher to use for dispatching events and responses.
68 */
69 private final Dispatcher dispatcher;
70
71 /***
72 * The asterisk server we are reading from.
73 */
74 private final AsteriskServer asteriskServer;
75
76 /***
77 * The socket to use for reading from the asterisk server.
78 */
79 private SocketConnectionFacade socket;
80
81 /***
82 * If set to <code>true</code>, terminates and closes the reader.
83 */
84 private boolean die = false;
85
86 /***
87 * Creates a new ManagerReaderImpl.
88 *
89 * @param dispatcher the dispatcher to use for dispatching events and responses.
90 */
91 public ManagerReaderImpl(final Dispatcher dispatcher, AsteriskServer asteriskServer)
92 {
93 this.dispatcher = dispatcher;
94 this.asteriskServer = asteriskServer;
95
96 this.eventBuilder = new EventBuilderImpl();
97 this.responseBuilder = new ResponseBuilderImpl();
98 }
99
100 /***
101 * Sets the socket to use for reading from the asterisk server.
102 *
103 * @param socket the socket to use for reading from the asterisk server.
104 */
105 public void setSocket(final SocketConnectionFacade socket)
106 {
107 this.socket = socket;
108 }
109
110 public void registerEventClass(Class eventClass)
111 {
112 eventBuilder.registerEventClass(eventClass);
113 }
114
115 /***
116 * Reads line by line from the asterisk server, sets the protocol identifier as soon as it is
117 * received and dispatches the received events and responses via the associated dispatcher.
118 *
119 * @see DefaultManagerConnection#dispatchEvent(ManagerEvent)
120 * @see DefaultManagerConnection#dispatchResponse(ManagerResponse)
121 * @see DefaultManagerConnection#setProtocolIdentifier(String)
122 */
123 public void run()
124 {
125 final Map buffer = new HashMap();
126 final List commandResult = new ArrayList();
127 String line;
128 boolean processingCommandResult = false;
129
130 if (socket == null)
131 {
132 throw new IllegalStateException("Unable to run: socket is null.");
133 }
134
135 this.die = false;
136
137 try
138 {
139 while ((line = socket.readLine()) != null && !this.die)
140 {
141
142
143 if (processingCommandResult)
144 {
145
146
147 if ("--END COMMAND--".equals(line) || " --END COMMAND--".equals(line))
148 {
149 CommandResponse commandResponse = new CommandResponse();
150
151 for (int crIdx = 0; crIdx < commandResult.size(); crIdx++)
152 {
153 String[] crNVPair = ((String) commandResult.get(crIdx)).split(" *: *", 2);
154
155 if (crNVPair[0].equalsIgnoreCase("ActionID"))
156 {
157
158
159
160 commandResult.remove(crIdx--);
161
162
163 commandResponse.setActionId(crNVPair[1]);
164 }
165 else if (crNVPair[0].equalsIgnoreCase("Privilege"))
166 {
167
168
169
170 commandResult.remove(crIdx--);
171 }
172 else
173 {
174
175
176 break;
177 }
178 }
179 commandResponse.setResponse("Follows");
180 commandResponse.setDateReceived(DateUtil.getDate());
181 commandResponse.setResult(commandResult);
182 Map attributes = new HashMap();
183 attributes.put("actionid", commandResponse.getActionId());
184 attributes.put("response", commandResponse.getResponse());
185 commandResponse.setAttributes(attributes);
186 dispatcher.dispatchResponse(commandResponse);
187 processingCommandResult = false;
188 }
189 else
190 {
191 commandResult.add(line);
192 }
193 continue;
194 }
195
196
197
198
199 if ("Response: Follows".equalsIgnoreCase(line))
200 {
201 processingCommandResult = true;
202 commandResult.clear();
203 continue;
204 }
205
206
207
208 if (line.startsWith("Asterisk Call Manager/"))
209 {
210 ConnectEvent connectEvent = new ConnectEvent(asteriskServer);
211 connectEvent.setProtocolIdentifier(line);
212 connectEvent.setDateReceived(DateUtil.getDate());
213 dispatcher.dispatchEvent(connectEvent);
214 continue;
215 }
216
217
218
219 if (line.length() == 0)
220 {
221 if (buffer.containsKey("response"))
222 {
223 ManagerResponse response = buildResponse(buffer);
224 logger.debug("attempting to build response");
225 if (response != null)
226 {
227 dispatcher.dispatchResponse(response);
228 }
229 }
230 else if (buffer.containsKey("event"))
231 {
232 logger.debug("attempting to build event: " + buffer.get("event"));
233 ManagerEvent event = buildEvent(asteriskServer, buffer);
234 if (event != null)
235 {
236 dispatcher.dispatchEvent(event);
237 }
238 else
239 {
240 logger.debug("buildEvent returned null");
241 }
242 }
243 else
244 {
245 if (buffer.size() > 0)
246 {
247 logger.debug("buffer contains neither response nor event");
248 }
249 }
250
251 buffer.clear();
252 }
253 else
254 {
255 int delimiterIndex;
256
257 delimiterIndex = line.indexOf(":");
258 if (delimiterIndex > 0 && line.length() > delimiterIndex + 2)
259 {
260 String name;
261 String value;
262
263 name = line.substring(0, delimiterIndex).toLowerCase();
264 value = line.substring(delimiterIndex + 2);
265
266 buffer.put(name, value);
267 logger.debug("Got name [" + name + "], value: [" + value + "]");
268 }
269 }
270 }
271 logger.info("Reached end of stream, terminating reader.");
272 }
273 catch (IOException e)
274 {
275 logger.info("IOException while reading from asterisk server, terminating reader thread: " + e.getMessage());
276 }
277 finally
278 {
279
280 DisconnectEvent disconnectEvent = new DisconnectEvent(asteriskServer);
281 disconnectEvent.setDateReceived(DateUtil.getDate());
282 dispatcher.dispatchEvent(disconnectEvent);
283 }
284 }
285
286 public void die()
287 {
288 this.die = true;
289 }
290
291 private ManagerResponse buildResponse(Map buffer)
292 {
293 ManagerResponse response;
294
295 response = responseBuilder.buildResponse(buffer);
296
297 if (response != null)
298 {
299 response.setDateReceived(DateUtil.getDate());
300 }
301
302 return response;
303 }
304
305 private ManagerEvent buildEvent(Object source, Map buffer)
306 {
307 ManagerEvent event;
308
309 event = eventBuilder.buildEvent(source, buffer);
310
311 if (event != null)
312 {
313 event.setDateReceived(DateUtil.getDate());
314 }
315
316 return event;
317 }
318 }