blob: 8dbc084c3ea327d3a81ac3ff3a4d0a0564ee175f [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.
*/
using Apache.NMS.ActiveMQ.Commands;
using System;
using System.IO;
using System.Text;
namespace Apache.NMS.ActiveMQ.OpenWire
{
/// <summary>
/// A base class with useful implementation inheritence methods
/// for creating marshallers of the OpenWire protocol
/// </summary>
public abstract class BaseDataStreamMarshaller
{
private static readonly String[] HEX_TABLE = new String[]{
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
};
public abstract DataStructure CreateObject();
public abstract byte GetDataStructureType();
public virtual int TightMarshal1(OpenWireFormat wireFormat, Object o, BooleanStream bs)
{
return 0;
}
public virtual void TightMarshal2(
OpenWireFormat wireFormat,
Object o,
BinaryWriter dataOut,
BooleanStream bs)
{
}
public virtual void TightUnmarshal(
OpenWireFormat wireFormat,
Object o,
BinaryReader dataIn,
BooleanStream bs)
{
}
protected virtual DataStructure TightUnmarshalNestedObject(
OpenWireFormat wireFormat,
BinaryReader dataIn,
BooleanStream bs)
{
return wireFormat.TightUnmarshalNestedObject(dataIn, bs);
}
protected virtual int TightMarshalNestedObject1(
OpenWireFormat wireFormat,
DataStructure o,
BooleanStream bs)
{
return wireFormat.TightMarshalNestedObject1(o, bs);
}
protected virtual void TightMarshalNestedObject2(
OpenWireFormat wireFormat,
DataStructure o,
BinaryWriter dataOut,
BooleanStream bs)
{
wireFormat.TightMarshalNestedObject2(o, dataOut, bs);
}
protected virtual DataStructure TightUnmarshalCachedObject(
OpenWireFormat wireFormat,
BinaryReader dataIn,
BooleanStream bs)
{
return wireFormat.TightUnmarshalNestedObject(dataIn, bs);
}
protected virtual int TightMarshalCachedObject1(
OpenWireFormat wireFormat,
DataStructure o,
BooleanStream bs)
{
return wireFormat.TightMarshalNestedObject1(o, bs);
}
protected virtual void TightMarshalCachedObject2(
OpenWireFormat wireFormat,
DataStructure o,
BinaryWriter dataOut,
BooleanStream bs)
{
wireFormat.TightMarshalNestedObject2(o, dataOut, bs);
}
protected virtual String TightUnmarshalString(BinaryReader dataIn, BooleanStream bs)
{
if(bs.ReadBoolean())
{
if(bs.ReadBoolean())
{
return ReadAsciiString(dataIn);
}
else
{
return dataIn.ReadString();
}
}
else
{
return null;
}
}
protected virtual int TightMarshalString1(String value, BooleanStream bs)
{
bs.WriteBoolean(value != null);
if (value != null)
{
int strlen = value.Length;
int utflen = 0;
int c = 0;
bool isOnlyAscii = true;
char[] charr = value.ToCharArray();
for (int i = 0; i < strlen; i++)
{
c = charr[i];
if ((c >= 0x0001) && (c <= 0x007F))
{
utflen++;
}
else if (c > 0x07FF)
{
utflen += 3;
isOnlyAscii = false;
}
else
{
isOnlyAscii = false;
utflen += 2;
}
}
if (utflen >= Int16.MaxValue)
throw new IOException("Encountered a String value that is too long to encode.");
bs.WriteBoolean(isOnlyAscii);
return utflen + 2;
}
else
{
return 0;
}
}
public static void TightMarshalString2(String value, BinaryWriter dataOut, BooleanStream bs)
{
if (bs.ReadBoolean())
{
// If we verified it only holds ascii values
if (bs.ReadBoolean())
{
dataOut.Write((short) value.Length);
// now lets write the bytes
char[] chars = value.ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
dataOut.Write((byte)(chars[i]&0xFF00>>8));
}
}
else
{
dataOut.Write(value);
}
}
}
public virtual int TightMarshalLong1(OpenWireFormat wireFormat, long o, BooleanStream bs)
{
if (o == 0L)
{
bs.WriteBoolean(false);
bs.WriteBoolean(false);
return 0;
}
else
{
ulong ul = (ulong) o;
if ((ul & 0xFFFFFFFFFFFF0000ul) == 0L)
{
bs.WriteBoolean(false);
bs.WriteBoolean(true);
return 2;
}
else if ((ul & 0xFFFFFFFF00000000ul) == 0L)
{
bs.WriteBoolean(true);
bs.WriteBoolean(false);
return 4;
}
else
{
bs.WriteBoolean(true);
bs.WriteBoolean(true);
return 8;
}
}
}
public virtual void TightMarshalLong2(
OpenWireFormat wireFormat,
long o,
BinaryWriter dataOut,
BooleanStream bs)
{
if (bs.ReadBoolean())
{
if (bs.ReadBoolean())
{
dataOut.Write(o);
}
else
{
dataOut.Write((int)o);
}
}
else
{
if (bs.ReadBoolean())
{
dataOut.Write((short)o);
}
}
}
public virtual long TightUnmarshalLong(OpenWireFormat wireFormat, BinaryReader dataIn, BooleanStream bs)
{
if (bs.ReadBoolean())
{
if (bs.ReadBoolean())
{
return dataIn.ReadInt64(); // dataIn.ReadInt64();
}
else
{
return dataIn.ReadUInt32();
}
}
else
{
if (bs.ReadBoolean())
{
return dataIn.ReadUInt16();
}
else
{
return 0;
}
}
}
protected virtual int TightMarshalObjectArray1(
OpenWireFormat wireFormat,
DataStructure[] objects,
BooleanStream bs)
{
if (objects != null)
{
int rc = 0;
bs.WriteBoolean(true);
rc += 2;
for (int i = 0; i < objects.Length; i++)
{
rc += TightMarshalNestedObject1(wireFormat, objects[i], bs);
}
return rc;
}
else
{
bs.WriteBoolean(false);
return 0;
}
}
protected virtual void TightMarshalObjectArray2(
OpenWireFormat wireFormat,
DataStructure[] objects,
BinaryWriter dataOut,
BooleanStream bs)
{
if (bs.ReadBoolean())
{
dataOut.Write((short) objects.Length);
for (int i = 0; i < objects.Length; i++)
{
TightMarshalNestedObject2(wireFormat, objects[i], dataOut, bs);
}
}
}
protected virtual BrokerError TightUnmarshalBrokerError(
OpenWireFormat wireFormat,
BinaryReader dataIn,
BooleanStream bs)
{
if (bs.ReadBoolean())
{
BrokerError answer = new BrokerError();
answer.ExceptionClass = TightUnmarshalString(dataIn, bs);
answer.Message = TightUnmarshalString(dataIn, bs);
if (wireFormat.StackTraceEnabled)
{
short length = dataIn.ReadInt16();
StackTraceElement[] stackTrace = new StackTraceElement[length];
for (int i = 0; i < stackTrace.Length; i++)
{
StackTraceElement element = new StackTraceElement();
element.ClassName = TightUnmarshalString(dataIn, bs);
element.MethodName = TightUnmarshalString(dataIn, bs);
element.FileName = TightUnmarshalString(dataIn, bs);
element.LineNumber = dataIn.ReadInt32();
stackTrace[i] = element;
}
answer.StackTraceElements = stackTrace;
answer.Cause = TightUnmarshalBrokerError(wireFormat, dataIn, bs);
}
return answer;
}
else
{
return null;
}
}
protected int TightMarshalBrokerError1(OpenWireFormat wireFormat, BrokerError o, BooleanStream bs)
{
if (o == null)
{
bs.WriteBoolean(false);
return 0;
}
else
{
int rc = 0;
bs.WriteBoolean(true);
rc += TightMarshalString1(o.ExceptionClass, bs);
rc += TightMarshalString1(o.Message, bs);
if (wireFormat.StackTraceEnabled)
{
rc += 2;
StackTraceElement[] stackTrace = o.StackTraceElements;
for (int i = 0; i < stackTrace.Length; i++)
{
StackTraceElement element = stackTrace[i];
rc += TightMarshalString1(element.ClassName, bs);
rc += TightMarshalString1(element.MethodName, bs);
rc += TightMarshalString1(element.FileName, bs);
rc += 4;
}
rc += TightMarshalBrokerError1(wireFormat, o.Cause, bs);
}
return rc;
}
}
protected void TightMarshalBrokerError2(
OpenWireFormat wireFormat,
BrokerError o,
BinaryWriter dataOut,
BooleanStream bs)
{
if (bs.ReadBoolean())
{
TightMarshalString2(o.ExceptionClass, dataOut, bs);
TightMarshalString2(o.Message, dataOut, bs);
if (wireFormat.StackTraceEnabled)
{
StackTraceElement[] stackTrace = o.StackTraceElements;
dataOut.Write((short) stackTrace.Length);
for (int i = 0; i < stackTrace.Length; i++)
{
StackTraceElement element = stackTrace[i];
TightMarshalString2(element.ClassName, dataOut, bs);
TightMarshalString2(element.MethodName, dataOut, bs);
TightMarshalString2(element.FileName, dataOut, bs);
dataOut.Write(element.LineNumber);
}
TightMarshalBrokerError2(wireFormat, o.Cause, dataOut, bs);
}
}
}
public virtual void LooseMarshal(
OpenWireFormat wireFormat,
Object o,
BinaryWriter dataOut)
{
}
public virtual void LooseUnmarshal(
OpenWireFormat wireFormat,
Object o,
BinaryReader dataIn)
{
}
protected virtual DataStructure LooseUnmarshalNestedObject(
OpenWireFormat wireFormat,
BinaryReader dataIn)
{
return wireFormat.LooseUnmarshalNestedObject(dataIn);
}
protected virtual void LooseMarshalNestedObject(
OpenWireFormat wireFormat,
DataStructure o,
BinaryWriter dataOut)
{
wireFormat.LooseMarshalNestedObject(o, dataOut);
}
protected virtual DataStructure LooseUnmarshalCachedObject(
OpenWireFormat wireFormat,
BinaryReader dataIn)
{
return wireFormat.LooseUnmarshalNestedObject(dataIn);
}
protected virtual void LooseMarshalCachedObject(
OpenWireFormat wireFormat,
DataStructure o,
BinaryWriter dataOut)
{
wireFormat.LooseMarshalNestedObject(o, dataOut);
}
protected virtual String LooseUnmarshalString(BinaryReader dataIn)
{
if (dataIn.ReadBoolean())
{
return dataIn.ReadString();
}
else
{
return null;
}
}
public static void LooseMarshalString(String value, BinaryWriter dataOut)
{
dataOut.Write(value != null);
if (value != null)
{
dataOut.Write(value);
}
}
public virtual void LooseMarshalLong(
OpenWireFormat wireFormat,
long o,
BinaryWriter dataOut)
{
dataOut.Write(o);
}
public virtual long LooseUnmarshalLong(OpenWireFormat wireFormat, BinaryReader dataIn)
{
return dataIn.ReadInt64();
}
protected virtual void LooseMarshalObjectArray(
OpenWireFormat wireFormat,
DataStructure[] objects,
BinaryWriter dataOut)
{
dataOut.Write(objects!=null);
if (objects!=null)
{
dataOut.Write((short) objects.Length);
for (int i = 0; i < objects.Length; i++)
{
LooseMarshalNestedObject(wireFormat, objects[i], dataOut);
}
}
}
protected virtual BrokerError LooseUnmarshalBrokerError(
OpenWireFormat wireFormat,
BinaryReader dataIn)
{
if (dataIn.ReadBoolean())
{
BrokerError answer = new BrokerError();
answer.ExceptionClass = LooseUnmarshalString(dataIn);
answer.Message = LooseUnmarshalString(dataIn);
if (wireFormat.StackTraceEnabled)
{
short length = dataIn.ReadInt16();
StackTraceElement[] stackTrace = new StackTraceElement[length];
for (int i = 0; i < stackTrace.Length; i++)
{
StackTraceElement element = new StackTraceElement();
element.ClassName = LooseUnmarshalString(dataIn);
element.MethodName = LooseUnmarshalString(dataIn);
element.FileName = LooseUnmarshalString(dataIn);
element.LineNumber = dataIn.ReadInt32();
stackTrace[i] = element;
}
answer.StackTraceElements = stackTrace;
answer.Cause = LooseUnmarshalBrokerError(wireFormat, dataIn);
}
return answer;
}
else
{
return null;
}
}
protected void LooseMarshalBrokerError(
OpenWireFormat wireFormat,
BrokerError o,
BinaryWriter dataOut)
{
dataOut.Write(o!=null);
if (o!=null)
{
LooseMarshalString(o.ExceptionClass, dataOut);
LooseMarshalString(o.Message, dataOut);
if (wireFormat.StackTraceEnabled)
{
StackTraceElement[] stackTrace = o.StackTraceElements;
dataOut.Write((short) stackTrace.Length);
for (int i = 0; i < stackTrace.Length; i++)
{
StackTraceElement element = stackTrace[i];
LooseMarshalString(element.ClassName, dataOut);
LooseMarshalString(element.MethodName, dataOut);
LooseMarshalString(element.FileName, dataOut);
dataOut.Write(element.LineNumber);
}
LooseMarshalBrokerError(wireFormat, o.Cause, dataOut);
}
}
}
protected virtual byte[] ReadBytes(BinaryReader dataIn, bool flag)
{
if (flag)
{
int size = dataIn.ReadInt32();
return dataIn.ReadBytes(size);
}
else
{
return null;
}
}
protected virtual byte[] ReadBytes(BinaryReader dataIn)
{
int size = dataIn.ReadInt32();
return dataIn.ReadBytes(size);
}
protected virtual byte[] ReadBytes(BinaryReader dataIn, int size)
{
return dataIn.ReadBytes(size);
}
protected virtual void WriteBytes(byte[] command, BinaryWriter dataOut)
{
dataOut.Write(command.Length);
dataOut.Write(command);
}
protected virtual String ReadAsciiString(BinaryReader dataIn)
{
int size = dataIn.ReadInt16();
byte[] data = new byte[size];
dataIn.Read(data, 0, size);
char[] text = new char[size];
for (int i = 0; i < size; i++)
{
text[i] = (char) data[i];
}
return new String(text);
}
/// <summary>
/// Converts the object to a String
/// </summary>
public static string ToString(MessageId id)
{
return ToString(id.ProducerId) + ":" + id.ProducerSequenceId;
}
/// <summary>
/// Converts the object to a String
/// </summary>
public static string ToString(ProducerId id)
{
return id.ConnectionId + ":" + id.SessionId + ":" + id.Value;
}
/// <summary>
/// Converts the given transaction ID into a String
/// </summary>
public static String ToString(TransactionId txnId)
{
if (txnId is LocalTransactionId)
{
LocalTransactionId ltxnId = (LocalTransactionId) txnId;
return "" + ltxnId.Value;
}
else if (txnId is XATransactionId)
{
XATransactionId xaTxnId = (XATransactionId) txnId;
return "XID:" + xaTxnId.FormatId + ":" + ToHexFromBytes(xaTxnId.GlobalTransactionId) + ":" + ToHexFromBytes(xaTxnId.BranchQualifier);
}
return null;
}
/// <summary>
/// Creates the byte array into hexidecimal
/// </summary>
public static String ToHexFromBytes(byte[] data)
{
StringBuilder buffer = new StringBuilder(data.Length * 2);
for (int i = 0; i < data.Length; i++)
{
buffer.Append(HEX_TABLE[0xFF & data[i]]);
}
return buffer.ToString();
}
}
}