Save This Page
Home » openjdk-7 » java » net » [javadoc | source]
    1   /*  ZNet - Java Compression Layer for a new Socket Factory
    2       Copyright (C) 1999, Free Software Rulez
    3   
    4       This program is free software; you can redistribute it and/or modify
    5       it under the terms of the GNU General Public License as published by
    6       the Free Software Foundation; either version 2 of the License, or
    7       (at your option) any later version.
    8   
    9       This program is distributed in the hope that it will be useful,
   10       but WITHOUT ANY WARRANTY; without even the implied warranty of
   11       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12       GNU General Public License for more details.
   13   
   14       You should have received a copy of the GNU General Public License
   15       along with this program; if not, write to the Free Software
   16       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   17   
   18           The author of this program may be contacted at morgiaclaudio@yahoo.it. */
   19   
   20   package java.net;
   21   
   22   import java.lang;
   23   import java.io;
   24   import java.util.Arrays;
   25   
   26   /**
   27    * This class implements an object type suitable to be serialized in a non-standard way.
   28    * To minimize the overhead that can occur in standard serialization, this class provides
   29    * methods to serialize and deserialize objects minimizing the overhead.
   30    * This class can represents compressed, uncompressed and ack objects.
   31    * @author <a href="mailto:morgiaclaudio@yahoo.it">Claudio Morgia</a>
   32    * @version 1.0
   33    */
   34   public class ZObject {
   35       /**
   36        * This static field represents the magic sequence that distinguishes serialized
   37        * ZObject instances.
   38        */
   39       static byte[] magic={0xc,0xa,0xf,0xe};
   40   
   41       /**
   42        * The data payload this object carries. If it isn't an ack object, that buffer contains compressed
   43        * data.
   44        */
   45       protected byte[] data;
   46   
   47       /**
   48        * This field can be one of the following type:<br>
   49        * <ul>
   50        * <li>ACK_TYPE for ack object,
   51        * <li>COMPR_TYPE for compressed object,
   52        * <li>UNCOMPR_TYPE for uncompressed object (actually nonsense).
   53        * </ul>
   54        */
   55       protected byte type;
   56   
   57       /**
   58        * The sequence number that distinguishes that object.
   59        * If it's an ack object, the sequence number is the same as the compressed object
   60        * that <i>generated</i> it, otherwise is automagically generated (using the method
   61        * {@link java.lang.Object#hashCode hashCode} applied to the data payload.
   62        */
   63       protected long seqnum;
   64   
   65       public static byte ACK_TYPE=0,COMPR_TYPE=1,UNCOMPR_TYPE=2;
   66   
   67       /**
   68        * Constructor used to build an <b>ack</b> object with a well-defined sequence number.
   69        * @param seqnum the sequence number to ack
   70        */
   71       public ZObject(long seqnum) {
   72   	this.seqnum=seqnum;
   73   	type=ACK_TYPE;
   74       }
   75   
   76       /**
   77        * Constructor used to build an object by deserializing data coming from an input stream,
   78        * tipically a socket input stream.
   79        * @see #setData(InputStream)
   80        * @throws java.net.AckException if the object is an ack object
   81        * @throws java.io.IOException if the object is not a ZObject instance or something else goes wrong
   82        */
   83       public ZObject(InputStream in) throws IOException,AckException {
   84   	setData(in);
   85       }
   86   
   87       /**
   88        * Constructor used to build an object by deserializing data coming from the buffer contained in
   89        * the passed datagram.
   90        * @see #setData(byte[])
   91        * @throws java.net.AckException if the object is an ack object
   92        * @throws java.net.NoMagicException if the object is not a ZObject instance
   93        * @throws java.io.IOException if something goes wrong
   94        */
   95       public ZObject(DatagramPacket packet) throws AckException,NoMagicException,IOException {
   96   	setData(packet.getData());
   97       }
   98   
   99       /**
  100        * This method is responsible for generic object creation and it's an utility method used by
  101        * constructors.
  102        * @param _data the data payload
  103        * @param type the object instance's type
  104        */
  105       protected void create(byte[] _data,byte type) {
  106   	this.data=_data;
  107   	this.type=type;
  108   	seqnum=Math.abs(data.hashCode());
  109       }
  110   
  111       /**
  112        * Constructor used to build a generic ZObject instance.
  113        * @param _data the data payload to encode
  114        * @param type the type of the instance
  115        * @throws java.io.IOException never thrown (actually)
  116        */
  117       public ZObject(byte[] _data,byte type) throws IOException {
  118   	create(_data,type);
  119       }
  120   
  121       /**
  122        * Constructor used to build a compressed object with a specific data payload.
  123        * @param _data the data payload to encode
  124        * @throws java.io.IOException never thrown (actually)
  125        */
  126       public ZObject(byte[] _data) throws IOException {
  127   	create(_data,COMPR_TYPE);
  128       }
  129   
  130       /**
  131        * This method actually performs encoding on the internal object using a ByteArrayOutputStream
  132        * as a container where internal fields get written into.
  133        * @return the encoded object in form of a byte array
  134        * @throws java.io.IOException if something goes wrong writing fields to the container
  135        * @see #serialize(long) serialization shrinked to the <b>long</b> case
  136        */
  137       public byte[] prepareData() throws IOException {
  138   	ByteArrayOutputStream out=new ByteArrayOutputStream();
  139   	out.write(magic);
  140   	out.write(type);
  141   	out.write(serialize(seqnum));
  142   	if (type!=ACK_TYPE) {
  143   	    out.write(serialize(data.length));
  144   	    out.write(data);
  145   	}
  146   	return out.toByteArray();
  147       }
  148   
  149       /**
  150        * This method returns the carried sequence number.
  151        * @return the carried sequence number
  152        */
  153       public long getSeqNum() {
  154   	return seqnum;
  155       }
  156   
  157       /**
  158        * This method returns the carried data payload.
  159        * @return the data payload in form of a byte array
  160        */
  161       public byte[] getData() {
  162   	return data;
  163       }
  164   
  165       /**
  166        * This method converts a passed <i>long</i> into a sequence of four bytes that can be written
  167        * to an output stream.
  168        * @param num the <i>long</i> to convert
  169        * @return an array of four bytes representing the passed <i>long</i>
  170        */
  171       protected static byte[] serialize(long num) {
  172   	byte[] res=new byte[4];
  173   	for (int i=0; i<4 ; i++) {
  174   	    res[i]=(byte)(num & 0xff);
  175   	    num>>=8;
  176   	}
  177   	return res;
  178       }
  179   
  180       /**
  181        * This method positivize the passed long using steps of value 256. This ensure the following relation
  182        * always true:
  183        * <code>&lt;result&gt; mod 256==x mod 256</code>
  184        */
  185       protected static long positivize(long x) {
  186   	while (x<0)
  187   	    x+=256;
  188   	return x;
  189       }
  190   
  191       /**
  192        * This method decodes an array of four bytes into a long value.
  193        * @param buf an array of four bytes
  194        * @return the decoded long value
  195        * @see #positivize(long)
  196        */
  197       protected static long deserialize(byte[] buf) {
  198   	int i;
  199   	long res=0;
  200   	for (i=3; i>0; i--) {
  201   	    res+=positivize(buf[i]);
  202   	    res<<=8;
  203   	}
  204   	res+=positivize(buf[i]);
  205   	return res;
  206       }
  207   
  208       /**
  209        * This method decodes the passed byte array trying to deserialize a ZObject instance.
  210        * @see #setData(InputStream)
  211        * @param dat the byte array that contains data to decode
  212        * @throws java.io.IOException actually never thrown
  213        * @throws java.net.AckException if the decoded object is an ack-type obejct
  214        */
  215       public void setData(byte[] dat) throws IOException,AckException {
  216   	setData(new ByteArrayInputStream(dat));
  217       }
  218   
  219       public synchronized boolean dump(byte[] buf,int len) {
  220   	D.p("---------------------------");
  221   	for (int i=0;i<len;i++)
  222   	    D.p("["+i+"]="+Long.toHexString(((long)buf[i])&0xff));
  223   	return false;
  224       }
  225   
  226       /**
  227        * This method decodes data from the input stream trying to deserialize a ZObject instance.
  228        * @param in the input stream from which data will be read
  229        * @throws java.io.IOException if data cannot be read from the input stream or object is not a ZObject instance
  230        * @throws java.net.AckException if the decoded object is an ack-type object
  231        */
  232       public void setData(InputStream in) throws IOException,AckException {
  233   	int dataLength;
  234   
  235   	byte[] buf=new byte[4];
  236   
  237   	if ((in.read(buf,0,4)==-1) || !Arrays.equals(buf,magic))
  238   	    throw new NoMagicException("No magic");
  239   
  240   	if ((in.read(buf,0,1)==-1))
  241   	    throw new IOException("Bad format");
  242   
  243   	type=buf[0];
  244   
  245   	buf=new byte[4];
  246   	if ((in.read(buf,0,4)==-1))
  247   	    throw new IOException("Bad format in sequence number");
  248   
  249   	seqnum=deserialize(buf);
  250   
  251   	if (type==ACK_TYPE)
  252   	    throw new AckException(seqnum);
  253   
  254   	if ((in.read(buf,0,4)==-1))
  255   	    throw new IOException("No data before header");
  256   
  257   	dataLength=(int)deserialize(buf);
  258   	buf=new byte[1024];
  259   	int length;
  260   	ByteArrayOutputStream databuf=new ByteArrayOutputStream();
  261   	while ((length=in.read(buf,0,Math.min(dataLength,1024)))!=0) {
  262   	    databuf.write(buf,0,length);
  263   	    dataLength-=length;
  264   	}
  265   
  266   	data=databuf.toByteArray();
  267       }
  268   
  269       public String toString() {
  270   	try {
  271   	    return new String(getData());
  272   	} catch(Exception e) {
  273   	    return new String();
  274   	}
  275       }
  276   }

Save This Page
Home » openjdk-7 » java » net » [javadoc | source]