/** * Copyright (c) 2011-2014 Exxeleron GmbH * * 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 com.exxeleron.qjava; import java.io.IOException; import java.io.OutputStream; /** * Provides serialization to q IPC protocol. * <p> * Methods of {@link QWriter} are not thread safe. * </p> */ public abstract class QWriter { protected OutputStream stream; private String encoding; protected ByteOutputStream writer = new ByteOutputStream(); protected ByteOutputStream header = new ByteOutputStream(8); protected int messageSize; protected int protocolVersion = 3; /** * Sets the output stream for serialization. * * @param outputStream * Output stream for serialized messages */ void setStream( final OutputStream stream ) { this.stream = stream; } /** * Sets encoding for string data serialization. * * @param encoding * Encoding used for serialization of string data */ void setEncoding( final String encoding ) { this.encoding = encoding; } /** * Retrieves string encoding * * @return charset name */ protected String getEncoding() { return encoding; } /** * Set the kdb+ protocol version. * * @param protocolVersion * kdb+ protocol version */ public void setProtocolVersion( final int protocolVersion ) { this.protocolVersion = protocolVersion; } /** * Retrieves kdb+ protocol version. * * @return {@link int} kdb+ protocol version */ public int getProtocolVersion() { return protocolVersion; } /** * Serializes object to q IPC protocol and writes as a message to the output stream. * * @param obj * Object to be serialized * @param msgType * Message type * @return total size of the message, includes header (8 bytes) and data payload * @throws IOException * @throws QException */ public int write( final Object obj, final QConnection.MessageType msgType ) throws IOException, QException { // serialize object writer.reset(); writeObject(obj); messageSize = writer.count() + 8; // write header header.reset(); header.write((byte) 1); // endianness header.write((byte) msgType.ordinal()); header.writeShort((short) 0); header.writeInt(messageSize); // write message stream.write(header.buffer(), 0, 8); stream.write(writer.buffer(), 0, writer.count()); return messageSize; } /** * Serializes object into an IPC stream. * * @param obj * object to be serialized * @throws IOException * in case of IO error * @throws QException * in case object cannot be serialized */ protected abstract void writeObject( final Object obj ) throws IOException, QException; /** * Verifies whether specified q type is compatible with current protocol version. * * @param qtype * qtype to be checked * @throws QWriterException * if specified q type is not valid in current protocol */ protected void checkProtocolVersionCompatibility( final QType qtype ) throws QWriterException { if ( protocolVersion < 3 && (qtype == QType.GUID || qtype == QType.GUID_LIST) ) { throw new QWriterException("kdb+ protocol version violation: guid not supported pre kdb+ v3.0"); } if ( protocolVersion < 1 && (qtype == QType.TIMESPAN || qtype == QType.TIMESPAN_LIST) ) { throw new QWriterException("kdb+ protocol version violation: timespan not supported pre kdb+ v2.6"); } if ( protocolVersion < 1 && (qtype == QType.TIMESTAMP || qtype == QType.TIMESTAMP_LIST) ) { throw new QWriterException("kdb+ protocol version violation: timestamp not supported pre kdb+ v2.6"); } } }