/* * * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * 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 version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ package com.sun.tck.wma.sms; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; /** * A generic message packet that treats the packet as an input or output stream * of data. */ public class MessagePacket { /** The maximum payload size for a datagram. */ private final int DATAGRAM_PACKET_LENGTH = 1500; /** The current read-write index into the data buffer (stream). */ private int index = 0; /** The data buffer (stream). */ private byte[] data; private boolean firstWrite = true; /** The byte output stream, used when creating a new packet. */ private ByteArrayOutputStream bos = null; /** The data output stream, used when creating a new packet. */ private DataOutputStream dos = null; /** * Construct a new message packet that can be populated with some data. */ public MessagePacket() { firstWrite = true; } /** * Construct a new message packet that contains the given payload. * * @param payload The bytes to be read. */ public MessagePacket(byte[] payload) { /* Make a clone of the payload (message) bytes. */ int length = payload.length; data = new byte[length]; for (int i = 0; i < length; i++) { data[i] = payload[i]; } } /** * Read an integer (32-bit) value from the data stream, starting at the * current index. * * @return The integer that was read from the data stream. * * @exception ArrayIndexOutOfBoundsException if reading goes beyond the * end of the data stream. */ public int getInt() { int x1 = ((int)(data[index++] & 0xff)); int x2 = ((int)(data[index++] & 0xff) << 8); int x3 = ((int)(data[index++] & 0xff) << 16); int x4 = ((int)(data[index++] & 0xff) << 24); return (x1 | x2 | x3 | x4); } /** * Write an integer (32-bit) value into the data stream and advance the * index. * * @param x The integer to be written. * * @exception ArrayIndexOutOfBoundsException if reading goes beyond the * end of the data stream. */ public void putInt(int x) throws IOException { checkFirstWrite(); dos.writeByte((byte) (x & 0xff)); dos.writeByte((byte)((x >> 8) & 0xff)); dos.writeByte((byte)((x >> 16) & 0xff)); dos.writeByte((byte)((x >> 24) & 0xff)); } /** * Read a short (16-bit) value from the data stream, starting at the * current index. * * @return The short that was read from the data stream. * * @exception ArrayIndexOutOfBoundsException if reading goes beyond the * end of the data stream. */ public short getShort() { short x1 = ((short)(data[index++] & 0xff)); short x2 = (short)((data[index++] & 0xff) << 8); return (short)(x1 | x2); } /** * Write a short (16-bit) value into the data stream and advance the * index. * * @param x The short to be written. * * @exception ArrayIndexOutOfBoundsException if reading goes beyond the * end of the data stream. */ public void putShort(short x) throws IOException { checkFirstWrite(); dos.writeByte((byte) (x & 0xff)); dos.writeByte((byte)((x >> 8) & 0xff)); } /** * Read a long (64-bit) value from data stream, starting at the current * index. * * @return The long value that was read from the data stream. * * @exception ArrayIndexOutOfBoundsException if reading goes beyond the * end of the data stream. */ public long getLong() { long x1 = ((long)(data[index++] & 0xff)); long x2 = ((long)(data[index++] & 0xff) << 8); long x3 = ((long)(data[index++] & 0xff) << 16); long x4 = ((long)(data[index++] & 0xff) << 24); long x5 = ((long)(data[index++] & 0xff) << 32); long x6 = ((long)(data[index++] & 0xff) << 40); long x7 = ((long)(data[index++] & 0xff) << 48); long x8 = ((long)(data[index++] & 0xff) << 56); return (x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8); } /** * Write a long (64-bit) value into the data stream and advance the index. * * @param x The long to be written. * * @exception ArrayIndexOutOfBoundsException if reading goes beyond the * end of the data stream. */ public void putLong(long x) throws IOException { checkFirstWrite(); dos.writeByte((byte) (x & 0xff)); dos.writeByte((byte)((x >> 8) & 0xff)); dos.writeByte((byte)((x >> 16) & 0xff)); dos.writeByte((byte)((x >> 24) & 0xff)); dos.writeByte((byte)((x >> 32) & 0xff)); dos.writeByte((byte)((x >> 40) & 0xff)); dos.writeByte((byte)((x >> 48) & 0xff)); dos.writeByte((byte)((x >> 56) & 0xff)); } /** * Write a string to the data stream, starting at the current index. The * characters in the string are written, followed by a null-character * terminator. * * @param s The string to be written. * * @exception ArrayIndexOutOfBoundsException if reading goes beyond the * end of the data stream. */ public void putString(String s) throws IOException { checkFirstWrite(); dos.writeBytes(s); dos.writeByte(0); } /** * Read a string from the data stream, starting at the current index. The * string is assumed to be terminated by a null character. * * @return The string of characters, converted to a * <code>java.lang.String</code> object. * * @exception ArrayIndexOutOfBoundsException if reading goes beyond the * end of the data stream. */ public String getString() { int offset = index; int len = 0; /* Determine length of string */ for (int i = index; i < data.length; i++) { if (data[i] == '\0') { break; } len++; } /* update index */ index += len + 1; return new String(data, offset, len); } /** * Write an array of bytes into the data stream, starting at the current * index. * * @param buf The buffer of bytes to be written into the data stream. * * @exception ArrayIndexOutOfBoundsException if reading goes beyond the * end of the data stream. */ public void putBytes(byte[] buf) throws IOException { checkFirstWrite(); dos.write(buf, 0, buf.length); } /** * Read an array of bytes from the data stream, starting at the current * index. The number of bytes to be read is specified by * <code>length</code>. The index is advanced by <code>length</code>. * * @param length The number of bytes to be read. * * @return The buffer of bytes that were read. * * @exception ArrayIndexOutOfBoundsException if reading goes beyond the * end of the data stream. */ public byte[] getBytes(int length) { byte[] buffer = new byte[length]; for (int i = 0; i < length; i++) { buffer[i] = data[index++]; } return buffer; } /** * Returns the contents of the packet as a byte array. * * @return The array of packet bytes. * * @exception IOException if there was a problem while closing the streams. */ public byte[] getData() throws IOException { byte[] buffer = new byte[0]; if (firstWrite == false) { dos.close(); buffer = bos.toByteArray(); bos.close(); } return buffer; } /** * Checks to see if the data output streams need to be opened. */ private void checkFirstWrite() { if (firstWrite == true) { firstWrite = false; bos = new ByteArrayOutputStream(); dos = new DataOutputStream(bos); } } }