/* * 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 { /// /// A base class with useful implementation inheritence methods /// for creating marshallers of the OpenWire protocol /// 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); } /// /// Converts the object to a String /// public static string ToString(MessageId id) { return ToString(id.ProducerId) + ":" + id.ProducerSequenceId; } /// /// Converts the object to a String /// public static string ToString(ProducerId id) { return id.ConnectionId + ":" + id.SessionId + ":" + id.Value; } /// /// Converts the given transaction ID into a String /// 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; } /// /// Creates the byte array into hexidecimal /// 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(); } } }