diff --git a/openwire-dotnet/src/OpenWire.Client/BrokerException.cs b/openwire-dotnet/src/OpenWire.Client/BrokerException.cs index 974987a689..e250c6921a 100755 --- a/openwire-dotnet/src/OpenWire.Client/BrokerException.cs +++ b/openwire-dotnet/src/OpenWire.Client/BrokerException.cs @@ -19,15 +19,34 @@ using System.Collections; using OpenWire.Client.Commands; using OpenWire.Client.Core; -namespace OpenWire.Client { - /// - /// Exception thrown when the broker returns an error - /// - public class BrokerException : OpenWireException { - public BrokerException(BrokerError cause) : base("The operation failed: Type: " - + cause.ExceptionClass - + " stack: " - + cause.StackTrace) { - } - } +namespace OpenWire.Client +{ + /// + /// Exception thrown when the broker returns an error + /// + public class BrokerException : OpenWireException + { + + private BrokerError brokerError; + + public BrokerException(BrokerError brokerError) : base( + brokerError.ExceptionClass + " : " + brokerError.Message) + { + this.brokerError = brokerError; + } + + public BrokerError BrokerError { + get { + return brokerError; + } + } + + public virtual string StackTrace + { + get { + return brokerError.StackTrace; + } + } + + } } diff --git a/openwire-dotnet/src/OpenWire.Client/Commands/Message.cs b/openwire-dotnet/src/OpenWire.Client/Commands/Message.cs index 2652563349..8f9e3e3a0e 100644 --- a/openwire-dotnet/src/OpenWire.Client/Commands/Message.cs +++ b/openwire-dotnet/src/OpenWire.Client/Commands/Message.cs @@ -1,19 +1,19 @@ /* - * Copyright 2006 The Apache Software Foundation or its licensors, as - * applicable. - * - * 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. - */ +* Copyright 2006 The Apache Software Foundation or its licensors, as +* applicable. +* +* 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. +*/ using System; using System.Collections; diff --git a/openwire-dotnet/src/OpenWire.Client/Commands/TransactionId.cs b/openwire-dotnet/src/OpenWire.Client/Commands/TransactionId.cs index 87387dbc55..55e4bcb7b0 100644 --- a/openwire-dotnet/src/OpenWire.Client/Commands/TransactionId.cs +++ b/openwire-dotnet/src/OpenWire.Client/Commands/TransactionId.cs @@ -1,19 +1,19 @@ /* - * Copyright 2006 The Apache Software Foundation or its licensors, as - * applicable. - * - * 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. - */ +* Copyright 2006 The Apache Software Foundation or its licensors, as +* applicable. +* +* 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. +*/ using System; using System.Collections; @@ -34,44 +34,42 @@ namespace OpenWire.Client.Commands public class TransactionId : AbstractCommand { public const byte ID_TransactionId = 0; - - - public override int GetHashCode() - { + + + public override int GetHashCode() { int answer = 0; return answer; - - } - - - public override bool Equals(object that) - { - if (that is TransactionId) - { - return Equals((TransactionId) that); - } - return false; - } - - public virtual bool Equals(TransactionId that) - { + + } + + + public override bool Equals(object that) { + if (that is TransactionId) { + return Equals((TransactionId) that); + } + return false; + } + + public virtual bool Equals(TransactionId that) { return true; - - } - - - public override string ToString() - { + + } + + + public override string ToString() { return GetType().Name + "[" + " ]"; - - } - - - - public override byte GetDataStructureType() - { + + } + + + + public override byte GetDataStructureType() { return ID_TransactionId; } + + + // Properties + } } diff --git a/openwire-dotnet/src/OpenWire.Client/Commands/WireFormatInfo.cs b/openwire-dotnet/src/OpenWire.Client/Commands/WireFormatInfo.cs index 9f6628cebb..e6e25cb7aa 100644 --- a/openwire-dotnet/src/OpenWire.Client/Commands/WireFormatInfo.cs +++ b/openwire-dotnet/src/OpenWire.Client/Commands/WireFormatInfo.cs @@ -37,13 +37,19 @@ namespace OpenWire.Client.Commands byte[] magic; int version; - int options; + bool cacheEnabled; + bool compressionEnabled; + bool stackTraceEnabled; + bool tcpNoDelayEnabled; public override string ToString() { return GetType().Name + "[" + " Magic=" + Magic + " Version=" + Version - + " Options=" + Options + + " CacheEnabled=" + CacheEnabled + + " CompressionEnabled=" + CompressionEnabled + + " StackTraceEnabled=" + StackTraceEnabled + + " TcpNoDelayEnabled=" + TcpNoDelayEnabled + " ]"; } @@ -69,10 +75,28 @@ namespace OpenWire.Client.Commands set { this.version = value; } } - public int Options + public bool CacheEnabled { - get { return options; } - set { this.options = value; } + get { return cacheEnabled; } + set { this.cacheEnabled = value; } + } + + public bool CompressionEnabled + { + get { return compressionEnabled; } + set { this.compressionEnabled = value; } + } + + public bool StackTraceEnabled + { + get { return stackTraceEnabled; } + set { this.stackTraceEnabled = value; } + } + + public bool TcpNoDelayEnabled + { + get { return tcpNoDelayEnabled; } + set { this.tcpNoDelayEnabled = value; } } } diff --git a/openwire-dotnet/src/OpenWire.Client/Connection.cs b/openwire-dotnet/src/OpenWire.Client/Connection.cs index 330a636006..d6b60c0f8e 100755 --- a/openwire-dotnet/src/OpenWire.Client/Connection.cs +++ b/openwire-dotnet/src/OpenWire.Client/Connection.cs @@ -10,11 +10,8 @@ namespace OpenWire.Client /// public class Connection : IConnection { - static private char[] MAGIC = new char[] { 'A', 'c', 't', 'i', 'v', 'e', 'M', 'Q' }; - private ITransport transport; private ConnectionInfo info; - private WireFormatInfo wireFormatInfo = new WireFormatInfo(); private BrokerInfo brokerInfo; // from broker private WireFormatInfo brokerWireFormatInfo; // from broker private IList sessions = new ArrayList(); @@ -165,11 +162,6 @@ namespace OpenWire.Client } if (!connected) { - // lets configure the wire format - wireFormatInfo.Magic = CreateMagicBytes(); - wireFormatInfo.Version = 1; - transport.Oneway(wireFormatInfo); - // now lets send the connection and see if we get an ack/nak SyncRequest(info); connected = true; @@ -230,19 +222,6 @@ namespace OpenWire.Client Console.WriteLine("ERROR:ÊUnknown command: " + command); } } - - /// - /// Method CreateMagicBytes - /// - /// A byte[] - private byte[] CreateMagicBytes() - { - byte[] answer = new byte[MAGIC.Length]; - for (int i = 0; i < answer.Length; i++) - { - answer[i] = (byte) MAGIC[i]; - } - return answer; - } + } } diff --git a/openwire-dotnet/src/OpenWire.Client/Core/BrokerError.cs b/openwire-dotnet/src/OpenWire.Client/Core/BrokerError.cs index b7e49a2b3e..a58a2a02f4 100755 --- a/openwire-dotnet/src/OpenWire.Client/Core/BrokerError.cs +++ b/openwire-dotnet/src/OpenWire.Client/Core/BrokerError.cs @@ -15,30 +15,76 @@ * limitations under the License. */ using System; +using System.Text; using OpenWire.Client.Core; +using System.IO; -namespace OpenWire.Client.Core { - /// - /// Represents an exception on the broker - /// - public class BrokerError : AbstractCommand { - private string message; - private string exceptionClass; - private string stackTrace; - - public string Message { - get { return message; } - set { message = value; } - } - - public string ExceptionClass { - get { return exceptionClass; } - set { exceptionClass = value; } - } - - public string StackTrace { - get { return stackTrace; } - set { stackTrace = value; } - } - } +namespace OpenWire.Client.Core +{ + public struct StackTraceElement + { + public string ClassName; + public string FileName; + public string MethodName; + public int LineNumber; + } + + + /// + /// Represents an exception on the broker + /// + public class BrokerError : AbstractCommand + { + private string message; + private string exceptionClass; + private StackTraceElement[] stackTraceElements = {}; + private BrokerError cause; + + public string Message + { + get { return message; } + set { message = value; } + } + + public string ExceptionClass + { + get { return exceptionClass; } + set { exceptionClass = value; } + } + + public StackTraceElement[] StackTraceElements + { + get { return stackTraceElements; } + set { stackTraceElements = value; } + } + + public BrokerError Cause + { + get { return cause; } + set { cause = value; } + } + + public String StackTrace { + get { + StringWriter writer = new StringWriter(); + PrintStackTrace(writer); + return writer.ToString(); + } + } + + public void PrintStackTrace(TextWriter writer) + { + writer.WriteLine(exceptionClass + ": " + message); + for (int i = 0; i < stackTraceElements.Length; i++) + { + StackTraceElement element = stackTraceElements[i]; + writer.WriteLine(" at " + element.ClassName + "." + element.MethodName + "(" + element.FileName + ":" + element.LineNumber + ")"); + } + if (cause != null) + { + writer.WriteLine("Nested Exception:"); + cause.PrintStackTrace(writer); + } + } + } } diff --git a/openwire-dotnet/src/OpenWire.Client/Core/DataStreamMarshaller.cs b/openwire-dotnet/src/OpenWire.Client/Core/DataStreamMarshaller.cs index 557388c7f2..5878c9a53e 100755 --- a/openwire-dotnet/src/OpenWire.Client/Core/DataStreamMarshaller.cs +++ b/openwire-dotnet/src/OpenWire.Client/Core/DataStreamMarshaller.cs @@ -525,12 +525,26 @@ namespace OpenWire.Client.Core { if (bs.ReadBoolean()) { - String clazz = ReadString(dataIn, bs); - String message = ReadString(dataIn, bs); - BrokerError answer = new BrokerError(); - answer.ExceptionClass = clazz; - answer.Message = message; + + answer.ExceptionClass = ReadString(dataIn, bs); + answer.Message = ReadString(dataIn, bs); + if (wireFormat.StackTraceEnabled) + { + short length = ReadShort(dataIn); + StackTraceElement[] stackTrace = new StackTraceElement[length]; + for (int i = 0; i < stackTrace.Length; i++) + { + StackTraceElement element = new StackTraceElement(); + element.ClassName = ReadString(dataIn, bs); + element.MethodName = ReadString(dataIn, bs); + element.FileName = ReadString(dataIn, bs); + element.LineNumber = ReadInt(dataIn); + stackTrace[i] = element; + } + answer.StackTraceElements = stackTrace; + answer.Cause = UnmarshalBrokerError(wireFormat, dataIn, bs); + } return answer; } else @@ -552,6 +566,21 @@ namespace OpenWire.Client.Core bs.WriteBoolean(true); rc += WriteString(o.ExceptionClass, bs); rc += WriteString(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 += WriteString(element.ClassName, bs); + rc += WriteString(element.MethodName, bs); + rc += WriteString(element.FileName, bs); + rc += 4; + } + rc += MarshalBrokerError(wireFormat, o.Cause, bs); + } + return rc; } } @@ -566,6 +595,21 @@ namespace OpenWire.Client.Core { WriteString(o.ExceptionClass, dataOut, bs); WriteString(o.Message, dataOut, bs); + if (wireFormat.StackTraceEnabled) + { + StackTraceElement[] stackTrace = o.StackTraceElements; + WriteShort((short) stackTrace.Length, dataOut); + + for (int i = 0; i < stackTrace.Length; i++) + { + StackTraceElement element = stackTrace[i]; + WriteString(element.ClassName, dataOut, bs); + WriteString(element.MethodName, bs); + WriteString(element.FileName, bs); + WriteInt(element.LineNumber, dataOut); + } + MarshalBrokerError(wireFormat, o.Cause, dataOut, bs); + } } } diff --git a/openwire-dotnet/src/OpenWire.Client/Core/OpenWireFormat.cs b/openwire-dotnet/src/OpenWire.Client/Core/OpenWireFormat.cs index 0d4f6c4d6c..3bd24f3437 100755 --- a/openwire-dotnet/src/OpenWire.Client/Core/OpenWireFormat.cs +++ b/openwire-dotnet/src/OpenWire.Client/Core/OpenWireFormat.cs @@ -28,17 +28,37 @@ namespace OpenWire.Client.Core /// public class OpenWireFormat { + static private char[] MAGIC = new char[] { 'A', 'c', 't', 'i', 'v', 'e', 'M', 'Q' }; + private DataStreamMarshaller[] dataMarshallers; private const byte NULL_TYPE = 0; - + private WireFormatInfo wireFormatInfo = new WireFormatInfo(); public OpenWireFormat() { + // lets configure the wire format + wireFormatInfo.Magic = CreateMagicBytes(); + wireFormatInfo.Version = 1; + wireFormatInfo.StackTraceEnabled = true; + wireFormatInfo.TcpNoDelayEnabled = true; + dataMarshallers = new DataStreamMarshaller[256]; MarshallerFactory factory = new MarshallerFactory(); factory.configure(this); } + public WireFormatInfo WireFormatInfo { + get { + return wireFormatInfo; + } + } + + public bool StackTraceEnabled { + get { + return wireFormatInfo.StackTraceEnabled; + } + } + public void addMarshaller(DataStreamMarshaller marshaller) { byte type = marshaller.GetDataStructureType(); @@ -182,5 +202,19 @@ namespace OpenWire.Client.Core return null; } } + + /// + /// Method CreateMagicBytes + /// + /// A byte[] + private byte[] CreateMagicBytes() + { + byte[] answer = new byte[MAGIC.Length]; + for (int i = 0; i < answer.Length; i++) + { + answer[i] = (byte) MAGIC[i]; + } + return answer; + } } } diff --git a/openwire-dotnet/src/OpenWire.Client/Core/SocketTransport.cs b/openwire-dotnet/src/OpenWire.Client/Core/SocketTransport.cs index fd60a4ce95..ed58030747 100755 --- a/openwire-dotnet/src/OpenWire.Client/Core/SocketTransport.cs +++ b/openwire-dotnet/src/OpenWire.Client/Core/SocketTransport.cs @@ -70,14 +70,13 @@ namespace OpenWire.Client.Core NetworkStream networkStream = new NetworkStream(socket); socketWriter = new BinaryWriter(networkStream); socketReader = new BinaryReader(networkStream); - /* - socketWriter = new BinaryWriter(new NetworkStream(socket)); - socketReader = new BinaryReader(new NetworkStream(socket)); - */ // now lets create the background read thread readThread = new Thread(new ThreadStart(ReadLoop)); readThread.Start(); + + // lets send the wireformat we're using + Oneway(wireformat.WireFormatInfo); } } @@ -101,8 +100,16 @@ namespace OpenWire.Client.Core public Response Request(Command command) { - FutureResponse response = AsyncRequest(command); - return response.Response; + FutureResponse future = AsyncRequest(command); + Response response = future.Response; + if (response is ExceptionResponse) + { + ExceptionResponse er = (ExceptionResponse) response; + BrokerError brokerError = er.Exception; + throw new BrokerException(brokerError); + } + + return response; } public void Dispose() @@ -149,20 +156,13 @@ namespace OpenWire.Client.Core if (response is ExceptionResponse) { ExceptionResponse er = (ExceptionResponse) response; - Exception e = new BrokerException(er.Exception); + BrokerError brokerError = er.Exception; if (this.Exception != null) { - this.Exception(this, e); - } - else - { - throw e; + this.Exception(this, new BrokerException(brokerError)); } } - else - { - future.Response = response; - } + future.Response = response; } else { diff --git a/openwire-dotnet/src/OpenWire.Client/IO/WireFormatInfoMarshaller.cs b/openwire-dotnet/src/OpenWire.Client/IO/WireFormatInfoMarshaller.cs index 585c962160..f50f908d61 100644 --- a/openwire-dotnet/src/OpenWire.Client/IO/WireFormatInfoMarshaller.cs +++ b/openwire-dotnet/src/OpenWire.Client/IO/WireFormatInfoMarshaller.cs @@ -58,7 +58,10 @@ namespace OpenWire.Client.IO WireFormatInfo info = (WireFormatInfo)o; info.Magic = ReadBytes(dataIn, 8); info.Version = DataStreamMarshaller.ReadInt(dataIn); - info.Options = DataStreamMarshaller.ReadInt(dataIn); + info.CacheEnabled = bs.ReadBoolean(); + info.CompressionEnabled = bs.ReadBoolean(); + info.StackTraceEnabled = bs.ReadBoolean(); + info.TcpNoDelayEnabled = bs.ReadBoolean(); } @@ -70,8 +73,12 @@ namespace OpenWire.Client.IO WireFormatInfo info = (WireFormatInfo)o; int rc = base.Marshal1(wireFormat, info, bs); - - return rc + 10; + bs.WriteBoolean(info.CacheEnabled); + bs.WriteBoolean(info.CompressionEnabled); + bs.WriteBoolean(info.StackTraceEnabled); + bs.WriteBoolean(info.TcpNoDelayEnabled); + + return rc + 9; } // @@ -83,7 +90,10 @@ namespace OpenWire.Client.IO WireFormatInfo info = (WireFormatInfo)o; dataOut.Write(info.Magic, 0, 8); DataStreamMarshaller.WriteInt(info.Version, dataOut); - DataStreamMarshaller.WriteInt(info.Options, dataOut); + bs.ReadBoolean(); + bs.ReadBoolean(); + bs.ReadBoolean(); + bs.ReadBoolean(); } } diff --git a/openwire-dotnet/tests/OpenWire.Client/BadConsumeTest.cs b/openwire-dotnet/tests/OpenWire.Client/BadConsumeTest.cs new file mode 100644 index 0000000000..5a6b81c9f1 --- /dev/null +++ b/openwire-dotnet/tests/OpenWire.Client/BadConsumeTest.cs @@ -0,0 +1,31 @@ +using NUnit.Framework; +using System; + +namespace OpenWire.Client +{ + [TestFixture] + public class BadConsumeTest : TestSupport + { + [Test] + public void TestBadConsumeOperationToTestExceptions() + { + IConnectionFactory factory = new ConnectionFactory("localhost", 61616); + using (IConnection connection = factory.CreateConnection()) + { + ISession session = connection.CreateSession(); + + try + { + IMessageConsumer consumer = session.CreateConsumer(null); + Assert.Fail("Should have thrown an exception!"); + } + catch (BrokerException e) + { + Console.WriteLine("Caught expected exception: " + e); + Console.WriteLine("Stack: " + e.StackTrace); + Console.WriteLine("BrokerStrack: " + e.BrokerError.StackTrace); + } + } + } + } +} diff --git a/openwire-dotnet/tests/OpenWire.Client/TestSupport.cs b/openwire-dotnet/tests/OpenWire.Client/TestSupport.cs index e5ddcd58af..56ade1e710 100644 --- a/openwire-dotnet/tests/OpenWire.Client/TestSupport.cs +++ b/openwire-dotnet/tests/OpenWire.Client/TestSupport.cs @@ -33,7 +33,6 @@ namespace OpenWire.Client public abstract class TestSupport { - [ Test ] public virtual void SendAndSyncReceive() { IConnectionFactory factory = new ConnectionFactory("localhost", 61616); @@ -81,8 +80,12 @@ namespace OpenWire.Client return destination; } - protected abstract IMessage CreateMessage(ISession session); + protected virtual IMessage CreateMessage(ISession session) { + return session.CreateMessage(); + } - protected abstract void AssertValidMessage(IMessage message); + protected virtual void AssertValidMessage(IMessage message) { + Assert.IsNotNull(message, "Null Message!"); + } } }