View Javadoc

1   /*
2    * $Id: TcpMessageDispatcher.java 7963 2007-08-21 08:53:15Z dirk.olmes $
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.providers.tcp;
12  
13  import org.mule.impl.MuleMessage;
14  import org.mule.providers.AbstractMessageDispatcher;
15  import org.mule.umo.UMOEvent;
16  import org.mule.umo.UMOMessage;
17  import org.mule.umo.endpoint.UMOImmutableEndpoint;
18  import org.mule.umo.transformer.TransformerException;
19  
20  import java.io.BufferedInputStream;
21  import java.io.BufferedOutputStream;
22  import java.io.DataInputStream;
23  import java.io.IOException;
24  import java.net.Socket;
25  import java.net.SocketTimeoutException;
26  
27  /**
28   * <code>TcpMessageDispatcher</code> will send transformed Mule events over TCP.
29   */
30  
31  public class TcpMessageDispatcher extends AbstractMessageDispatcher
32  {
33      private final TcpConnector connector;
34  
35      public TcpMessageDispatcher(UMOImmutableEndpoint endpoint)
36      {
37          super(endpoint);
38          this.connector = (TcpConnector) endpoint.getConnector();
39      }
40  
41      protected synchronized void doDispatch(UMOEvent 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      protected synchronized UMOMessage doSend(UMOEvent event) throws Exception
55      {
56          Socket socket = connector.getSocket(event.getEndpoint());
57          try
58          {
59              dispatchToSocket(socket, event);
60  
61              if (useRemoteSync(event))
62              {
63                  try
64                  {
65                      Object result = receiveFromSocket(socket, event.getTimeout());
66                      if (result == null)
67                      {
68                          return null;
69                      }
70                      return new MuleMessage(connector.getMessageAdapter(result));
71                  }
72                  catch (SocketTimeoutException e)
73                  {
74                      // we don't necessarily expect to receive a response here
75                      logger.info("Socket timed out normally while doing a synchronous receive on endpointUri: "
76                          + event.getEndpoint().getEndpointURI());
77                      return null;
78                  }
79              }
80              else
81              {
82                  return event.getMessage();
83              }
84          }
85          finally
86          {
87              connector.releaseSocket(socket, event.getEndpoint());
88          }
89      }
90  
91      // Socket management (get and release) is handled outside this method
92      private void dispatchToSocket(Socket socket, UMOEvent event) throws Exception
93      {
94          Object payload = event.getTransformedMessage();
95          write(socket, payload);
96      }
97  
98      private void write(Socket socket, Object data) throws IOException, TransformerException
99      {
100         BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
101         connector.getTcpProtocol().write(bos, data);
102         bos.flush();
103     }
104 
105     private Object receiveFromSocket(Socket socket, int timeout) throws IOException
106     {
107         DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
108         if (timeout >= 0)
109         {
110             socket.setSoTimeout(timeout);
111         }
112         return connector.getTcpProtocol().read(dis);
113     }
114 
115     /**
116      * Make a specific request to the underlying transport
117      * 
118      * @param timeout the maximum time the operation should block before returning.
119      *            The call should return immediately if there is data available. If
120      *            no data becomes available before the timeout elapses, null will be
121      *            returned
122      * @return the result of the request wrapped in a UMOMessage object. Null will be
123      *         returned if no data was avaialable
124      * @throws Exception if the call to the underlying protocal cuases an exception
125      */
126     protected UMOMessage doReceive(long timeout) throws Exception
127     {
128         Socket socket = connector.getSocket(endpoint);
129         try
130         {
131             Object result = receiveFromSocket(socket, (int)timeout);
132             if (result == null)
133             {
134                 return null;
135             }
136             return new MuleMessage(connector.getMessageAdapter(result));
137         }
138         catch (SocketTimeoutException e)
139         {
140             // we don't necesarily expect to receive a resonse here
141             if (logger.isDebugEnabled())
142             {
143                 logger.debug("Socket timed out normally while doing a synchronous receive on endpointUri: "
144                     + endpoint.getEndpointURI());
145             }
146             return null;
147         }
148         finally
149         {
150             connector.releaseSocket(socket, endpoint);
151         }
152     }
153 
154     protected synchronized void doDispose()
155     {
156         try
157         {
158             doDisconnect();
159         }
160         catch (Exception e)
161         {
162             logger.error("Failed to shutdown the dispatcher.", e);
163         }
164     }
165 
166     protected void doConnect() throws Exception
167     {
168         // Test the connection
169         if (connector.isValidateConnections())
170         {
171             Socket socket = connector.getSocket(endpoint);
172             connector.releaseSocket(socket, endpoint);
173         }
174     }
175 
176     protected void doDisconnect() throws Exception
177     {
178         //nothing to do
179     }
180     
181 }