/*
 * Drizzle JDBC
 *
 * Copyright (C) 2009 Marcus Eriksson (krummas@gmail.com)
 * All rights reserved.
 *
 * Copyright (C) 2009 Sun Microsystems
 * All rights reserved.
 *
 * Use and distribution licensed under the BSD license.
 */
package org.drizzle.jdbc.internal.common.packet;

import java.io.IOException;
import java.io.InputStream;

/**
 * Class to represent a raw packet as transferred over the wire. First we
 * got 3 bytes specifying the actual length, then one byte packet sequence
 * number and then n bytes with user data.
 *
 */
public class RawPacket {

    static final RawPacket IOEXCEPTION_PILL = new RawPacket(null, -1);
    private final byte[] rawBytes;
    private final int packetSeq;

    /**
     * Get the next packet from the stream
     *
     * @param is the input stream to read the next packet from
     * @return The next packet from the stream, or NULL if the stream is closed
     * @throws java.io.IOException if an error occurs while reading data
     */
    static RawPacket nextPacket(InputStream is) throws IOException {
        int length = readLength(is);
        if (length == -1) {
            return null;
        }

        if (length < 0) {
            throw new IOException("Got negative packet size: " + length);
        }

        int packetSeq = readPacketSeq(is);

        byte[] rawBytes = new byte[length];

        int nr = safeRead(is, rawBytes, length);
        if (nr == -1) {
            throw new IOException("EOF. Expected " + length + ", got " + nr);
            /* EOF */
        }

        return new RawPacket(rawBytes, packetSeq);
    }

    private RawPacket(byte[] rawBytes, int packetSeq) {
        this.rawBytes = rawBytes;
        this.packetSeq = packetSeq;
    }


    private static int safeRead(InputStream is, byte[] buffer, int length) throws IOException{
        int offset = 0;
        int left = length;
        do {
            int nr = is.read(buffer, offset, left);
            if (nr == -1) {
                return nr;
            }
            offset += nr;
            left -= nr;
        } while (left > 0);

        return length;
    }

    private static byte readPacketSeq(InputStream reader) throws IOException {
        int val = reader.read();
        if (val == -1) {
            throw new IOException("EOF");
        }

        return (byte) val;
    }

    private static int readLength(InputStream reader) throws IOException {
        byte[] lengthBuffer = new byte[3];

        int nr = safeRead(reader, lengthBuffer, 3);
        if (nr == -1) {
            return -1;
        } else if (nr != 3) {
            throw new IOException("Incomplete read! Expected 3, got " + nr);
        }

        return (lengthBuffer[0] & 0xff) + ((lengthBuffer[1] & 0xff) << 8) + ((lengthBuffer[2] & 0xff) << 16);
    }

    public byte[] getRawBytes() {
        return rawBytes;
    }

    public int getPacketSeq() {
        return packetSeq;
    }
}

@@ -1392,24 +1392,16 @@
 rawBytes
-, length
 );%0A     
@@ -1402,37 +1402,41 @@
 %0A        if (nr 
-== -1
+!= length
 ) %7B%0A            
@@ -1505,30 +1505,8 @@
 r);%0A
-            /* EOF */%0A
     
@@ -1704,16 +1704,485 @@
     %7D%0A%0A%0A
+    /**%0A     * Read a number of bytes from the stream and store it in the buffer, and%0A     * fix the problem with %22incomplete%22 reads by doing another read if we%0A     * don't have all of the data yet.%0A     *%0A     * @param is the input stream to read from%0A     * @param buffer where to store the data%0A     * @return the number of bytes read (should be == length if we didn't hit EOF)%0A     * @throws java.io.IOException if an error occurs while reading the stream%0A     */%0A
     priv
@@ -2238,20 +2238,8 @@
 ffer
-, int length
 ) th
@@ -2299,16 +2299,23 @@
  left = 
+buffer.
 length;%0A
@@ -2542,16 +2542,23 @@
  return 
+buffer.
 length;%0A
@@ -2957,11 +2957,8 @@
 ffer
-, 3
 );%0A 
@@ -3242,73 +3242,291 @@
  %7D%0A%0A
-    public byte%5B%5D getRawBytes() %7B%0A        return rawBytes;%0A    %7D%0A
+%0A    /**%0A     * Get the raw bytes in the package%0A     * @return an array with the payload of the package%0A     */%0A    public byte%5B%5D getRawBytes() %7B%0A        return rawBytes;%0A    %7D%0A%0A    /**%0A     * Get the package sequence number%0A     * @return the sequence number of the package%0A     */
 %0A   

Update javadoc and minor code cleanup