/* * PacketSerializer.java * * Created on May 13, 2007, 4:09 PM ************************************************************************* * Copyright 2008 Paul Smith * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ao.protocol.packets.utils; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.nio.charset.Charset; /** * AOPacketSerializer is a utility class for serializing packets for transmission. * * @author Paul Smith */ public class PacketSerializer { private ByteArrayOutputStream m_buffer; private DataOutputStream m_output; public final Charset UTF8_CHARSET = Charset.forName("UTF-8"); /** Creates a new instance of PacketSerializer */ public PacketSerializer() { this(Short.MAX_VALUE); } // end PacketSerializer() /** * Creates a new instance of AOPacketSerializer. * This version of the constructor accepts an estimate * of the total length of the packet's data. The estimate * is not required to be exact, but a better estimate will * likely improve performance when serializing a packet. * * @param size * an estimate of the total length of the packet's binary data */ public PacketSerializer(int size) { m_buffer = new ByteArrayOutputStream(size); m_output = new DataOutputStream(m_buffer); } // end PacketSerializer() /** * Serializes a byte (8 bits) * @see PacketParser#parseByte() */ public void write(byte data) { try { m_output.writeByte(data); } catch (IOException e) { e.printStackTrace(); } } // end write() /** * Serializes a short (16 bits) * @see PacketParser#parseShort() */ public void write(short data) { try { m_output.writeShort(data); } catch (IOException e) { e.printStackTrace(); } } // end write() /** * Serializes a int (32 bits) * @see PacketParser#parseInt() */ public void write(int data) { try { m_output.writeInt(data); } catch (IOException e) { e.printStackTrace(); } } // end write() /** * Serializes a long (64 bits) * @see PacketParser#parseLong() */ public void write(long data) { try { m_output.writeLong(data); } catch (IOException e) { e.printStackTrace(); } } // end write() /** * <p>Serializes a string (16 bit length, 8*length bit character data)</p> * * <p>NOTE: Characters are serialized as 8 bit ASCII, rather than Java's normal 16 bit Unicode.</p> * * @see #write(short) * @see PacketParser#parseString() */ public void write(String data) { try { m_output.writeUTF(data); /** byte[] utf8 = data.getBytes(UTF8_CHARSET); char[] chars = data.toCharArray(); int length = chars.length; m_output.writeShort(length); for (int i = 0; i < length; ++i) { m_output.writeByte(chars[i]); } // end for */ } catch (IOException e) { e.printStackTrace(); } } // end write() /** * Serializes a int array (16 bit length, 32*length bit int data) * * @see #write(short) * @see #write(int) * @see PacketParser#parseIntArray() */ public void write(int[] data) { try { m_output.writeShort( data.length ); for (int i : data) { write(i); } } catch (IOException e) { e.printStackTrace(); } } // end write() /** * Serializes a string array (16 bit length, data[0], data[1], data[2], ...) * * @see #write(short) * @see #write(String) * @see PacketParser#parseStringArray() */ public void write(String[] data) { try { m_output.writeShort( data.length ); for (String s : data) { write(s); } } catch (IOException e) { e.printStackTrace(); } } // end write() /** Returns the net results of all previous calls to write */ public byte[] getResult() { return m_buffer.toByteArray(); } /** * Serializes a 40 bit chunck of data * * @see #write(byte) * @see PacketParser#parse40Bit() */ public void write40Bit(byte[] data) { if (data.length != 5) { throw new IllegalArgumentException( "This chunk of data is composed of " + (data.length*8) + " bits rather than 40 bits" ); } else { for (byte b : data) { write(b); } } // end else } // end write40Bit() /** Closes the serializer's underlying stream */ public void close() { try { m_output.close(); m_output = null; m_buffer = null; } catch (IOException e) { e.printStackTrace(); } catch (NullPointerException e){ } } // end close() @Override protected void finalize() throws Throwable { super.finalize(); close(); } // end dispose() } // end class PacketSerializer