Package freenet.support

Source Code of freenet.support.Serializer

/*
Dijjer - A Peer to Peer HTTP Cache
Copyright (C) 2004,2005  Change.Tv, Inc

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package freenet.support;

import java.io.DataInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import freenet.io.WritableToDataOutputStream;
import freenet.io.comm.Peer;
import freenet.keys.Key;
import freenet.keys.NodeCHK;
import freenet.keys.NodeSSK;
import freenet.node.NewPacketFormat;

/**
* @author ian
*
* To change the template for this generated type comment go to Window - Preferences - Java - Code Generation - Code and
* Comments
*/
public class Serializer {

    public static final String VERSION = "$Id: Serializer.java,v 1.5 2005/09/15 18:16:04 amphibian Exp $";
  /**
   * Maximum bit array size in bits.
   */
  public static final int MAX_BITARRAY_SIZE = 2048*8;
  /**
   * Maximum incoming array length in bytes.
   */
  //Max packet format size - 4 to account for starting size integer.
  public static final int MAX_ARRAY_LENGTH = NewPacketFormat.MAX_MESSAGE_SIZE - 4;

  public static List<Object> readListFromDataInputStream(Class<?> elementType, DataInput dis) throws IOException {
    LinkedList<Object> ret = new LinkedList<Object>();
    int length = dis.readInt();
    for (int x = 0; x < length; x++) {
      ret.add(readFromDataInputStream(elementType, dis));
    }
    return ret;
  }

  /**
   * Attempts to read an object of the specified type from the input.
   * @param type type to read.
   * @param dis input to read from.
   * @return object read.
   * @throws IOException if a read operation result in an IO error or an unexpected value is encountered.
   */
  public static Object readFromDataInputStream(Class<?> type, DataInput dis) throws IOException {
    if (type.equals(Boolean.class)) {
      final byte bool = dis.readByte();
      /* Using readByte() instead of readBoolean() because values other than 0 or 1 indicate
       * problems: only 0 and 1 are written.
       */
      switch (bool) {
        case 1: return Boolean.TRUE;
        case 0: return Boolean.FALSE;
        default: throw new IOException("Boolean is non boolean value: " + bool);
      }
    } else if (type.equals(Byte.class)) {
      return dis.readByte();
    } else if (type.equals(Short.class)) {
      return dis.readShort();
    } else if (type.equals(Integer.class)) {
      return dis.readInt();
    } else if (type.equals(Long.class)) {
      return dis.readLong();
    } else if (type.equals(Double.class)) {
        return dis.readDouble();
    } else if (type.equals(Float.class)) {
      return dis.readFloat();
    } else if (type.equals(String.class)) {
      final int length = dis.readInt();
      //TODO: Track read size so far and limit based on that? Might not be necessary.
      //TODO: Should these be IO Exceptions or IllegalArgumentExceptions?
      if (length < 0 || length > MAX_ARRAY_LENGTH) {
        throw new IOException("Invalid string length: " + length);
      }
      StringBuilder sb = new StringBuilder(length);
      for (int x = 0; x < length; x++) {
        sb.append(dis.readChar());
      }
      return sb.toString();
    } else if (type.equals(Buffer.class)) {
      return new Buffer(dis);
    } else if (type.equals(ShortBuffer.class)) {
        return new ShortBuffer(dis);
    } else if (type.equals(Peer.class)) {
      return new Peer(dis);
    } else if (type.equals(BitArray.class)) {
      return new BitArray(dis, MAX_BITARRAY_SIZE);
    } else if (type.equals(NodeCHK.class)) {
      // Use Key.read(...) rather than NodeCHK-specific method because write(...) writes the TYPE field.
      return Key.read(dis);
    } else if (type.equals(NodeSSK.class)) {
      // Use Key.read(...) rather than NodeSSK-specific method because write(...) writes the TYPE field.
      return Key.read(dis);
    } else if (type.equals(Key.class)) {
        return Key.read(dis);
    } else if (type.equals(double[].class)) {
      // & 0xFF for unsigned byte. Can be up to 255, no negatives.
      double[] array = new double[dis.readByte() & 0xFF];
      for (int i = 0; i < array.length; i++) array[i] = dis.readDouble();
      return array;
    } else if (type.equals(float[].class)) {
      final short length = dis.readShort();
      if (length < 0 || length > MAX_ARRAY_LENGTH/4) {
        throw new IOException("Invalid flat array length: " + length);
      }
      float[] array = new float[length];
      for (int i = 0; i < array.length; i++) array[i] = dis.readFloat();
      return array;
    } else {
      throw new RuntimeException("Unrecognised field type: " + type);
    }
  }

  public static void writeToDataOutputStream(Object object, DataOutputStream dos) throws IOException
    Class<?> type = object.getClass();
    if (type.equals(Long.class)) {
      dos.writeLong((Long) object);
    } else if (type.equals(Boolean.class)) {
      dos.writeBoolean((Boolean) object);
    } else if (type.equals(Integer.class)) {
      dos.writeInt((Integer) object);
    } else if (type.equals(Short.class)) {
      dos.writeShort((Short) object);
    } else if (type.equals(Double.class)) {
      dos.writeDouble((Double) object);
    } else if (type.equals(Float.class)) {
      dos.writeFloat((Float)object);
    } else if (WritableToDataOutputStream.class.isAssignableFrom(type)) {
      ((WritableToDataOutputStream) object).writeToDataOutputStream(dos);
    } else if (type.equals(String.class)) {
      String s = (String) object;
      dos.writeInt(s.length());
      for (int x = 0; x < s.length(); x++) {
        dos.writeChar(s.charAt(x));
      }
    } else if (type.equals(LinkedList.class)) {
      LinkedList<?> ll = (LinkedList<?>) object;
      synchronized (ll) {
        dos.writeInt(ll.size());
        for (Object o : ll) {
          writeToDataOutputStream(o, dos);
        }
      }
    } else if (type.equals(Byte.class)) {
      dos.write((Byte) object);
    } else if (type.equals(double[].class))  {
      // writeByte() takes the eight lower-order bits - length capped to 255.
      final double[] array = (double[])object;
      if (array.length > 255) {
        throw new IllegalArgumentException("Cannot serialize an array of more than 255 doubles; attempted to " +
                                           "serialize " + array.length + ".");
      }
      dos.writeByte(array.length);
      for (double element : array) dos.writeDouble(element);
    } else if (type.equals(float[].class)) {
      dos.writeShort(((float[])object).length);
      for (float element : (float[])object) dos.writeFloat(element);
    } else {
      throw new RuntimeException("Unrecognised field type: " + type);
    }
  }

  /** Only works for simple messages!! */
  public static int length(Class<?> type, int maxStringLength) {
    if (type.equals(Long.class)) {
      return 8;
    } else if (type.equals(Boolean.class)) {
      return 1;
    } else if (type.equals(Integer.class)) {
      return 4;
    } else if (type.equals(Short.class)) {
      return 2;
    } else if (type.equals(Double.class)) {
      return 8;
    } else if (WritableToDataOutputStream.class.isAssignableFrom(type)) {
      throw new IllegalArgumentException("Unknown length for "+type);
    } else if (type.equals(String.class)) {
      return 4 + maxStringLength * 2; // Written as chars
    } else if (type.equals(LinkedList.class)) {
      throw new IllegalArgumentException("Unknown length for LinkedList");
    } else if (type.equals(Byte.class)) {
      return 1;
    } else {
      throw new RuntimeException("Unrecognised field type: " + type);
    }
  }
}
TOP

Related Classes of freenet.support.Serializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.