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-2004 (C) Exoffice Technologies Inc. All Rights Reserved.
42 *
43 * $Id: BytesMessageImpl.java,v 1.12 2004/01/29 12:00:37 tanderson Exp $
44 *
45 * Date Author Changes
46 * 02/26/2000 jimm Created
47 */
48
49 package org.exolab.jms.message;
50
51 import java.io.ByteArrayInputStream;
52 import java.io.ByteArrayOutputStream;
53 import java.io.DataInputStream;
54 import java.io.DataOutputStream;
55 import java.io.EOFException;
56 import java.io.IOException;
57 import java.io.ObjectInput;
58 import java.io.ObjectOutput;
59 import java.io.UTFDataFormatException;
60
61 import javax.jms.BytesMessage;
62 import javax.jms.JMSException;
63 import javax.jms.MessageEOFException;
64 import javax.jms.MessageFormatException;
65 import javax.jms.MessageNotReadableException;
66 import javax.jms.MessageNotWriteableException;
67
68
69 /***
70 * This class implements the {@link BytesMessage} interface
71 *
72 * @version $Revision: 1.12 $ $Date: 2004/01/29 12:00:37 $
73 * @author <a href="mailto:mourikis@intalio.com">Jim Mourikis</a>
74 * @author <a href="mailto:tima@intalio.com">Tim Anderson</a>
75 * @see BytesMessage
76 */
77 public final class BytesMessageImpl extends MessageImpl
78 implements BytesMessage {
79
80 /***
81 * Object version no. for serialization
82 */
83 static final long serialVersionUID = 1;
84
85 /***
86 * Empty byte array for initialisation purposes
87 */
88 private static final byte[] EMPTY = new byte[]{};
89
90 /***
91 * The byte stream to store data
92 */
93 private byte[] _bytes = EMPTY;
94
95 /***
96 * The stream used for writes
97 */
98 private DataOutputStream _out = null;
99
100 /***
101 * The byte stream backing the output stream
102 */
103 private ByteArrayOutputStream _byteOut = null;
104
105 /***
106 * The stream used for reads
107 */
108 private DataInputStream _in = null;
109
110 /***
111 * The byte stream backing the input stream
112 */
113 private ByteArrayInputStream _byteIn = null;
114
115 /***
116 * The offset of the byte stream to start reading from. This defaults
117 * to 0, and only applies to messages that are cloned from a
118 * read-only instance where part of the stream had already been read.
119 */
120 private int _offset = 0;
121
122 /***
123 * Construct a new BytesMessage. When first created, the message is in
124 * write-only mode.
125 *
126 * @throws JMSException if the message type can't be set
127 */
128 public BytesMessageImpl() throws JMSException {
129 setJMSType("BytesMessage");
130 }
131
132 /***
133 * Clone an instance of this object
134 *
135 * @return a copy of this object
136 * @throws CloneNotSupportedException if object or attributes aren't
137 * cloneable
138 */
139 public final Object clone() throws CloneNotSupportedException {
140 BytesMessageImpl result = (BytesMessageImpl) super.clone();
141 if (_bodyReadOnly) {
142 result._bytes = new byte[_bytes.length];
143 System.arraycopy(_bytes, 0, result._bytes, 0, _bytes.length);
144 if (_byteIn != null) {
145 // if a client subsequently reads from the cloned object,
146 // start reading from offset of the original stream
147 _offset = _bytes.length - _byteIn.available();
148 }
149 result._byteIn = null;
150 result._in = null;
151 } else {
152 if (_out != null) {
153 try {
154 _out.flush();
155 } catch (IOException exception) {
156 throw new CloneNotSupportedException(
157 exception.getMessage());
158 }
159 result._bytes = _byteOut.toByteArray();
160 result._byteOut = null;
161 result._out = null;
162 } else {
163 result._bytes = new byte[_bytes.length];
164 System.arraycopy(_bytes, 0, result._bytes, 0, _bytes.length);
165 }
166 }
167
168 return result;
169 }
170
171 /***
172 * Serialize out this message's data
173 *
174 * @param out the stream to serialize out to
175 * @throws IOException if any I/O exceptions occurr
176 */
177 public final void writeExternal(ObjectOutput out) throws IOException {
178 // If it was in write mode, extract the byte array.
179 if (!_bodyReadOnly && _out != null) {
180 _out.flush();
181 _bytes = _byteOut.toByteArray();
182 }
183
184 super.writeExternal(out);
185 out.writeLong(serialVersionUID);
186 out.writeInt(_bytes.length);
187 out.write(_bytes);
188 out.flush();
189 }
190
191 /***
192 * Serialize in this message's data
193 *
194 * @param in the stream to serialize in from
195 * @throws ClassNotFoundException if the class for an object being
196 * restored cannot be found.
197 * @throws IOException if any I/O exceptions occur
198 */
199 public final void readExternal(ObjectInput in)
200 throws ClassNotFoundException, IOException {
201 super.readExternal(in);
202 long version = in.readLong();
203 if (version == serialVersionUID) {
204 int length = in.readInt();
205 _bytes = new byte[length];
206 in.readFully(_bytes);
207 } else {
208 throw new IOException("Incorrect version enountered: " + version +
209 ". This version = " + serialVersionUID);
210 }
211 }
212
213 /***
214 * Read a <code>boolean</code> from the bytes message stream
215 *
216 * @return the <code>boolean</code> value read
217 * @throws JMSException if JMS fails to read message due to some internal
218 * JMS error
219 * @throws MessageEOFException if end of bytes stream
220 * @throws MessageNotReadableException if message is in write-only mode
221 */
222 public final boolean readBoolean() throws JMSException {
223 boolean result = false;
224 prepare();
225 try {
226 result = _in.readBoolean();
227 } catch (IOException exception) {
228 revert(exception);
229 }
230 return result;
231 }
232
233 /***
234 * Read a signed 8-bit value from the bytes message stream
235 *
236 * @return the next byte from the bytes message stream as a signed 8-bit
237 * <code>byte</code>
238 * @throws JMSException if JMS fails to read message due to some internal
239 * JMS error
240 * @throws MessageEOFException if end of message stream
241 * @throws MessageNotReadableException if message is in write-only mode
242 */
243 public final byte readByte() throws JMSException {
244 byte result = 0;
245 prepare();
246 try {
247 result = _in.readByte();
248 } catch (IOException exception) {
249 revert(exception);
250 }
251 return result;
252 }
253
254 /***
255 * Read an unsigned 8-bit number from the bytes message stream
256 *
257 * @return the next byte from the bytes message stream, interpreted as an
258 * unsigned 8-bit number
259 * @throws JMSException if JMS fails to read message due to some internal
260 * JMS error
261 * @throws MessageNotReadableException if message is in write-only mode
262 * @throws MessageEOFException if end of message stream
263 */
264 public final int readUnsignedByte() throws JMSException {
265 int result = 0;
266 prepare();
267 try {
268 result = _in.readUnsignedByte();
269 } catch (IOException exception) {
270 revert(exception);
271 }
272 return result;
273 }
274
275 /***
276 * Read a signed 16-bit number from the bytes message stream
277 *
278 * @return the next two bytes from the bytes message stream, interpreted
279 * as a signed 16-bit number
280 * @throws JMSException if JMS fails to read message due to some internal
281 * JMS error
282 * @throws MessageEOFException if end of message stream
283 * @throws MessageNotReadableException if message is in write-only mode
284 */
285 public final short readShort() throws JMSException {
286 short result = 0;
287 prepare();
288 try {
289 result = _in.readShort();
290 } catch (IOException exception) {
291 revert(exception);
292 }
293 return result;
294 }
295
296 /***
297 * Read an unsigned 16-bit number from the bytes message stream
298 *
299 * @return the next two bytes from the bytes message stream, interpreted
300 * as an unsigned 16-bit integer
301 *
302 * @throws JMSException if JMS fails to read message due to some internal
303 * JMS error
304 * @throws MessageEOFException if end of message stream
305 * @throws MessageNotReadableException if message is in write-only mode
306 */
307 public final int readUnsignedShort() throws JMSException {
308 int result = 0;
309 prepare();
310 try {
311 result = _in.readUnsignedShort();
312 } catch (IOException exception) {
313 revert(exception);
314 }
315 return result;
316 }
317
318 /***
319 * Read a Unicode character value from the bytes message stream
320 *
321 * @return the next two bytes from the bytes message stream as a Unicode
322 * character
323 * @throws JMSException if JMS fails to read message due to some internal
324 * JMS error
325 * @throws MessageEOFException if end of message stream
326 * @throws MessageNotReadableException if message is in write-only mode
327 */
328 public final char readChar() throws JMSException {
329 char result = 0;
330 prepare();
331 try {
332 result = _in.readChar();
333 } catch (IOException exception) {
334 revert(exception);
335 }
336 return result;
337 }
338
339 /***
340 * Read a signed 32-bit integer from the bytes message stream
341 *
342 * @return the next four bytes from the bytes message stream, interpreted
343 * as an <code>int</code>
344 * @throws JMSException if JMS fails to read message due to some internal
345 * JMS error
346 * @throws MessageEOFException if end of message stream
347 * @throws MessageNotReadableException if message is in write-only mode
348 */
349 public final int readInt() throws JMSException {
350 int result = 0;
351 prepare();
352 try {
353 result = _in.readInt();
354 } catch (IOException exception) {
355 revert(exception);
356 }
357 return result;
358 }
359
360 /***
361 * Read a signed 64-bit integer from the bytes message stream
362 *
363 * @return the next eight bytes from the bytes message stream, interpreted
364 * as a <code>long</code>.
365 * @throws JMSException if JMS fails to read message due to some internal
366 * JMS error
367 * @throws MessageEOFException if end of message stream
368 * @throws MessageNotReadableException if message is in write-only mode
369 */
370 public final long readLong() throws JMSException {
371 long result = 0;
372 prepare();
373 try {
374 result = _in.readLong();
375 } catch (IOException exception) {
376 revert(exception);
377 }
378 return result;
379 }
380
381 /***
382 * Read a <code>float</code> from the bytes message stream
383 *
384 * @return the next four bytes from the bytes message stream, interpreted
385 * as a <code>float</code>
386 * @throws JMSException if JMS fails to read message due to some internal
387 * JMS error
388 * @throws MessageEOFException if end of message stream
389 * @throws MessageNotReadableException if message is in write-only mode
390 */
391 public final float readFloat() throws JMSException {
392 float result = 0;
393 prepare();
394 try {
395 result = _in.readFloat();
396 } catch (IOException exception) {
397 revert(exception);
398 }
399 return result;
400 }
401
402 /***
403 * Read a <code>double</code> from the bytes message stream
404 *
405 * @return the next eight bytes from the bytes message stream,
406 * interpreted as a <code>double</code>
407 * @throws JMSException if JMS fails to read message due to some internal
408 * JMS error
409 * @throws MessageEOFException if end of message stream
410 * @throws MessageNotReadableException if message is in write-only mode
411 */
412 public final double readDouble() throws JMSException {
413 double result = 0;
414 prepare();
415 try {
416 result = _in.readDouble();
417 } catch (IOException exception) {
418 revert(exception);
419 }
420 return result;
421 }
422
423 /***
424 * Read in a string that has been encoded using a modified UTF-8 format
425 * from the bytes message stream
426 *
427 * <p>For more information on the UTF-8 format, see "File System Safe
428 * UCS Transformation Format (FSS_UFT)", X/Open Preliminary Specification,
429 * X/Open Company Ltd., Document Number: P316. This information also
430 * appears in ISO/IEC 10646, Annex P.
431 *
432 * @return a Unicode string from the bytes message stream
433 * @throws JMSException if JMS fails to read message due to some internal
434 * JMS error
435 * @throws MessageEOFException if end of message stream
436 * @throws MessageFormatException if string has an invalid format
437 * @throws MessageNotReadableException if message is in write-only mode
438 */
439 public final String readUTF() throws JMSException {
440 String result = null;
441 prepare();
442 try {
443 result = _in.readUTF();
444 } catch (IOException exception) {
445 revert(exception);
446 }
447 return result;
448 }
449
450 /***
451 * Read a byte array from the bytes message stream
452 *
453 * <p>If the length of array <code>value</code> is less than
454 * the bytes remaining to be read from the stream, the array should
455 * be filled. A subsequent call reads the next increment, etc.
456 *
457 * <p>If the bytes remaining in the stream is less than the length of
458 * array <code>value</code>, the bytes should be read into the array.
459 * The return value of the total number of bytes read will be less than
460 * the length of the array, indicating that there are no more bytes left
461 * to be read from the stream. The next read of the stream returns -1.
462 *
463 * @param value the buffer into which the data is read
464 * @return the total number of bytes read into the buffer, or -1 if
465 * there is no more data because the end of the stream has been reached
466 * @throws JMSException if JMS fails to read message due to some internal
467 * JMS error
468 * @throws MessageNotReadableException if message is in write-only mode
469 */
470 public final int readBytes(byte[] value) throws JMSException {
471 return readBytes(value, value.length);
472 }
473
474 /***
475 * Read a portion of the bytes message stream.
476 *
477 * <p>If the length of array <code>value</code> is less than
478 * the bytes remaining to be read from the stream, the array should
479 * be filled. A subsequent call reads the next increment, etc.
480 *
481 * <p>If the bytes remaining in the stream is less than the length of
482 * array <code>value</code>, the bytes should be read into the array.
483 * The return value of the total number of bytes read will be less than
484 * the length of the array, indicating that there are no more bytes left
485 * to be read from the stream. The next read of the stream returns -1.
486 *
487 * <p> If <code>length</code> is negative, or
488 * <code>length</code> is greater than the length of the array
489 * <code>value</code>, then an <code>IndexOutOfBoundsException</code> is
490 * thrown. No bytes will be read from the stream for this exception case.
491 *
492 * @param value the buffer into which the data is read.
493 * @param length the number of bytes to read. Must be less than or equal
494 * to value.length.
495 * @return the total number of bytes read into the buffer, or -1 if
496 * there is no more data because the end of the stream has been reached.
497 * @throws IndexOutOfBoundsException if <code>length</code> is invalid
498 * @throws JMSException if JMS fails to read message due to some internal
499 * JMS error
500 * @throws MessageNotReadableException if message is in write-only mode
501 */
502 public final int readBytes(byte[] value, int length) throws JMSException {
503 int read = -1;
504 prepare();
505
506 if (length < 0 || length > value.length) {
507 throw new IndexOutOfBoundsException(
508 "Length must be > 0 and less than array size");
509 }
510 try {
511 _in.mark(length);
512 int remain = _in.available();
513 if (remain == 0) {
514 read = -1;
515 } else if (length <= remain) {
516 read = length;
517 _in.read(value, 0, length);
518 } else {
519 _in.readFully(value, 0, remain);
520 read = remain;
521 }
522 } catch (EOFException ignore) {
523 } catch (IOException exception) {
524 revert(exception);
525 }
526 return read;
527 }
528
529 /***
530 * Write a <code>boolean</code> to the bytes message stream as a 1-byte
531 * value.
532 * The value <code>true</code> is written out as the value
533 * <code>(byte)1</code>; the value <code>false</code> is written out as
534 * the value <code>(byte)0</code>.
535 *
536 * @param value the <code>boolean</code> value to be written
537 * @throws JMSException if JMS fails to write message due to some internal
538 * JMS error
539 * @throws MessageNotWriteableException if message is in read-only mode
540 */
541 public final void writeBoolean(boolean value) throws JMSException {
542 checkWrite();
543 try {
544 getOutputStream().writeBoolean(value);
545 } catch (IOException exception) {
546 raise(exception);
547 }
548 }
549
550 /***
551 * Write out a <code>byte</code> to the bytes message stream as a 1-byte
552 * value
553 *
554 * @param value the <code>byte</code> value to be written
555 * @throws JMSException if JMS fails to write message due to some internal
556 * JMS error
557 * @throws MessageNotWriteableException if message is in read-only mode
558 */
559 public final void writeByte(byte value) throws JMSException {
560 checkWrite();
561 try {
562 getOutputStream().writeByte(value);
563 } catch (IOException exception) {
564 raise(exception);
565 }
566 }
567
568 /***
569 * Write a <code>short</code> to the bytes message stream as two bytes,
570 * high byte first
571 *
572 * @param value the <code>short</code> to be written
573 * @throws JMSException if JMS fails to write message due to some internal
574 * JMS error
575 * @throws MessageNotWriteableException if message is in read-only mode
576 */
577 public final void writeShort(short value) throws JMSException {
578 checkWrite();
579 try {
580 getOutputStream().writeShort(value);
581 } catch (IOException exception) {
582 raise(exception);
583 }
584 }
585
586 /***
587 * Write a <code>char</code> to the bytes message stream as a 2-byte
588 * value, high byte first.
589 *
590 * @param value the <code>char</code> value to be written
591 * @throws MessageNotWriteableException if message is in read-only mode
592 * @throws JMSException if JMS fails to write message due to some internal
593 * JMS error
594 */
595 public final void writeChar(char value) throws JMSException {
596 checkWrite();
597 try {
598 getOutputStream().writeChar(value);
599 } catch (IOException exception) {
600 raise(exception);
601 }
602 }
603
604 /***
605 * Write an <code>int</code> to the bytes message stream as four bytes,
606 * high byte first.
607 *
608 * @param value the <code>int</code> to be written
609 * @throws JMSException if JMS fails to write message due to some internal
610 * JMS error
611 * @throws MessageNotWriteableException if message is in read-only mode
612 */
613 public final void writeInt(int value) throws JMSException {
614 checkWrite();
615 try {
616 getOutputStream().writeInt(value);
617 } catch (IOException exception) {
618 raise(exception);
619 }
620 }
621
622 /***
623 * Write a <code>long</code> to the bytes message stream as eight bytes,
624 * high byte first
625 *
626 * @param value the <code>long</code> to be written
627 * @throws JMSException if JMS fails to write message due to some internal
628 * JMS error
629 * @throws MessageNotWriteableException if message is in read-only mode
630 */
631 public final void writeLong(long value) throws JMSException {
632 checkWrite();
633 try {
634 getOutputStream().writeLong(value);
635 } catch (IOException exception) {
636 raise(exception);
637 }
638 }
639
640 /***
641 * Convert the float argument to an <code>int</code> using the
642 * <code>floatToIntBits</code> method in class <code>Float</code>,
643 * and then writes that <code>int</code> value to the bytes message
644 * stream as a 4-byte quantity, high byte first.
645 *
646 * @param value the <code>float</code> value to be written.
647 * @throws JMSException if JMS fails to write message due to some internal
648 * JMS error
649 * @throws MessageNotWriteableException if message is in read-only mode
650 */
651 public final void writeFloat(float value) throws JMSException {
652 checkWrite();
653 try {
654 getOutputStream().writeFloat(value);
655 } catch (IOException exception) {
656 raise(exception);
657 }
658 }
659
660
661 /***
662 * Convert the double argument to a <code>long</code> using the
663 * <code>doubleToLongBits</code> method in class <code>Double</code>,
664 * and then writes that <code>long</code> value to the bytes message
665 * stream as an 8-byte quantity, high byte first.
666 *
667 * @param value the <code>double</code> value to be written.
668 * @throws JMSException if JMS fails to write message due to some internal
669 * JMS error
670 * @throws MessageNotWriteableException if message is in read-only mode
671 */
672 public final void writeDouble(double value) throws JMSException {
673 checkWrite();
674 try {
675 getOutputStream().writeDouble(value);
676 } catch (IOException exception) {
677 raise(exception);
678 }
679 }
680
681 /***
682 * Write a string to the bytes message stream using UTF-8 encoding in a
683 * machine-independent manner.
684 *
685 * <p>For more information on the UTF-8 format, see "File System Safe
686 * UCS Transformation Format (FSS_UFT)", X/Open Preliminary Specification,
687 * X/Open Company Ltd., Document Number: P316. This information also
688 * appears in ISO/IEC 10646, Annex P.
689 *
690 * @param value the <code>String</code> value to be written
691 * @throws MessageNotWriteableException if message is in read-only mode
692 * @throws JMSException if JMS fails to write message due to some internal
693 * JMS error
694 */
695 public final void writeUTF(String value) throws JMSException {
696 checkWrite();
697 try {
698 getOutputStream().writeUTF(value);
699 } catch (IOException exception) {
700 raise(exception);
701 }
702 }
703
704 /***
705 * Write a byte array to the bytes message stream
706 *
707 * @param value the byte array to be written.
708 * @throws JMSException if JMS fails to write message due to some internal
709 * JMS error
710 * @throws MessageNotWriteableException if message is in read-only mode
711 */
712 public final void writeBytes(byte[] value) throws JMSException {
713 checkWrite();
714 try {
715 getOutputStream().write(value);
716 } catch (IOException exception) {
717 raise(exception);
718 }
719 }
720
721 /***
722 * Write a portion of a byte array to the bytes message stream
723 *
724 * @param value the byte array value to be written.
725 * @param offset the initial offset within the byte array.
726 * @param length the number of bytes to use.
727 * @throws JMSException if JMS fails to write message due to some internal
728 * JMS error
729 * @throws MessageNotWriteableException if message is in read-only mode
730 */
731 public final void writeBytes(byte[] value, int offset, int length)
732 throws JMSException {
733 checkWrite();
734 try {
735 getOutputStream().write(value, offset, length);
736 } catch (IOException exception) {
737 raise(exception);
738 }
739 }
740
741 /***
742 * Write a Java object to the bytes message stream.
743 *
744 * <p>Note that this method only works for the objectified primitive
745 * object types (Integer, Double, Long ...), String's and byte arrays.
746 *
747 * @param value the Java object to be written. Must not be null.
748 *
749 * @throws JMSException if JMS fails to write message due to some internal
750 * JMS error
751 * @throws MessageFormatException if object is invalid type
752 * @throws MessageNotWriteableException if message in read-only mode
753 * @throws NullPointerException if parameter <code>value</code> is null
754 */
755 public final void writeObject(Object value) throws JMSException {
756 if (value instanceof Boolean) {
757 writeBoolean(((Boolean) value).booleanValue());
758 } else if (value instanceof Byte) {
759 writeByte(((Byte) value).byteValue());
760 } else if (value instanceof Short) {
761 writeShort(((Short) value).shortValue());
762 } else if (value instanceof Character) {
763 writeChar(((Character) value).charValue());
764 } else if (value instanceof Integer) {
765 writeInt(((Integer) value).intValue());
766 } else if (value instanceof Long) {
767 writeLong(((Long) value).longValue());
768 } else if (value instanceof Float) {
769 writeFloat(((Float) value).floatValue());
770 } else if (value instanceof Double) {
771 writeDouble(((Double) value).doubleValue());
772 } else if (value instanceof String) {
773 writeUTF((String) value);
774 } else if (value instanceof byte[]) {
775 writeBytes((byte[]) value);
776 } else if (value == null) {
777 throw new NullPointerException(
778 "BytesMessage does not support null");
779 } else {
780 throw new MessageFormatException("Cannot write objects of type=" +
781 value.getClass().getName());
782 }
783 }
784
785 /***
786 * Put the message body in read-only mode, and reposition the stream of
787 * bytes to the beginning
788 *
789 * @throws JMSException if JMS fails to reset the message due to some
790 * internal JMS error
791 */
792 public final void reset() throws JMSException {
793 try {
794 if (!_bodyReadOnly) {
795 _bodyReadOnly = true;
796 if (_out != null) {
797 _out.flush();
798 _bytes = _byteOut.toByteArray();
799 _byteOut = null;
800 _out.close();
801 _out = null;
802 }
803 } else {
804 if (_in != null) {
805 _byteIn = null;
806 _in.close();
807 _in = null;
808 }
809 }
810 } catch (IOException exception) {
811 raise(exception);
812 }
813 }
814
815 /***
816 * Overide the super class method to reset the streams, and put the
817 * message body in write only mode.
818 *
819 * <p>If <code>clearBody</code> is called on a message in read-only mode,
820 * the message body is cleared and the message is in write-only mode.
821 * bytes to the beginning.
822 *
823 * <p>If <code>clearBody</code> is called on a message already in
824 * write-only mode, the spec does not define the outcome, so do nothing.
825 * Client must then call <code>reset</code>, followed by
826 * <code>clearBody</code> to reset the stream at the beginning for a
827 * new write.
828 * @throws JMSException if JMS fails to reset the message due to some
829 * internal JMS error
830 */
831 public final void clearBody() throws JMSException {
832 try {
833 if (_bodyReadOnly) {
834 // in read-only mode
835 _bodyReadOnly = false;
836 if (_in != null) {
837 _byteIn = null;
838 _in.close();
839 _in = null;
840 _offset = 0;
841 }
842 } else if (_out != null) {
843 // already in write-only mode
844 _byteOut = null;
845 _out.close();
846 _out = null;
847 }
848 _bytes = EMPTY;
849 _byteOut = null;
850 _out = null;
851 } catch (IOException exception) {
852 raise(exception);
853 }
854 }
855
856 /***
857 * Set the read-only mode of the message.
858 *
859 * @param readOnly if true, make the message body and properties read-only,
860 * and invoke {@link #reset}
861 * @throws JMSException if the read-only mode cannot be changed
862 */
863 public final void setReadOnly(boolean readOnly) throws JMSException {
864 if (readOnly) {
865 reset();
866 }
867 super.setReadOnly(readOnly);
868 }
869
870 /***
871 * Prepare to do a read
872 *
873 * @throws JMSException if the current position in the stream can't be
874 * marked
875 * @throws MessageNotReadableException if the message is in write-only mode
876 */
877 private final void prepare() throws JMSException {
878 checkRead();
879 getInputStream();
880 try {
881 _in.mark(_bytes.length - _in.available());
882 } catch (IOException exception) {
883 raise(exception);
884 }
885 }
886
887 /***
888 * Reverts the stream to its prior position if an I/O exception is
889 * thrown, and propagates the exception as a JMSException
890 *
891 * @param exception the exception that caused the reset
892 * @throws JMSException for general IOException errors
893 * @throws MessageEOFException if end-of-file was reached
894 */
895 private final void revert(IOException exception) throws JMSException {
896 try {
897 _in.reset();
898 } catch (IOException ignore) {
899 }
900 JMSException error = null;
901 if (exception instanceof EOFException) {
902 error = new MessageEOFException(exception.getMessage());
903 } else if (exception instanceof UTFDataFormatException) {
904 error = new MessageFormatException(exception.getMessage());
905 } else {
906 error = new JMSException(exception.getMessage());
907 }
908 error.setLinkedException(exception);
909 throw error;
910 }
911
912 /***
913 * Initialise the input stream if it hasn't been intialised
914 *
915 * @return the input stream
916 */
917 private DataInputStream getInputStream() {
918 if (_in == null) {
919 _byteIn = new ByteArrayInputStream(_bytes, _offset,
920 _bytes.length - _offset);
921 _in = new DataInputStream(_byteIn);
922 }
923 return _in;
924 }
925
926 /***
927 * Initialise the output stream if it hasn't been intialised
928 *
929 * @return the output stream
930 * @throws IOException if the output stream can't be created
931 */
932 private final DataOutputStream getOutputStream() throws IOException {
933 if (_out == null) {
934 _byteOut = new ByteArrayOutputStream();
935 _out = new DataOutputStream(_byteOut);
936 _out.write(_bytes);
937 }
938 return _out;
939 }
940
941 /***
942 * Helper to raise a JMSException when an I/O error occurs
943 *
944 * @param exception the exception that caused the failure
945 * @throws JMSException
946 */
947 private final void raise(IOException exception) throws JMSException {
948 JMSException error = new JMSException(exception.getMessage());
949 error.setLinkedException(exception);
950 throw error;
951 }
952
953 } //-- BytesMessageImpl
This page was automatically generated by Maven