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