1
2
3
4
5
6
7
8
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
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
99 disposing.set(true);
100 if (socket != null)
101 {
102 socket.close();
103 }
104
105 }
106
107 protected void doStart() throws UMOException
108 {
109
110 }
111
112 protected void doStop() throws UMOException
113 {
114
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
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
144
145
146
147
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
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
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 }