1 /* 2 * $Id: LengthProtocol.java 7976 2007-08-21 14:26:13Z 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.protocols; 12 13 import java.io.DataInputStream; 14 import java.io.DataOutputStream; 15 import java.io.IOException; 16 import java.io.InputStream; 17 import java.io.OutputStream; 18 19 import org.apache.commons.logging.Log; 20 import org.apache.commons.logging.LogFactory; 21 22 /** 23 * The LengthProtocol is an application level tcp protocol that can be used to 24 * transfer large amounts of data without risking some data to be loss. The protocol 25 * is defined by sending / reading an integer (the packet length) and then the data 26 * to be transferred. 27 * 28 * <p>Note that use of this protocol must be symmetric - both the sending and receiving 29 * connectors must use the same protocol.</p> 30 */ 31 public class LengthProtocol extends DefaultProtocol 32 { 33 34 private static final Log logger = LogFactory.getLog(LengthProtocol.class); 35 // TODO - can we not get this from the API somewhere? 36 private static final int SIZE_INT = 4; 37 38 public LengthProtocol() 39 { 40 super(NO_STREAM, SIZE_INT); 41 } 42 43 public Object read(InputStream is) throws IOException 44 { 45 // original comments indicated that we nede to use read(byte[]) rather than readInt() 46 // to avoid socket timeouts - don't understand, but don't want to risk change. 47 48 // first read the data necessary to know the length of the payload 49 DataInputStream dis = new DataInputStream(is); 50 dis.mark(SIZE_INT); 51 // this pulls through SIZE_INT bytes 52 if (null == super.read(dis, SIZE_INT)) 53 { 54 return null; // eof 55 } 56 57 // reset and read the integer 58 dis.reset(); 59 int length = dis.readInt(); 60 if (logger.isDebugEnabled()) 61 { 62 logger.debug("length: " + length); 63 } 64 65 // finally read the rest of the data 66 byte[] buffer = new byte[length]; 67 dis.readFully(buffer); 68 if (logger.isDebugEnabled()) 69 { 70 logger.debug("length read: " + buffer.length); 71 } 72 73 return buffer; 74 } 75 76 // @Override 77 protected void writeByteArray(OutputStream os, byte[] data) throws IOException 78 { 79 // Write the length and then the data. 80 DataOutputStream dos = new DataOutputStream(os); 81 dos.writeInt(data.length); 82 dos.write(data); 83 dos.flush(); 84 } 85 86 /** 87 * Read all four bytes for initial integer (limit is set in read) 88 * 89 * @param len Amount transferred last call (-1 on EOF or socket error) 90 * @param available Amount available 91 * @return true if the transfer should continue 92 */ 93 // @Override 94 protected boolean isRepeat(int len, int available) 95 { 96 return true; 97 } 98 99 }