Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/activemq/message/ActiveMQBytesMessage.java


1   /** 
2    * 
3    * Copyright 2004 Protique Ltd
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License"); 
6    * you may not use this file except in compliance with the License. 
7    * You may obtain a copy of the License at 
8    * 
9    * http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License. 
16   * 
17   **/
18  package org.activemq.message;
19  
20  import javax.jms.BytesMessage;
21  import javax.jms.JMSException;
22  import javax.jms.MessageEOFException;
23  import javax.jms.MessageFormatException;
24  import javax.jms.MessageNotReadableException;
25  import javax.jms.MessageNotWriteableException;
26  
27  import org.activemq.io.util.ByteArray;
28  import org.activemq.io.util.ByteArrayCompression;
29  
30  import java.io.ByteArrayInputStream;
31  import java.io.ByteArrayOutputStream;
32  import java.io.DataInputStream;
33  import java.io.DataOutputStream;
34  import java.io.EOFException;
35  import java.io.IOException;
36  
37  /**
38   * A <CODE>BytesMessage</CODE> object is used to send a message containing a stream of uninterpreted bytes. It
39   * inherits from the <CODE>Message</CODE> interface and adds a bytes message body. The receiver of the message
40   * supplies the interpretation of the bytes.
41   * <P>
42   * The <CODE>BytesMessage</CODE> methods are based largely on those found in <CODE>java.io.DataInputStream</CODE>
43   * and <CODE>java.io.DataOutputStream</CODE>.
44   * <P>
45   * This message type is for client encoding of existing message formats. If possible, one of the other self-defining
46   * message types should be used instead.
47   * <P>
48   * Although the JMS API allows the use of message properties with byte messages, they are typically not used, since the
49   * inclusion of properties may affect the format.
50   * <P>
51   * The primitive types can be written explicitly using methods for each type. They may also be written generically as
52   * objects. For instance, a call to <CODE>BytesMessage.writeInt(6)</CODE> is equivalent to <CODE>
53   * BytesMessage.writeObject(new Integer(6))</CODE>. Both forms are provided, because the explicit form is convenient
54   * for static programming, and the object form is needed when types are not known at compile time.
55   * <P>
56   * When the message is first created, and when <CODE>clearBody</CODE> is called, the body of the message is in
57   * write-only mode. After the first call to <CODE>reset</CODE> has been made, the message body is in read-only mode.
58   * After a message has been sent, the client that sent it can retain and modify it without affecting the message that
59   * has been sent. The same message object can be sent multiple times. When a message has been received, the provider
60   * has called <CODE>reset</CODE> so that the message body is in read-only mode for the client.
61   * <P>
62   * If <CODE>clearBody</CODE> is called on a message in read-only mode, the message body is cleared and the message is
63   * in write-only mode.
64   * <P>
65   * If a client attempts to read a message in write-only mode, a <CODE>MessageNotReadableException</CODE> is thrown.
66   * <P>
67   * If a client attempts to write a message in read-only mode, a <CODE>MessageNotWriteableException</CODE> is thrown.
68   * 
69   * @see javax.jms.Session#createBytesMessage()
70   * @see javax.jms.MapMessage
71   * @see javax.jms.Message
72   * @see javax.jms.ObjectMessage
73   * @see javax.jms.StreamMessage
74   * @see javax.jms.TextMessage
75   */
76  public class ActiveMQBytesMessage extends ActiveMQMessage implements BytesMessage {
77      private DataOutputStream dataOut;
78      private ByteArrayOutputStream bytesOut;
79      private DataInputStream dataIn;
80      private transient long bodyLength = 0;
81  
82      /**
83       * Return the type of Packet
84       * 
85       * @return integer representation of the type of Packet
86       */
87      public int getPacketType() {
88          return ACTIVEMQ_BYTES_MESSAGE;
89      }
90  
91      /**
92       * @return Returns a shallow copy of the message instance
93       * @throws JMSException
94       */
95      public ActiveMQMessage shallowCopy() throws JMSException {
96          ActiveMQBytesMessage other = new ActiveMQBytesMessage();
97          this.initializeOther(other);
98          try {
99              other.setBodyAsBytes(this.getBodyAsBytes());
100         }
101         catch (IOException e) {
102             JMSException jmsEx = new JMSException("setBodyAsBytes() failed");
103             jmsEx.setLinkedException(e);
104             throw jmsEx;
105         }
106         return other;
107     }
108 
109     /**
110      * @return Returns a deep copy of the message - note the header fields are only shallow copied
111      * @throws JMSException
112      */
113     public ActiveMQMessage deepCopy() throws JMSException {
114         ActiveMQBytesMessage other = new ActiveMQBytesMessage();
115         this.initializeOther(other);
116         try {
117             if (this.getBodyAsBytes() != null) {
118                 ByteArray data = this.getBodyAsBytes().copy();
119                 other.setBodyAsBytes(data);
120             }
121         }
122         catch (IOException e) {
123             JMSException jmsEx = new JMSException("setBodyAsBytes() failed");
124             jmsEx.setLinkedException(e);
125             throw jmsEx;
126         }
127         return other;
128     }
129 
130     /**
131      * @param bodyAsBytes The bodyAsBytes to set.
132      * @param offset
133      * @param length
134      */
135     public void setBodyAsBytes(byte[] bodyAsBytes,int offset, int length) {
136         super.setBodyAsBytes(bodyAsBytes,offset,length);
137         dataOut = null;
138         dataIn = null;
139     }
140 
141     /**
142      * @return Returns the data body
143      * @throws IOException if an exception occurs retreiving the data
144      */
145     public ByteArray getBodyAsBytes() throws IOException {
146         if (this.dataOut != null) {
147             this.dataOut.flush();
148             byte[] data = this.bytesOut.toByteArray();
149             super.setBodyAsBytes(data,0,data.length);
150             dataOut.close();
151             dataOut = null;
152         }
153         return super.getBodyAsBytes();
154     }
155     
156     
157 
158     /**
159      * Clears out the message body. Clearing a message's body does not clear its header values or property entries.
160      * <P>
161      * If this message body was read-only, calling this method leaves the message body in the same state as an empty
162      * body in a newly created message.
163      *
164      * @throws JMSException if the JMS provider fails to clear the message body due to some internal error.
165      */
166     public void clearBody() throws JMSException {
167         super.clearBody();
168         this.dataOut = null;
169         this.dataIn = null;
170         this.bytesOut = null;
171     }
172 
173     /**
174      * Gets the number of bytes of the message body when the message is in read-only mode. The value returned can be
175      * used to allocate a byte array. The value returned is the entire length of the message body, regardless of where
176      * the pointer for reading the message is currently located.
177      *
178      * @return number of bytes in the message
179      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
180      * @throws MessageNotReadableException if the message is in write-only mode.
181      * @since 1.1
182      */
183     public long getBodyLength() throws JMSException {
184         initializeReading();
185         return bodyLength;
186     }
187 
188     /**
189      * Reads a <code>boolean</code> from the bytes message stream.
190      *
191      * @return the <code>boolean</code> value read
192      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
193      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
194      * @throws MessageNotReadableException if the message is in write-only mode.
195      */
196     public boolean readBoolean() throws JMSException {
197         initializeReading();
198         try {
199             return this.dataIn.readBoolean();
200         }
201         catch (EOFException eof) {
202             JMSException jmsEx = new MessageEOFException(eof.getMessage());
203             jmsEx.setLinkedException(eof);
204             throw jmsEx;
205         }
206         catch (IOException ioe) {
207             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
208             jmsEx.setLinkedException(ioe);
209             throw jmsEx;
210         }
211     }
212 
213     /**
214      * Reads a signed 8-bit value from the bytes message stream.
215      *
216      * @return the next byte from the bytes message stream as a signed 8-bit <code>byte</code>
217      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
218      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
219      * @throws MessageNotReadableException if the message is in write-only mode.
220      */
221     public byte readByte() throws JMSException {
222         initializeReading();
223         try {
224             return this.dataIn.readByte();
225         }
226         catch (EOFException eof) {
227             JMSException jmsEx = new MessageEOFException(eof.getMessage());
228             jmsEx.setLinkedException(eof);
229             throw jmsEx;
230         }
231         catch (IOException ioe) {
232             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
233             jmsEx.setLinkedException(ioe);
234             throw jmsEx;
235         }
236     }
237 
238     /**
239      * Reads an unsigned 8-bit number from the bytes message stream.
240      *
241      * @return the next byte from the bytes message stream, interpreted as an unsigned 8-bit number
242      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
243      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
244      * @throws MessageNotReadableException if the message is in write-only mode.
245      */
246     public int readUnsignedByte() throws JMSException {
247         initializeReading();
248         try {
249             return this.dataIn.readUnsignedByte();
250         }
251         catch (EOFException eof) {
252             JMSException jmsEx = new MessageEOFException(eof.getMessage());
253             jmsEx.setLinkedException(eof);
254             throw jmsEx;
255         }
256         catch (IOException ioe) {
257             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
258             jmsEx.setLinkedException(ioe);
259             throw jmsEx;
260         }
261     }
262 
263     /**
264      * Reads a signed 16-bit number from the bytes message stream.
265      *
266      * @return the next two bytes from the bytes message stream, interpreted as a signed 16-bit number
267      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
268      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
269      * @throws MessageNotReadableException if the message is in write-only mode.
270      */
271     public short readShort() throws JMSException {
272         initializeReading();
273         try {
274             return this.dataIn.readShort();
275         }
276         catch (EOFException eof) {
277             JMSException jmsEx = new MessageEOFException(eof.getMessage());
278             jmsEx.setLinkedException(eof);
279             throw jmsEx;
280         }
281         catch (IOException ioe) {
282             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
283             jmsEx.setLinkedException(ioe);
284             throw jmsEx;
285         }
286     }
287 
288     /**
289      * Reads an unsigned 16-bit number from the bytes message stream.
290      *
291      * @return the next two bytes from the bytes message stream, interpreted as an unsigned 16-bit integer
292      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
293      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
294      * @throws MessageNotReadableException if the message is in write-only mode.
295      */
296     public int readUnsignedShort() throws JMSException {
297         initializeReading();
298         try {
299             return this.dataIn.readUnsignedShort();
300         }
301         catch (EOFException eof) {
302             JMSException jmsEx = new MessageEOFException(eof.getMessage());
303             jmsEx.setLinkedException(eof);
304             throw jmsEx;
305         }
306         catch (IOException ioe) {
307             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
308             jmsEx.setLinkedException(ioe);
309             throw jmsEx;
310         }
311     }
312 
313     /**
314      * Reads a Unicode character value from the bytes message stream.
315      *
316      * @return the next two bytes from the bytes message stream as a Unicode character
317      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
318      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
319      * @throws MessageNotReadableException if the message is in write-only mode.
320      */
321     public char readChar() throws JMSException {
322         initializeReading();
323         try {
324             return this.dataIn.readChar();
325         }
326         catch (EOFException eof) {
327             JMSException jmsEx = new MessageEOFException(eof.getMessage());
328             jmsEx.setLinkedException(eof);
329             throw jmsEx;
330         }
331         catch (IOException ioe) {
332             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
333             jmsEx.setLinkedException(ioe);
334             throw jmsEx;
335         }
336     }
337 
338     /**
339      * Reads a signed 32-bit integer from the bytes message stream.
340      *
341      * @return the next four bytes from the bytes message stream, interpreted as an <code>int</code>
342      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
343      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
344      * @throws MessageNotReadableException if the message is in write-only mode.
345      */
346     public int readInt() throws JMSException {
347         initializeReading();
348         try {
349             return this.dataIn.readInt();
350         }
351         catch (EOFException eof) {
352             JMSException jmsEx = new MessageEOFException(eof.getMessage());
353             jmsEx.setLinkedException(eof);
354             throw jmsEx;
355         }
356         catch (IOException ioe) {
357             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
358             jmsEx.setLinkedException(ioe);
359             throw jmsEx;
360         }
361     }
362 
363     /**
364      * Reads a signed 64-bit integer from the bytes message stream.
365      *
366      * @return the next eight bytes from the bytes message stream, interpreted as a <code>long</code>
367      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
368      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
369      * @throws MessageNotReadableException if the message is in write-only mode.
370      */
371     public long readLong() throws JMSException {
372         initializeReading();
373         try {
374             return this.dataIn.readLong();
375         }
376         catch (EOFException eof) {
377             JMSException jmsEx = new MessageEOFException(eof.getMessage());
378             jmsEx.setLinkedException(eof);
379             throw jmsEx;
380         }
381         catch (IOException ioe) {
382             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
383             jmsEx.setLinkedException(ioe);
384             throw jmsEx;
385         }
386     }
387 
388     /**
389      * Reads a <code>float</code> from the bytes message stream.
390      *
391      * @return the next four bytes from the bytes message stream, interpreted as a <code>float</code>
392      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
393      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
394      * @throws MessageNotReadableException if the message is in write-only mode.
395      */
396     public float readFloat() throws JMSException {
397         initializeReading();
398         try {
399             return this.dataIn.readFloat();
400         }
401         catch (EOFException eof) {
402             JMSException jmsEx = new MessageEOFException(eof.getMessage());
403             jmsEx.setLinkedException(eof);
404             throw jmsEx;
405         }
406         catch (IOException ioe) {
407             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
408             jmsEx.setLinkedException(ioe);
409             throw jmsEx;
410         }
411     }
412 
413     /**
414      * Reads a <code>double</code> from the bytes message stream.
415      *
416      * @return the next eight bytes from the bytes message stream, interpreted as a <code>double</code>
417      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
418      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
419      * @throws MessageNotReadableException if the message is in write-only mode.
420      */
421     public double readDouble() throws JMSException {
422         initializeReading();
423         try {
424             return this.dataIn.readDouble();
425         }
426         catch (EOFException eof) {
427             JMSException jmsEx = new MessageEOFException(eof.getMessage());
428             jmsEx.setLinkedException(eof);
429             throw jmsEx;
430         }
431         catch (IOException ioe) {
432             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
433             jmsEx.setLinkedException(ioe);
434             throw jmsEx;
435         }
436     }
437 
438     /**
439      * Reads a string that has been encoded using a modified UTF-8 format from the bytes message stream.
440      * <P>
441      * For more information on the UTF-8 format, see "File System Safe UCS Transformation Format (FSS_UTF)", X/Open
442      * Preliminary Specification, X/Open Company Ltd., Document Number: P316. This information also appears in ISO/IEC
443      * 10646, Annex P.
444      *
445      * @return a Unicode string from the bytes message stream
446      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
447      * @throws MessageEOFException         if unexpected end of bytes stream has been reached.
448      * @throws MessageNotReadableException if the message is in write-only mode.
449      */
450     public String readUTF() throws JMSException {
451         initializeReading();
452         try {
453             return this.dataIn.readUTF();
454         }
455         catch (EOFException eof) {
456             JMSException jmsEx = new MessageEOFException(eof.getMessage());
457             jmsEx.setLinkedException(eof);
458             throw jmsEx;
459         }
460         catch (IOException ioe) {
461             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
462             jmsEx.setLinkedException(ioe);
463             throw jmsEx;
464         }
465     }
466 
467     /**
468      * Reads a byte array from the bytes message stream.
469      * <P>
470      * If the length of array <code>value</code> is less than the number of bytes remaining to be read from the
471      * stream, the array should be filled. A subsequent call reads the next increment, and so on.
472      * <P>
473      * If the number of bytes remaining in the stream is less than the length of array <code>value</code>, the bytes
474      * should be read into the array. The return value of the total number of bytes read will be less than the length
475      * of the array, indicating that there are no more bytes left to be read from the stream. The next read of the
476      * stream returns -1.
477      *
478      * @param value the buffer into which the data is read
479      * @return the total number of bytes read into the buffer, or -1 if there is no more data because the end of the
480      *         stream has been reached
481      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
482      * @throws MessageNotReadableException if the message is in write-only mode.
483      */
484     public int readBytes(byte[] value) throws JMSException {
485         return readBytes(value, value.length);
486     }
487 
488     /**
489      * Reads a portion of the bytes message stream.
490      * <P>
491      * If the length of array <code>value</code> is less than the number of bytes remaining to be read from the
492      * stream, the array should be filled. A subsequent call reads the next increment, and so on.
493      * <P>
494      * If the number of bytes remaining in the stream is less than the length of array <code>value</code>, the bytes
495      * should be read into the array. The return value of the total number of bytes read will be less than the length
496      * of the array, indicating that there are no more bytes left to be read from the stream. The next read of the
497      * stream returns -1.
498      * <p/>
499      * If <code>length</code> is negative, or <code>length</code> is greater than the length of the array <code>value</code>,
500      * then an <code>IndexOutOfBoundsException</code> is thrown. No bytes will be read from the stream for this
501      * exception case.
502      *
503      * @param value  the buffer into which the data is read
504      * @param length the number of bytes to read; must be less than or equal to <code>value.length</code>
505      * @return the total number of bytes read into the buffer, or -1 if there is no more data because the end of the
506      *         stream has been reached
507      * @throws JMSException                if the JMS provider fails to read the message due to some internal error.
508      * @throws MessageNotReadableException if the message is in write-only mode.
509      */
510     public int readBytes(byte[] value, int length) throws JMSException {
511         initializeReading();
512         try {
513             int n = 0;
514             while (n < length) {
515                 int count = this.dataIn.read(value, n, length - n);
516                 if (count < 0) {
517                     break;
518                 }
519                 n += count;
520             }
521             if (n == 0 && length > 0) {
522                 n = -1;
523             }
524             return n;
525         }
526         catch (EOFException eof) {
527             JMSException jmsEx = new MessageEOFException(eof.getMessage());
528             jmsEx.setLinkedException(eof);
529             throw jmsEx;
530         }
531         catch (IOException ioe) {
532             JMSException jmsEx = new JMSException("Format error occured" + ioe.getMessage());
533             jmsEx.setLinkedException(ioe);
534             throw jmsEx;
535         }
536     }
537 
538     /**
539      * Writes a <code>boolean</code> to the bytes message stream as a 1-byte value. The value <code>true</code> is
540      * written as the value <code>(byte)1</code>; the value <code>false</code> is written as the value <code>(byte)0</code>.
541      *
542      * @param value the <code>boolean</code> value to be written
543      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
544      * @throws MessageNotWriteableException if the message is in read-only mode.
545      */
546     public void writeBoolean(boolean value) throws JMSException {
547         initializeWriting();
548         try {
549             this.dataOut.writeBoolean(value);
550         }
551         catch (IOException ioe) {
552             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
553             jmsEx.setLinkedException(ioe);
554             throw jmsEx;
555         }
556     }
557 
558     /**
559      * Writes a <code>byte</code> to the bytes message stream as a 1-byte value.
560      *
561      * @param value the <code>byte</code> value to be written
562      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
563      * @throws MessageNotWriteableException if the message is in read-only mode.
564      */
565     public void writeByte(byte value) throws JMSException {
566         initializeWriting();
567         try {
568             this.dataOut.writeByte(value);
569         }
570         catch (IOException ioe) {
571             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
572             jmsEx.setLinkedException(ioe);
573             throw jmsEx;
574         }
575     }
576 
577     /**
578      * Writes a <code>short</code> to the bytes message stream as two bytes, high byte first.
579      *
580      * @param value the <code>short</code> to be written
581      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
582      * @throws MessageNotWriteableException if the message is in read-only mode.
583      */
584     public void writeShort(short value) throws JMSException {
585         initializeWriting();
586         try {
587             this.dataOut.writeShort(value);
588         }
589         catch (IOException ioe) {
590             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
591             jmsEx.setLinkedException(ioe);
592             throw jmsEx;
593         }
594     }
595 
596     /**
597      * Writes a <code>char</code> to the bytes message stream as a 2-byte value, high byte first.
598      *
599      * @param value the <code>char</code> value to be written
600      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
601      * @throws MessageNotWriteableException if the message is in read-only mode.
602      */
603     public void writeChar(char value) throws JMSException {
604         initializeWriting();
605         try {
606             this.dataOut.writeChar(value);
607         }
608         catch (IOException ioe) {
609             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
610             jmsEx.setLinkedException(ioe);
611             throw jmsEx;
612         }
613     }
614 
615     /**
616      * Writes an <code>int</code> to the bytes message stream as four bytes, high byte first.
617      *
618      * @param value the <code>int</code> to be written
619      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
620      * @throws MessageNotWriteableException if the message is in read-only mode.
621      */
622     public void writeInt(int value) throws JMSException {
623         initializeWriting();
624         try {
625             this.dataOut.writeInt(value);
626         }
627         catch (IOException ioe) {
628             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
629             jmsEx.setLinkedException(ioe);
630             throw jmsEx;
631         }
632     }
633 
634     /**
635      * Writes a <code>long</code> to the bytes message stream as eight bytes, high byte first.
636      *
637      * @param value the <code>long</code> to be written
638      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
639      * @throws MessageNotWriteableException if the message is in read-only mode.
640      */
641     public void writeLong(long value) throws JMSException {
642         initializeWriting();
643         try {
644             this.dataOut.writeLong(value);
645         }
646         catch (IOException ioe) {
647             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
648             jmsEx.setLinkedException(ioe);
649             throw jmsEx;
650         }
651     }
652 
653     /**
654      * Converts the <code>float</code> argument to an <code>int</code> using the <code>floatToIntBits</code>
655      * method in class <code>Float</code>, and then writes that <code>int</code> value to the bytes message stream
656      * as a 4-byte quantity, high byte first.
657      *
658      * @param value the <code>float</code> value to be written
659      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
660      * @throws MessageNotWriteableException if the message is in read-only mode.
661      */
662     public void writeFloat(float value) throws JMSException {
663         initializeWriting();
664         try {
665             this.dataOut.writeFloat(value);
666         }
667         catch (IOException ioe) {
668             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
669             jmsEx.setLinkedException(ioe);
670             throw jmsEx;
671         }
672     }
673 
674     /**
675      * Converts the <code>double</code> argument to a <code>long</code> using the <code>doubleToLongBits</code>
676      * method in class <code>Double</code>, and then writes that <code>long</code> value to the bytes message
677      * stream as an 8-byte quantity, high byte first.
678      *
679      * @param value the <code>double</code> value to be written
680      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
681      * @throws MessageNotWriteableException if the message is in read-only mode.
682      */
683     public void writeDouble(double value) throws JMSException {
684         initializeWriting();
685         try {
686             this.dataOut.writeDouble(value);
687         }
688         catch (IOException ioe) {
689             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
690             jmsEx.setLinkedException(ioe);
691             throw jmsEx;
692         }
693     }
694 
695     /**
696      * Writes a string to the bytes message stream using UTF-8 encoding in a machine-independent manner.
697      * <P>
698      * For more information on the UTF-8 format, see "File System Safe UCS Transformation Format (FSS_UTF)", X/Open
699      * Preliminary Specification, X/Open Company Ltd., Document Number: P316. This information also appears in ISO/IEC
700      * 10646, Annex P.
701      *
702      * @param value the <code>String</code> value to be written
703      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
704      * @throws MessageNotWriteableException if the message is in read-only mode.
705      */
706     public void writeUTF(String value) throws JMSException {
707         initializeWriting();
708         try {
709             this.dataOut.writeUTF(value);
710         }
711         catch (IOException ioe) {
712             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
713             jmsEx.setLinkedException(ioe);
714             throw jmsEx;
715         }
716     }
717 
718     /**
719      * Writes a byte array to the bytes message stream.
720      *
721      * @param value the byte array to be written
722      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
723      * @throws MessageNotWriteableException if the message is in read-only mode.
724      */
725     public void writeBytes(byte[] value) throws JMSException {
726         initializeWriting();
727         try {
728             this.dataOut.write(value);
729         }
730         catch (IOException ioe) {
731             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
732             jmsEx.setLinkedException(ioe);
733             throw jmsEx;
734         }
735     }
736 
737     /**
738      * Writes a portion of a byte array to the bytes message stream.
739      *
740      * @param value  the byte array value to be written
741      * @param offset the initial offset within the byte array
742      * @param length the number of bytes to use
743      * @throws JMSException                 if the JMS provider fails to write the message due to some internal error.
744      * @throws MessageNotWriteableException if the message is in read-only mode.
745      */
746     public void writeBytes(byte[] value, int offset, int length) throws JMSException {
747         initializeWriting();
748         try {
749             this.dataOut.write(value, offset, length);
750         }
751         catch (IOException ioe) {
752             JMSException jmsEx = new JMSException("Could not write data:" + ioe.getMessage());
753             jmsEx.setLinkedException(ioe);
754             throw jmsEx;
755         }
756     }
757 
758     /**
759      * Writes an object to the bytes message stream.
760      * <P>
761      * This method works only for the objectified primitive object types (<code>Integer</code>,<code>Double</code>,
762      * <code>Long</code> &nbsp;...), <code>String</code> objects, and byte arrays.
763      *
764      * @param value the object in the Java programming language ("Java object") to be written; it must not be null
765      * @throws JMSException                   if the JMS provider fails to write the message due to some internal error.
766      * @throws MessageFormatException         if the object is of an invalid type.
767      * @throws MessageNotWriteableException   if the message is in read-only mode.
768      * @throws java.lang.NullPointerException if the parameter <code>value</code> is null.
769      */
770     public void writeObject(Object value) throws JMSException {
771         if (value == null) {
772             throw new NullPointerException();
773         }
774         initializeWriting();
775         if (value instanceof Boolean) {
776             writeBoolean(((Boolean) value).booleanValue());
777         }
778         else if (value instanceof Character) {
779             writeChar(((Character) value).charValue());
780         }
781         else if (value instanceof Byte) {
782             writeByte(((Byte) value).byteValue());
783         }
784         else if (value instanceof Short) {
785             writeShort(((Short) value).shortValue());
786         }
787         else if (value instanceof Integer) {
788             writeInt(((Integer) value).intValue());
789         }
790         else if (value instanceof Double) {
791             writeDouble(((Double) value).doubleValue());
792         }
793         else if (value instanceof Long) {
794             writeLong(((Long) value).longValue());
795         }
796         else if (value instanceof Float) {
797             writeFloat(((Float) value).floatValue());
798         }
799         else if (value instanceof Double) {
800             writeDouble(((Double) value).doubleValue());
801         }
802         else if (value instanceof String) {
803             writeUTF(value.toString());
804         }
805         else if (value instanceof byte[]) {
806             writeBytes((byte[]) value);
807         }
808         else {
809             throw new MessageFormatException("Cannot write non-primitive type:" + value.getClass());
810         }
811     }
812 
813     /**
814      * Puts the message body in read-only mode and repositions the stream of bytes to the beginning.
815      * 
816      * @throws JMSException if an internal error occurs
817      */
818     public void reset() throws JMSException {
819         super.readOnlyMessage = true;
820         if (this.dataOut != null) {
821             try {
822                 this.dataOut.flush();
823                 byte[] data = this.bytesOut.toByteArray();
824                 super.setBodyAsBytes(data,0,data.length);
825                 dataOut.close();
826             }
827             catch (IOException ioe) {
828                 JMSException jmsEx = new JMSException("reset failed: " + ioe.getMessage());
829                 jmsEx.setLinkedException(ioe);
830                 throw jmsEx;
831             }
832         }
833         this.bytesOut = null;
834         this.dataIn = null;
835         this.dataOut = null;
836     }
837 
838     private void initializeWriting() throws MessageNotWriteableException {
839         if (super.readOnlyMessage) {
840             throw new MessageNotWriteableException("This message is in read-only mode");
841         }
842         if (this.dataOut == null) {
843             this.bytesOut = new ByteArrayOutputStream();
844             this.dataOut = new DataOutputStream(this.bytesOut);
845         }
846     }
847 
848     private void initializeReading() throws MessageNotReadableException {
849         if (!super.readOnlyMessage) {
850             throw new MessageNotReadableException("This message is in write-only mode");
851         }
852         try {
853             ByteArray data = super.getBodyAsBytes();
854             if (this.dataIn == null && data != null) {
855                 if (ByteArrayCompression.isCompressed(data)){
856                     ByteArrayCompression compression = new ByteArrayCompression();
857                     data = compression.inflate(data);
858                 }
859                 this.bodyLength = data.getLength();
860                 ByteArrayInputStream bytesIn = new ByteArrayInputStream(data.getBuf(),data.getOffset(),data.getLength());
861                 this.dataIn = new DataInputStream(bytesIn);
862             }
863         }
864         catch (IOException e) {
865             MessageNotReadableException mnr = new MessageNotReadableException("getBodyAsBytes failed");
866             mnr.setLinkedException(e);
867             throw mnr;
868         }
869     }
870 
871     public String toString() {
872         return super.toString() + " ActiveMQBytesMessage{ " +
873                 "bytesOut = " + bytesOut +
874                 ", dataOut = " + dataOut +
875                 ", dataIn = " + dataIn +
876                 " }";
877     }
878 }