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