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 tma@netspace.net.au.
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 2003-2004 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: BasicStreamMessage.java,v 1.2 2004/02/02 03:49:55 tanderson Exp $
44   */
45  
46  package org.exolab.jmscts.jms.message;
47  
48  import java.util.ArrayList;
49  import java.util.List;
50  
51  import javax.jms.JMSException;
52  import javax.jms.MessageEOFException;
53  import javax.jms.MessageFormatException;
54  import javax.jms.MessageNotWriteableException;
55  import javax.jms.StreamMessage;
56  
57  
58  /***
59   * This class provides a basic implementation of the javax.jms.ObjectMessage
60   * interface.
61   *
62   * @version     $Revision: 1.2 $ $Date: 2004/02/02 03:49:55 $
63   * @author      <a href="mailto:tma@netspace.net.au">Tim Anderson</a>
64   * @see         javax.jms.StreamMessage
65   */
66  public class BasicStreamMessage extends BasicMessage implements StreamMessage {
67  
68      /***
69       * The message body
70       */
71      private List _body = new ArrayList();
72  
73      /***
74       * Index into the body array
75       */
76      private int _index = 0;
77  
78  
79      /***
80       * Current byte array field being processed
81       */
82      private byte[] _bytes;
83  
84      /***
85       * Non-zero if incrementally reading a byte array using
86       * {@link #readBytes(byte[])}
87       */
88      private int _bytesRead = 0;
89  
90  
91      /***
92       * Construct a new <code>BasicStreamMessage</code>.
93       * When first created, the message is in write-only mode.
94       */
95      public BasicStreamMessage() {
96      }
97  
98      /***
99       * Read a <code>boolean</code> from the bytes message stream
100      *
101      * @return the <code>boolean</code> value read
102      * @throws JMSException if JMS fails to read message due to some internal
103      * JMS error
104      * @throws MessageEOFException if end of message stream
105      * @throws MessageFormatException if this type conversion is invalid
106      */
107     public boolean readBoolean() throws JMSException {
108         boolean result = FormatConverter.getBoolean(readNext());
109         _index++;
110         return result;
111     }
112 
113     /***
114      * Read a byte value from the stream message
115      *
116      * @return the next byte from the stream message as an 8-bit
117      * <code>byte</code>
118      * @throws JMSException if JMS fails to read message due to some internal
119      * JMS error
120      * @throws MessageEOFException if end of message stream
121      * @throws MessageFormatException if this type conversion is invalid
122      * @throws NumberFormatException if numeric conversion is invalid
123      */
124     public byte readByte() throws JMSException {
125         byte result = FormatConverter.getByte(readNext());
126         _index++;
127         return result;
128     }
129 
130     /***
131      * Read a 16-bit number from the stream message.
132      *
133      * @return a 16-bit number from the stream message
134      * @throws JMSException if JMS fails to read message due to some internal
135      * JMS error
136      * @throws MessageEOFException if end of message stream
137      * @throws MessageFormatException if this type conversion is invalid
138      * @throws NumberFormatException if numeric conversion is invalid
139      */
140     public short readShort() throws JMSException {
141         short result = FormatConverter.getShort(readNext());
142         _index++;
143         return result;
144     }
145 
146     /***
147      * Read a Unicode character value from the stream message
148      *
149      * @return a Unicode character from the stream message
150      * @throws JMSException if JMS fails to read message due to some internal
151      * JMS error
152      * @throws MessageEOFException if end of message stream
153      * @throws MessageFormatException if this type conversion is invalid
154      */
155     public char readChar() throws JMSException {
156         char result = FormatConverter.getChar(readNext());
157         _index++;
158         return result;
159     }
160 
161     /***
162      * Read a 32-bit integer from the stream message
163      *
164      * @return a 32-bit integer value from the stream message, interpreted
165      * as an <code>int</code>
166      * @throws JMSException if JMS fails to read message due to some internal
167      * JMS error
168      * @throws MessageEOFException if end of message stream
169      * @throws MessageFormatException if this type conversion is invalid
170      * @throws NumberFormatException if numeric conversion is invalid
171      */
172     public int readInt() throws JMSException {
173         int result = FormatConverter.getInt(readNext());
174         _index++;
175         return result;
176     }
177 
178     /***
179      * Read a 64-bit integer from the stream message
180      *
181      * @return a 64-bit integer value from the stream message, interpreted as
182      * a <code>long</code>
183      * @throws JMSException if JMS fails to read message due to some internal
184      * JMS error
185      * @throws MessageEOFException if end of message stream
186      * @throws MessageFormatException if this type conversion is invalid
187      * @throws NumberFormatException if numeric conversion is invalid
188      */
189     public long readLong() throws JMSException {
190         long result = FormatConverter.getLong(readNext());
191         _index++;
192         return result;
193     }
194 
195     /***
196      * Read a <code>float</code> from the stream message
197      *
198      * @return a <code>float</code> value from the stream message
199      * @throws JMSException if JMS fails to read message due to some internal
200      * JMS error
201      * @throws MessageEOFException if end of message stream
202      * @throws MessageFormatException if this type conversion is invalid
203      * @throws NullPointerException if the value is null
204      * @throws NumberFormatException if numeric conversion is invalid
205      */
206     public float readFloat() throws JMSException {
207         float result = FormatConverter.getFloat(readNext());
208         _index++;
209         return result;
210     }
211 
212     /***
213      * Read a <code>double</code> from the stream message
214      *
215      * @return a <code>double</code> value from the stream message
216      * @throws JMSException if JMS fails to read message due to some internal
217      * JMS error
218      * @throws MessageEOFException if end of message stream
219      * @throws MessageFormatException if this type conversion is invalid
220      * @throws NullPointerException if the value is null
221      * @throws NumberFormatException if numeric conversion is invalid
222      */
223     public double readDouble() throws JMSException {
224         double result = FormatConverter.getDouble(readNext());
225         _index++;
226         return result;
227     }
228 
229     /***
230      * Read in a string from the stream message
231      *
232      * @return a Unicode string from the stream message
233      * @throws JMSException if JMS fails to read message due to some internal
234      * JMS error
235      * @throws MessageEOFException if end of message stream
236      * @throws MessageFormatException if this type conversion is invalid
237      */
238     public String readString() throws JMSException {
239         String result = FormatConverter.getString(readNext());
240         _index++;
241         return result;
242     }
243 
244     /***
245      * Read a byte array field from the stream message into the
246      * specified byte[] object (the read buffer).
247      * <p>
248      * To read the field value, readBytes should be successively called
249      * until it returns a value less than the length of the read buffer.
250      * The value of the bytes in the buffer following the last byte
251      * read are undefined.
252      * <p>
253      * If readBytes returns a value equal to the length of the buffer, a
254      * subsequent readBytes call must be made. If there are no more bytes
255      * to be read this call will return -1.
256      * <p>
257      * If the bytes array field value is null, readBytes returns -1.
258      * <p>
259      * If the bytes array field value is empty, readBytes returns 0.
260      * <p>
261      * Once the first readBytes call on a byte[] field value has been done,
262      * the full value of the field must be read before it is valid to read
263      * the next field. An attempt to read the next field before that has
264      * been done will throw a MessageFormatException.
265      * <p>
266      * To read the byte field value into a new byte[] object, use the
267      * {@link #readObject} method.
268      *
269      * @param value the buffer into which the data is read.
270      * @return the total number of bytes read into the buffer, or -1 if
271      * there is no more data because the end of the byte field has been
272      * reached.
273      * @throws JMSException if JMS fails to read message due to some internal
274      * JMS error
275      * @throws MessageEOFException if an end of message stream
276      * @throws MessageFormatException if this type conversion is invalid
277      */
278     public int readBytes(byte[] value) throws JMSException {
279         int read = 0;            // the number of bytes read
280         if (_bytes == null) {
281             Object next = readNext();
282             if (!(next instanceof byte[])) {
283                 throw new MessageFormatException("Field is not a byte array");
284             }
285             _bytes = (byte[]) next;
286             _bytesRead = 0;
287             _index++;
288         }
289         int available = _bytes.length - _bytesRead;
290 
291         if (available == 0) {
292             if (_bytesRead != 0) { // not the first invocation
293                 read = -1;
294             }
295         } else {
296             if (value.length <= available) {
297                 read = value.length;
298             } else {
299                 read = available;
300             }
301             System.arraycopy(_bytes, _bytesRead, value, 0, value.length);
302             _bytesRead += read;
303         }
304         return read;
305     }
306 
307     /***
308      * Read a Java object from the stream message
309      * <p>
310      * Note that this method can be used to return in objectified format,
311      * an object that had been written to the stream with the equivalent
312      * <code>writeObject</code> method call, or it's equivalent primitive
313      * write<type> method.
314      * <p>
315      * Note that byte values are returned as byte[], not Byte[].
316      *
317      * @return a Java object from the stream message, in objectified
318      * format (eg. if it set as an int, then a Integer is returned).
319      * @throws JMSException if JMS fails to read message due to some internal
320      * JMS error
321      * @throws MessageEOFException if end of message stream
322      */
323     public Object readObject() throws JMSException {
324         Object result = readNext();
325         _index++;
326         return result;
327     }
328 
329     /***
330      * Write a <code>boolean</code> to the stream message.
331      * The value <code>true</code> is written out as the value
332      * <code>(byte)1</code>; the value <code>false</code> is written out as
333      * the value <code>(byte)0</code>.
334      *
335      * @param value the <code>boolean</code> value to be written.
336      * @throws MessageNotWriteableException if message in read-only mode
337      */
338     public void writeBoolean(boolean value)
339         throws MessageNotWriteableException {
340         checkWrite();
341         _body.add(new Boolean(value));
342     }
343 
344     /***
345      * Write out a <code>byte</code> to the stream message
346      *
347      * @param value the <code>byte</code> value to be written
348      * @throws MessageNotWriteableException if message in read-only mode
349      */
350     public void writeByte(byte value) throws MessageNotWriteableException {
351         checkWrite();
352         _body.add(new Byte(value));
353     }
354 
355     /***
356      * Write a <code>short</code> to the stream message
357      *
358      * @param value the <code>short</code> to be written
359      * @throws MessageNotWriteableException if message in read-only mode
360      */
361     public void writeShort(short value) throws MessageNotWriteableException {
362         checkWrite();
363         _body.add(new Short(value));
364     }
365 
366     /***
367      * Write a <code>char</code> to the stream message
368      *
369      * @param value the <code>char</code> value to be written
370      * @throws MessageNotWriteableException if message in read-only mode
371      */
372     public void writeChar(char value) throws MessageNotWriteableException {
373         checkWrite();
374         _body.add(new Character(value));
375     }
376 
377     /***
378      * Write an <code>int</code> to the stream message
379      *
380      * @param value the <code>int</code> to be written
381      * @throws MessageNotWriteableException if message in read-only mode
382      */
383     public void writeInt(int value) throws MessageNotWriteableException {
384         checkWrite();
385         _body.add(new Integer(value));
386     }
387 
388     /***
389      * Write a <code>long</code> to the stream message
390      *
391      * @param value the <code>long</code> to be written
392      * @throws MessageNotWriteableException if message in read-only mode
393      */
394     public void writeLong(long value) throws MessageNotWriteableException {
395         checkWrite();
396         _body.add(new Long(value));
397     }
398 
399     /***
400      * Write a <code>float</code> to the stream message
401      *
402      * @param value the <code>float</code> value to be written
403      * @throws MessageNotWriteableException if message in read-only mode
404      */
405     public void writeFloat(float value) throws MessageNotWriteableException {
406         checkWrite();
407         _body.add(new Float(value));
408     }
409 
410     /***
411      * Write a <code>double</code> to the stream message
412      *
413      * @param value the <code>double</code> value to be written
414      * @throws MessageNotWriteableException if message in read-only mode
415      */
416     public void writeDouble(double value) throws MessageNotWriteableException {
417         checkWrite();
418         _body.add(new Double(value));
419     }
420 
421     /***
422      * Write a string to the stream message
423      *
424      * @param value the <code>String</code> value to be written
425      * @throws MessageNotWriteableException if message in read-only mode
426      */
427     public void writeString(String value) throws MessageNotWriteableException {
428         checkWrite();
429         _body.add(value);
430     }
431 
432     /***
433      * Write a byte array field to the stream message
434      * <p>
435      * The byte array <code>value</code> is written as a byte array field
436      * into the StreamMessage. Consecutively written byte array fields are
437      * treated as two distinct fields when reading byte array fields.
438      *
439      * @param value the byte array to be written
440      * @throws MessageNotWriteableException if message in read-only mode
441      */
442     public void writeBytes(byte[] value) throws MessageNotWriteableException {
443         writeBytes(value, 0, value.length);
444     }
445 
446     /***
447      * Write a portion of a byte array as a byte array field to the stream
448      * message
449      * <p>
450      * The a portion of the byte array <code>value</code> is written as a
451      * byte array field into the StreamMessage. Consecutively written byte
452      * array fields are treated as two distinct fields when reading byte
453      * array fields.
454      *
455      * @param value the byte array value to be written
456      * @param offset the initial offset within the byte array
457      * @param length the number of bytes to write
458      * @throws MessageNotWriteableException if message in read-only mode
459      */
460     public void writeBytes(byte[] value, int offset, int length)
461         throws  MessageNotWriteableException {
462         checkWrite();
463         byte[] buffer = new byte[length];
464         System.arraycopy(value, offset, buffer, 0, length);
465         _body.add(buffer);
466     }
467 
468     /***
469      * Write a Java object to the stream message
470      * <p>
471      * Note that this method only works for the objectified primitive
472      * object types (Integer, Double, Long ...), String's and byte arrays.
473      *
474      * @param value the Java object to be written
475      * @throws JMSException if JMS fails to write message due to
476      * some internal JMS error
477      * @throws MessageFormatException if the object is invalid
478      * @throws MessageNotWriteableException if message in read-only mode
479      */
480     public void writeObject(Object value) throws JMSException {
481         if (value == null) {
482             checkWrite();
483             _body.add(null);
484         } else if (value instanceof Boolean) {
485             writeBoolean(((Boolean) value).booleanValue());
486         } else if (value instanceof Byte) {
487             writeByte(((Byte) value).byteValue());
488         } else if (value instanceof byte[]) {
489             writeBytes((byte[]) value);
490         } else if (value instanceof Short) {
491             writeShort(((Short) value).shortValue());
492         } else if (value instanceof Character) {
493             writeChar(((Character) value).charValue());
494         } else if (value instanceof Integer) {
495             writeInt(((Integer) value).intValue());
496         } else if (value instanceof Long) {
497             writeLong(((Long) value).longValue());
498         } else if (value instanceof Float) {
499             writeFloat(((Float) value).floatValue());
500         } else if (value instanceof Double) {
501             writeDouble(((Double) value).doubleValue());
502         } else if (value instanceof String) {
503             writeString((String) value);
504         } else {
505             throw new MessageFormatException(
506                 "Objects of type " + value.getClass().getName()
507                 + " are not supported by StreamMessage");
508         }
509     }
510 
511     /***
512      * Put the message body in read-only mode, and reposition the stream
513      * to the beginning
514      */
515     public void reset() {
516         setBodyReadOnly(true);
517         _index = 0;
518         _bytes = null;
519         _bytesRead = 0;
520     }
521 
522     /***
523      * Clear the message body
524      *
525      * @throws JMSException if JMS fails to reset the message due to
526      * some internal JMS error.
527      */
528     public void clearBody() throws JMSException {
529         super.clearBody();
530         _body.clear();
531         _index = 0;
532         _bytes = null;
533         _bytesRead = 0;
534     }
535 
536     /***
537      * Set the read-only mode of the message.
538      *
539      * @param readOnly if true, make the message body and properties read-only,
540      * and invoke {@link #reset}
541      * @throws JMSException if the read-only mode cannot be changed
542      */
543     public void setReadOnly(boolean readOnly) throws JMSException {
544         super.setReadOnly(readOnly);
545         if (readOnly) {
546             reset();
547         }
548     }
549 
550     /***
551      * Read the next object from the stream message
552      *
553      * @return a Java object from the stream message, in objectified
554      * format (eg. if it set as an int, then a Integer is returned).
555      * @throws JMSException if JMS fails to read message due to some internal
556      * JMS error
557      * @throws MessageEOFException if end of message stream
558      * @throws MessageFormatException if a byte array has not been fully read
559      * by {@link #readBytes(byte[])}
560      */
561     private Object readNext() throws JMSException {
562         checkRead();
563 
564         if (_bytesRead != 0) {
565             throw new MessageFormatException(
566                 "Cannot read the next field until the byte array is read");
567         }
568 
569         if (_index == _body.size()) {
570             throw new MessageEOFException("End of stream");
571         }
572         return _body.get(_index);
573     }
574 
575 }
This page was automatically generated by Maven