View Javadoc

1   /*
2    * $Id: TcpMessageDispatcher.java 10961 2008-02-22 19:01:02Z dfeist $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
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.transformer.TransformerException;
19  import org.mule.transport.AbstractMessageDispatcher;
20  
21  import java.io.BufferedInputStream;
22  import java.io.BufferedOutputStream;
23  import java.io.DataInputStream;
24  import java.io.IOException;
25  import java.net.Socket;
26  import java.net.SocketTimeoutException;
27  
28  /**
29   * Send transformed Mule events over TCP.
30   */
31  public class TcpMessageDispatcher extends AbstractMessageDispatcher
32  {
33  
34      private final TcpConnector connector;
35  
36      public TcpMessageDispatcher(OutboundEndpoint endpoint)
37      {
38          super(endpoint);
39          this.connector = (TcpConnector) endpoint.getConnector();
40      }
41  
42      protected synchronized void doDispatch(MuleEvent event) throws Exception
43      {
44          Socket socket = connector.getSocket(event.getEndpoint());
45          try 
46          {
47              dispatchToSocket(socket, event);
48          }
49          finally 
50          {
51              connector.releaseSocket(socket, event.getEndpoint());
52          }
53      }
54  
55      protected synchronized MuleMessage doSend(MuleEvent event) throws Exception
56      {
57          Socket socket = connector.getSocket(event.getEndpoint());
58          dispatchToSocket(socket, event);
59  
60          try 
61          {
62              if (useRemoteSync(event))
63              {
64                  try
65                  {
66                      Object result = receiveFromSocket(socket, event.getTimeout(), endpoint);
67                      if (result == null)
68                      {
69                          return null;
70                      }
71                      
72                      if (result instanceof MuleMessage)
73                      {
74                      	return (MuleMessage) result;
75                      }
76                      
77                      return new DefaultMuleMessage(connector.getMessageAdapter(result));
78                  }
79                  catch (SocketTimeoutException e)
80                  {
81                      // we don't necessarily expect to receive a response here
82                      logger.info("Socket timed out normally while doing a synchronous receive on endpointUri: "
83                          + event.getEndpoint().getEndpointURI());
84                      return null;
85                  }
86              }
87              else
88              {
89                  return event.getMessage();
90              }
91          }
92          finally
93          {
94              if (!useRemoteSync(event))
95              {
96                  connector.releaseSocket(socket, endpoint);
97              }
98          }
99          
100     }
101 
102     // Socket management (get and release) is handled outside this method
103     private void dispatchToSocket(Socket socket, MuleEvent event) throws Exception
104     {
105         Object payload = event.transformMessage();
106         write(socket, payload);
107     }
108 
109     private void write(Socket socket, Object data) throws IOException, TransformerException
110     {
111         BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
112         connector.getTcpProtocol().write(bos, data);
113         bos.flush();
114     }
115 
116     protected static Object receiveFromSocket(final Socket socket, int timeout, final ImmutableEndpoint endpoint)
117             throws IOException
118     {
119         final TcpConnector connector = (TcpConnector) endpoint.getConnector();
120         DataInputStream underlyingIs = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
121         TcpInputStream tis = new TcpInputStream(underlyingIs)
122         {
123             public void close() throws IOException
124             {
125                 try
126                 {
127                     connector.releaseSocket(socket, endpoint);
128                 }
129                 catch (IOException e)
130                 {
131                    throw e;
132                 }
133                 catch (Exception e)
134                 {
135                     IOException e2 = new IOException();
136                     e2.initCause(e);
137                     throw e2;
138                 }
139             }
140 
141         };
142 
143         if (timeout >= 0)
144         {
145             socket.setSoTimeout(timeout);
146         }
147 
148         try
149         {
150             return connector.getTcpProtocol().read(tis);
151         }
152         finally
153         {
154             if (!tis.isStreaming())
155             {
156                 tis.close();
157             }
158         }
159     }
160 
161     protected synchronized void doDispose()
162     {
163         try
164         {
165             doDisconnect();
166         }
167         catch (Exception e)
168         {
169             logger.error("Failed to shutdown the dispatcher.", e);
170         }
171     }
172 
173     protected void doConnect() throws Exception
174     {
175         // Test the connection
176         if (connector.isValidateConnections())
177         {
178             Socket socket = connector.getSocket(endpoint);
179             connector.releaseSocket(socket, endpoint);
180         }
181     }
182 
183     protected void doDisconnect() throws Exception
184     {
185         //nothing to do
186     }
187     
188 }