View Javadoc

1   /*
2    * $Id: UdpMessageReceiver.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.providers.udp;
12  
13  import org.mule.config.i18n.CoreMessages;
14  import org.mule.impl.MuleMessage;
15  import org.mule.providers.AbstractMessageReceiver;
16  import org.mule.providers.udp.i18n.UdpMessages;
17  import org.mule.umo.UMOComponent;
18  import org.mule.umo.UMOException;
19  import org.mule.umo.UMOMessage;
20  import org.mule.umo.endpoint.UMOEndpoint;
21  import org.mule.umo.lifecycle.Disposable;
22  import org.mule.umo.lifecycle.InitialisationException;
23  import org.mule.umo.provider.UMOConnector;
24  import org.mule.umo.provider.UMOMessageAdapter;
25  import org.mule.umo.transformer.UMOTransformer;
26  
27  import java.io.IOException;
28  import java.net.DatagramPacket;
29  import java.net.DatagramSocket;
30  import java.net.InetAddress;
31  import java.net.SocketTimeoutException;
32  import java.net.URI;
33  import java.net.UnknownHostException;
34  
35  import javax.resource.spi.work.Work;
36  import javax.resource.spi.work.WorkException;
37  import javax.resource.spi.work.WorkManager;
38  
39  /**
40   * <code>UdpMessageReceiver</code> receives UDP message packets.
41   */
42  public class UdpMessageReceiver extends AbstractMessageReceiver implements Work
43  {
44      protected DatagramSocket socket = null;
45      protected InetAddress inetAddress;
46      protected int bufferSize;
47      private URI uri;
48      protected UMOTransformer responseTransformer = null;
49  
50      public UdpMessageReceiver(UMOConnector connector, UMOComponent component, UMOEndpoint endpoint)
51          throws InitialisationException
52      {
53          super(connector, component, endpoint);
54          bufferSize = ((UdpConnector)connector).getReceiveBufferSize();
55  
56          uri = endpoint.getEndpointURI().getUri();
57  
58          try
59          {
60              if(!"null".equalsIgnoreCase(uri.getHost()))
61              {
62                  inetAddress = InetAddress.getByName(uri.getHost());
63              }
64          }
65          catch (UnknownHostException e)
66          {
67              throw new InitialisationException(UdpMessages.failedToLocateHost(uri), e, this);
68          }
69  
70          responseTransformer = getResponseTransformer();
71      }
72  
73      protected void doConnect() throws Exception
74      {
75          try
76          {
77              socket = ((UdpConnector)connector).getSocket(endpoint);
78          }
79          catch (Exception e)
80          {
81              throw new InitialisationException(UdpMessages.failedToBind(uri), e, this);
82          }
83  
84          try
85          {
86              getWorkManager().scheduleWork(this, WorkManager.INDEFINITE, null, connector);
87          }
88          catch (WorkException e)
89          {
90              throw new InitialisationException(CoreMessages.failedToScheduleWork(), e, this);
91          }
92      }
93  
94      protected void doDisconnect() throws Exception
95      {
96          // this will cause the server thread to quit
97          disposing.set(true);
98          if (socket != null)
99          {
100             socket.close();
101         }
102 
103     }
104 
105     protected void doStart() throws UMOException
106     {
107         // nothing to do
108     }
109 
110     protected void doStop() throws UMOException
111     {
112         // nothing to do
113     }
114 
115     protected UMOTransformer getResponseTransformer() throws InitialisationException
116     {
117         UMOTransformer transformer = component.getDescriptor().getResponseTransformer();
118         if (transformer == null)
119         {
120             return connector.getDefaultResponseTransformer();
121         }
122         return transformer;
123     }
124 
125     protected DatagramSocket createSocket(URI uri, InetAddress inetAddress) throws IOException
126     {
127         return new DatagramSocket(uri.getPort(), inetAddress);
128     }
129 
130     /**
131      * Obtain the serverSocket
132      */
133     public DatagramSocket getSocket()
134     {
135         return socket;
136     }
137 
138     protected DatagramPacket createPacket()
139     {
140         DatagramPacket packet = new DatagramPacket(new byte[bufferSize], bufferSize);
141 //        if (uri.getPort() > 0)
142 //        {
143 //            packet.setPort(uri.getPort());
144 //        }
145 //        packet.setAddress(inetAddress);
146         return packet;
147     }
148 
149     public void run()
150     {
151         while (!disposing.get())
152         {
153             if (connector.isStarted())
154             {
155 
156                 try
157                 {
158                     DatagramPacket packet = createPacket();
159                     try
160                     {
161                         socket.receive(packet);
162 
163                         if (logger.isTraceEnabled())
164                         {
165                             logger.trace("Received packet on: " + uri);
166                         }
167 
168                         Work work = createWork(packet);
169                         try
170                         {
171                             getWorkManager().scheduleWork(work, WorkManager.INDEFINITE, null, connector);
172                         }
173                         catch (WorkException e)
174                         {
175                             logger.error("Udp receiver interrupted: " + e.getMessage(), e);
176                         }
177                     }
178                     catch (SocketTimeoutException e)
179                     {
180                         // ignore
181                     }
182 
183                 }
184                 catch (Exception e)
185                 {
186                     if (!connector.isDisposed() && !disposing.get())
187                     {
188                         logger.debug("Accept failed on socket: " + e, e);
189                         handleException(e);
190                     }
191                 }
192             }
193         }
194     }
195 
196     public void release()
197     {
198         dispose();
199     }
200 
201     protected void doDispose()
202     {
203         if (socket != null && !socket.isClosed())
204         {
205             logger.debug("Closing Udp connection: " + uri);
206             socket.close();
207             logger.info("Closed Udp connection: " + uri);
208         }
209     }
210 
211     protected Work createWork(DatagramPacket packet) throws IOException
212     {
213         return new UdpWorker(new DatagramSocket(0), packet);
214     }
215 
216     protected class UdpWorker implements Work, Disposable
217     {
218         private DatagramSocket socket = null;
219         private DatagramPacket packet;
220 
221         public UdpWorker(DatagramSocket socket, DatagramPacket packet)
222         {
223             this.socket = socket;
224             this.packet = packet;
225         }
226 
227         public void release()
228         {
229             dispose();
230         }
231 
232         public void dispose()
233         {
234             if (socket != null && !socket.isClosed())
235             {
236                 try
237                 {
238                     socket.close();
239                 }
240                 catch (Exception e)
241                 {
242                     logger.error("Socket close failed", e);
243                 }
244             }
245             socket = null;
246         }
247 
248         /**
249          * Accept requests from a given Udp address
250          */
251         public void run()
252         {
253             UMOMessage returnMessage = null;
254             try
255             {
256                 UMOMessageAdapter adapter = connector.getMessageAdapter(packet);
257                 returnMessage = routeMessage(new MuleMessage(adapter), endpoint.isSynchronous());
258 
259                 if (returnMessage != null)
260                 {
261                     byte[] data;
262                     if (responseTransformer != null)
263                     {
264                         Object response = responseTransformer.transform(returnMessage.getPayload());
265                         if (response instanceof byte[])
266                         {
267                             data = (byte[])response;
268                         }
269                         else
270                         {
271                             data = response.toString().getBytes();
272                         }
273                     }
274                     else
275                     {
276                         data = returnMessage.getPayloadAsBytes();
277                     }
278                     DatagramPacket result = new DatagramPacket(data, data.length, packet.getAddress(),
279                         packet.getPort());
280                     socket.send(result);
281                 }
282             }
283             catch (Exception e)
284             {
285                 if (!disposing.get())
286                 {
287                     handleException(e);
288                 }
289             }
290             finally
291             {
292                 dispose();
293             }
294         }
295     }
296 }