0001: /*
0002: * JBoss, Home of Professional Open Source.
0003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
0004: * as indicated by the @author tags. See the copyright.txt file in the
0005: * distribution for a full listing of individual contributors.
0006: *
0007: * This is free software; you can redistribute it and/or modify it
0008: * under the terms of the GNU Lesser General Public License as
0009: * published by the Free Software Foundation; either version 2.1 of
0010: * the License, or (at your option) any later version.
0011: *
0012: * This software is distributed in the hope that it will be useful,
0013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0015: * Lesser General Public License for more details.
0016: *
0017: * You should have received a copy of the GNU Lesser General Public
0018: * License along with this software; if not, write to the Free
0019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
0021: */
0022: package org.jboss.mq;
0023:
0024: import java.io.Externalizable;
0025: import java.io.IOException;
0026: import java.io.ObjectInput;
0027: import java.io.ObjectOutput;
0028: import java.io.Serializable;
0029: import java.util.Collections;
0030: import java.util.Enumeration;
0031: import java.util.HashMap;
0032: import java.util.HashSet;
0033: import java.util.Map;
0034:
0035: import javax.jms.Destination;
0036: import javax.jms.JMSException;
0037: import javax.jms.Message;
0038: import javax.jms.MessageFormatException;
0039: import javax.jms.MessageNotWriteableException;
0040: import javax.jms.Session;
0041:
0042: import org.jboss.util.Primitives;
0043: import org.jboss.util.Strings;
0044:
0045: /**
0046: * This class implements javax.jms.Message
0047: *
0048: * @author Norbert Lataille (Norbert.Lataille@m4x.org)
0049: * @author Hiram Chirino (Cojonudo14@hotmail.com)
0050: * @author David Maplesden (David.Maplesden@orion.co.nz)
0051: * @author <a href="mailto:adrian@jboss.org">Adrian Brock</a>
0052: * @version $Revision: 57198 $
0053: */
0054: public class SpyMessage implements Serializable, Message, Comparable,
0055: Cloneable, Externalizable {
0056: // Constants -----------------------------------------------------
0057:
0058: /** The serialVersionUID */
0059: private final static long serialVersionUID = 467206190892964404L;
0060:
0061: /**
0062: * Standard property for delivery count
0063: */
0064: public static final String PROPERTY_DELIVERY_COUNT = "JMSXDeliveryCount";
0065:
0066: /**
0067: * JBoss-vendor specific property for scheduling a JMS message. In
0068: * milliseconds since January 1, 1970.
0069: */
0070: public static final String PROPERTY_SCHEDULED_DELIVERY = "JMS_JBOSS_SCHEDULED_DELIVERY";
0071:
0072: /**
0073: * JBoss-vendor specific property specifying redelivery delay of a message.
0074: * The message will be rescheduled for delivery from the time at which it
0075: * was unacknowledged, plus the given period.
0076: */
0077: public static final String PROPERTY_REDELIVERY_DELAY = "JMS_JBOSS_REDELIVERY_DELAY";
0078:
0079: /**
0080: * JBoss-vendor specific property for getting the count of redelivery
0081: * attempts of a message.
0082: */
0083: public static final String PROPERTY_REDELIVERY_COUNT = "JMS_JBOSS_REDELIVERY_COUNT";
0084:
0085: /**
0086: * JBoss-vendor specific property specifying the limit of redelivery
0087: * attempts of a message. The message will be redelivered a given number of
0088: * times. If not set, the container default is used.
0089: */
0090: public static final String PROPERTY_REDELIVERY_LIMIT = "JMS_JBOSS_REDELIVERY_LIMIT";
0091:
0092: /**
0093: * JBoss-vendor property name holding original destination.
0094: */
0095: public static final String PROPERTY_ORIG_DESTINATION = "JBOSS_ORIG_DESTINATION";
0096:
0097: /**
0098: * JBoss-vendor property name holding original expiration value.
0099: */
0100: public static final String PROPERTY_ORIG_EXPIRATION = "JBOSS_ORIG_EXPIRATION";
0101:
0102: /**
0103: * JBoss-vendor property name holding original message ID value.
0104: */
0105: public static final String PROPERTY_ORIG_MESSAGEID = "JBOSS_ORIG_MESSAGEID";
0106:
0107: /** An object message */
0108: protected static final byte OBJECT_MESS = 1;
0109: /** An bytes message */
0110: protected static final byte BYTES_MESS = 2;
0111: /** A map message */
0112: protected static final byte MAP_MESS = 3;
0113: /** A text message */
0114: protected static final byte TEXT_MESS = 4;
0115: /** A stream message */
0116: protected static final byte STREAM_MESS = 5;
0117: /** An encapsulated message */
0118: protected static final byte ENCAP_MESS = 6;
0119: /** A plain message */
0120: protected static final byte SPY_MESS = 7;
0121:
0122: /** A byte property */
0123: protected static final int BYTE = 0;
0124: /** A short property */
0125: protected static final int SHORT = 1;
0126: /** An integer property */
0127: protected static final int INT = 2;
0128: /** A long property */
0129: protected static final int LONG = 3;
0130: /** A float property */
0131: protected static final int FLOAT = 4;
0132: /** A double property */
0133: protected static final int DOUBLE = 5;
0134: /** A boolean property */
0135: protected static final int BOOLEAN = 6;
0136: /** A string property */
0137: protected static final int STRING = 7;
0138: /** An object property */
0139: protected static final int OBJECT = 8;
0140: /** A null property */
0141: protected static final int NULL = 9;
0142:
0143: /** Reserved identifiers */
0144: private static final HashSet reservedIdentifiers = new HashSet();
0145:
0146: // Attributes ----------------------------------------------------
0147:
0148: /** The message header */
0149: public Header header = new Header();
0150:
0151: /** The acknowledgement request for this message */
0152: public transient AcknowledgementRequest ack;
0153:
0154: /** The session for this message */
0155: public transient SpySession session;
0156:
0157: // Static --------------------------------------------------------
0158:
0159: static {
0160: reservedIdentifiers.add("NULL");
0161: reservedIdentifiers.add("TRUE");
0162: reservedIdentifiers.add("FALSE");
0163: reservedIdentifiers.add("NOT");
0164: reservedIdentifiers.add("AND");
0165: reservedIdentifiers.add("OR");
0166: reservedIdentifiers.add("BETWEEN");
0167: reservedIdentifiers.add("LIKE");
0168: reservedIdentifiers.add("IN");
0169: reservedIdentifiers.add("IS");
0170: reservedIdentifiers.add("ESCAPE");
0171: }
0172:
0173: /**
0174: * Write a message
0175: *
0176: * @param message the message
0177: * @param out the output
0178: * @throws IOException for any error
0179: */
0180: public static void writeMessage(SpyMessage message, ObjectOutput out)
0181: throws IOException {
0182: if (message instanceof SpyEncapsulatedMessage)
0183: out.writeByte(ENCAP_MESS);
0184: else if (message instanceof SpyObjectMessage)
0185: out.writeByte(OBJECT_MESS);
0186: else if (message instanceof SpyBytesMessage)
0187: out.writeByte(BYTES_MESS);
0188: else if (message instanceof SpyMapMessage)
0189: out.writeByte(MAP_MESS);
0190: else if (message instanceof SpyTextMessage)
0191: out.writeByte(TEXT_MESS);
0192: else if (message instanceof SpyStreamMessage)
0193: out.writeByte(STREAM_MESS);
0194: else
0195: out.writeByte(SPY_MESS);
0196: message.writeExternal(out);
0197: }
0198:
0199: /**
0200: * Read a message
0201: *
0202: * @param in the input
0203: * @return the message
0204: * @throws IOException for any error
0205: */
0206: public static SpyMessage readMessage(ObjectInput in)
0207: throws IOException {
0208: SpyMessage message = null;
0209: byte type = in.readByte();
0210: switch (type) {
0211: case OBJECT_MESS:
0212: message = MessagePool.getObjectMessage();
0213: break;
0214: case BYTES_MESS:
0215: message = MessagePool.getBytesMessage();
0216: break;
0217: case MAP_MESS:
0218: message = MessagePool.getMapMessage();
0219: break;
0220: case STREAM_MESS:
0221: message = MessagePool.getStreamMessage();
0222: break;
0223: case TEXT_MESS:
0224: message = MessagePool.getTextMessage();
0225: break;
0226: case ENCAP_MESS:
0227: message = MessagePool.getEncapsulatedMessage();
0228: break;
0229: default:
0230: message = MessagePool.getMessage();
0231: }
0232: try {
0233: message.readExternal(in);
0234: } catch (ClassNotFoundException cnf) {
0235: throw new IOException(
0236: "Class not found when reading in spy message.");
0237: }
0238: return message;
0239: }
0240:
0241: // Constructors --------------------------------------------------
0242:
0243: // Public --------------------------------------------------------
0244:
0245: /**
0246: * Clear the message body
0247: *
0248: * @throws JMSException for any error
0249: */
0250: public void clearBody() throws JMSException {
0251: //Inherited classes clear their content here
0252: header.msgReadOnly = false;
0253: }
0254:
0255: /**
0256: * Acknowledge a message
0257: *
0258: * @throws JMSException for any error
0259: */
0260: public void acknowledge() throws JMSException {
0261: if (session == null)
0262: throw new JMSException(
0263: "This message was not recieved from the provider");
0264:
0265: if (session.acknowledgeMode == Session.CLIENT_ACKNOWLEDGE)
0266: doAcknowledge();
0267: }
0268:
0269: /**
0270: * Set the message to read only
0271: */
0272: public void setReadOnlyMode() {
0273: header.jmsPropertiesReadWrite = false;
0274: header.msgReadOnly = true;
0275: }
0276:
0277: /**
0278: * Clone the message
0279: *
0280: * @return the cloned message
0281: * @throws JMSException for any error
0282: */
0283: public SpyMessage myClone() throws JMSException {
0284: SpyMessage result = MessagePool.getMessage();
0285: result.copyProps(this );
0286: return result;
0287: }
0288:
0289: /**
0290: * Copy the properties
0291: *
0292: * @param original the message with original properties
0293: * @throws JMSException for any error
0294: */
0295: public void copyProps(SpyMessage original) throws JMSException {
0296: try {
0297: this .setJMSCorrelationID(original.getJMSCorrelationID());
0298: } catch (JMSException e) {
0299: //must be as bytes
0300: this .setJMSCorrelationIDAsBytes(original
0301: .getJMSCorrelationIDAsBytes());
0302: }
0303: this .setJMSDeliveryMode(original.getJMSDeliveryMode());
0304: this .setJMSDestination(original.getJMSDestination());
0305: this .setJMSExpiration(original.getJMSExpiration());
0306: this .setJMSMessageID(original.getJMSMessageID());
0307: this .setJMSPriority(original.getJMSPriority());
0308: this .setJMSRedelivered(original.getJMSRedelivered());
0309: this .setJMSReplyTo(original.getJMSReplyTo());
0310: this .setJMSTimestamp(original.getJMSTimestamp());
0311: this .setJMSType(original.getJMSType());
0312: this .header.jmsProperties.putAll(original.header.jmsProperties);
0313:
0314: //Spy Message special header.jmsPropertiess
0315: this .header.jmsPropertiesReadWrite = original.header.jmsPropertiesReadWrite;
0316: this .header.msgReadOnly = original.header.msgReadOnly;
0317: this .header.producerClientId = original.header.producerClientId;
0318: if (original.header.durableSubscriberID != null)
0319: this .header.durableSubscriberID = new DurableSubscriptionID(
0320: original.header.durableSubscriberID.clientID,
0321: original.header.durableSubscriberID.subscriptionName,
0322: original.header.durableSubscriberID.selector);
0323: }
0324:
0325: /**
0326: * Test whether a message has expired
0327: *
0328: * @return true when expired false otherwise
0329: */
0330: public boolean isOutdated() {
0331: if (header.jmsExpiration == 0)
0332: return false;
0333: long ts = System.currentTimeMillis();
0334: return header.jmsExpiration < ts;
0335: }
0336:
0337: /**
0338: * Actually acknowledge a message
0339: *
0340: * @throws JMSException for any error
0341: */
0342: public void doAcknowledge() throws JMSException {
0343: session.doAcknowledge(this , getAcknowledgementRequest(true));
0344: }
0345:
0346: /**
0347: * Create an acknowledgement request for the message
0348: */
0349: public void createAcknowledgementRequest(int subscriptionId) {
0350: ack = new AcknowledgementRequest();
0351: ack.destination = header.jmsDestination;
0352: ack.messageID = header.jmsMessageID;
0353: ack.subscriberId = subscriptionId;
0354: }
0355:
0356: /**
0357: * Get an acknowledgement request for the message
0358: *
0359: * @param isAck true for an ack, false for a nack
0360: * @throws JMSException for any error
0361: */
0362: public AcknowledgementRequest getAcknowledgementRequest(
0363: boolean isAck) throws JMSException {
0364: //don't know if we have to copy but to be on safe side...
0365: AcknowledgementRequest item = new AcknowledgementRequest(isAck);
0366: item.destination = ack.destination;
0367: item.messageID = ack.messageID;
0368: item.subscriberId = ack.subscriberId;
0369: return item;
0370: }
0371:
0372: // Comparable implementation -------------------------------------
0373:
0374: public int compareTo(Object o) {
0375: SpyMessage sm = (SpyMessage) o;
0376:
0377: if (header.jmsPriority > sm.header.jmsPriority) {
0378: return -1;
0379: }
0380: if (header.jmsPriority < sm.header.jmsPriority) {
0381: return 1;
0382: }
0383: return (int) (header.messageId - sm.header.messageId);
0384: }
0385:
0386: // Message implementation ----------------------------------------
0387:
0388: public String getJMSMessageID() {
0389: return header.jmsMessageID;
0390: }
0391:
0392: public void setJMSMessageID(String id) throws JMSException {
0393: header.jmsMessageID = id;
0394: }
0395:
0396: public long getJMSTimestamp() {
0397: return header.jmsTimeStamp;
0398: }
0399:
0400: public void setJMSTimestamp(long timestamp) throws JMSException {
0401: header.jmsTimeStamp = timestamp;
0402: }
0403:
0404: public byte[] getJMSCorrelationIDAsBytes() throws JMSException {
0405: if (header.jmsCorrelationID)
0406: throw new JMSException("JMSCorrelationID is a string");
0407: return header.jmsCorrelationIDbyte;
0408: }
0409:
0410: public void setJMSCorrelationIDAsBytes(byte[] correlationID)
0411: throws JMSException {
0412: header.jmsCorrelationID = false;
0413: header.jmsCorrelationIDbyte = (byte[]) correlationID.clone();
0414: header.jmsCorrelationIDString = null;
0415: }
0416:
0417: public void setJMSCorrelationID(String correlationID)
0418: throws JMSException {
0419: header.jmsCorrelationID = true;
0420: header.jmsCorrelationIDString = correlationID;
0421: header.jmsCorrelationIDbyte = null;
0422: }
0423:
0424: public String getJMSCorrelationID() throws JMSException {
0425: if (!header.jmsCorrelationID)
0426: throw new JMSException("JMSCorrelationID is an array");
0427: return header.jmsCorrelationIDString;
0428: }
0429:
0430: public Destination getJMSReplyTo() {
0431: return header.jmsReplyTo;
0432: }
0433:
0434: public void setJMSReplyTo(Destination replyTo) throws JMSException {
0435: header.jmsReplyTo = replyTo;
0436: }
0437:
0438: public Destination getJMSDestination() {
0439: return header.jmsDestination;
0440: }
0441:
0442: public void setJMSDestination(Destination destination)
0443: throws JMSException {
0444: header.jmsDestination = destination;
0445: }
0446:
0447: public int getJMSDeliveryMode() {
0448: return header.jmsDeliveryMode;
0449: }
0450:
0451: public void setJMSDeliveryMode(int deliveryMode)
0452: throws JMSException {
0453: header.jmsDeliveryMode = deliveryMode;
0454: }
0455:
0456: public boolean getJMSRedelivered() {
0457: return header.jmsRedelivered;
0458: }
0459:
0460: public void setJMSRedelivered(boolean redelivered)
0461: throws JMSException {
0462: header.jmsRedelivered = redelivered;
0463: }
0464:
0465: public String getJMSType() {
0466: return header.jmsType;
0467: }
0468:
0469: public void setJMSType(String type) throws JMSException {
0470: header.jmsType = type;
0471: }
0472:
0473: public long getJMSExpiration() {
0474: return header.jmsExpiration;
0475: }
0476:
0477: public void setJMSExpiration(long expiration) throws JMSException {
0478: header.jmsExpiration = expiration;
0479: }
0480:
0481: public int getJMSPriority() {
0482: return header.jmsPriority;
0483: }
0484:
0485: public void setJMSPriority(int priority) throws JMSException {
0486: if (priority < 0 || priority > 10)
0487: throw new JMSException("Unsupported priority '" + priority
0488: + "': priority must be from 0-10");
0489: header.jmsPriority = priority;
0490: }
0491:
0492: public void clearProperties() throws JMSException {
0493: header.jmsProperties.clear();
0494: header.jmsPropertiesReadWrite = true;
0495: }
0496:
0497: public boolean propertyExists(String name) throws JMSException {
0498: return header.jmsProperties.containsKey(name);
0499: }
0500:
0501: public boolean getBooleanProperty(String name) throws JMSException {
0502: Object value = header.jmsProperties.get(name);
0503: if (value == null)
0504: return Boolean.valueOf(null).booleanValue();
0505:
0506: if (value instanceof Boolean)
0507: return ((Boolean) value).booleanValue();
0508: else if (value instanceof String)
0509: return Boolean.valueOf((String) value).booleanValue();
0510: else
0511: throw new MessageFormatException("Invalid conversion");
0512: }
0513:
0514: public byte getByteProperty(String name) throws JMSException {
0515: Object value = header.jmsProperties.get(name);
0516: if (value == null)
0517: throw new NumberFormatException("Message property '" + name
0518: + "' not set.");
0519:
0520: if (value instanceof Byte)
0521: return ((Byte) value).byteValue();
0522: else if (value instanceof String)
0523: return Byte.parseByte((String) value);
0524: else
0525: throw new MessageFormatException("Invalid conversion");
0526: }
0527:
0528: public short getShortProperty(String name) throws JMSException {
0529: Object value = header.jmsProperties.get(name);
0530: if (value == null)
0531: throw new NumberFormatException("Message property '" + name
0532: + "' not set.");
0533:
0534: if (value instanceof Byte)
0535: return ((Byte) value).shortValue();
0536: else if (value instanceof Short)
0537: return ((Short) value).shortValue();
0538: else if (value instanceof String)
0539: return Short.parseShort((String) value);
0540: else
0541: throw new MessageFormatException("Invalid conversion");
0542: }
0543:
0544: public int getIntProperty(String name) throws JMSException {
0545: Object value = header.jmsProperties.get(name);
0546: if (value == null)
0547: throw new NumberFormatException("Message property '" + name
0548: + "' not set.");
0549:
0550: if (value instanceof Byte)
0551: return ((Byte) value).intValue();
0552: else if (value instanceof Short)
0553: return ((Short) value).intValue();
0554: else if (value instanceof Integer)
0555: return ((Integer) value).intValue();
0556: else if (value instanceof String)
0557: return Integer.parseInt((String) value);
0558: else
0559: throw new MessageFormatException("Invalid conversion");
0560: }
0561:
0562: public long getLongProperty(String name) throws JMSException {
0563: Object value = header.jmsProperties.get(name);
0564: if (value == null)
0565: throw new NumberFormatException("Message property '" + name
0566: + "' not set.");
0567:
0568: if (value instanceof Byte)
0569: return ((Byte) value).longValue();
0570: else if (value instanceof Short)
0571: return ((Short) value).longValue();
0572: else if (value instanceof Integer)
0573: return ((Integer) value).longValue();
0574: else if (value instanceof Long)
0575: return ((Long) value).longValue();
0576: else if (value instanceof String)
0577: return Long.parseLong((String) value);
0578: else
0579: throw new MessageFormatException("Invalid conversion");
0580: }
0581:
0582: public float getFloatProperty(String name) throws JMSException {
0583: Object value = header.jmsProperties.get(name);
0584: if (value == null)
0585: return Float.valueOf(null).floatValue();
0586:
0587: if (value instanceof Float)
0588: return ((Float) value).floatValue();
0589: else if (value instanceof String)
0590: return Float.parseFloat((String) value);
0591: else
0592: throw new MessageFormatException("Invalid conversion");
0593: }
0594:
0595: public double getDoubleProperty(String name) throws JMSException {
0596: Object value = header.jmsProperties.get(name);
0597: if (value == null)
0598: return Double.valueOf(null).doubleValue();
0599:
0600: if (value instanceof Float)
0601: return ((Float) value).doubleValue();
0602: else if (value instanceof Double)
0603: return ((Double) value).doubleValue();
0604: else if (value instanceof String)
0605: return Double.parseDouble((String) value);
0606: else
0607: throw new MessageFormatException("Invalid conversion");
0608: }
0609:
0610: public String getStringProperty(String name) throws JMSException {
0611: Object value = header.jmsProperties.get(name);
0612: if (value == null)
0613: return null;
0614:
0615: if (value instanceof Boolean)
0616: return ((Boolean) value).toString();
0617: else if (value instanceof Byte)
0618: return ((Byte) value).toString();
0619: else if (value instanceof Short)
0620: return ((Short) value).toString();
0621: else if (value instanceof Integer)
0622: return ((Integer) value).toString();
0623: else if (value instanceof Long)
0624: return ((Long) value).toString();
0625: else if (value instanceof Float)
0626: return ((Float) value).toString();
0627: else if (value instanceof Double)
0628: return ((Double) value).toString();
0629: else if (value instanceof String)
0630: return (String) value;
0631: else
0632: throw new MessageFormatException("Invalid conversion");
0633: }
0634:
0635: public Object getObjectProperty(String name) throws JMSException {
0636: Object value = header.jmsProperties.get(name);
0637: return value;
0638: }
0639:
0640: public Enumeration getPropertyNames() throws JMSException {
0641: Enumeration names = Collections
0642: .enumeration(header.jmsProperties.keySet());
0643: return names;
0644: }
0645:
0646: public void setBooleanProperty(String name, boolean value)
0647: throws JMSException {
0648: if (!header.jmsPropertiesReadWrite)
0649: throw new MessageNotWriteableException(
0650: "Properties are read-only");
0651: Boolean b = Primitives.valueOf(value);
0652: checkProperty(name, b);
0653: header.jmsProperties.put(name, b);
0654: }
0655:
0656: public void setByteProperty(String name, byte value)
0657: throws JMSException {
0658: if (!header.jmsPropertiesReadWrite)
0659: throw new MessageNotWriteableException(
0660: "Properties are read-only");
0661: Byte b = new Byte(value);
0662: checkProperty(name, b);
0663: header.jmsProperties.put(name, b);
0664: }
0665:
0666: public void setShortProperty(String name, short value)
0667: throws JMSException {
0668: if (!header.jmsPropertiesReadWrite)
0669: throw new MessageNotWriteableException(
0670: "Properties are read-only");
0671: Short s = new Short(value);
0672: checkProperty(name, s);
0673: header.jmsProperties.put(name, s);
0674: }
0675:
0676: public void setIntProperty(String name, int value)
0677: throws JMSException {
0678: if (!header.jmsPropertiesReadWrite)
0679: throw new MessageNotWriteableException(
0680: "Properties are read-only");
0681: Integer i = new Integer(value);
0682: checkProperty(name, i);
0683: header.jmsProperties.put(name, i);
0684: }
0685:
0686: public void setLongProperty(String name, long value)
0687: throws JMSException {
0688: if (!header.jmsPropertiesReadWrite)
0689: throw new MessageNotWriteableException(
0690: "Properties are read-only");
0691: Long l = new Long(value);
0692: checkProperty(name, l);
0693: header.jmsProperties.put(name, l);
0694: }
0695:
0696: public void setFloatProperty(String name, float value)
0697: throws JMSException {
0698: if (!header.jmsPropertiesReadWrite)
0699: throw new MessageNotWriteableException(
0700: "Properties are read-only");
0701: Float f = new Float(value);
0702: checkProperty(name, f);
0703: header.jmsProperties.put(name, f);
0704: }
0705:
0706: public void setDoubleProperty(String name, double value)
0707: throws JMSException {
0708: if (!header.jmsPropertiesReadWrite)
0709: throw new MessageNotWriteableException(
0710: "Properties are read-only");
0711: Double d = new Double(value);
0712: checkProperty(name, d);
0713: header.jmsProperties.put(name, d);
0714: }
0715:
0716: public void setStringProperty(String name, String value)
0717: throws JMSException {
0718: if (!header.jmsPropertiesReadWrite)
0719: throw new MessageNotWriteableException(
0720: "Properties are read-only");
0721: checkProperty(name, value);
0722: header.jmsProperties.put(name, value);
0723: }
0724:
0725: public void setObjectProperty(String name, Object value)
0726: throws JMSException {
0727: if (!header.jmsPropertiesReadWrite)
0728: throw new MessageNotWriteableException(
0729: "Properties are read-only");
0730: checkProperty(name, value);
0731: if (value instanceof Boolean)
0732: header.jmsProperties.put(name, value);
0733: else if (value instanceof Byte)
0734: header.jmsProperties.put(name, value);
0735: else if (value instanceof Short)
0736: header.jmsProperties.put(name, value);
0737: else if (value instanceof Integer)
0738: header.jmsProperties.put(name, value);
0739: else if (value instanceof Long)
0740: header.jmsProperties.put(name, value);
0741: else if (value instanceof Float)
0742: header.jmsProperties.put(name, value);
0743: else if (value instanceof Double)
0744: header.jmsProperties.put(name, value);
0745: else if (value instanceof String)
0746: header.jmsProperties.put(name, value);
0747: else if (value == null)
0748: header.jmsProperties.put(name, null);
0749: else
0750: throw new MessageFormatException("Invalid object type");
0751: }
0752:
0753: // Externalizable implementation ---------------------------------
0754:
0755: public void writeExternal(ObjectOutput out) throws IOException {
0756: SpyDestination.writeDest(out, header.jmsDestination);
0757: out.writeInt(header.jmsDeliveryMode);
0758: out.writeLong(header.jmsExpiration);
0759: out.writeInt(header.jmsPriority);
0760: writeString(out, header.jmsMessageID);
0761: out.writeLong(header.jmsTimeStamp);
0762: out.writeBoolean(header.jmsCorrelationID);
0763: writeString(out, header.jmsCorrelationIDString);
0764: if (header.jmsCorrelationIDbyte == null)
0765: out.writeInt(-1);
0766: else {
0767: out.writeInt(header.jmsCorrelationIDbyte.length);
0768: out.write(header.jmsCorrelationIDbyte);
0769: }
0770: SpyDestination.writeDest(out, header.jmsReplyTo);
0771: writeString(out, header.jmsType);
0772: out.writeBoolean(header.jmsRedelivered);
0773: out.writeBoolean(header.jmsPropertiesReadWrite);
0774: out.writeBoolean(header.msgReadOnly);
0775: writeString(out, header.producerClientId);
0776: //write out header.jmsPropertiess
0777: java.util.Set entrySet = header.jmsProperties.entrySet();
0778: out.writeInt(entrySet.size());
0779: for (java.util.Iterator it = entrySet.iterator(); it.hasNext();) {
0780: Map.Entry me = (Map.Entry) it.next();
0781: out.writeUTF((String) me.getKey());
0782: Object value = me.getValue();
0783: if (value == null) {
0784: out.writeByte(OBJECT);
0785: out.writeObject(value);
0786: } else if (value instanceof String) {
0787: out.writeByte(STRING);
0788: out.writeUTF((String) value);
0789: } else if (value instanceof Integer) {
0790: out.writeByte(INT);
0791: out.writeInt(((Integer) value).intValue());
0792: } else if (value instanceof Boolean) {
0793: out.writeByte(BOOLEAN);
0794: out.writeBoolean(((Boolean) value).booleanValue());
0795: } else if (value instanceof Byte) {
0796: out.writeByte(BYTE);
0797: out.writeByte(((Byte) value).byteValue());
0798: } else if (value instanceof Short) {
0799: out.writeByte(SHORT);
0800: out.writeShort(((Short) value).shortValue());
0801: } else if (value instanceof Long) {
0802: out.writeByte(LONG);
0803: out.writeLong(((Long) value).longValue());
0804: } else if (value instanceof Float) {
0805: out.writeByte(FLOAT);
0806: out.writeFloat(((Float) value).floatValue());
0807: } else if (value instanceof Double) {
0808: out.writeByte(DOUBLE);
0809: out.writeDouble(((Double) value).doubleValue());
0810: } else {
0811: out.writeByte(OBJECT);
0812: out.writeObject(value);
0813: }
0814: }
0815: }
0816:
0817: public void readExternal(ObjectInput in) throws IOException,
0818: ClassNotFoundException {
0819: header.jmsDestination = SpyDestination.readDest(in);
0820: header.jmsDeliveryMode = in.readInt();
0821: header.jmsExpiration = in.readLong();
0822: header.jmsPriority = in.readInt();
0823: header.jmsMessageID = readString(in);
0824: header.jmsTimeStamp = in.readLong();
0825: header.jmsCorrelationID = in.readBoolean();
0826: header.jmsCorrelationIDString = readString(in);
0827: int length = in.readInt();
0828: if (length < 0)
0829: header.jmsCorrelationIDbyte = null;
0830: else {
0831: header.jmsCorrelationIDbyte = new byte[length];
0832: in.readFully(header.jmsCorrelationIDbyte);
0833: }
0834: header.jmsReplyTo = SpyDestination.readDest(in);
0835: header.jmsType = readString(in);
0836: header.jmsRedelivered = in.readBoolean();
0837: header.jmsPropertiesReadWrite = in.readBoolean();
0838: header.msgReadOnly = in.readBoolean();
0839: header.producerClientId = readString(in);
0840: //read in header.jmsPropertiess
0841: header.jmsProperties = new HashMap();
0842: int size = in.readInt();
0843: for (int i = 0; i < size; i++) {
0844: String key = in.readUTF();
0845: byte type = in.readByte();
0846: Object value = null;
0847: switch (type) {
0848: case BYTE:
0849: value = new Byte(in.readByte());
0850: break;
0851: case SHORT:
0852: value = new Short(in.readShort());
0853: break;
0854: case INT:
0855: value = new Integer(in.readInt());
0856: break;
0857: case LONG:
0858: value = new Long(in.readLong());
0859: break;
0860: case FLOAT:
0861: value = new Float(in.readFloat());
0862: break;
0863: case DOUBLE:
0864: value = new Double(in.readDouble());
0865: break;
0866: case BOOLEAN:
0867: value = Primitives.valueOf(in.readBoolean());
0868: break;
0869: case STRING:
0870: value = in.readUTF();
0871: break;
0872: default:
0873: value = in.readObject();
0874: }
0875: header.jmsProperties.put(key, value);
0876: }
0877: }
0878:
0879: // Object overrides ----------------------------------------------
0880:
0881: public String toString() {
0882: return getClass().getName() + " {\n" + header + "\n" + "}";
0883: }
0884:
0885: // Package protected ---------------------------------------------
0886:
0887: /**
0888: * Check a property is valid
0889: *
0890: * @param name the name
0891: * @param value the value
0892: * @throws JMSException for any error
0893: */
0894: void checkProperty(String name, Object value) throws JMSException {
0895: if (name == null)
0896: throw new IllegalArgumentException(
0897: "The name of a property must not be null.");
0898:
0899: if (name.equals(""))
0900: throw new IllegalArgumentException(
0901: "The name of a property must not be an empty String.");
0902:
0903: if (reservedIdentifiers.contains(name))
0904: throw new IllegalArgumentException("The property name '"
0905: + name + "' is reserved due to selector syntax.");
0906:
0907: if (name.regionMatches(false, 0, "JMS_", 0, 4)) {
0908: if (name.equals(PROPERTY_SCHEDULED_DELIVERY)) {
0909: if (!(value instanceof Long))
0910: throw new JMSException(name + " must be Long: "
0911: + value);
0912: } else if (name.equals(PROPERTY_REDELIVERY_DELAY)) {
0913: if (!(value instanceof Number))
0914: throw new JMSException(name + " must be Number: "
0915: + value);
0916: } else if (name.equals(PROPERTY_REDELIVERY_COUNT)) {
0917: if (!(value instanceof Number))
0918: throw new JMSException(name + " must be Number: "
0919: + value);
0920: } else if (name.equals(PROPERTY_REDELIVERY_LIMIT)) {
0921: if (!(value instanceof Number))
0922: throw new JMSException(name + " must be Number: "
0923: + value);
0924: } else if (name.equals(PROPERTY_ORIG_EXPIRATION)) {
0925: if (!(value instanceof Long))
0926: throw new JMSException(name + " must be Long: "
0927: + value);
0928: } else if (name.equals(PROPERTY_ORIG_DESTINATION)) {
0929: // no validation
0930: } else if (name.equals(PROPERTY_ORIG_MESSAGEID)) {
0931: // no validation
0932: } else {
0933: throw new JMSException("Illegal property name: " + name);
0934: }
0935: }
0936:
0937: if (name.regionMatches(false, 0, "JMSX", 0, 4)) {
0938: if (name.equals("JMSXGroupID"))
0939: return;
0940: if (name.equals("JMSXGroupSeq"))
0941: return;
0942: throw new JMSException("Illegal property name: " + name);
0943: }
0944:
0945: if (Strings.isValidJavaIdentifier(name) == false)
0946: throw new IllegalArgumentException("The property name '"
0947: + name + "' is not a valid java identifier.");
0948:
0949: }
0950:
0951: /**
0952: * Clear a message
0953: *
0954: * @throws JMSException for any error
0955: */
0956: void clearMessage() throws JMSException {
0957: clearBody();
0958: this .ack = null;
0959: this .session = null;
0960: //Set by send() method
0961: this .header.jmsDestination = null;
0962: this .header.jmsDeliveryMode = -1;
0963: this .header.jmsExpiration = 0;
0964: this .header.jmsPriority = -1;
0965: this .header.jmsMessageID = null;
0966: this .header.jmsTimeStamp = 0;
0967: //Set by the client
0968: this .header.jmsCorrelationID = true;
0969: this .header.jmsCorrelationIDString = null;
0970: this .header.jmsCorrelationIDbyte = null;
0971: this .header.jmsReplyTo = null;
0972: this .header.jmsType = null;
0973: //Set by the provider
0974: this .header.jmsRedelivered = false;
0975: //Properties
0976: this .header.jmsProperties.clear();
0977: this .header.jmsPropertiesReadWrite = true;
0978: //Message body
0979: this .header.msgReadOnly = false;
0980: //For noLocal to be able to tell if this was a locally produced message
0981: this .header.producerClientId = null;
0982: //For durable subscriptions
0983: this .header.durableSubscriberID = null;
0984: //For ordering in the JMSServerQueue (set on the server side)
0985: this .header.messageId = 0;
0986: }
0987:
0988: // Protected -----------------------------------------------------
0989:
0990: // Private -------------------------------------------------------
0991:
0992: /**
0993: * Write a string
0994: *
0995: * @param out the output
0996: * @param s the string
0997: * @throws IOException for any error
0998: */
0999: private static void writeString(ObjectOutput out, String s)
1000: throws IOException {
1001: if (s == null)
1002: out.writeByte(NULL);
1003: else {
1004: out.writeByte(STRING);
1005: out.writeUTF(s);
1006: }
1007: }
1008:
1009: /**
1010: * Read a string
1011: *
1012: * @param in the input
1013: * @return the string
1014: * @throws IOException for any error
1015: */
1016: private static String readString(ObjectInput in) throws IOException {
1017: byte b = in.readByte();
1018: if (b == NULL)
1019: return null;
1020: else
1021: return in.readUTF();
1022: }
1023:
1024: // Inner classes -------------------------------------------------
1025:
1026: /**
1027: * The message headers
1028: */
1029: public static class Header {
1030: /** The destination */
1031: public Destination jmsDestination = null;
1032: /** The delivery mode */
1033: public int jmsDeliveryMode = -1;
1034: /** The expiration time */
1035: public long jmsExpiration = 0;
1036: /** The message priority */
1037: public int jmsPriority = -1;
1038: /** The message id */
1039: public String jmsMessageID = null;
1040: /** The send timestamp */
1041: public long jmsTimeStamp = 0;
1042: /** Whether the correlation is a string */
1043: public boolean jmsCorrelationID = true;
1044: /** The correlation string */
1045: public String jmsCorrelationIDString = null;
1046: /** The correlation in bytes */
1047: public byte[] jmsCorrelationIDbyte = null;
1048: /** The reply to destination */
1049: public Destination jmsReplyTo = null;
1050: /** The message type */
1051: public String jmsType = null;
1052: /** Set by the provider */
1053: public boolean jmsRedelivered = false;
1054: /** Properties */
1055: public HashMap jmsProperties = new HashMap();
1056: /** Whether the properties are writable */
1057: public boolean jmsPropertiesReadWrite = true;
1058: /** Message body */
1059: public boolean msgReadOnly = false;
1060: /** For noLocal to be able to tell if this was a locally produced message */
1061: public String producerClientId;
1062: /** For durable subscriptions */
1063: public DurableSubscriptionID durableSubscriberID = null;
1064: /** For ordering in the JMSServerQueue (set on the server side) */
1065: public transient long messageId;
1066:
1067: public String toString() {
1068: StringBuffer buffer = new StringBuffer(100);
1069: buffer.append("Header { \n");
1070: buffer.append(" jmsDestination : ").append(
1071: jmsDestination).append('\n');
1072: buffer.append(" jmsDeliveryMode : ").append(
1073: jmsDeliveryMode).append('\n');
1074: buffer.append(" jmsExpiration : ")
1075: .append(jmsExpiration).append('\n');
1076: buffer.append(" jmsPriority : ").append(jmsPriority)
1077: .append('\n');
1078: buffer.append(" jmsMessageID : ").append(jmsMessageID)
1079: .append('\n');
1080: buffer.append(" jmsTimeStamp : ").append(jmsTimeStamp)
1081: .append('\n');
1082: buffer.append(" jmsCorrelationID: ").append(
1083: jmsCorrelationIDString).append('\n');
1084: buffer.append(" jmsReplyTo : ").append(jmsReplyTo)
1085: .append('\n');
1086: buffer.append(" jmsType : ").append(jmsType)
1087: .append('\n');
1088: buffer.append(" jmsRedelivered : ").append(
1089: jmsRedelivered).append('\n');
1090: buffer.append(" jmsProperties : ")
1091: .append(jmsProperties).append('\n');
1092: buffer.append(" jmsPropReadWrite: ").append(
1093: jmsPropertiesReadWrite).append('\n');
1094: buffer.append(" msgReadOnly : ").append(msgReadOnly)
1095: .append('\n');
1096: buffer.append(" producerClientId: ").append(
1097: producerClientId).append('\n');
1098: buffer.append('}');
1099: return buffer.toString();
1100: }
1101: }
1102: }
|