001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.activemq.command; 018 019 import java.io.DataInputStream; 020 import java.io.DataOutputStream; 021 import java.io.IOException; 022 import java.io.InputStream; 023 import java.io.OutputStream; 024 import java.util.Collections; 025 import java.util.Enumeration; 026 import java.util.HashMap; 027 import java.util.Map; 028 import java.util.zip.DeflaterOutputStream; 029 import java.util.zip.InflaterInputStream; 030 031 import javax.jms.JMSException; 032 import javax.jms.MapMessage; 033 import javax.jms.MessageFormatException; 034 import javax.jms.MessageNotWriteableException; 035 036 import org.apache.activemq.ActiveMQConnection; 037 import org.apache.activemq.util.ByteArrayInputStream; 038 import org.apache.activemq.util.ByteArrayOutputStream; 039 import org.apache.activemq.util.ByteSequence; 040 import org.apache.activemq.util.JMSExceptionSupport; 041 import org.apache.activemq.util.MarshallingSupport; 042 import org.apache.activemq.wireformat.WireFormat; 043 044 /** 045 * A <CODE>MapMessage</CODE> object is used to send a set of name-value pairs. 046 * The names are <CODE>String</CODE> objects, and the values are primitive 047 * data types in the Java programming language. The names must have a value that 048 * is not null, and not an empty string. The entries can be accessed 049 * sequentially or randomly by name. The order of the entries is undefined. 050 * <CODE>MapMessage</CODE> inherits from the <CODE>Message</CODE> interface 051 * and adds a message body that contains a Map. 052 * <P> 053 * The primitive types can be read or written explicitly using methods for each 054 * type. They may also be read or written generically as objects. For instance, 055 * a call to <CODE>MapMessage.setInt("foo", 6)</CODE> is equivalent to 056 * <CODE> MapMessage.setObject("foo", new Integer(6))</CODE>. Both forms are 057 * provided, because the explicit form is convenient for static programming, and 058 * the object form is needed when types are not known at compile time. 059 * <P> 060 * When a client receives a <CODE>MapMessage</CODE>, it is in read-only mode. 061 * If a client attempts to write to the message at this point, a 062 * <CODE>MessageNotWriteableException</CODE> is thrown. If 063 * <CODE>clearBody</CODE> is called, the message can now be both read from and 064 * written to. 065 * <P> 066 * <CODE>MapMessage</CODE> objects support the following conversion table. The 067 * marked cases must be supported. The unmarked cases must throw a 068 * <CODE>JMSException</CODE>. The <CODE>String</CODE> -to-primitive 069 * conversions may throw a runtime exception if the primitive's 070 * <CODE>valueOf()</CODE> method does not accept it as a valid 071 * <CODE> String</CODE> representation of the primitive. 072 * <P> 073 * A value written as the row type can be read as the column type. <p/> 074 * 075 * <PRE> 076 * | | boolean byte short char int long float double String byte[] |---------------------------------------------------------------------- 077 * |boolean | X X |byte | X X X X X |short | X X X X |char | X X |int | X X X |long | X X |float | X X X |double | X X 078 * |String | X X X X X X X X |byte[] | X |---------------------------------------------------------------------- 079 * <p/> 080 * </PRE> 081 * 082 * <p/> 083 * <P> 084 * Attempting to read a null value as a primitive type must be treated as 085 * calling the primitive's corresponding <code>valueOf(String)</code> 086 * conversion method with a null value. Since <code>char</code> does not 087 * support a <code>String</code> conversion, attempting to read a null value 088 * as a <code>char</code> must throw a <code>NullPointerException</code>. 089 * 090 * @openwire:marshaller code="25" 091 * @see javax.jms.Session#createMapMessage() 092 * @see javax.jms.BytesMessage 093 * @see javax.jms.Message 094 * @see javax.jms.ObjectMessage 095 * @see javax.jms.StreamMessage 096 * @see javax.jms.TextMessage 097 */ 098 public class ActiveMQMapMessage extends ActiveMQMessage implements MapMessage { 099 100 public static final byte DATA_STRUCTURE_TYPE = CommandTypes.ACTIVEMQ_MAP_MESSAGE; 101 102 protected transient Map<String, Object> map = new HashMap<String, Object>(); 103 104 public Message copy() { 105 ActiveMQMapMessage copy = new ActiveMQMapMessage(); 106 copy(copy); 107 return copy; 108 } 109 110 private void copy(ActiveMQMapMessage copy) { 111 storeContent(); 112 super.copy(copy); 113 } 114 115 // We only need to marshal the content if we are hitting the wire. 116 public void beforeMarshall(WireFormat wireFormat) throws IOException { 117 super.beforeMarshall(wireFormat); 118 storeContent(); 119 } 120 121 private void storeContent() { 122 try { 123 if (getContent() == null && !map.isEmpty()) { 124 ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 125 OutputStream os = bytesOut; 126 ActiveMQConnection connection = getConnection(); 127 if (connection != null && connection.isUseCompression()) { 128 compressed = true; 129 os = new DeflaterOutputStream(os); 130 } 131 DataOutputStream dataOut = new DataOutputStream(os); 132 MarshallingSupport.marshalPrimitiveMap(map, dataOut); 133 dataOut.close(); 134 setContent(bytesOut.toByteSequence()); 135 } 136 } catch (IOException e) { 137 throw new RuntimeException(e); 138 } 139 } 140 141 /** 142 * Builds the message body from data 143 * 144 * @throws JMSException 145 * @throws IOException 146 */ 147 private void loadContent() throws JMSException { 148 try { 149 if (getContent() != null && map.isEmpty()) { 150 ByteSequence content = getContent(); 151 InputStream is = new ByteArrayInputStream(content); 152 if (isCompressed()) { 153 is = new InflaterInputStream(is); 154 } 155 DataInputStream dataIn = new DataInputStream(is); 156 map = MarshallingSupport.unmarshalPrimitiveMap(dataIn); 157 dataIn.close(); 158 } 159 } catch (IOException e) { 160 throw JMSExceptionSupport.create(e); 161 } 162 } 163 164 public byte getDataStructureType() { 165 return DATA_STRUCTURE_TYPE; 166 } 167 168 public String getJMSXMimeType() { 169 return "jms/map-message"; 170 } 171 172 /** 173 * Clears out the message body. Clearing a message's body does not clear its 174 * header values or property entries. 175 * <P> 176 * If this message body was read-only, calling this method leaves the 177 * message body in the same state as an empty body in a newly created 178 * message. 179 */ 180 public void clearBody() throws JMSException { 181 super.clearBody(); 182 map.clear(); 183 } 184 185 /** 186 * Returns the <CODE>boolean</CODE> value with the specified name. 187 * 188 * @param name the name of the <CODE>boolean</CODE> 189 * @return the <CODE>boolean</CODE> value with the specified name 190 * @throws JMSException if the JMS provider fails to read the message due to 191 * some internal error. 192 * @throws MessageFormatException if this type conversion is invalid. 193 */ 194 public boolean getBoolean(String name) throws JMSException { 195 initializeReading(); 196 Object value = map.get(name); 197 if (value == null) { 198 return false; 199 } 200 if (value instanceof Boolean) { 201 return ((Boolean)value).booleanValue(); 202 } 203 if (value instanceof String) { 204 return Boolean.valueOf(value.toString()).booleanValue(); 205 } else { 206 throw new MessageFormatException(" cannot read a boolean from " + value.getClass().getName()); 207 } 208 } 209 210 /** 211 * Returns the <CODE>byte</CODE> value with the specified name. 212 * 213 * @param name the name of the <CODE>byte</CODE> 214 * @return the <CODE>byte</CODE> value with the specified name 215 * @throws JMSException if the JMS provider fails to read the message due to 216 * some internal error. 217 * @throws MessageFormatException if this type conversion is invalid. 218 */ 219 public byte getByte(String name) throws JMSException { 220 initializeReading(); 221 Object value = map.get(name); 222 if (value == null) { 223 return 0; 224 } 225 if (value instanceof Byte) { 226 return ((Byte)value).byteValue(); 227 } 228 if (value instanceof String) { 229 return Byte.valueOf(value.toString()).byteValue(); 230 } else { 231 throw new MessageFormatException(" cannot read a byte from " + value.getClass().getName()); 232 } 233 } 234 235 /** 236 * Returns the <CODE>short</CODE> value with the specified name. 237 * 238 * @param name the name of the <CODE>short</CODE> 239 * @return the <CODE>short</CODE> value with the specified name 240 * @throws JMSException if the JMS provider fails to read the message due to 241 * some internal error. 242 * @throws MessageFormatException if this type conversion is invalid. 243 */ 244 public short getShort(String name) throws JMSException { 245 initializeReading(); 246 Object value = map.get(name); 247 if (value == null) { 248 return 0; 249 } 250 if (value instanceof Short) { 251 return ((Short)value).shortValue(); 252 } 253 if (value instanceof Byte) { 254 return ((Byte)value).shortValue(); 255 } 256 if (value instanceof String) { 257 return Short.valueOf(value.toString()).shortValue(); 258 } else { 259 throw new MessageFormatException(" cannot read a short from " + value.getClass().getName()); 260 } 261 } 262 263 /** 264 * Returns the Unicode character value with the specified name. 265 * 266 * @param name the name of the Unicode character 267 * @return the Unicode character value with the specified name 268 * @throws JMSException if the JMS provider fails to read the message due to 269 * some internal error. 270 * @throws MessageFormatException if this type conversion is invalid. 271 */ 272 public char getChar(String name) throws JMSException { 273 initializeReading(); 274 Object value = map.get(name); 275 if (value == null) { 276 throw new NullPointerException(); 277 } 278 if (value instanceof Character) { 279 return ((Character)value).charValue(); 280 } else { 281 throw new MessageFormatException(" cannot read a short from " + value.getClass().getName()); 282 } 283 } 284 285 /** 286 * Returns the <CODE>int</CODE> value with the specified name. 287 * 288 * @param name the name of the <CODE>int</CODE> 289 * @return the <CODE>int</CODE> value with the specified name 290 * @throws JMSException if the JMS provider fails to read the message due to 291 * some internal error. 292 * @throws MessageFormatException if this type conversion is invalid. 293 */ 294 public int getInt(String name) throws JMSException { 295 initializeReading(); 296 Object value = map.get(name); 297 if (value == null) { 298 return 0; 299 } 300 if (value instanceof Integer) { 301 return ((Integer)value).intValue(); 302 } 303 if (value instanceof Short) { 304 return ((Short)value).intValue(); 305 } 306 if (value instanceof Byte) { 307 return ((Byte)value).intValue(); 308 } 309 if (value instanceof String) { 310 return Integer.valueOf(value.toString()).intValue(); 311 } else { 312 throw new MessageFormatException(" cannot read an int from " + value.getClass().getName()); 313 } 314 } 315 316 /** 317 * Returns the <CODE>long</CODE> value with the specified name. 318 * 319 * @param name the name of the <CODE>long</CODE> 320 * @return the <CODE>long</CODE> value with the specified name 321 * @throws JMSException if the JMS provider fails to read the message due to 322 * some internal error. 323 * @throws MessageFormatException if this type conversion is invalid. 324 */ 325 public long getLong(String name) throws JMSException { 326 initializeReading(); 327 Object value = map.get(name); 328 if (value == null) { 329 return 0; 330 } 331 if (value instanceof Long) { 332 return ((Long)value).longValue(); 333 } 334 if (value instanceof Integer) { 335 return ((Integer)value).longValue(); 336 } 337 if (value instanceof Short) { 338 return ((Short)value).longValue(); 339 } 340 if (value instanceof Byte) { 341 return ((Byte)value).longValue(); 342 } 343 if (value instanceof String) { 344 return Long.valueOf(value.toString()).longValue(); 345 } else { 346 throw new MessageFormatException(" cannot read a long from " + value.getClass().getName()); 347 } 348 } 349 350 /** 351 * Returns the <CODE>float</CODE> value with the specified name. 352 * 353 * @param name the name of the <CODE>float</CODE> 354 * @return the <CODE>float</CODE> value with the specified name 355 * @throws JMSException if the JMS provider fails to read the message due to 356 * some internal error. 357 * @throws MessageFormatException if this type conversion is invalid. 358 */ 359 public float getFloat(String name) throws JMSException { 360 initializeReading(); 361 Object value = map.get(name); 362 if (value == null) { 363 return 0; 364 } 365 if (value instanceof Float) { 366 return ((Float)value).floatValue(); 367 } 368 if (value instanceof String) { 369 return Float.valueOf(value.toString()).floatValue(); 370 } else { 371 throw new MessageFormatException(" cannot read a float from " + value.getClass().getName()); 372 } 373 } 374 375 /** 376 * Returns the <CODE>double</CODE> value with the specified name. 377 * 378 * @param name the name of the <CODE>double</CODE> 379 * @return the <CODE>double</CODE> value with the specified name 380 * @throws JMSException if the JMS provider fails to read the message due to 381 * some internal error. 382 * @throws MessageFormatException if this type conversion is invalid. 383 */ 384 public double getDouble(String name) throws JMSException { 385 initializeReading(); 386 Object value = map.get(name); 387 if (value == null) { 388 return 0; 389 } 390 if (value instanceof Double) { 391 return ((Double)value).doubleValue(); 392 } 393 if (value instanceof Float) { 394 return ((Float)value).floatValue(); 395 } 396 if (value instanceof String) { 397 return Float.valueOf(value.toString()).floatValue(); 398 } else { 399 throw new MessageFormatException(" cannot read a double from " + value.getClass().getName()); 400 } 401 } 402 403 /** 404 * Returns the <CODE>String</CODE> value with the specified name. 405 * 406 * @param name the name of the <CODE>String</CODE> 407 * @return the <CODE>String</CODE> value with the specified name; if there 408 * is no item by this name, a null value is returned 409 * @throws JMSException if the JMS provider fails to read the message due to 410 * some internal error. 411 * @throws MessageFormatException if this type conversion is invalid. 412 */ 413 public String getString(String name) throws JMSException { 414 initializeReading(); 415 Object value = map.get(name); 416 if (value == null) { 417 return null; 418 } 419 if (value instanceof byte[]) { 420 throw new MessageFormatException("Use getBytes to read a byte array"); 421 } else { 422 return value.toString(); 423 } 424 } 425 426 /** 427 * Returns the byte array value with the specified name. 428 * 429 * @param name the name of the byte array 430 * @return a copy of the byte array value with the specified name; if there 431 * is no item by this name, a null value is returned. 432 * @throws JMSException if the JMS provider fails to read the message due to 433 * some internal error. 434 * @throws MessageFormatException if this type conversion is invalid. 435 */ 436 public byte[] getBytes(String name) throws JMSException { 437 initializeReading(); 438 Object value = map.get(name); 439 if (value instanceof byte[]) { 440 return (byte[])value; 441 } else { 442 throw new MessageFormatException(" cannot read a byte[] from " + value.getClass().getName()); 443 } 444 } 445 446 /** 447 * Returns the value of the object with the specified name. 448 * <P> 449 * This method can be used to return, in objectified format, an object in 450 * the Java programming language ("Java object") that had been stored in the 451 * Map with the equivalent <CODE>setObject</CODE> method call, or its 452 * equivalent primitive <CODE>set <I>type </I></CODE> method. 453 * <P> 454 * Note that byte values are returned as <CODE>byte[]</CODE>, not 455 * <CODE>Byte[]</CODE>. 456 * 457 * @param name the name of the Java object 458 * @return a copy of the Java object value with the specified name, in 459 * objectified format (for example, if the object was set as an 460 * <CODE>int</CODE>, an <CODE>Integer</CODE> is returned); if 461 * there is no item by this name, a null value is returned 462 * @throws JMSException if the JMS provider fails to read the message due to 463 * some internal error. 464 */ 465 public Object getObject(String name) throws JMSException { 466 initializeReading(); 467 return map.get(name); 468 } 469 470 /** 471 * Returns an <CODE>Enumeration</CODE> of all the names in the 472 * <CODE>MapMessage</CODE> object. 473 * 474 * @return an enumeration of all the names in this <CODE>MapMessage</CODE> 475 * @throws JMSException 476 */ 477 public Enumeration<String> getMapNames() throws JMSException { 478 initializeReading(); 479 return Collections.enumeration(map.keySet()); 480 } 481 482 protected void put(String name, Object value) throws JMSException { 483 if (name == null) { 484 throw new IllegalArgumentException("The name of the property cannot be null."); 485 } 486 if (name.length() == 0) { 487 throw new IllegalArgumentException("The name of the property cannot be an emprty string."); 488 } 489 map.put(name, value); 490 } 491 492 /** 493 * Sets a <CODE>boolean</CODE> value with the specified name into the Map. 494 * 495 * @param name the name of the <CODE>boolean</CODE> 496 * @param value the <CODE>boolean</CODE> value to set in the Map 497 * @throws JMSException if the JMS provider fails to write the message due 498 * to some internal error. 499 * @throws IllegalArgumentException if the name is null or if the name is an 500 * empty string. 501 * @throws MessageNotWriteableException if the message is in read-only mode. 502 */ 503 public void setBoolean(String name, boolean value) throws JMSException { 504 initializeWriting(); 505 put(name, value ? Boolean.TRUE : Boolean.FALSE); 506 } 507 508 /** 509 * Sets a <CODE>byte</CODE> value with the specified name into the Map. 510 * 511 * @param name the name of the <CODE>byte</CODE> 512 * @param value the <CODE>byte</CODE> value to set in the Map 513 * @throws JMSException if the JMS provider fails to write the message due 514 * to some internal error. 515 * @throws IllegalArgumentException if the name is null or if the name is an 516 * empty string. 517 * @throws MessageNotWriteableException if the message is in read-only mode. 518 */ 519 public void setByte(String name, byte value) throws JMSException { 520 initializeWriting(); 521 put(name, Byte.valueOf(value)); 522 } 523 524 /** 525 * Sets a <CODE>short</CODE> value with the specified name into the Map. 526 * 527 * @param name the name of the <CODE>short</CODE> 528 * @param value the <CODE>short</CODE> value to set in the Map 529 * @throws JMSException if the JMS provider fails to write the message due 530 * to some internal error. 531 * @throws IllegalArgumentException if the name is null or if the name is an 532 * empty string. 533 * @throws MessageNotWriteableException if the message is in read-only mode. 534 */ 535 public void setShort(String name, short value) throws JMSException { 536 initializeWriting(); 537 put(name, Short.valueOf(value)); 538 } 539 540 /** 541 * Sets a Unicode character value with the specified name into the Map. 542 * 543 * @param name the name of the Unicode character 544 * @param value the Unicode character value to set in the Map 545 * @throws JMSException if the JMS provider fails to write the message due 546 * to some internal error. 547 * @throws IllegalArgumentException if the name is null or if the name is an 548 * empty string. 549 * @throws MessageNotWriteableException if the message is in read-only mode. 550 */ 551 public void setChar(String name, char value) throws JMSException { 552 initializeWriting(); 553 put(name, Character.valueOf(value)); 554 } 555 556 /** 557 * Sets an <CODE>int</CODE> value with the specified name into the Map. 558 * 559 * @param name the name of the <CODE>int</CODE> 560 * @param value the <CODE>int</CODE> value to set in the Map 561 * @throws JMSException if the JMS provider fails to write the message due 562 * to some internal error. 563 * @throws IllegalArgumentException if the name is null or if the name is an 564 * empty string. 565 * @throws MessageNotWriteableException if the message is in read-only mode. 566 */ 567 public void setInt(String name, int value) throws JMSException { 568 initializeWriting(); 569 put(name, Integer.valueOf(value)); 570 } 571 572 /** 573 * Sets a <CODE>long</CODE> value with the specified name into the Map. 574 * 575 * @param name the name of the <CODE>long</CODE> 576 * @param value the <CODE>long</CODE> value to set in the Map 577 * @throws JMSException if the JMS provider fails to write the message due 578 * to some internal error. 579 * @throws IllegalArgumentException if the name is null or if the name is an 580 * empty string. 581 * @throws MessageNotWriteableException if the message is in read-only mode. 582 */ 583 public void setLong(String name, long value) throws JMSException { 584 initializeWriting(); 585 put(name, Long.valueOf(value)); 586 } 587 588 /** 589 * Sets a <CODE>float</CODE> value with the specified name into the Map. 590 * 591 * @param name the name of the <CODE>float</CODE> 592 * @param value the <CODE>float</CODE> value to set in the Map 593 * @throws JMSException if the JMS provider fails to write the message due 594 * to some internal error. 595 * @throws IllegalArgumentException if the name is null or if the name is an 596 * empty string. 597 * @throws MessageNotWriteableException if the message is in read-only mode. 598 */ 599 public void setFloat(String name, float value) throws JMSException { 600 initializeWriting(); 601 put(name, new Float(value)); 602 } 603 604 /** 605 * Sets a <CODE>double</CODE> value with the specified name into the Map. 606 * 607 * @param name the name of the <CODE>double</CODE> 608 * @param value the <CODE>double</CODE> value to set in the Map 609 * @throws JMSException if the JMS provider fails to write the message due 610 * to some internal error. 611 * @throws IllegalArgumentException if the name is null or if the name is an 612 * empty string. 613 * @throws MessageNotWriteableException if the message is in read-only mode. 614 */ 615 public void setDouble(String name, double value) throws JMSException { 616 initializeWriting(); 617 put(name, new Double(value)); 618 } 619 620 /** 621 * Sets a <CODE>String</CODE> value with the specified name into the Map. 622 * 623 * @param name the name of the <CODE>String</CODE> 624 * @param value the <CODE>String</CODE> value to set in the Map 625 * @throws JMSException if the JMS provider fails to write the message due 626 * to some internal error. 627 * @throws IllegalArgumentException if the name is null or if the name is an 628 * empty string. 629 * @throws MessageNotWriteableException if the message is in read-only mode. 630 */ 631 public void setString(String name, String value) throws JMSException { 632 initializeWriting(); 633 put(name, value); 634 } 635 636 /** 637 * Sets a byte array value with the specified name into the Map. 638 * 639 * @param name the name of the byte array 640 * @param value the byte array value to set in the Map; the array is copied 641 * so that the value for <CODE>name </CODE> will not be 642 * altered by future modifications 643 * @throws JMSException if the JMS provider fails to write the message due 644 * to some internal error. 645 * @throws NullPointerException if the name is null, or if the name is an 646 * empty string. 647 * @throws MessageNotWriteableException if the message is in read-only mode. 648 */ 649 public void setBytes(String name, byte[] value) throws JMSException { 650 initializeWriting(); 651 if (value != null) { 652 put(name, value); 653 } else { 654 map.remove(name); 655 } 656 } 657 658 /** 659 * Sets a portion of the byte array value with the specified name into the 660 * Map. 661 * 662 * @param name the name of the byte array 663 * @param value the byte array value to set in the Map 664 * @param offset the initial offset within the byte array 665 * @param length the number of bytes to use 666 * @throws JMSException if the JMS provider fails to write the message due 667 * to some internal error. 668 * @throws IllegalArgumentException if the name is null or if the name is an 669 * empty string. 670 * @throws MessageNotWriteableException if the message is in read-only mode. 671 */ 672 public void setBytes(String name, byte[] value, int offset, int length) throws JMSException { 673 initializeWriting(); 674 byte[] data = new byte[length]; 675 System.arraycopy(value, offset, data, 0, length); 676 put(name, data); 677 } 678 679 /** 680 * Sets an object value with the specified name into the Map. 681 * <P> 682 * This method works only for the objectified primitive object types (<code>Integer</code>,<code>Double</code>, 683 * <code>Long</code> ...), <code>String</code> objects, and byte 684 * arrays. 685 * 686 * @param name the name of the Java object 687 * @param value the Java object value to set in the Map 688 * @throws JMSException if the JMS provider fails to write the message due 689 * to some internal error. 690 * @throws IllegalArgumentException if the name is null or if the name is an 691 * empty string. 692 * @throws MessageFormatException if the object is invalid. 693 * @throws MessageNotWriteableException if the message is in read-only mode. 694 */ 695 public void setObject(String name, Object value) throws JMSException { 696 initializeWriting(); 697 if (value != null) { 698 // byte[] not allowed on properties 699 if (!(value instanceof byte[])) { 700 checkValidObject(value); 701 } 702 put(name, value); 703 } else { 704 put(name, null); 705 } 706 } 707 708 /** 709 * Indicates whether an item exists in this <CODE>MapMessage</CODE> 710 * object. 711 * 712 * @param name the name of the item to test 713 * @return true if the item exists 714 * @throws JMSException if the JMS provider fails to determine if the item 715 * exists due to some internal error. 716 */ 717 public boolean itemExists(String name) throws JMSException { 718 initializeReading(); 719 return map.containsKey(name); 720 } 721 722 private void initializeReading() throws JMSException { 723 loadContent(); 724 } 725 726 private void initializeWriting() throws MessageNotWriteableException { 727 checkReadOnlyBody(); 728 setContent(null); 729 } 730 731 public String toString() { 732 return super.toString() + " ActiveMQMapMessage{ " + "theTable = " + map + " }"; 733 } 734 735 public Map<String, Object> getContentMap() throws JMSException { 736 initializeReading(); 737 return map; 738 } 739 }