View Javadoc

1   /*
2    *  Copyright 2004-2006 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 org.asteriskjava.fastagi.internal;
18  
19  import java.util.List;
20  import java.util.concurrent.BlockingQueue;
21  import java.util.concurrent.LinkedBlockingQueue;
22  
23  import org.asteriskjava.fastagi.AgiException;
24  import org.asteriskjava.fastagi.MappingStrategy;
25  import org.asteriskjava.fastagi.command.AsyncAgiBreakCommand;
26  import org.asteriskjava.manager.event.AsyncAgiEvent;
27  import org.asteriskjava.manager.ManagerConnection;
28  
29  /**
30   * An AgiConnectionHandler for AsyncAGI.
31   * <p/>
32   * It reads the request using a AsyncAgiReader and runs the AgiScript configured to
33   * handle this type of request. Finally it sends an {@link org.asteriskjava.fastagi.command.AsyncAgiBreakCommand}.
34   *
35   * @author srt
36   * @version $Id$
37   */
38  public class AsyncAgiConnectionHandler extends AgiConnectionHandler
39  {
40      private final ManagerConnection connection;
41      private volatile String channelName;
42      private final List<String> environment;
43      private final BlockingQueue<AsyncAgiEvent> asyncAgiEvents;
44      private AsyncAgiWriter writer;
45  
46      /**
47       * Creates a new FastAGIConnectionHandler to handle the given FastAGI socket connection.
48       *
49       * @param mappingStrategy    the strategy to use to determine which script to run.
50       * @param asyncAgiStartEvent the AsyncAgiEvent that started this connection, must be a start sub event.
51       * @param agiChannelFactory  The factory to use for creating new AgiChannel instances.
52       * @throws IllegalArgumentException if asyncAgiStartEvent is not a start sub type".
53       */
54      public AsyncAgiConnectionHandler(MappingStrategy mappingStrategy, AsyncAgiEvent asyncAgiStartEvent, AgiChannelFactory agiChannelFactory) throws IllegalArgumentException
55      {
56          super(mappingStrategy, agiChannelFactory);
57          if (!asyncAgiStartEvent.isStart())
58          {
59              throw new IllegalArgumentException("AsyncAgiEvent passed to AsyncAgiConnectionHandler is not a start sub event");
60          }
61          connection = (ManagerConnection) asyncAgiStartEvent.getSource();
62          channelName = asyncAgiStartEvent.getChannel();
63          environment = asyncAgiStartEvent.decodeEnv();
64          asyncAgiEvents = new LinkedBlockingQueue<AsyncAgiEvent>();
65          setIgnoreMissingScripts(true);
66      }
67  
68      @Override
69      protected AgiReader createReader()
70      {
71          return new AsyncAgiReader(connection, environment, asyncAgiEvents);
72      }
73  
74      @Override
75      protected AgiWriter createWriter()
76      {
77          writer = new AsyncAgiWriter(connection, channelName);
78          return writer;
79      }
80  
81      @Override
82      public void release()
83      {
84          if (writer != null && (getScript() != null || ! isIgnoreMissingScripts()))
85          {
86              try
87              {
88                  writer.sendCommand(new AsyncAgiBreakCommand());
89              }
90              catch (AgiException e) // NOPMD
91              {
92                  // ignore
93              }
94          }
95      }
96  
97      public void onAsyncAgiExecEvent(AsyncAgiEvent event)
98      {
99          asyncAgiEvents.offer(event);
100     }
101 
102     public void onAsyncAgiEndEvent(AsyncAgiEvent event)
103     {
104         asyncAgiEvents.offer(event);
105     }
106 
107     public void updateChannelName(String channelName)
108     {
109         this.channelName = channelName;
110         writer.updateChannelName(channelName);
111     }
112 }