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