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