View Javadoc

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