| /* |
| * 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.Collections.Generic; |
| using System.Collections; |
| using System.Linq; |
| using System.Text; |
| using System.Threading.Tasks; |
| using System.Reflection; |
| using Apache.NMS; |
| using Amqp.Framing; |
| using Amqp; |
| |
| namespace Apache.NMS.AMQP.Util |
| { |
| class ExceptionSupport |
| { |
| private static readonly Dictionary<string, Type> errTypeMap; |
| |
| static ExceptionSupport() |
| { |
| // mapping of amqp .Net Lite error code to NMS exception type |
| |
| errTypeMap = new Dictionary<string, Type>(); |
| errTypeMap.Add(NMSErrorCode.CONNECTION_TIME_OUT, typeof(NMSConnectionException)); |
| errTypeMap.Add(ErrorCode.ConnectionRedirect, typeof(NMSConnectionException)); |
| errTypeMap.Add(ErrorCode.ConnectionForced, typeof(NMSConnectionException)); |
| errTypeMap.Add(ErrorCode.IllegalState, typeof(IllegalStateException)); |
| |
| errTypeMap.Add(NMSErrorCode.INTERNAL_ERROR, typeof(NMSException)); |
| errTypeMap.Add(NMSErrorCode.UNKNOWN_ERROR, typeof(NMSException)); |
| errTypeMap.Add(NMSErrorCode.SESSION_TIME_OUT, typeof(NMSException)); |
| errTypeMap.Add(NMSErrorCode.LINK_TIME_OUT, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.DecodeError, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.DetachForced, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.ErrantLink, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.FrameSizeTooSmall, typeof(NMSConnectionException)); |
| errTypeMap.Add(ErrorCode.FramingError, typeof(NMSConnectionException)); |
| errTypeMap.Add(ErrorCode.HandleInUse, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.InternalError, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.InvalidField, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.LinkRedirect, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.MessageReleased, typeof(IllegalStateException)); |
| errTypeMap.Add(ErrorCode.MessageSizeExceeded, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.NotAllowed, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.NotFound, typeof(InvalidDestinationException)); |
| errTypeMap.Add(ErrorCode.NotImplemented, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.PreconditionFailed, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.ResourceDeleted, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.ResourceLimitExceeded, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.ResourceLocked, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.Stolen, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.TransactionRollback, typeof(TransactionRolledBackException)); |
| errTypeMap.Add(ErrorCode.TransactionTimeout, typeof(TransactionInProgressException)); |
| errTypeMap.Add(ErrorCode.TransactionUnknownId, typeof(TransactionRolledBackException)); |
| errTypeMap.Add(ErrorCode.TransferLimitExceeded, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.UnattachedHandle, typeof(NMSException)); |
| errTypeMap.Add(ErrorCode.UnauthorizedAccess, typeof(NMSSecurityException)); |
| errTypeMap.Add(ErrorCode.WindowViolation, typeof(NMSException)); |
| |
| } |
| |
| private static FieldInfo[] GetConstants(Type type) |
| { |
| ArrayList list = new ArrayList(); |
| FieldInfo[] fields = type.GetFields( |
| BindingFlags.Static | |
| BindingFlags.Public | |
| BindingFlags.FlattenHierarchy |
| ); |
| foreach (FieldInfo field in fields) |
| { |
| if (field.IsLiteral && !field.IsInitOnly) |
| list.Add(field); |
| } |
| return (FieldInfo[])list.ToArray(typeof(FieldInfo)); |
| } |
| |
| private static string[] GetStringConstants(Type type) |
| { |
| FieldInfo[] fields = GetConstants(type); |
| ArrayList list = new ArrayList(fields.Length); |
| foreach(FieldInfo fi in fields) |
| { |
| if (fi.FieldType.Equals(typeof(string))) |
| { |
| list.Add(fi.GetValue(null)); |
| } |
| } |
| return (string[])list.ToArray(typeof(string)); |
| } |
| |
| public static NMSException GetTimeoutException(IAmqpObject obj, string format, params object[] args) |
| { |
| return GetTimeoutException(obj, string.Format(format, args)); |
| } |
| |
| public static NMSException GetTimeoutException(IAmqpObject obj, string message) |
| { |
| Error e = null; |
| if (obj is Amqp.Connection) |
| { |
| e = NMSError.CONNECTION_TIMEOUT; |
| } |
| else if (obj is Amqp.Session) |
| { |
| e = NMSError.SESSION_TIMEOUT; |
| } |
| else if (obj is Amqp.Link) |
| { |
| e = NMSError.LINK_TIMEOUT; |
| } |
| |
| return GetException(e, message); |
| |
| } |
| |
| public static NMSException GetException(IAmqpObject obj, string format, params object[] args) |
| { |
| return GetException(obj, string.Format(format, args)); |
| } |
| |
| public static NMSException GetException(Error amqpErr, string format, params object[] args) |
| { |
| return GetException(amqpErr, string.Format(format, args)); |
| } |
| |
| public static NMSException GetException(IAmqpObject obj, string message="") |
| { |
| return GetException(obj.Error, message); |
| } |
| |
| public static NMSException GetException(Error amqpErr, string message = "", Exception e = null) |
| { |
| string errCode = null; |
| string errMessage = null; |
| string additionalErrInfo = null; |
| if (amqpErr == null) |
| { |
| amqpErr = NMSError.INTERNAL; |
| } |
| |
| errCode = amqpErr.Condition.ToString(); |
| errMessage = amqpErr.Description; |
| |
| errMessage = errMessage != null ? ", Description = " + errMessage : ""; |
| |
| if (amqpErr.Info != null && amqpErr.Info.Count > 0) |
| { |
| additionalErrInfo = ", ErrorInfo = " + Types.ConversionSupport.ToString(amqpErr.Info); |
| } |
| if (null == e) |
| { |
| // no exception given, create a NMSunthrownException to hold the |
| // stack and use it as the innerException in the constructors for |
| // the NMSexception we create., the custom StackTrace() will allow exception listeners to |
| // see the stack to here |
| e = new NMSProviderError(errCode, errMessage); |
| } |
| NMSException ex = null; |
| Type exType = null; |
| if(errTypeMap.TryGetValue(errCode, out exType)) |
| { |
| ConstructorInfo ci = exType.GetConstructor(new[] { typeof(string), typeof(string), typeof(Exception) }); |
| object inst = ci.Invoke(new object[] { message + errMessage + additionalErrInfo , errCode, e }); |
| ex = inst as NMSException; |
| } |
| else |
| { |
| ex = new NMSException(message + errMessage + additionalErrInfo, errCode, e); |
| } |
| return ex; |
| |
| } |
| |
| public static NMSException Wrap(Exception e, string format, params object[] args) |
| { |
| return Wrap(e, string.Format(format, args)); |
| } |
| |
| public static NMSException Wrap(Exception e, string message = "") |
| { |
| if(e == null) |
| { |
| return null; |
| } |
| NMSException nmsEx = null; |
| string exMessage = message; |
| if (exMessage == null || exMessage.Length == 0) |
| { |
| exMessage = e.Message; |
| } |
| if (e is NMSException) |
| { |
| return e as NMSException; |
| } |
| else if (e is AmqpException) |
| { |
| Error err = (e as AmqpException).Error; |
| nmsEx = GetException(err, message, e); |
| Tracer.DebugFormat("Encoutered AmqpException {0} and created NMS Exception {1}.", e, nmsEx); |
| } |
| else |
| { |
| nmsEx = new NMSException(exMessage, NMSErrorCode.INTERNAL_ERROR, e); |
| } |
| |
| return nmsEx; |
| } |
| |
| } |
| |
| #region Exceptions |
| |
| |
| public class InvalidPropertyException : NMSException |
| { |
| protected static string ExFormat = "Invalid Property {0}. Cause: {1}"; |
| |
| public InvalidPropertyException(string property, string message) : base(string.Format(ExFormat, property, message)) |
| { |
| exceptionErrorCode = NMSErrorCode.PROPERTY_ERROR; |
| } |
| } |
| // The API converts AMPQ Errors to NMSProviderError. This is typically added to |
| // the Exception queue and passed to the ExceptionListener. As the Exception is |
| // instantiated but never thrown, it does not have an exception-stack trace. We add |
| // one to the private member InstanceTrace and override StackTrace so useful |
| // information can be displayed. |
| |
| internal class NMSProviderError : NMSException |
| { |
| private string InstanceTrace; |
| |
| public NMSProviderError() : base() |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(1, true); |
| InstanceTrace = trace.ToString(); |
| } |
| |
| public NMSProviderError(string message) : base(message) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(1, true); |
| InstanceTrace = trace.ToString(); |
| } |
| |
| public NMSProviderError(string message, string errorCode) : base(message, errorCode) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(1, true); |
| InstanceTrace = trace.ToString(); |
| } |
| |
| public NMSProviderError(string message, NMSException innerException) : base(message, innerException) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(1, true); |
| InstanceTrace = trace.ToString(); |
| exceptionErrorCode = innerException.ErrorCode ?? NMSErrorCode.INTERNAL_ERROR; |
| } |
| |
| public NMSProviderError(string message, Exception innerException) : base(message, innerException) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(1, true); |
| InstanceTrace = trace.ToString(); |
| } |
| |
| public NMSProviderError(string message, string errorCode, Exception innerException) : base(message, errorCode, innerException) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(1, true); |
| InstanceTrace = trace.ToString(); |
| } |
| |
| public override string StackTrace |
| { |
| get |
| { |
| string stack = base.StackTrace; |
| if (stack == null || stack.Length == 0) |
| { |
| stack = InstanceTrace; |
| } |
| if (InnerException != null && (InnerException.StackTrace != null && InnerException.StackTrace.Length > 0)) |
| { |
| stack += "\nCause " + InnerException.Message + " : \n" + |
| InnerException.StackTrace; |
| |
| } |
| return stack; |
| } |
| } |
| } |
| |
| #endregion |
| |
| #region Error Codes |
| |
| internal static class NMSError |
| { |
| public static Error SESSION_TIMEOUT = new Error(NMSErrorCode.SESSION_TIME_OUT) { Description = "Session Begin Request has timed out." }; |
| public static Error CONNECTION_TIMEOUT = new Error(NMSErrorCode.SESSION_TIME_OUT) { Description = "Connection Open Request has timed out." }; |
| public static Error LINK_TIMEOUT = new Error(NMSErrorCode.SESSION_TIME_OUT) { Description = "Link Attach Request has timed out." }; |
| public static Error PROPERTY = new Error(NMSErrorCode.PROPERTY_ERROR) { Description = "Property Error." }; |
| public static Error UNKNOWN = new Error(NMSErrorCode.UNKNOWN_ERROR) { Description = "Unknown Error." }; |
| public static Error INTERNAL = new Error(NMSErrorCode.INTERNAL_ERROR) { Description = "Internal Error." }; |
| |
| } |
| internal static class NMSErrorCode |
| { |
| public static string CONNECTION_TIME_OUT = "nms:connection:timout"; |
| public static string SESSION_TIME_OUT = "nms:session:timout"; |
| public static string LINK_TIME_OUT = "nms:link:timeout"; |
| public static string PROPERTY_ERROR = "nms:property:error"; |
| public static string UNKNOWN_ERROR = "nms:unknown"; |
| public static string INTERNAL_ERROR = "nms:internal"; |
| } |
| |
| #endregion |
| } |