View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
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.OutboundEndpoint;
13  import org.mule.api.retry.RetryContext;
14  import org.mule.api.transformer.TransformerException;
15  import org.mule.transport.NullPayload;
16  
17  import java.io.BufferedOutputStream;
18  import java.io.IOException;
19  import java.net.Socket;
20  import java.net.SocketTimeoutException;
21  
22  /**
23   * <code>LocalSocketTcpMessageDispatcher</code> will send transformed Mule events
24   * over TCP. It contains a local socket that reuses on each message dispatch
25   * 
26   * @since 2.2.6
27   */
28  public class LocalSocketTcpMessageDispatcher extends TcpMessageDispatcher
29  {
30      private AbstractTcpSocketFactory socketFactory;
31  
32      private Socket socket;
33  
34      public LocalSocketTcpMessageDispatcher(OutboundEndpoint endpoint)
35      {
36          super(endpoint);
37          this.socketFactory = this.getConnector().getSocketFactory();
38      }
39  
40      @Override
41      public TcpConnector getConnector()
42      {
43          return (TcpConnector) super.getConnector();
44      }
45  
46      @Override
47      protected void doDispatch(MuleEvent event) throws Exception
48      {
49          dispatchToSocket(event);
50      }
51  
52      @Override
53      protected synchronized MuleMessage doSend(MuleEvent event) throws Exception
54      {
55          try
56          {
57              dispatchToSocket(event);
58              if (returnResponse(event))
59              {
60                  try
61                  {
62                      Object result = receiveFromSocket(socket, event.getTimeout(), endpoint);
63                      if (result == null)
64                      {
65                          return new DefaultMuleMessage(NullPayload.getInstance(), this.getConnector().getMuleContext());
66                      }
67  
68                      if (result instanceof MuleMessage)
69                      {
70                          return (MuleMessage) result;
71                      }
72  
73  					return new DefaultMuleMessage(result, this.getConnector()
74  							.getMuleContext());
75                  }
76                  catch (Exception ex)
77                  {
78                      if (logger.isInfoEnabled())
79                      {
80                          logger.info("Error occurred while Reading; Message: " + ex.getMessage(), ex);
81                      }
82                      closeSocket();
83                      throw ex;
84                  }
85  
86              }
87              else
88              {
89                  return event.getMessage();
90              }
91          }
92          finally
93          {
94              if (!this.getConnector().isKeepSendSocketOpen())
95              {
96                  closeSocket();
97              }
98          }
99      }
100 
101     private void closeSocket()
102     {
103         try
104         {
105             socket.close();
106             socket = null;
107         }
108         catch (Exception ex)
109         {
110             logger.info("Error occurred while closing socket; Message: " + ex.getMessage());
111         }
112     }
113 
114     protected void dispatchToSocket(MuleEvent event) throws Exception
115     {
116         if (socket == null || socket.isClosed())
117         {
118             if (logger.isDebugEnabled())
119             {
120                 logger.debug("Socket is null; Creating... ");
121             }
122             TcpSocketKey socketKey = new TcpSocketKey(endpoint);
123             socket = (Socket) socketFactory.makeObject(socketKey); // connector.getSocket(event.getEndpoint());
124         }
125         if (logger.isDebugEnabled())
126         {
127             logger.debug("Is socket closed? " + (socket != null && socket.isClosed()));
128         }
129         try
130         {
131             Object payload = event.getMessage().getPayload();// getTransformedMessage();
132             // following line was added set the payload in the threadlocal
133             // so that a protocol class can use the thread local and pick the
134             // transformed
135             // message.
136             event.getMessage().setPayload(payload);
137             // OptimizedRequestContext.unsafeRewriteEvent(new DefaultMuleMessage(
138             // payload));
139             write(payload);
140             return;
141         }
142         catch (IOException ioEx)
143         {
144             closeSocket();
145             if (logger.isInfoEnabled())
146             {
147                 logger.info("Error occurred while Writing; Message: " + ioEx.getMessage(), ioEx);
148             }
149             if (ioEx instanceof SocketTimeoutException)
150             {
151                 throw ioEx;
152             }
153         }
154         catch (Exception ex)
155         {
156             logger.info("Unknown Error occurred while Writing; Message: " + ex.getMessage(), ex);
157         }
158     }
159 
160     private void write(Object data) throws IOException, TransformerException
161     {
162         BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
163         this.getConnector().getTcpProtocol().write(bos, data);
164         bos.flush();
165     }
166 
167     @Override
168     public RetryContext validateConnection(RetryContext retryContext)
169     {
170         try
171         {
172             retryContext.setOk();
173         }
174         catch (Exception ex)
175         {
176             retryContext.setFailed(ex);
177         }
178         return retryContext;
179     }
180 }