/* Copyright (c) 2001-2019, 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.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;

Atomic transmission packet from HyperSQL server to ODBC client. Sample usage outPacket = OdbcPacketOutputStream.newOdbcPacketOutputStream(); ... // For each packet you need to transmit: outPacket.reset(); outPacket.write(this); outPacket.write(that); outPacket.xmit('X', hsqlDataOutputStream);
/** * Atomic transmission packet from HyperSQL server to ODBC client. * * Sample usage * <CODE> * outPacket = OdbcPacketOutputStream.newOdbcPacketOutputStream(); * ... * // For each packet you need to transmit: * outPacket.reset(); * outPacket.write(this); * outPacket.write(that); * outPacket.xmit('X', hsqlDataOutputStream); * </CODE> */
class OdbcPacketOutputStream extends DataOutputStream { private ByteArrayOutputStream byteArrayOutputStream; private ByteArrayOutputStream stringWriterOS = new ByteArrayOutputStream(); private DataOutputStream stringWriterDos = new DataOutputStream(stringWriterOS); private int packetStart = 0; // Stream's "written" at start of packet. public int getSize() { return written - packetStart; }
Wrapper method to write a null-terminated String.
/** * Wrapper method to write a null-terminated String. */
synchronized void write(String s) throws IOException { write(s, true); } synchronized void write(String s, boolean nullTerm) throws IOException { stringWriterDos.writeUTF(s); write(stringWriterOS.toByteArray(), 2, stringWriterOS.size() - 2); stringWriterOS.reset(); if (nullTerm) { writeByte(0); } } synchronized void writeSized(String s) throws IOException { stringWriterDos.writeUTF(s); byte[] ba = stringWriterOS.toByteArray(); stringWriterOS.reset(); writeInt(ba.length - 2); write(ba, 2, ba.length - 2); } synchronized void reset() throws IOException { byteArrayOutputStream.reset(); packetStart = written; writeInt(-1); // length placeholder } static OdbcPacketOutputStream newOdbcPacketOutputStream() throws IOException { return new OdbcPacketOutputStream(new ByteArrayOutputStream()); } protected OdbcPacketOutputStream( ByteArrayOutputStream byteArrayOutputStream) throws IOException { super(byteArrayOutputStream); this.byteArrayOutputStream = byteArrayOutputStream; reset(); }
Returns:packet size (which does not count the type byte).
/** * @return packet size (which does not count the type byte). */
synchronized int xmit(char packetType, org.hsqldb.lib.DataOutputStream destinationStream) throws IOException { byte[] ba = byteArrayOutputStream.toByteArray(); ba[0] = (byte) (ba.length >> 24); ba[1] = (byte) (ba.length >> 16); ba[2] = (byte) (ba.length >> 8); ba[3] = (byte) ba.length; reset(); destinationStream.writeByte(packetType); destinationStream.write(ba); destinationStream.flush(); return ba.length; } synchronized public void close() throws IOException { super.close(); stringWriterDos.close(); }
The behavior here is purposefully different from java.io.DataOutputStream.writeChar(int), which writes 2 bytes. We are supporting only 1-byte characters, or don't care about the high bits.
/** * The behavior here is purposefully different from * java.io.DataOutputStream.writeChar(int), which writes 2 bytes. * * We are supporting only 1-byte characters, or don't care about the * high bits. */
synchronized public void writeByteChar(char c) throws IOException { writeByte(c); } }