View Javadoc

1   /*
2    * $Id: SafeProtocol.java 10489 2008-01-23 17:53:38Z 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.protocols;
12  
13  import org.mule.ResponseOutputStream;
14  import org.mule.transport.tcp.TcpProtocol;
15  
16  import java.io.IOException;
17  import java.io.InputStream;
18  import java.io.OutputStream;
19  import java.net.Socket;
20  
21  /**
22   * This precedes every message with a cookie.
23   * It should probably not be used in production.
24   * We use ths protocol as the default because previously people tended to use DefaultProtocol without considering packet fragmentation etc.
25   * You should probably change to LengthProtocol.
26   * Remember - both sender and receiver must use the same protocol.
27   */
28  public class SafeProtocol implements TcpProtocol
29  {
30  
31      public static final String COOKIE = "You are using SafeProtocol";
32      private TcpProtocol delegate = new LengthProtocol();
33      private TcpProtocol cookieProtocol = new LengthProtocol(COOKIE.length());
34  
35      public Object read(InputStream is) throws IOException
36      {
37          if (assertSiblingSafe(is))
38          {
39              Object result = delegate.read(is);
40              if (null == result)
41              {
42                  // EOF after cookie but before data
43                  helpUser();
44              }
45              return result;
46          }
47          else
48          {
49              return null;
50          }
51      }
52  
53      public void write(OutputStream os, Object data) throws IOException
54      {
55          assureSibling(os);
56          delegate.write(os, data);
57      }
58  
59      public ResponseOutputStream createResponse(Socket socket) throws IOException
60      {
61          return new ResponseOutputStream(socket, new ProtocolStream(this, false, socket.getOutputStream()));
62      }
63  
64      private void assureSibling(OutputStream os) throws IOException
65      {
66          cookieProtocol.write(os, COOKIE);
67      }
68  
69      /**
70       * @param is Stream to read data from
71       * @return true if further data are available; false if EOF
72       * @throws IOException
73       */
74      private boolean assertSiblingSafe(InputStream is) throws IOException
75      {
76          Object cookie = null;
77          try
78          {
79              cookie = cookieProtocol.read(is);
80          }
81          catch (Exception e)
82          {
83              helpUser(e);
84          }
85          if (null != cookie)
86          {
87              if (!(cookie instanceof byte[]
88                      && ((byte[]) cookie).length == COOKIE.length()
89                      && COOKIE.equals(new String((byte[]) cookie))))
90              {
91                  helpUser();
92              }
93              else
94              {
95                  return true;
96              }
97          }
98          return false; // eof
99      }
100 
101     private void helpUser() throws IOException
102     {
103         throw new IOException("You are not using a consistent protocol on your TCP transport. "
104                 + "Please read the documentation for the TCP transport, "
105                 + "paying particular attention to the protocol parameter.");
106     }
107 
108     private void helpUser(Exception e) throws IOException
109     {
110         throw (IOException) new IOException("An error occurred while verifying your connection.  "
111                 + "You may not be using a consistent protocol on your TCP transport. "
112                 + "Please read the documentation for the TCP transport, "
113                 + "paying particular attention to the protocol parameter.").initCause(e);
114     }
115 
116     public void setMaxMessageLength(int maxMessageLength)
117     {
118         delegate = new LengthProtocol(maxMessageLength);
119     }
120 
121 }