View Javadoc

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