blob: cb927301bbb13f513316f69a01baf6c350b3ffcf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
#ifndef _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_BYTESMESSAGECOMMAND_H_
#define _ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_BYTESMESSAGECOMMAND_H_
#include <cms/BytesMessage.h>
#include <activemq/connector/stomp/commands/StompMessage.h>
#include <activemq/connector/stomp/commands/CommandConstants.h>
#include <activemq/exceptions/IllegalStateException.h>
#include <activemq/io/ByteArrayInputStream.h>
#include <activemq/io/ByteArrayOutputStream.h>
#include <activemq/io/DataInputStream.h>
#include <activemq/io/DataOutputStream.h>
namespace activemq{
namespace connector{
namespace stomp{
namespace commands{
/**
* Implements the interface for a cms::BytesMessage. Uses the template
* class StompMessage to implement all cms::Message type functionality
* and implements the BytesMessage interface here.
*/
class BytesMessageCommand : public StompMessage< cms::BytesMessage >
{
private:
/**
* Flag that indicates what state the stream is in. If true, the
* message may only be read from. If false, the message may only be
* written to.
*/
bool readOnly;
/**
* InputStream that wraps around the frame's body when in read-only
* mode.
*/
io::ByteArrayInputStream inputStream;
/**
* OutputStream that wraps around the frame's body when in write-only
* mode.
*/
io::ByteArrayOutputStream outputStream;
/**
* DataInputStream wrapper around the input stream.
*/
io::DataInputStream dataInputStream;
/**
* DataOutputStream wrapper around the output stream.
*/
io::DataOutputStream dataOutputStream;
public:
/**
* Default constructor. Initializes in write-only mode.
*/
BytesMessageCommand() :
StompMessage< cms::BytesMessage >(),
dataInputStream(&inputStream),
dataOutputStream(&outputStream)
{
initialize( getFrame() );
clearBody();
}
/**
* Constructor for initialization in read-only mode.
* @param frame The stomp frame that was received from the broker.
*/
BytesMessageCommand( StompFrame* frame ) :
StompMessage< cms::BytesMessage >( frame ),
dataInputStream(&inputStream),
dataOutputStream(&outputStream)
{
validate( getFrame() );
reset();
}
virtual ~BytesMessageCommand() {}
/**
* Clears out the body of the message. This does not clear the
* headers or properties.
*/
virtual void clearBody(){
// Invoke base class's version.
StompMessage<cms::BytesMessage>::clearBody();
// Set the stream in write only mode.
readOnly = false;
outputStream.setBuffer( getBytes() );
}
/**
* Marshals the command to a stomp frame.
* @returns the stomp frame representation of this
* command.
* @throws MarshalException if the command is not
* in a state that can be marshaled.
*/
virtual const StompFrame& marshal()
throw (marshal::MarshalException)
{
// Before we send out the frame tag it with the content length
// as this is a bytes message and we can't ensure we have only
// a trailing NULL.
setPropertyValue(
CommandConstants::toString(
CommandConstants::HEADER_CONTENTLENGTH),
util::Long::toString( getFrame().getBodyLength() ) );
return StompMessage<cms::BytesMessage>::marshal();
}
/**
* Puts the message body in read-only mode and repositions the stream
* of bytes to the beginning.
* @throws CMSException
*/
virtual void reset() throw ( cms::CMSException ){
readOnly = true;
inputStream.setBuffer( getBytes() );
}
/**
* Clonse this message exactly, returns a new instance that the
* caller is required to delete.
* @return new copy of this message
*/
virtual cms::BytesMessage* clone() const {
StompFrame* frame = getFrame().clone();
return new BytesMessageCommand( frame );
}
/**
* sets the bytes given to the message body.
* @param buffer Byte Buffer to copy
* @param numBytes Number of bytes in Buffer to copy
* @throws CMSException
*/
virtual void setBodyBytes( const unsigned char* buffer,
std::size_t numBytes )
throw( cms::CMSException ) {
checkWriteOnly();
this->setBytes( buffer, numBytes );
}
/**
* Gets the bytes that are contained in this message, user should
* copy this data into a user allocated buffer. Call
* <code>getBodyLength</code> to determine the number of bytes
* to expect.
* @return const pointer to a byte buffer
*/
virtual const unsigned char* getBodyBytes() const {
const std::vector<unsigned char>& bytes = getBytes();
if( bytes.size() == 0 ){
return NULL;
}
return &this->getBytes()[0];
}
/**
* Returns the number of bytes contained in the body of this message.
* @return number of bytes.
*/
virtual std::size_t getBodyLength() const {
return this->getNumBytes();
}
/**
* Reads a Boolean from the Bytes message stream
* @returns boolean value from stream
* @throws CMSException
*/
virtual bool readBoolean() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readBoolean();
}
/**
* Writes a boolean to the bytes message stream as a 1-byte value.
* The value true is written as the value (byte)1; the value false
* is written as the value (byte)0.
* @param value - boolean to write to the stream
* @throws CMSException
*/
virtual void writeBoolean( bool value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeBoolean( value );
}
/**
* Reads a Byte from the Bytes message stream
* @returns unsigned char value from stream
* @throws CMSException
*/
virtual unsigned char readByte() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readByte();
}
/**
* Writes a byte to the bytes message stream as a 1-byte value
* @param value - byte to write to the stream
* @throws CMSException
*/
virtual void writeByte( unsigned char value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeByte( value );
}
/**
* Reads a byte array from the bytes message stream.
*
* If the length of vector value is less than the number of bytes
* remaining to be read from the stream, the vector should be filled. A
* subsequent call reads the next increment, and so on.
*
* If the number of bytes remaining in the stream is less than the
* length of vector value, the bytes should be read into the vector. The
* return value of the total number of bytes read will be less than the
* length of the vector, indicating that there are no more bytes left to
* be read from the stream. The next read of the stream returns -1.
*
* @param value - buffer to place data in
* @returns the total number of bytes read into the buffer, or -1 if
* there is no more data because the end of the stream has
* been reached
* @throws CMSException if an error occurs.
*/
virtual std::size_t readBytes( std::vector<unsigned char>& value )
throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.read( value );
}
/**
* Writes a byte array to the bytes message stream using the vector
* size as the number of bytes to write.
* @param value - bytes to write to the stream
* @throws CMSException
*/
virtual void writeBytes( const std::vector<unsigned char>& value )
throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.write( value );
}
/**
* Reads a portion of the bytes message stream.
*
* If the length of array value is less than the number of bytes
* remaining to be read from the stream, the array should be filled. A
* subsequent call reads the next increment, and so on.
*
* If the number of bytes remaining in the stream is less than the
* length of array value, the bytes should be read into the array. The
* return value of the total number of bytes read will be less than the
* length of the array, indicating that there are no more bytes left to
* be read from the stream. The next read of the stream returns -1.
*
* If length is negative, or length is greater than the length of the
* array value, then an IndexOutOfBoundsException is thrown. No bytes
* will be read from the stream for this exception case.
*
* @param value - the buffer into which the data is read
* @param length - the number of bytes to read; must be less than or
* equal to value.length
* @returns the total number of bytes read into the buffer, or -1 if
* there is no more data because the end of the stream has
* been reached
* @throws CMSException
*/
virtual std::size_t readBytes( unsigned char*& buffer, std::size_t length )
throw ( cms::CMSException )
{
checkReadOnly();
return dataInputStream.read( buffer, 0, length );
}
/**
* Writes a portion of a byte array to the bytes message stream.
* size as the number of bytes to write.
* @param value - bytes to write to the stream
* @param offset - the initial offset within the byte array
* @param length - the number of bytes to use
* @throws CMSException
*/
virtual void writeBytes( const unsigned char* value,
std::size_t offset,
std::size_t length ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.write( value, offset, length );
}
/**
* Reads a Char from the Bytes message stream
* @returns char value from stream
* @throws CMSException
*/
virtual char readChar() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readChar();
}
/**
* Writes a char to the bytes message stream as a 1-byte value
* @param value - char to write to the stream
* @throws CMSException
*/
virtual void writeChar( char value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeChar( value );
}
/**
* Reads a 32 bit float from the Bytes message stream
* @returns double value from stream
* @throws CMSException
*/
virtual float readFloat() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readFloat();
}
/**
* Writes a float to the bytes message stream as a 4 byte value
* @param value - float to write to the stream
* @throws CMSException
*/
virtual void writeFloat( float value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeFloat( value );
}
/**
* Reads a 64 bit double from the Bytes message stream
* @returns double value from stream
* @throws CMSException
*/
virtual double readDouble() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readDouble();
}
/**
* Writes a double to the bytes message stream as a 8 byte value
* @param value - double to write to the stream
* @throws CMSException
*/
virtual void writeDouble( double value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeDouble( value );
}
/**
* Reads a 16 bit signed short from the Bytes message stream
* @returns short value from stream
* @throws CMSException
*/
virtual short readShort() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readShort();
}
/**
* Writes a signed short to the bytes message stream as a 2 byte value
* @param value - signed short to write to the stream
* @throws CMSException
*/
virtual void writeShort( short value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeShort( value );
}
/**
* Reads a 16 bit unsigned short from the Bytes message stream
* @returns unsigned short value from stream
* @throws CMSException
*/
virtual unsigned short readUnsignedShort() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readUnsignedShort();
}
/**
* Writes a unsigned short to the bytes message stream as a 2 byte value
* @param value - unsigned short to write to the stream
* @throws CMSException
*/
virtual void writeUnsignedShort( unsigned short value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeUnsignedShort( value );
}
/**
* Reads a 32 bit signed intger from the Bytes message stream
* @returns int value from stream
* @throws CMSException
*/
virtual int readInt() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readInt();
}
/**
* Writes a signed int to the bytes message stream as a 4 byte value
* @param value - signed int to write to the stream
* @throws CMSException
*/
virtual void writeInt( int value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeInt( value );
}
/**
* Reads a 64 bit long from the Bytes message stream
* @returns long long value from stream
* @throws CMSException
*/
virtual long long readLong() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readLong();
}
/**
* Writes a long long to the bytes message stream as a 8 byte value
* @param value - signed long long to write to the stream
* @throws CMSException
*/
virtual void writeLong( long long value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeLong( value );
}
/**
* Reads an ASCII String from the Bytes message stream
* @returns String from stream
* @throws CMSException
*/
virtual std::string readString() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readString();
}
/**
* Writes an ASCII String to the Bytes message stream
* @param value The string to be written to the stream.
* @throws CMSException
*/
virtual void writeString( const std::string& value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeChars( value );
}
/**
* Reads an UTF String from the BytesMessage stream
* @returns String from stream
* @throws CMSException
*/
virtual std::string readUTF() throw ( cms::CMSException ){
checkReadOnly();
return dataInputStream.readUTF();
}
/**
* Writes an UTF String to the BytesMessage stream
* @param value The string to be written to the stream.
* @throws CMSException
*/
virtual void writeUTF( const std::string& value ) throw ( cms::CMSException ){
checkWriteOnly();
dataOutputStream.writeUTF( value );
}
protected:
/**
* Throws an exception if not in write-only mode.
* @throws CMSException.
*/
void checkWriteOnly() throw (cms::CMSException){
if( readOnly ){
throw exceptions::IllegalStateException( __FILE__, __LINE__,
"message is in read-only mode and cannot be written to" );
}
}
/**
* Throws an exception if not in read-only mode.
* @throws CMSException
*/
void checkReadOnly() throw (cms::CMSException){
if( !readOnly ){
throw exceptions::IllegalStateException( __FILE__, __LINE__,
"message is in write-only mode and cannot be read from" );
}
}
};
}}}}
#endif /*_ACTIVEMQ_CONNECTOR_STOMP_COMMANDS_BYTESMESSAGECOMMAND_H_*/