Package org.hsqldb.server

Source Code of org.hsqldb.server.OdbcPacketInputStream

/* Copyright (c) 2001-2010, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


package org.hsqldb.server;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.hsqldb.HsqlException;
import org.hsqldb.types.BinaryData;

/**
* An atomic transfer packet received from a HyperSQL client.
*
* Since we read and cache all data for the packet upon instantiation, the
* available method is reliable and may be relied upon.
*
* @see #available()
*/
class OdbcPacketInputStream extends DataInputStream {
    char packetType;
    private InputStream bufferStream;

    /**
     * Instantiate a packet of the specified type and size.
     */
    static OdbcPacketInputStream newOdbcPacketInputStream(
    char cType, InputStream streamSource, int sizeInt) throws IOException {
        return newOdbcPacketInputStream(
            cType, streamSource, new Integer(sizeInt));
    }

    /**
     * Instantiate a packet of the specified type, with size determined by
     * the first int read from the given stream.
     */
    static OdbcPacketInputStream newOdbcPacketInputStream(
    char cType, InputStream streamSource) throws IOException {
        return newOdbcPacketInputStream(cType, streamSource, null);
    }

    static private OdbcPacketInputStream newOdbcPacketInputStream(
    char cType, InputStream streamSource, Integer packetSizeObj)
    throws IOException {
        int bytesRead, i;
        int packetSize = 0;

        if (packetSizeObj == null) {
            byte[] fourBytes = new byte[4];
            bytesRead = 0;
            while ((i = streamSource.read(fourBytes, bytesRead,
                fourBytes.length - bytesRead)) > 0) {
                bytesRead += i;
            }
            if (bytesRead != fourBytes.length) {
                throw new EOFException("Failed to read size header int");
            }
            packetSize =
                ((fourBytes[0] & 0xff) << 24) + ((fourBytes[1] & 0xff) <<16)
                + ((fourBytes[2] & 0xff) << 8) + (fourBytes[3] & 0xff) - 4;
            // Minus 4 because this counts the size int itself.
        } else {
            packetSize = packetSizeObj.intValue();
        }
        byte[] xferBuffer = new byte[packetSize];
        bytesRead = 0;
        while ((i = streamSource.read(xferBuffer, bytesRead,
            xferBuffer.length - bytesRead)) > 0) {
            bytesRead += i;
        }
        if (bytesRead != xferBuffer.length) {
            throw new EOFException (
                    "Failed to read packet contents from given stream");
        }
        return new OdbcPacketInputStream(
            cType, new ByteArrayInputStream(xferBuffer));
    }

    private OdbcPacketInputStream(char packetType, InputStream bufferStream) {
        super(bufferStream);
        this.packetType = packetType;
    }

    /**
     * Generate a String/String Map from null-terminated String pairs, until
     * a '\0' character is read in place of the first key character.
     *
     * @return the generated Map
     * @throws EOFException if the rest of packet does not contained the
     *                   required, well-formed null-terminated string pairs.
     */
    Map readStringPairs() throws IOException {
        String key;
        Map map = new HashMap();
        while (true) {
            key = readString();
            if (key.length() < 1) {
                break;
            }
            map.put(key, readString());
        }
        return map;
    }

    /**
     * Reads a NULL-TERMINATED String.
     *
     * @throws IOException if attempt to read past end of packet.
     */
    String readString() throws IOException {
        /* Would be MUCH easier to do this with Java6's String
         * encoding/decoding operations */
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        baos.write((byte) 'X');
        baos.write((byte) 'X');
        // Place-holders to be replaced with short length

        int i;
        while ((i = readByte()) > 0) {
            baos.write((byte) i);
        }
        byte[] ba = baos.toByteArray();
        baos.close();

        int len = ba.length - 2;
        ba[0] = (byte) (len >>> 8);
        ba[1] = (byte) len;

        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(ba));
        String s = dis.readUTF();
        //String s = DataInputStream.readUTF(dis);
        // TODO:  Test the previous two to see if one works better for
        // high-order characters.
        dis.close();
        return s;
    }

    BinaryData readSizedBinaryData() throws IOException {
        int len = readInt();
        try {
            return (len < 0) ? null : new BinaryData((long) len, this);
        } catch (HsqlException he) {
            throw new IOException(he.getMessage());
        }
    }

    String readSizedString() throws IOException {
        int len = readInt();
        return (len < 0) ? null : readString(len);
    }

    /**
     * These Strings are not null-terminated.
     *
     * @param len Bytes to read (not necessarily characters to be returned!
     * @throws IOException if attempt to read past end of packet.
     */
    String readString(int len) throws IOException {
        /* Would be MUCH easier to do this with Java6's String
         * encoding/decoding operations */
        int bytesRead = 0;
        int i;
        byte[] ba = new byte[len + 2];
        ba[0] = (byte) (len >>> 8);
        ba[1] = (byte) len;
        while ((i = read(ba, 2 + bytesRead, len - bytesRead)) > -1
            && bytesRead < len) {
            bytesRead += i;
        }
        if (bytesRead != len) {
            throw new EOFException("Packet ran dry");
        }
        for (i = 2; i < ba.length - 1; i++) {
            if (ba[i] == 0) {
                throw new RuntimeException(
                        "Null internal to String at offset " + (i - 2));
            }
        }

        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(ba));
        String s = dis.readUTF();
        //String s = DataInputStream.readUTF(dis);
        // TODO:  Test the previous two to see if one works better for
        // high-order characters.
        dis.close();
        return s;
    }

    public char readByteChar() throws IOException {
        return (char) readByte();
    }
}
TOP

Related Classes of org.hsqldb.server.OdbcPacketInputStream

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.