1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.tcp;
12
13 import org.mule.DefaultMuleMessage;
14 import org.mule.api.MuleEvent;
15 import org.mule.api.MuleMessage;
16 import org.mule.api.endpoint.ImmutableEndpoint;
17 import org.mule.api.endpoint.OutboundEndpoint;
18 import org.mule.api.retry.RetryContext;
19 import org.mule.api.transformer.TransformerException;
20 import org.mule.transport.AbstractMessageDispatcher;
21 import org.mule.transport.NullPayload;
22
23 import java.io.BufferedInputStream;
24 import java.io.BufferedOutputStream;
25 import java.io.DataInputStream;
26 import java.io.IOException;
27 import java.net.Socket;
28 import java.net.SocketTimeoutException;
29
30
31
32
33 public class TcpMessageDispatcher extends AbstractMessageDispatcher
34 {
35
36 private final TcpConnector connector;
37
38 public TcpMessageDispatcher(OutboundEndpoint endpoint)
39 {
40 super(endpoint);
41 this.connector = (TcpConnector) endpoint.getConnector();
42 }
43
44 @Override
45 protected synchronized void doDispatch(MuleEvent event) throws Exception
46 {
47 Socket socket = connector.getSocket(endpoint);
48 try
49 {
50 dispatchToSocket(socket, event);
51 }
52 finally
53 {
54 connector.releaseSocket(socket, endpoint);
55 }
56 }
57
58 private void doDispatchToSocket(Socket socket, MuleEvent event) throws Exception
59 {
60 try
61 {
62 dispatchToSocket(socket, event);
63 }
64 catch(Exception e)
65 {
66 connector.releaseSocket(socket, endpoint);
67 throw new Exception(e);
68 }
69 }
70
71 @Override
72 protected synchronized MuleMessage doSend(MuleEvent event) throws Exception
73 {
74 Socket socket = connector.getSocket(endpoint);
75 doDispatchToSocket(socket, event);
76 try
77 {
78 if (returnResponse(event))
79 {
80 try
81 {
82 Object result = receiveFromSocket(socket, event.getTimeout(), endpoint);
83 if (result == null)
84 {
85 return new DefaultMuleMessage(NullPayload.getInstance(), connector.getMuleContext());
86 }
87
88 if (result instanceof MuleMessage)
89 {
90 return (MuleMessage) result;
91 }
92
93 return createMuleMessage(result, endpoint.getEncoding());
94 }
95 catch (SocketTimeoutException e)
96 {
97
98 logger.info("Socket timed out normally while doing a synchronous receive on endpointUri: "
99 + endpoint.getEndpointURI());
100 return new DefaultMuleMessage(NullPayload.getInstance(), connector.getMuleContext());
101 }
102 }
103 else
104 {
105 return new DefaultMuleMessage(NullPayload.getInstance(), connector.getMuleContext());
106 }
107 }
108 finally
109 {
110 if (!returnResponse(event))
111 {
112 connector.releaseSocket(socket, endpoint);
113 }
114 }
115
116 }
117
118
119 private void dispatchToSocket(Socket socket, MuleEvent event) throws Exception
120 {
121 Object payload = event.getMessage().getPayload();
122 write(socket, payload);
123 }
124
125 private void write(Socket socket, Object data) throws IOException, TransformerException
126 {
127 BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
128 connector.getTcpProtocol().write(bos, data);
129 bos.flush();
130 }
131
132 protected static Object receiveFromSocket(final Socket socket, int timeout, final ImmutableEndpoint endpoint)
133 throws IOException
134 {
135 final TcpConnector connector = (TcpConnector) endpoint.getConnector();
136 DataInputStream underlyingIs = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
137 TcpInputStream tis = new TcpInputStream(underlyingIs)
138 {
139 @Override
140 public void close() throws IOException
141 {
142 try
143 {
144 connector.releaseSocket(socket, endpoint);
145 }
146 catch (IOException e)
147 {
148 throw e;
149 }
150 catch (Exception e)
151 {
152 IOException e2 = new IOException();
153 e2.initCause(e);
154 throw e2;
155 }
156 }
157
158 };
159
160 if (timeout >= 0)
161 {
162 socket.setSoTimeout(timeout);
163 }
164
165 try
166 {
167 return connector.getTcpProtocol().read(tis);
168 }
169 finally
170 {
171 if (!tis.isStreaming())
172 {
173 tis.close();
174 }
175 }
176 }
177
178 @Override
179 protected synchronized void doDispose()
180 {
181 try
182 {
183 doDisconnect();
184 }
185 catch (Exception e)
186 {
187 logger.error("Failed to shutdown the dispatcher.", e);
188 }
189 }
190
191 @Override
192 protected void doConnect() throws Exception
193 {
194
195 }
196
197 @Override
198 protected void doDisconnect() throws Exception
199 {
200
201 }
202
203 @Override
204 public RetryContext validateConnection(RetryContext retryContext)
205 {
206 Socket socket = null;
207 try
208 {
209 socket = connector.getSocket(endpoint);
210
211 retryContext.setOk();
212 }
213 catch (Exception ex)
214 {
215 retryContext.setFailed(ex);
216 }
217 finally
218 {
219 if (socket != null)
220 {
221 try
222 {
223 connector.releaseSocket(socket, endpoint);
224 }
225 catch (Exception e)
226 {
227 if (logger.isDebugEnabled())
228 {
229 logger.debug("Failed to release a socket " + socket, e);
230 }
231 }
232 }
233 }
234
235 return retryContext;
236 }
237 }