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