/* * 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 Apache.NMS.Util; using Apache.NMS.XMS.Util; using IBM.XMS; namespace Apache.NMS.XMS { /// /// Represents a message either to be sent to a message broker or received /// from a message broker. /// class Message : Apache.NMS.IMessage { public IBM.XMS.IMessage xmsMessage; #region Constructors /// /// Constructs a Message object. /// /// XMS message. public Message(IBM.XMS.IMessage message) { this.xmsMessage = message; } #endregion #region IMessage Members #region Acknowledgement /// /// If using client acknowledgement mode on the session then this /// method will acknowledge that the message has been processed /// correctly. /// public void Acknowledge() { try { this.xmsMessage.Acknowledge(); } catch(Exception ex) { ExceptionUtil.WrapAndThrowNMSException(ex); } } #endregion #region Message body private bool readOnlyMsgBody = false; /// /// Whether the message body is read-only. /// public virtual bool ReadOnlyBody { get { return this.readOnlyMsgBody; } set { this.readOnlyMsgBody = value; } } /// /// Clears out the message body. Clearing a message's body does not /// clear its header values or property entries. /// If this message body was read-only, calling this method leaves /// the message body in the same state as an empty body in a newly /// created message. /// public void ClearBody() { try { this.ReadOnlyBody = false; this.xmsMessage.ClearBody(); } catch(Exception ex) { ExceptionUtil.WrapAndThrowNMSException(ex); } } #endregion #region Message properties #region General comments // https://docs.oracle.com/cd/E19798-01/821-1841/bnces/index.html // A JMS message has three parts: a header, properties, and a body. // A JMS message header contains a number of predefined fields that // contain values that both clients and providers use to identify // and to route messages: // Header Field Set By // JMSDestination send or publish method // JMSDeliveryMode send or publish method // JMSExpiration send or publish method // JMSPriority send or publish method // JMSMessageID send or publish method // JMSTimestamp send or publish method // JMSCorrelationID Client // JMSReplyTo Client // JMSType Client // JMSRedelivered JMS provider // Properties can be created and set for messages if values are needed // in addition to those provided by the header fields. // The JMS API provides some predefined property names that a provider // can support. The use either of these predefined properties or of // user-defined properties is optional. // The JMS API defines five message body formats: // Message Type Body Contains // TextMessage A java.lang.String object. // MapMessage A set of name-value pairs, with names as String // objects and values as primitive types. // BytesMessage A stream of uninterpreted bytes. // StreamMessage A stream of primitive values, filled and read // sequentially. // ObjectMessage A Serializable object. // Message Nothing. Composed of header fields and properties // only. // // http://www-01.ibm.com/support/knowledgecenter/SSFKSJ_8.0.0/com.ibm.mq.msc.doc/xms_cmesmod.htm?lang=en // The XMS message model is the same as the WebSphere® MQ classes for // JMS message model. // In particular, XMS implements the same message header fields and // message properties that WebSphere MQ classes for JMS implements: // JMS header fields. These fields have names that commence // with the prefix JMS. // JMS defined properties. These fields have properties whose names // commence with the prefix JMSX. // IBM® defined properties. These fields have properties whose names // commence with the prefix JMS_IBM_. // // Apache.NMS redefines JMS message header fields with an "NMS" prefix: // JMS NMS IBM.XMS // Destination JMSDestination IDestination NMSDestination IDestination JMSDestination // int JMSDeliveryMode MsgDeliveryMode NMSDeliveryMode DeliveryMode JMSDeliveryMode // long JMSExpiration [TimeSpan NMSTimeToLive] Int64 JMSExpiration // int JMSPriority MsgPriority NMSPriority Int32 JMSPriority // String JMSMessageID string NMSMessageId String JMSMessageID // long JMSTimestamp DateTime NMSTimestamp Int64 JMSTimestamp // String JMSCorrelationID string NMSCorrelationID String JMSCorrelationID // Destination JMSReplyTo IDestination NMSReplyTo IDestination JMSReplyTo // String JMSType string NMSType String JMSType // boolean JMSRedelivered bool NMSRedelivered Boolean JMSRedelivered // Properties are set and retrieved through typed SetXxxProperty and // GetXxxProperty methods. // Unlike JMS, Apache.NMS does not expose those methods in the // IMessage interface, but through the IPrimitiveMap interface, // implemented by the MessageProperties class, exposed through // the IMessage.Properties property. // The MessagePropertyIntercepter propertyHelper intercepts get and // set invocations on properties whose name starts with "NMS", and // maps them to the equivalent message header fields through // reflection. Other invocations are routed to the // MessageProperties.Get/SetObjetProperty methods, which in turn // invokes xmsMessage.Get/SetObjectProperty. // // XMS message properties are: // XMSC.JMS_DESTINATION = "JMSDestination" // XMSC.JMS_DELIVERY_MODE = "JMSDeliveryMode" // XMSC.JMS_EXPIRATION = "JMSExpiration" // XMSC.JMS_PRIORITY = "JMSPriority" // XMSC.JMS_MESSAGEID = "JMSMessageID" // XMSC.JMS_TIMESTAMP = "JMSTimestamp" // XMSC.JMS_CORRELATIONID = "JMSCorrelationID" // XMSC.JMS_REPLYTO = "JMSReplyto" // XMSC.JMS_TYPE = "JMSType" // XMSC.JMS_REDELIVERED = "JMSRedelivered" // // XMSC.JMSX_USERID = "JMSXUserID" // XMSC.JMSX_APPID = "JMSXAppID" // XMSC.JMSX_DELIVERY_COUNT = "JMSXDeliveryCount" // XMSC.JMSX_GROUPID = "JMSXGroupID" // XMSC.JMSX_GROUPSEQ = "JMSXGroupSeq" // XMSC.JMSX_STATE = "JMSXState" // XMSC.JMSX_PRODUCER_TXID = "JMSXProducerTXID" // XMSC.JMSX_CONSUMER_TXID = "JMSXConsumerTXID" // XMSC.JMSX_RCV_TIMESTAMP = "JMSXRcvTimestamp" // XMSC.JMS_IBM_REPORT_EXCEPTION = "JMS_IBM_Report_Exception" // XMSC.JMS_IBM_REPORT_EXPIRATION = "JMS_IBM_Report_Expiration" // XMSC.JMS_IBM_REPORT_COA = "JMS_IBM_Report_COA" // XMSC.JMS_IBM_REPORT_COD = "JMS_IBM_Report_COD" // XMSC.JMS_IBM_REPORT_NAN = "JMS_IBM_Report_NAN" // XMSC.JMS_IBM_REPORT_PAN = "JMS_IBM_Report_PAN" // XMSC.JMS_IBM_REPORT_PASS_MSG_ID = "JMS_IBM_Report_Pass_Msg_ID" // XMSC.JMS_IBM_REPORT_PASS_CORREL_ID = "JMS_IBM_Report_Pass_Correl_ID" // XMSC.JMS_IBM_REPORT_DISCARD_MSG = "JMS_IBM_Report_Discard_Msg" // XMSC.JMS_IBM_MSGTYPE = "JMS_IBM_MsgType" // XMSC.JMS_IBM_FEEDBACK = "JMS_IBM_Feedback" // XMSC.JMS_IBM_FORMAT = "JMS_IBM_Format" // XMSC.JMS_IBM_PUTAPPLTYPE = "JMS_IBM_PutApplType" // XMSC.JMS_IBM_ENCODING = "JMS_IBM_Encoding" // XMSC.JMS_IBM_CHARACTER_SET = "JMS_IBM_Character_Set" // XMSC.JMS_IBM_PUTDATE = "JMS_IBM_PutDate" // XMSC.JMS_IBM_PUTTIME = "JMS_IBM_PutTime" // XMSC.JMS_IBM_LAST_MSG_IN_GROUP = "JMS_IBM_Last_Msg_In_Group" // XMSC.JMS_IBM_EXCEPTIONREASON = "JMS_IBM_ExceptionReason" // XMSC.JMS_IBM_EXCEPTIONTIMESTAMP = "JMS_IBM_ExceptionTimestamp" // XMSC.JMS_IBM_EXCEPTIONMESSAGE = "JMS_IBM_ExceptionMessage" // XMSC.JMS_IBM_SYSTEM_MESSAGEID = "JMS_IBM_System_MessageID" // XMSC.JMS_IBM_EXCEPTIONPROBLEMDESTINATION = "JMS_IBM_ExceptionProblemDestination" // XMSC.JMS_IBM_ARM_CORRELATOR = "JMS_IBM_ArmCorrelator" // XMSC.JMS_IBM_WAS_RM_CORRELATOR = "JMS_IBM_RMCorrelator" // XMSC.JMS_IBM_CONNECTIONID = "JMS_IBM_ConnectionID" // XMSC.JMS_IBM_RETAIN = "JMS_IBM_Retain" // XMSC.JMS_IBM_MQMD_REPORT = "JMS_IBM_MQMD_Report" // XMSC.JMS_IBM_MQMD_MSGTYPE = "JMS_IBM_MQMD_MsgType" // XMSC.JMS_IBM_MQMD_EXPIRY = "JMS_IBM_MQMD_Expiry" // XMSC.JMS_IBM_MQMD_FEEDBACK = "JMS_IBM_MQMD_Feedback" // XMSC.JMS_IBM_MQMD_ENCODING = "JMS_IBM_MQMD_Encoding" // XMSC.JMS_IBM_MQMD_CODEDCHARSETID = "JMS_IBM_MQMD_CodedCharSetId" // XMSC.JMS_IBM_MQMD_FORMAT = "JMS_IBM_MQMD_Format" // XMSC.JMS_IBM_MQMD_PRIORITY = "JMS_IBM_MQMD_Priority" // XMSC.JMS_IBM_MQMD_PERSISTENCE = "JMS_IBM_MQMD_Persistence" // XMSC.JMS_IBM_MQMD_MSGID = "JMS_IBM_MQMD_MsgId" // XMSC.JMS_IBM_MQMD_CORRELID = "JMS_IBM_MQMD_CorrelId" // XMSC.JMS_IBM_MQMD_BACKOUTCOUNT = "JMS_IBM_MQMD_BackoutCount" // XMSC.JMS_IBM_MQMD_REPLYTOQ = "JMS_IBM_MQMD_ReplyToQ" // XMSC.JMS_IBM_MQMD_REPLYTOQMGR = "JMS_IBM_MQMD_ReplyToQMgr" // XMSC.JMS_IBM_MQMD_USERIDENTIFIER = "JMS_IBM_MQMD_UserIdentifier" // XMSC.JMS_IBM_MQMD_ACCOUNTINGTOKEN = "JMS_IBM_MQMD_AccountingToken" // XMSC.JMS_IBM_MQMD_APPLIDENTITYDATA = "JMS_IBM_MQMD_ApplIdentityData" // XMSC.JMS_IBM_MQMD_PUTAPPLTYPE = "JMS_IBM_MQMD_PutApplType" // XMSC.JMS_IBM_MQMD_PUTAPPLNAME = "JMS_IBM_MQMD_PutApplName" // XMSC.JMS_IBM_MQMD_PUTDATE = "JMS_IBM_MQMD_PutDate" // XMSC.JMS_IBM_MQMD_PUTTIME = "JMS_IBM_MQMD_PutTime" // XMSC.JMS_IBM_MQMD_APPLORIGINDATA = "JMS_IBM_MQMD_ApplOriginData" // XMSC.JMS_IBM_MQMD_GROUPID = "JMS_IBM_MQMD_GroupId" // XMSC.JMS_IBM_MQMD_MSGSEQNUMBER = "JMS_IBM_MQMD_MsgSeqNumber" // XMSC.JMS_IBM_MQMD_OFFSET = "JMS_IBM_MQMD_Offset" // XMSC.JMS_IBM_MQMD_MSGFLAGS = "JMS_IBM_MQMD_MsgFlags" // XMSC.JMS_IBM_MQMD_ORIGINALLENGTH = "JMS_IBM_MQMD_OriginalLength" // XMSC.JMS_TOG_ARM_CORRELATOR = "JMS_TOG_ARM_Correlator" #endregion #region General methods private bool readOnlyMsgProperties = false; /// /// Whether the message properties is read-only. /// public virtual bool ReadOnlyProperties { get { return this.readOnlyMsgProperties; } set { if(this.propertyHelper != null) { this.propertyHelper.ReadOnly = value; } this.readOnlyMsgProperties = value; } } /// /// Clears a message's properties. /// The message's header fields and body are not cleared. /// public void ClearProperties() { try { this.ReadOnlyProperties = false; this.xmsMessage.ClearProperties(); } catch(Exception ex) { ExceptionUtil.WrapAndThrowNMSException(ex); } } private Apache.NMS.IPrimitiveMap properties = null; private Apache.NMS.Util.MessagePropertyIntercepter propertyHelper; /// /// Provides access to the message properties (headers) /// public Apache.NMS.IPrimitiveMap Properties { get { if(properties == null) { properties = XMSConvert.ToMessageProperties(this.xmsMessage); propertyHelper = new Apache.NMS.Util.MessagePropertyIntercepter( this, properties, this.ReadOnlyProperties); } return propertyHelper; } } #endregion #region Message header fields /// /// The correlation ID used to correlate messages from conversations /// or long running business processes. /// public string NMSCorrelationID { get { try { return this.xmsMessage.JMSCorrelationID; } catch(Exception ex) { ExceptionUtil.WrapAndThrowNMSException(ex); return null; } } set { try { this.xmsMessage.JMSCorrelationID = value; } catch(Exception ex) { ExceptionUtil.WrapAndThrowNMSException(ex); } } } /// /// The destination of the message. /// public Apache.NMS.IDestination NMSDestination { get { return XMSConvert.ToNMSDestination( this.xmsMessage.JMSDestination); } set { try { this.xmsMessage.JMSDestination = XMSConvert.ToXMSDestination(value); } catch(Exception ex) { ExceptionUtil.WrapAndThrowNMSException(ex); } } } protected TimeSpan timeToLive; /// /// The amount of time that this message is valid for. /// null if this message does not expire. /// public TimeSpan NMSTimeToLive { get { return this.timeToLive; } set { this.timeToLive = value; } } /// /// The message ID which is set by the provider. /// public string NMSMessageId { get { return this.xmsMessage.JMSMessageID; } set { this.xmsMessage.JMSMessageID = value; } } /// /// Whether or not this message is persistent. /// public MsgDeliveryMode NMSDeliveryMode { get { return XMSConvert.ToNMSMsgDeliveryMode( this.xmsMessage.JMSDeliveryMode); } set { try { this.xmsMessage.JMSDeliveryMode = XMSConvert.ToJMSDeliveryMode(value); } catch(Exception ex) { ExceptionUtil.WrapAndThrowNMSException(ex); } } } /// /// The Priority on this message. /// public MsgPriority NMSPriority { get { return (MsgPriority)this.xmsMessage.JMSPriority; } set { try { this.xmsMessage.JMSPriority = (int)value; } catch(Exception ex) { ExceptionUtil.WrapAndThrowNMSException(ex); } } } /// /// Returns true if this message has been redelivered to this or /// another consumer before being acknowledged successfully. /// public bool NMSRedelivered { get { return this.xmsMessage.JMSRedelivered; } set { throw new NMSException("JMSRedelivered cannot be set."); } } /// /// The destination that the consumer of this message should send /// replies to. /// public Apache.NMS.IDestination NMSReplyTo { get { return XMSConvert.ToNMSDestination( this.xmsMessage.JMSReplyTo); } set { try { this.xmsMessage.JMSReplyTo = XMSConvert.ToXMSDestination(value); } catch(Exception ex) { ExceptionUtil.WrapAndThrowNMSException(ex); } } } /// /// The timestamp of when the message was pubished in UTC time. If the /// publisher disables setting the timestamp on the message, the time /// will be set to the start of the UNIX epoch (1970-01-01 00:00:00). /// public DateTime NMSTimestamp { get { return DateUtils.ToDateTime(this.xmsMessage.JMSTimestamp); } set { this.xmsMessage.JMSTimestamp = DateUtils.ToJavaTime(value); } } /// /// The type name of this message. /// public string NMSType { get { return this.xmsMessage.JMSType; } set { try { this.xmsMessage.JMSType = value; } catch(Exception ex) { ExceptionUtil.WrapAndThrowNMSException(ex); } } } #endregion #endregion #endregion #region Event handlers public virtual void OnSend() { this.ReadOnlyProperties = true; this.ReadOnlyBody = true; } public virtual void OnMessageRollback() { } #endregion } }