View Javadoc

1   /***
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Exoffice Technologies.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Exoffice Technologies. Exolab is a registered
23   *    trademark of Exoffice Technologies.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 2000-2005 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: MessageImpl.java,v 1.2 2005/03/18 03:50:12 tanderson Exp $
44   */
45  package org.exolab.jms.message;
46  
47  import java.io.Externalizable;
48  import java.io.IOException;
49  import java.io.ObjectInput;
50  import java.io.ObjectOutput;
51  import java.util.Enumeration;
52  
53  import javax.jms.Destination;
54  import javax.jms.JMSException;
55  import javax.jms.Message;
56  import javax.jms.MessageNotReadableException;
57  import javax.jms.MessageNotWriteableException;
58  
59  
60  /***
61   * This class implements the javax.jms.Message interface.
62   *
63   * @version     $Revision: 1.2 $ $Date: 2005/03/18 03:50:12 $
64   * @author      <a href="mailto:mourikis@exolab.org">Jim Mourikis</a>
65   * @see         javax.jms.Message
66   */
67  public class MessageImpl implements
68          Message, Externalizable, Cloneable {
69  
70      /***
71       * Object version no. for serialization.
72       */
73      static final long serialVersionUID = 1;
74  
75      /***
76       * This is a reference to the session that created the message. It
77       * is used for acknowledgment
78       */
79      private MessageSessionIfc _session = null;
80  
81      /***
82       * Contains the message header information as specified by the JMS
83       * specifications.
84       */
85      private MessageHeader _messageHeader = new MessageHeader();
86  
87      /***
88       * The message properties
89       */
90      private MessageProperties _messageProperties = new MessageProperties();
91  
92      /***
93       * If true, message properties are read-only.
94       */
95      protected boolean _propertiesReadOnly = false;
96  
97      /***
98       * If true, the message body is read-only.
99       */
100     protected boolean _bodyReadOnly = false;
101 
102     /***
103      * The time that the message was accepted by the server.
104      */
105     protected long _acceptedTime;
106 
107     /***
108      * The sequence number assigned to the message by server when the message
109      * is accepted.
110      */
111     protected long _sequenceNumber;
112 
113     /***
114      * The identity of the connection that this was received on.
115      */
116     protected transient long _connectionId;
117 
118     /***
119      * This flag indicates that the message has been processed by the provider.
120      */
121     protected boolean _processed = false;
122 
123     /***
124      * Empty byte array for initialisation purposes.
125      */
126     protected static final byte[] EMPTY = new byte[0];
127 
128 
129     /***
130      * Default constructor, required to support externalization.
131      */
132     public MessageImpl() {
133     }
134 
135     /***
136      * Clone an instance of this object.
137      *
138      * @return a new copy of this object
139      * @throws CloneNotSupportedException if object or attributesare not
140      * cloneable
141      */
142     public Object clone() throws CloneNotSupportedException {
143         MessageImpl result = (MessageImpl) super.clone();
144         result._messageHeader = (MessageHeader) _messageHeader.clone();
145         result._messageProperties =
146                 (MessageProperties) _messageProperties.clone();
147         return result;
148     }
149 
150     // implementation of Externalizable.writeExternal
151     public void writeExternal(ObjectOutput out) throws IOException {
152         out.writeLong(serialVersionUID);
153         // the individual read-only states are meaningless when streaming;
154         // they only affect the client when clearProperties or clearBody is
155         // is invoked
156         out.writeBoolean(_propertiesReadOnly || _bodyReadOnly);
157         out.writeBoolean(_processed);
158         out.writeLong(_acceptedTime);
159         out.writeLong(_sequenceNumber);
160         out.writeObject(_messageHeader);
161         out.writeObject(_messageProperties);
162     }
163 
164     // implementation of Externalizable.readExternal
165     public void readExternal(ObjectInput in)
166             throws IOException, ClassNotFoundException {
167         long version = in.readLong();
168         if (version == serialVersionUID) {
169             boolean readOnly = in.readBoolean();
170             _propertiesReadOnly = readOnly;
171             _bodyReadOnly = readOnly;
172             _processed = in.readBoolean();
173             _acceptedTime = in.readLong();
174             _sequenceNumber = in.readLong();
175             _messageHeader = (MessageHeader) in.readObject();
176             _messageProperties = (MessageProperties) in.readObject();
177         } else {
178             throw new IOException("Incorrect version enountered: " +
179                                   version + ". This version = " +
180                                   serialVersionUID);
181         }
182     }
183 
184     public void setSession(MessageSessionIfc session) {
185         _session = session;
186         MessageId id = _messageHeader.getMessageId();
187         if (id != null) {
188             _messageHeader.setAckMessageID(id.getId());
189         }
190     }
191 
192     public String getJMSMessageID() throws JMSException {
193         return _messageHeader.getJMSMessageID();
194     }
195 
196     public void setJMSMessageID(String id) throws JMSException {
197         _messageHeader.setJMSMessageID(id);
198     }
199 
200     /***
201      * Returns the identifier of the message for acknowledgment.
202      * This will typically be the same as that returned by
203      * {@link #getJMSMessageID}, unless the message was republished after
204      * its receipt. If the message is republished, this method will return
205      * the original message identifier, whereas {@link #getJMSMessageID} will
206      * return that of the last publication.
207      *
208      * @return the identifier of the message for acknowledgment
209      */
210     public String getAckMessageID() {
211         return _messageHeader.getAckMessageID();
212     }
213 
214 
215     public long getJMSTimestamp() throws JMSException {
216         return _messageHeader.getJMSTimestamp();
217     }
218 
219     public void setJMSTimestamp(long timestamp) throws JMSException {
220         _messageHeader.setJMSTimestamp(timestamp);
221     }
222 
223     /***
224      * Return the wildcard value if there is one.
225      *
226      * @return the wildcard string
227      */
228     public String getWildcard() {
229         return _messageHeader.getWildcard();
230     }
231 
232     /***
233      * Return the message id
234      *
235      * @return MessageId
236      */
237     public MessageId getMessageId() {
238         return _messageHeader.getMessageId();
239     }
240 
241     /***
242      * Set the wildcard string.
243      *
244      * @param wildcard The wildcard.
245      */
246     public void setWildcard(String wildcard) {
247         _messageHeader.setWildcard(wildcard);
248     }
249 
250     /***
251      * Returns the value of the consumer identifier
252      *
253      * @return the value of the consumer identifier
254      */
255     public long getConsumerId() {
256         return _messageHeader.getConsumerId();
257     }
258 
259     /***
260      * Set the value of the consumer identifer
261      *
262      * @param consumerId the consumer identifier
263      */
264     public void setConsumerId(long consumerId) {
265         _messageHeader.setConsumerId(consumerId);
266     }
267 
268     // Not supported
269     public byte[] getJMSCorrelationIDAsBytes() throws JMSException {
270         return _messageHeader.getJMSCorrelationIDAsBytes();
271     }
272 
273     // Not supported
274     public void setJMSCorrelationIDAsBytes(byte[] correlationID)
275             throws JMSException {
276         _messageHeader.setJMSCorrelationIDAsBytes(correlationID);
277     }
278 
279     public void setJMSCorrelationID(String correlationID) throws JMSException {
280         _messageHeader.setJMSCorrelationID(correlationID);
281     }
282 
283     public String getJMSCorrelationID() throws JMSException {
284         return _messageHeader.getJMSCorrelationID();
285     }
286 
287     public Destination getJMSReplyTo() throws JMSException {
288         return _messageHeader.getJMSReplyTo();
289     }
290 
291     public void setJMSReplyTo(Destination replyTo) throws JMSException {
292         _messageHeader.setJMSReplyTo(replyTo);
293     }
294 
295     public Destination getJMSDestination() throws JMSException {
296         return _messageHeader.getJMSDestination();
297     }
298 
299     public void setJMSDestination(Destination destination)
300             throws JMSException {
301         _messageHeader.setJMSDestination(destination);
302     }
303 
304     public int getJMSDeliveryMode() throws JMSException {
305         return _messageHeader.getJMSDeliveryMode();
306     }
307 
308     public void setJMSDeliveryMode(int deliveryMode) throws JMSException {
309         _messageHeader.setJMSDeliveryMode(deliveryMode);
310     }
311 
312     public boolean getJMSRedelivered() throws JMSException {
313         return _messageHeader.getJMSRedelivered();
314     }
315 
316     public void setJMSRedelivered(boolean redelivered) throws JMSException {
317         _messageHeader.setJMSRedelivered(redelivered);
318     }
319 
320     public String getJMSType() throws JMSException {
321         return _messageHeader.getJMSType();
322     }
323 
324     public void setJMSType(String type) throws JMSException {
325         _messageHeader.setJMSType(type);
326     }
327 
328     public long getJMSExpiration() throws JMSException {
329         return _messageHeader.getJMSExpiration();
330     }
331 
332     public void setJMSExpiration(long expiration) throws JMSException {
333         _messageHeader.setJMSExpiration(expiration);
334     }
335 
336     public int getJMSPriority() throws JMSException {
337         return _messageHeader.getJMSPriority();
338     }
339 
340     public void setJMSPriority(int priority) throws JMSException {
341         _messageHeader.setJMSPriority(priority);
342     }
343 
344     public void clearProperties() throws JMSException {
345         _messageProperties.clearProperties();
346         _propertiesReadOnly = false;
347     }
348 
349     public boolean propertyExists(String name) throws JMSException {
350         return _messageProperties.propertyExists(name);
351     }
352 
353     public boolean getBooleanProperty(String name) throws JMSException {
354         return _messageProperties.getBooleanProperty(name);
355     }
356 
357     public byte getByteProperty(String name) throws JMSException {
358         return _messageProperties.getByteProperty(name);
359     }
360 
361     public short getShortProperty(String name) throws JMSException {
362         return _messageProperties.getShortProperty(name);
363     }
364 
365     public int getIntProperty(String name) throws JMSException {
366         return _messageProperties.getIntProperty(name);
367     }
368 
369     public long getLongProperty(String name) throws JMSException {
370         return _messageProperties.getLongProperty(name);
371     }
372 
373     public float getFloatProperty(String name) throws JMSException {
374         return _messageProperties.getFloatProperty(name);
375     }
376 
377     public double getDoubleProperty(String name) throws JMSException {
378         return _messageProperties.getDoubleProperty(name);
379     }
380 
381     public String getStringProperty(String name) throws JMSException {
382         return _messageProperties.getStringProperty(name);
383     }
384 
385     public Object getObjectProperty(String name) throws JMSException {
386         return _messageProperties.getObjectProperty(name);
387     }
388 
389     public Enumeration getPropertyNames() throws JMSException {
390         return _messageProperties.getPropertyNames();
391     }
392 
393     public void setBooleanProperty(String name, boolean value)
394             throws JMSException {
395         checkPropertyWrite();
396         _messageProperties.setBooleanProperty(name, value);
397     }
398 
399     public void setByteProperty(String name, byte value) throws JMSException {
400         checkPropertyWrite();
401         _messageProperties.setByteProperty(name, value);
402     }
403 
404     public void setShortProperty(String name, short value)
405             throws JMSException {
406         checkPropertyWrite();
407         _messageProperties.setShortProperty(name, value);
408     }
409 
410     public void setIntProperty(String name, int value) throws JMSException {
411         checkPropertyWrite();
412         _messageProperties.setIntProperty(name, value);
413     }
414 
415     public void setLongProperty(String name, long value) throws JMSException {
416         checkPropertyWrite();
417         _messageProperties.setLongProperty(name, value);
418     }
419 
420     public void setFloatProperty(String name, float value)
421             throws JMSException {
422         checkPropertyWrite();
423         _messageProperties.setFloatProperty(name, value);
424     }
425 
426     public void setDoubleProperty(String name, double value)
427             throws JMSException {
428         checkPropertyWrite();
429         _messageProperties.setDoubleProperty(name, value);
430     }
431 
432     public void setStringProperty(String name, String value)
433             throws JMSException {
434         checkPropertyWrite();
435         _messageProperties.setStringProperty(name, value);
436     }
437 
438     public void setObjectProperty(String name, Object value)
439             throws JMSException {
440         checkPropertyWrite();
441         _messageProperties.setObjectProperty(name, value);
442     }
443 
444     /***
445      * Acknowledge the message through the session that dispatched it.
446      * Throw JMSException is there is no session attached to the message
447      *
448      * @throws JMSException if acknowledgement fails
449      */
450     public void acknowledge() throws JMSException {
451         if (getAckMessageID() == null) {
452             throw new JMSException(
453                     "Cannot acknowledge message: no identifier");
454         }
455         if (_session == null) {
456             throw new JMSException(
457                     "Cannot acknowledge message: unknown session");
458         }
459         _session.acknowledgeMessage(this);
460     }
461 
462     public void clearBody() throws JMSException {
463         _bodyReadOnly = false;
464     }
465 
466     public final void checkPropertyWrite()
467             throws MessageNotWriteableException {
468         if (_propertiesReadOnly) {
469             throw new MessageNotWriteableException(
470                     "Message in read-only mode");
471         }
472     }
473 
474     public final void checkWrite() throws MessageNotWriteableException {
475         if (_bodyReadOnly) {
476             throw new MessageNotWriteableException(
477                     "Message in read-only mode");
478         }
479     }
480 
481     public final void checkRead() throws MessageNotReadableException {
482         if (_bodyReadOnly == false) {
483             throw new MessageNotReadableException(
484                     "Message in write-only mode");
485         }
486     }
487 
488     // implementation of Identifiable.getId()
489     public String getId() {
490         return _messageHeader.getMessageId().getId();
491     }
492 
493     /***
494      * Set the time that the message was accepted by the server. This is
495      * different to the JMSTimestamp, which denotes the time that the message
496      * was handed off to the provider.
497      *
498      * @param time the time that the message was accepted by the server
499      */
500     public void setAcceptedTime(long time) {
501         _acceptedTime = time;
502     }
503 
504     /***
505      * Return the time that the messages was accepted by the server
506      *
507      * @return time in milliseconds
508      */
509     public long getAcceptedTime() {
510         return _acceptedTime;
511     }
512 
513     /***
514      * Set the sequence number for this message. Not mandatory.
515      *
516      * @param seq the sequence number, which is used for ordering
517      */
518     public void setSequenceNumber(long seq) {
519         _sequenceNumber = seq;
520     }
521 
522     /***
523      * Return the sequence number associated with this message
524      *
525      * @return the sequence number
526      */
527     public long getSequenceNumber() {
528         return _sequenceNumber;
529     }
530 
531     /***
532      * Set the id of the connection that this message was received on
533      *
534      * @param id the connection id
535      */
536     public void setConnectionId(long id) {
537         _connectionId = id;
538     }
539 
540     /***
541      * Return the id of the connection that this messaged was received on
542      *
543      * @return the connection id
544      */
545     public long getConnectionId() {
546         return _connectionId;
547     }
548 
549     /***
550      * Set the processed state of the message
551      *
552      * @param state true if message has been processed by provider
553      */
554     public void setProcessed(boolean state) {
555         _processed = state;
556     }
557 
558     /***
559      * Check whether the message has been processed
560      *
561      * @return true if the message has been processed
562      */
563     public boolean getProcessed() {
564         return _processed;
565     }
566 
567     /***
568      * Set the read-only state of the message
569      *
570      * @param readOnly if true, make the message body and properties read-only
571      * @throws JMSException if the read-only state cannot be changed
572      */
573     public void setReadOnly(boolean readOnly) throws JMSException {
574         _propertiesReadOnly = readOnly;
575         _bodyReadOnly = readOnly;
576     }
577 
578     /***
579      * Get the read-only state of the message. Note that this only returns true
580      * if both properties and body are read-only
581      *
582      * @return true if the message is read-only
583      */
584     public final boolean getReadOnly() {
585         return _propertiesReadOnly && _bodyReadOnly;
586     }
587 
588     /***
589      * Set the JMSXRcvTimestamp property. This bypasses the read-only
590      * check to avoid unwanted exceptions.
591      */
592     public void setJMSXRcvTimestamp(long timestamp) {
593         _messageProperties.setJMSXRcvTimestamp(timestamp);
594     }
595 
596 }