/* * 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. */ using System; using System.IO; using Apache.NMS.Util; namespace Apache.NMS.MSMQ { public class StreamMessage : BaseMessage, IStreamMessage { private EndianBinaryReader dataIn = null; private EndianBinaryWriter dataOut = null; private MemoryStream byteBuffer = null; private int bytesRemaining = -1; public bool ReadBoolean() { InitializeReading(); try { long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if(type == PrimitiveMap.BOOLEAN_TYPE) { return this.dataIn.ReadBoolean(); } else if(type == PrimitiveMap.STRING_TYPE) { return Boolean.Parse(this.dataIn.ReadString16()); } else if(type == PrimitiveMap.NULL) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new NMSException("Cannot convert Null type to a bool"); } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a Boolean type."); } } catch(FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } } catch(EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch(IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } } public byte ReadByte() { InitializeReading(); try { long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if(type == PrimitiveMap.BYTE_TYPE) { return this.dataIn.ReadByte(); } else if(type == PrimitiveMap.STRING_TYPE) { return Byte.Parse(this.dataIn.ReadString16()); } else if(type == PrimitiveMap.NULL) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new NMSException("Cannot convert Null type to a byte"); } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a Byte type."); } } catch(FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } } catch(EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch(IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } } public char ReadChar() { InitializeReading(); try { long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if(type == PrimitiveMap.CHAR_TYPE) { return this.dataIn.ReadChar(); } else if(type == PrimitiveMap.NULL) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new NMSException("Cannot convert Null type to a char"); } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a Char type."); } } catch(FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } } catch(EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch(IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } } public short ReadInt16() { InitializeReading(); try { long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if(type == PrimitiveMap.SHORT_TYPE) { return this.dataIn.ReadInt16(); } else if(type == PrimitiveMap.BYTE_TYPE) { return this.dataIn.ReadByte(); } else if(type == PrimitiveMap.STRING_TYPE) { return Int16.Parse(this.dataIn.ReadString16()); } else if(type == PrimitiveMap.NULL) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new NMSException("Cannot convert Null type to a short"); } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a Int16 type."); } } catch(FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } } catch(EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch(IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } } public int ReadInt32() { InitializeReading(); try { long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if(type == PrimitiveMap.INTEGER_TYPE) { return this.dataIn.ReadInt32(); } else if(type == PrimitiveMap.SHORT_TYPE) { return this.dataIn.ReadInt16(); } else if(type == PrimitiveMap.BYTE_TYPE) { return this.dataIn.ReadByte(); } else if(type == PrimitiveMap.STRING_TYPE) { return Int32.Parse(this.dataIn.ReadString16()); } else if(type == PrimitiveMap.NULL) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new NMSException("Cannot convert Null type to a int"); } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a Int32 type."); } } catch(FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } } catch(EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch(IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } } public long ReadInt64() { InitializeReading(); try { long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if(type == PrimitiveMap.LONG_TYPE) { return this.dataIn.ReadInt64(); } else if(type == PrimitiveMap.INTEGER_TYPE) { return this.dataIn.ReadInt32(); } else if(type == PrimitiveMap.SHORT_TYPE) { return this.dataIn.ReadInt16(); } else if(type == PrimitiveMap.BYTE_TYPE) { return this.dataIn.ReadByte(); } else if(type == PrimitiveMap.STRING_TYPE) { return Int64.Parse(this.dataIn.ReadString16()); } else if(type == PrimitiveMap.NULL) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new NMSException("Cannot convert Null type to a long"); } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a Int64 type."); } } catch(FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } } catch(EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch(IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } } public float ReadSingle() { InitializeReading(); try { long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if(type == PrimitiveMap.FLOAT_TYPE) { return this.dataIn.ReadSingle(); } else if(type == PrimitiveMap.STRING_TYPE) { return Single.Parse(this.dataIn.ReadString16()); } else if(type == PrimitiveMap.NULL) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new NMSException("Cannot convert Null type to a float"); } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a Single type."); } } catch(FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } } catch(EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch(IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } } public double ReadDouble() { InitializeReading(); try { long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if(type == PrimitiveMap.DOUBLE_TYPE) { return this.dataIn.ReadDouble(); } else if(type == PrimitiveMap.FLOAT_TYPE) { return this.dataIn.ReadSingle(); } else if(type == PrimitiveMap.STRING_TYPE) { return Single.Parse(this.dataIn.ReadString16()); } else if(type == PrimitiveMap.NULL) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new NMSException("Cannot convert Null type to a double"); } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a Double type."); } } catch(FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } } catch(EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch(IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } } public string ReadString() { InitializeReading(); long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if(type == PrimitiveMap.BIG_STRING_TYPE) { return this.dataIn.ReadString32(); } else if(type == PrimitiveMap.STRING_TYPE) { return this.dataIn.ReadString16(); } else if(type == PrimitiveMap.LONG_TYPE) { return this.dataIn.ReadInt64().ToString(); } else if(type == PrimitiveMap.INTEGER_TYPE) { return this.dataIn.ReadInt32().ToString(); } else if(type == PrimitiveMap.SHORT_TYPE) { return this.dataIn.ReadInt16().ToString(); } else if(type == PrimitiveMap.FLOAT_TYPE) { return this.dataIn.ReadSingle().ToString(); } else if(type == PrimitiveMap.DOUBLE_TYPE) { return this.dataIn.ReadDouble().ToString(); } else if(type == PrimitiveMap.CHAR_TYPE) { return this.dataIn.ReadChar().ToString(); } else if(type == PrimitiveMap.BYTE_TYPE) { return this.dataIn.ReadByte().ToString(); } else if(type == PrimitiveMap.BOOLEAN_TYPE) { return this.dataIn.ReadBoolean().ToString(); } else if(type == PrimitiveMap.NULL) { return null; } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a known type."); } } catch(FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } catch(EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch(IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } } public int ReadBytes(byte[] value) { InitializeReading(); if(value == null) { throw new NullReferenceException("Passed Byte Array is null"); } try { if(this.bytesRemaining == -1) { long startingPos = this.byteBuffer.Position; byte type = this.dataIn.ReadByte(); if(type != PrimitiveMap.BYTE_ARRAY_TYPE) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Not a byte array"); } this.bytesRemaining = this.dataIn.ReadInt32(); } else if(this.bytesRemaining == 0) { this.bytesRemaining = -1; return -1; } if(value.Length <= this.bytesRemaining) { // small buffer this.bytesRemaining -= value.Length; this.dataIn.Read(value, 0, value.Length); return value.Length; } else { // big buffer int rc = this.dataIn.Read(value, 0, this.bytesRemaining); this.bytesRemaining = 0; return rc; } } catch(EndOfStreamException ex) { throw NMSExceptionSupport.CreateMessageEOFException(ex); } catch(IOException ex) { throw NMSExceptionSupport.CreateMessageFormatException(ex); } } public Object ReadObject() { InitializeReading(); long startingPos = this.byteBuffer.Position; try { int type = this.dataIn.ReadByte(); if(type == PrimitiveMap.BIG_STRING_TYPE) { return this.dataIn.ReadString32(); } else if(type == PrimitiveMap.STRING_TYPE) { return this.dataIn.ReadString16(); } else if(type == PrimitiveMap.LONG_TYPE) { return this.dataIn.ReadInt64(); } else if(type == PrimitiveMap.INTEGER_TYPE) { return this.dataIn.ReadInt32(); } else if(type == PrimitiveMap.SHORT_TYPE) { return this.dataIn.ReadInt16(); } else if(type == PrimitiveMap.FLOAT_TYPE) { return this.dataIn.ReadSingle(); } else if(type == PrimitiveMap.DOUBLE_TYPE) { return this.dataIn.ReadDouble(); } else if(type == PrimitiveMap.CHAR_TYPE) { return this.dataIn.ReadChar(); } else if(type == PrimitiveMap.BYTE_TYPE) { return this.dataIn.ReadByte(); } else if(type == PrimitiveMap.BOOLEAN_TYPE) { return this.dataIn.ReadBoolean(); } else if(type == PrimitiveMap.BYTE_ARRAY_TYPE) { int length = this.dataIn.ReadInt32(); byte[] data = new byte[length]; this.dataIn.Read(data, 0, length); return data; } else if(type == PrimitiveMap.NULL) { return null; } else { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw new MessageFormatException("Value is not a known type."); } } catch(FormatException e) { this.byteBuffer.Seek(startingPos, SeekOrigin.Begin); throw NMSExceptionSupport.CreateMessageFormatException(e); } catch(EndOfStreamException e) { throw NMSExceptionSupport.CreateMessageEOFException(e); } catch(IOException e) { throw NMSExceptionSupport.CreateMessageFormatException(e); } } public void WriteBoolean(bool value) { InitializeWriting(); try { this.dataOut.Write(PrimitiveMap.BOOLEAN_TYPE); this.dataOut.Write(value); } catch(IOException e) { NMSExceptionSupport.Create(e); } } public void WriteByte(byte value) { InitializeWriting(); try { this.dataOut.Write(PrimitiveMap.BYTE_TYPE); this.dataOut.Write(value); } catch(IOException e) { NMSExceptionSupport.Create(e); } } public void WriteBytes(byte[] value) { InitializeWriting(); this.WriteBytes(value, 0, value.Length); } public void WriteBytes(byte[] value, int offset, int length) { InitializeWriting(); try { this.dataOut.Write(PrimitiveMap.BYTE_ARRAY_TYPE); this.dataOut.Write((int) length); this.dataOut.Write(value, offset, length); } catch(IOException e) { NMSExceptionSupport.Create(e); } } public void WriteChar(char value) { InitializeWriting(); try { this.dataOut.Write(PrimitiveMap.CHAR_TYPE); this.dataOut.Write(value); } catch(IOException e) { NMSExceptionSupport.Create(e); } } public void WriteInt16(short value) { InitializeWriting(); try { this.dataOut.Write(PrimitiveMap.SHORT_TYPE); this.dataOut.Write(value); } catch(IOException e) { NMSExceptionSupport.Create(e); } } public void WriteInt32(int value) { InitializeWriting(); try { this.dataOut.Write(PrimitiveMap.INTEGER_TYPE); this.dataOut.Write(value); } catch(IOException e) { NMSExceptionSupport.Create(e); } } public void WriteInt64(long value) { InitializeWriting(); try { this.dataOut.Write(PrimitiveMap.LONG_TYPE); this.dataOut.Write(value); } catch(IOException e) { NMSExceptionSupport.Create(e); } } public void WriteSingle(float value) { InitializeWriting(); try { this.dataOut.Write(PrimitiveMap.FLOAT_TYPE); this.dataOut.Write(value); } catch(IOException e) { NMSExceptionSupport.Create(e); } } public void WriteDouble(double value) { InitializeWriting(); try { this.dataOut.Write(PrimitiveMap.DOUBLE_TYPE); this.dataOut.Write(value); } catch(IOException e) { NMSExceptionSupport.Create(e); } } public void WriteString(string value) { InitializeWriting(); try { if(value.Length > 8192) { this.dataOut.Write(PrimitiveMap.BIG_STRING_TYPE); this.dataOut.WriteString32(value); } else { this.dataOut.Write(PrimitiveMap.STRING_TYPE); this.dataOut.WriteString16(value); } } catch(IOException e) { NMSExceptionSupport.Create(e); } } public void WriteObject(Object value) { InitializeWriting(); if(value is System.Byte) { this.WriteByte((byte) value); } else if(value is Char) { this.WriteChar((char) value); } else if(value is Boolean) { this.WriteBoolean((bool) value); } else if(value is Int16) { this.WriteInt16((short) value); } else if(value is Int32) { this.WriteInt32((int) value); } else if(value is Int64) { this.WriteInt64((long) value); } else if(value is Single) { this.WriteSingle((float) value); } else if(value is Double) { this.WriteDouble((double) value); } else if(value is byte[]) { this.WriteBytes((byte[]) value); } else if(value is String) { this.WriteString((string) value); } else { throw new MessageFormatException("Cannot write non-primitive type:" + value.GetType()); } } public override void ClearBody() { base.ClearBody(); this.byteBuffer = null; this.dataIn = null; this.dataOut = null; this.bytesRemaining = -1; } public void Reset() { StoreContent(); this.dataIn = null; this.dataOut = null; this.byteBuffer = null; this.bytesRemaining = -1; this.ReadOnlyBody = true; } private void InitializeReading() { FailIfWriteOnlyBody(); if(this.dataIn == null) { // TODO - Add support for Message Compression. this.byteBuffer = new MemoryStream(this.Content, false); dataIn = new EndianBinaryReader(byteBuffer); } } private void InitializeWriting() { FailIfReadOnlyBody(); if(this.dataOut == null) { // TODO - Add support for Message Compression. this.byteBuffer = new MemoryStream(); this.dataOut = new EndianBinaryWriter(byteBuffer); } } private void StoreContent() { if(dataOut != null) { dataOut.Close(); // TODO - Add support for Message Compression. this.Content = byteBuffer.ToArray(); this.dataOut = null; this.byteBuffer = null; } } } }