View Javadoc

1   /*
2    * Copyright  2004-2005 Stefan Reuter
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *
16   */
17  package net.sf.asterisk.fastagi;
18  
19  import java.io.IOException;
20  
21  import net.sf.asterisk.fastagi.command.VerboseCommand;
22  import net.sf.asterisk.fastagi.impl.AGIChannelImpl;
23  import net.sf.asterisk.fastagi.impl.AGIReaderImpl;
24  import net.sf.asterisk.fastagi.impl.AGIWriterImpl;
25  import net.sf.asterisk.io.SocketConnectionFacade;
26  
27  import net.sf.asterisk.util.Log;
28  import net.sf.asterisk.util.LogFactory;
29  
30  /***
31   * An AGIConnectionHandler is created and run by the AGIServer whenever a new
32   * socket connection from an Asterisk Server is received.<br>
33   * It reads the request using an AGIReader and runs the AGIScript configured to
34   * handle this type of request. Finally it closes the socket connection.
35   * 
36   * @author srt
37   * @version $Id: AGIConnectionHandler.java,v 1.13 2005/11/04 21:49:01 srt Exp $
38   */
39  public class AGIConnectionHandler implements Runnable
40  {
41      private final Log logger = LogFactory.getLog(getClass());
42      private static final ThreadLocal channel = new ThreadLocal();
43  
44      /***
45       * The socket connection.
46       */
47      private SocketConnectionFacade socket;
48  
49      /***
50       * The strategy to use to determine which script to run.
51       */
52      private MappingStrategy mappingStrategy;
53  
54      /***
55       * Creates a new AGIConnectionHandler to handle the given socket connection.
56       * 
57       * @param socket the socket connection to handle.
58       * @param mappingStrategy the strategy to use to determine which script to
59       *            run.
60       */
61      public AGIConnectionHandler(SocketConnectionFacade socket,
62              MappingStrategy mappingStrategy)
63      {
64          this.socket = socket;
65          this.mappingStrategy = mappingStrategy;
66      }
67  
68      protected AGIReader createReader()
69      {
70          return new AGIReaderImpl(socket);
71      }
72  
73      protected AGIWriter createWriter()
74      {
75          return new AGIWriterImpl(socket);
76      }
77  
78      public void run()
79      {
80          try
81          {
82              AGIReader reader;
83              AGIWriter writer;
84              AGIRequest request;
85              AGIChannel channel;
86              AGIScript script;
87              Thread thread;
88              String threadName;
89  
90              reader = createReader();
91              writer = createWriter();
92  
93              request = reader.readRequest();
94              channel = new AGIChannelImpl(writer, reader);
95  
96              script = mappingStrategy.determineScript(request);
97  
98              thread = Thread.currentThread();
99              threadName = thread.getName();
100             AGIConnectionHandler.channel.set(channel);
101 
102             if (script != null)
103             {
104                 logger.info("Begin AGIScript " + script.getClass().getName()
105                         + " on " + threadName);
106                 script.service(request, channel);
107                 logger.info("End AGIScript " + script.getClass().getName()
108                         + " on " + threadName);
109             }
110             else
111             {
112                 String error;
113 
114                 error = "No script configured for URL '"
115                         + request.getRequestURL() + "' (script '"
116                         + request.getScript() + "')";
117                 channel.sendCommand(new VerboseCommand(error, 1));
118                 logger.error(error);
119             }
120         }
121         catch (AGIException e)
122         {
123             logger.error("AGIException while handling request", e);
124         }
125         catch (Exception e)
126         {
127             logger.error("Unexpected Exception while handling request", e);
128         }
129         finally
130         {
131             AGIConnectionHandler.channel.set(null);
132             try
133             {
134                 socket.close();
135             }
136             catch (IOException e)
137             {
138                 // swallow
139             }
140         }
141     }
142 
143     /***
144      * Returns the AGIChannel associated with the current thread.<br>
145      * 
146      * @return the AGIChannel associated with the current thread or
147      *         <code>null</code> if none is associated.
148      */
149     static AGIChannel getChannel()
150     {
151         return (AGIChannel) AGIConnectionHandler.channel.get();
152     }
153 }