View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.transport.udp;
8   
9   import org.mule.DefaultMuleMessage;
10  import org.mule.api.MuleEvent;
11  import org.mule.api.MuleMessage;
12  import org.mule.api.endpoint.ImmutableEndpoint;
13  import org.mule.api.endpoint.OutboundEndpoint;
14  import org.mule.api.retry.RetryContext;
15  import org.mule.api.transformer.DataType;
16  import org.mule.transport.AbstractMessageDispatcher;
17  import org.mule.transport.NullPayload;
18  
19  import java.io.IOException;
20  import java.net.DatagramPacket;
21  import java.net.DatagramSocket;
22  import java.net.InetAddress;
23  
24  /**
25   * <code>UdpMessageDispatcher</code> is responsible for dispatching MuleEvents as
26   * UDP packets on the network
27   */
28  
29  public class UdpMessageDispatcher extends AbstractMessageDispatcher
30  {
31      protected final UdpConnector connector;
32  
33      public UdpMessageDispatcher(OutboundEndpoint endpoint)
34      {
35          super(endpoint);
36          this.connector = (UdpConnector)endpoint.getConnector();
37      }
38  
39      @Override
40      public RetryContext validateConnection(RetryContext retryContext)
41      {
42          DatagramSocket socket = null;
43          try
44          {
45              socket = connector.getSocket(endpoint);
46  
47              retryContext.setOk();
48          }
49          catch (Exception ex)
50          {
51              retryContext.setFailed(ex);
52          }
53          finally
54          {
55              if (socket != null)
56              {
57                  try
58                  {
59                      connector.releaseSocket(socket, endpoint);
60                  }
61                  catch (Exception e)
62                  {
63                      if (logger.isDebugEnabled())
64                      {
65                          logger.debug("Failed to release a socket " + socket, e);
66                      }
67                  }
68              }
69          }
70  
71          return retryContext;
72  
73      }
74  
75      @Override
76      protected void doConnect() throws Exception
77      {
78          // nothing, there is an optional validation in validateConnection()
79          
80      }
81  
82      @Override
83      protected void doDisconnect() throws Exception
84      {
85          // nothing to do
86      }
87  
88  
89      @Override
90      protected synchronized void doDispatch(MuleEvent event) throws Exception
91      {
92          ImmutableEndpoint ep = event.getEndpoint();
93  
94          DatagramSocket socket = connector.getSocket(ep);
95          try
96          {
97              byte[] payload = event.transformMessage(DataType.BYTE_ARRAY_DATA_TYPE);
98  
99              int port = ep.getEndpointURI().getPort();
100             InetAddress inetAddress = null;
101             //TODO, check how expensive this operation is
102             if("null".equalsIgnoreCase(ep.getEndpointURI().getHost()))
103             {
104                 inetAddress = InetAddress.getLocalHost();
105             }
106             else
107             {
108                 inetAddress = InetAddress.getByName(ep.getEndpointURI().getHost());
109             }
110 
111             write(socket, payload, port, inetAddress);
112         }
113         finally
114         {
115             connector.releaseSocket(socket, ep);
116         }
117     }
118 
119     protected void write(DatagramSocket socket, byte[] data, int port, InetAddress inetAddress) throws IOException
120     {
121         DatagramPacket packet = new DatagramPacket(data, data.length);
122         if (port >= 0)
123         {
124             packet.setPort(port);
125         }
126         packet.setAddress(inetAddress);
127         socket.send(packet);
128     }
129 
130     @Override
131     protected synchronized MuleMessage doSend(MuleEvent event) throws Exception
132     {
133         doDispatch(event);
134         // If we're doing sync receive try and read return info from socket
135         if (event.getEndpoint().getExchangePattern().hasResponse())
136         {
137             DatagramSocket socket = connector.getSocket(event.getEndpoint());
138             DatagramPacket result = receive(socket, event.getTimeout());
139             if (result == null)
140             {
141                 return createNullMuleMessage();
142             }
143             return createMuleMessage(result, event.getMessage(), endpoint.getEncoding());
144         }
145         else
146         {
147             return new DefaultMuleMessage(NullPayload.getInstance(), connector.getMuleContext());
148         }
149     }
150 
151     private DatagramPacket receive(DatagramSocket socket, int timeout) throws IOException
152     {
153         int origTimeout = socket.getSoTimeout();
154         try
155         {
156             DatagramPacket packet = new DatagramPacket(new byte[connector.getReceiveBufferSize()],
157                 connector.getReceiveBufferSize());
158 
159             if(timeout > 0 && timeout != socket.getSoTimeout())
160             {
161                 socket.setSoTimeout(timeout);
162             }
163             socket.receive(packet);
164             return packet;
165         }
166         finally
167         {
168             if(socket.getSoTimeout()!= origTimeout)
169             {
170                 socket.setSoTimeout(origTimeout);
171             }
172         }
173     }
174 
175     @Override
176     protected void doDispose()
177     {
178         // template method
179     }
180 }