View Javadoc
1 /*** 2 * Copyright (c) 2002, CodeStreet LLC. All rights reserved. 3 * <p> 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * <p> 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. Redistributions in binary 9 * form must reproduce the above copyright notice, this list of conditions and 10 * the following disclaimer in the documentation and/or other materials provided 11 * with the distribution. Neither the name of CodeStreet LLC. nor the names of 12 * its contributors may be used to endorse or promote products derived from this 13 * software without specific prior written permission. 14 * <p> 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 * <p> 27 */ 28 29 package com.codestreet.messageforge; 30 31 import javax.jms.*; 32 33 import java.util.Iterator; 34 import java.util.List; 35 import java.util.Date; 36 import java.util.ArrayList; 37 import java.util.Enumeration; 38 import java.util.Map; 39 40 public abstract class ConverterJMS extends Converter 41 { 42 /*** 43 * Set TIBCO message extension flag. 44 * 45 * @param ext 46 * TIBCO message extension flag. 47 */ 48 public static void setTibcoJmsMsgExt(boolean ext) 49 { 50 tibcoJmsMsgExt_ = ext; 51 } 52 53 /*** 54 * Get TIBCO message extension flag. 55 * 56 * @return TIBCO message extension flag. 57 */ 58 public static boolean getTibcoJmsMsgExt() 59 { 60 return tibcoJmsMsgExt_; 61 } 62 63 /*** 64 * Create a <tt>javax.jms.MapMessage</tt> from a <tt>RMapMessage</tt>. 65 * The marshalling to JMS is done by in three steps: First a <tt>String</tt> 66 * property with the name of the message is set in the 67 * <tt>javax.jms.MapMessage</tt>. Next all fields in the 68 * <tt>RMapMessage</tt> that are supported in JMS are copied to the 69 * <tt>javax.jms.MapMessage</tt>. Finally, all fields in the 70 * <tt>RMapMessage</tt> that are not supported by JMS are converted into 71 * XML and add to the <tt>javax.jms.MapMessage</tt> as a <tt>String</tt>. 72 * <p> 73 * 74 * @param source 75 * Source message. 76 * @param session 77 * JMS session. This is used to created nested map messages if 78 * necessary. 79 * @return <tt>javax.jms.MapMessage</tt>. 80 * @see RMapMessage 81 * @see RMsg 82 * @see javax.jms.Session 83 * @see javax.jms.MapMessage 84 */ 85 public static javax.jms.MapMessage marshal(RMapMessage source, 86 javax.jms.Session session) throws ConverterException 87 { 88 if (session == null) 89 { 90 throw new ConverterException( 91 "Supplied JMS Session was null. Can not convert to MapMessage"); 92 } 93 try 94 { 95 MapMessage target = session.createMapMessage(); 96 if (getTibcoJmsMsgExt()) 97 target.setBooleanProperty("JMS_TIBCO_MSG_EXT", true); 98 return marshal(source, target, session); 99 } 100 catch (Exception ex) 101 { 102 throw new ConverterException(ex); 103 } 104 } 105 106 /*** 107 * Create a <tt>javax.jms.MapMessage</tt> from a <tt>RMapMessage</tt>. 108 * The marshalling to JMS is done by in three steps: First a <tt>String</tt> 109 * property with the name of the message is set in the 110 * <tt>javax.jms.MapMessage</tt>. Next all fields in the 111 * <tt>RMapMessage</tt> that are supported in JMS are copied to the 112 * <tt>javax.jms.MapMessage</tt>. Finally, all fields in the 113 * <tt>RMapMessage</tt> that are not supported by JMS are converted into 114 * XML and add to the <tt>javax.jms.MapMessage</tt> as a <tt>String</tt>. 115 * <p> 116 * 117 * @param source 118 * Source message. 119 * @param target 120 * Target map message. 121 * @param session 122 * JMS session. This is used to created nested map messages if 123 * necessary. 124 * @return <tt>javax.jms.MapMessage</tt>. 125 * @see RMapMessage 126 * @see RMsg 127 * @see javax.jms.Session 128 * @see javax.jms.MapMessage 129 */ 130 public static javax.jms.MapMessage marshal(RMapMessage source, 131 MapMessage target, javax.jms.Session session) 132 throws ConverterException 133 { 134 if (session == null) 135 { 136 throw new ConverterException( 137 "Supplied JMS Session was null. Cannot convert to MapMessage"); 138 } 139 if (source == null) 140 { 141 throw new ConverterException( 142 "Supplied source MapMessage was null. Cannot convert to MapMessage."); 143 } 144 if (target == null) 145 { 146 throw new ConverterException( 147 "Supplied target MapMessage was null. Cannot convert to MapMessage."); 148 } 149 try 150 { 151 // Set message name as a String property 152 target.setStringProperty(MSG_NAME, source.getName()); 153 154 // First pass - put all JMS supported fields directly into the 155 // MapMessage 156 boolean tibMsgExt = getTibcoJmsMsgExt(); 157 RFld[] flds = source.getFieldsAsArray(); 158 for (int i = flds.length - 1; i >= 0; --i) 159 { 160 RFldInterface srcFld = flds[i]; 161 if (srcFld.isValSet()) 162 { 163 String fldName = srcFld.getName(); 164 RFldType type = srcFld.getType(); 165 if (tibMsgExt) 166 { 167 if (srcFld.getType().isComplex()) 168 { 169 if (type == RFldType.DECIMAL) 170 { 171 String strVal = Converter 172 .getBigDecimalFormatter().format( 173 srcFld.getValueAsObject()); 174 if (srcFld.isProperty()) 175 addProperty(target, srcFld 176 .getPropertyName(), strVal); 177 target.setString(fldName, strVal); 178 } 179 else if (type == RFldType.BEAN) 180 { 181 target.setBooleanProperty("JMS_TIBCO_MSG_EXT", 182 true); 183 target.setObject(fldName, ConverterBeanAndJMS 184 .marshal(srcFld.getValueAsObject(), 185 session)); 186 } 187 else if (type == RFldType.BEANLIST) 188 { 189 RFldBeanList beanLst = (RFldBeanList) srcFld; 190 List lst = beanLst.getValue(); 191 if (lst != null) 192 { 193 target.setBooleanProperty( 194 "JMS_TIBCO_MSG_EXT", true); 195 196 MapMessage outer = session 197 .createMapMessage(); 198 outer.setBooleanProperty( 199 "JMS_TIBCO_MSG_EXT", true); 200 outer.setInt("length", lst.size()); 201 for (int j = 0; j < lst.size(); ++j) 202 { 203 outer.setObject(String.valueOf(j), 204 ConverterBeanAndJMS.marshal(lst 205 .get(j), session)); 206 } 207 target.setObject(fldName, outer); 208 } 209 } 210 else if (type == RFldType.MSGOBJ) 211 { 212 RFldMsgObj obj = (RFldMsgObj) srcFld; 213 target.setObject(fldName, ConverterJMS.marshal( 214 obj.getValue(), session)); 215 } 216 else if (type == RFldType.MSGOBJARRAY) 217 { 218 MapMessage outer = session.createMapMessage(); 219 outer.setBooleanProperty("JMS_TIBCO_MSG_EXT", 220 true); 221 RFldMsgObjArray objA = (RFldMsgObjArray) srcFld; 222 outer.setInt("length", objA.length()); 223 for (int j = 0; j < objA.length(); ++j) 224 { 225 RMsg elem = objA.getElement(j); 226 outer 227 .setObject(String.valueOf(j), 228 ConverterJMS.marshal(elem, 229 session)); 230 } 231 target.setObject(fldName, outer); 232 } 233 else if (type == RFldType.MSGOBJHASHTABLE) 234 { 235 MapMessage outer = session.createMapMessage(); 236 outer.setBooleanProperty("JMS_TIBCO_MSG_EXT", 237 true); 238 java.util.Hashtable hash = ((RFldMsgObjHashtable) srcFld) 239 .getValue(); 240 for (Enumeration en = hash.keys(); en 241 .hasMoreElements();) 242 { 243 String key = (String) en.nextElement(); 244 RMsg elem = (RMsg) hash.get(key); 245 outer.setObject(key, ConverterJMS.marshal( 246 elem, session)); 247 } 248 target.setObject(fldName, outer); 249 } 250 else if (type == RFldType.STRINGARRAY) 251 { 252 MapMessage outer = session.createMapMessage(); 253 outer.setBooleanProperty("JMS_TIBCO_MSG_EXT", 254 false); 255 RFldStringArray strA = (RFldStringArray) srcFld; 256 outer.setInt("length", strA.length()); 257 for (int j = 0; j < strA.length(); ++j) 258 { 259 String elem = strA.getElement(j); 260 outer.setString(String.valueOf(j), elem); 261 } 262 target.setObject(fldName, outer); 263 } 264 else if (type == RFldType.STRINGLIST) 265 { 266 MapMessage outer = session.createMapMessage(); 267 outer.setBooleanProperty("JMS_TIBCO_MSG_EXT", 268 false); 269 List strL = ((RFldStringList) srcFld) 270 .getValue(); 271 outer.setInt("length", strL.size()); 272 for (int j = 0; j < strL.size(); ++j) 273 { 274 String elem = (String) strL.get(j); 275 outer.setString(String.valueOf(j), elem); 276 } 277 target.setObject(fldName, outer); 278 } 279 else if (type == RFldType.STRINGHASHTABLE) 280 { 281 MapMessage outer = session.createMapMessage(); 282 outer.setBooleanProperty("JMS_TIBCO_MSG_EXT", 283 false); 284 java.util.Hashtable hash = ((RFldMsgObjHashtable) srcFld) 285 .getValue(); 286 for (Enumeration en = hash.keys(); en 287 .hasMoreElements();) 288 { 289 String key = (String) en.nextElement(); 290 String elem = (String) hash.get(key); 291 outer.setString(key, elem); 292 } 293 target.setObject(fldName, outer); 294 } 295 else if (type == RFldType.STRINGARRAY) 296 { 297 MapMessage outer = session.createMapMessage(); 298 outer.setBooleanProperty("JMS_TIBCO_MSG_EXT", 299 false); 300 RFldStringArray strA = (RFldStringArray) srcFld; 301 outer.setInt("length", strA.length()); 302 for (int j = 0; j < strA.length(); ++j) 303 { 304 String elem = strA.getElement(j); 305 outer.setString(String.valueOf(j), elem); 306 } 307 target.setObject(fldName, outer); 308 } 309 else if (type == RFldType.DATEARRAY) 310 { 311 MapMessage outer = session.createMapMessage(); 312 outer.setBooleanProperty("JMS_TIBCO_MSG_EXT", 313 false); 314 RFldDatetimeArray dtArray = (RFldDatetimeArray) srcFld; 315 outer.setInt("length", dtArray.length()); 316 for (int j = 0; j < dtArray.length(); ++j) 317 { 318 Date elem = dtArray.getElement(j); 319 String sDate = RDateFormat.getInstance() 320 .format(elem); 321 outer.setString(String.valueOf(j), sDate); 322 } 323 target.setObject(fldName, outer); 324 } 325 } 326 else 327 { 328 if (type == RFldType.DATETIME) 329 { 330 RFldDatetime dt = (RFldDatetime) srcFld; 331 String strVal = RDateFormat.getInstance() 332 .format(dt.getValue()); 333 target.setObject(fldName, strVal); 334 if (srcFld.isProperty()) 335 addProperty(target, srcFld 336 .getPropertyName(), strVal); 337 } 338 else 339 { 340 target.setBooleanProperty("JMS_TIBCO_MSG_EXT", 341 true); 342 target.setObject(fldName, srcFld 343 .getValueAsObject()); 344 } 345 } 346 } 347 else if (type.isJMSSupported()) 348 { 349 if (srcFld.isProperty()) 350 addProperty(target, srcFld.getPropertyName(), 351 srcFld.getValueAsObject()); 352 target.setObject(fldName, srcFld.getValueAsObject()); 353 } 354 else if (type == RFldType.DECIMAL) 355 { 356 String strVal = Converter.getBigDecimalFormatter() 357 .format(srcFld.getValueAsObject()); 358 if (srcFld.isProperty()) 359 addProperty(target, srcFld.getPropertyName(), 360 strVal); 361 target.setString(fldName, strVal); 362 } 363 } 364 } 365 366 // Second pass - convert all non-JMS supported fields 367 // / to XML and put into specially named String field 368 if (!tibMsgExt) 369 { 370 String xml = ConverterXML.marshal(true, source); 371 if (xml != null) 372 target.setString(XML_FIELD_NAME, xml); 373 } 374 375 return target; 376 } 377 catch (Exception ex) 378 { 379 throw new ConverterException(ex); 380 } 381 } 382 383 /*** 384 * Add JMS property to target message. 385 * 386 * @param target 387 * Target message. 388 * @param propName 389 * Property name. 390 * @param propVal 391 * Property value. Must be a supported type. 392 * @throws JMSException 393 */ 394 private static final void addProperty(final Message target, 395 final String propName, final Object propVal) throws JMSException 396 { 397 if (propVal instanceof String) 398 target.setStringProperty(propName, (String) propVal); 399 else if (propVal instanceof Long) 400 target.setLongProperty(propName, ((Long) propVal).longValue()); 401 else if (propVal instanceof Boolean) 402 target.setBooleanProperty(propName, ((Boolean) propVal) 403 .booleanValue()); 404 else if (propVal instanceof Integer) 405 target.setIntProperty(propName, ((Integer) propVal).intValue()); 406 else if (propVal instanceof Double) 407 target 408 .setDoubleProperty(propName, ((Double) propVal) 409 .doubleValue()); 410 else if (propVal instanceof Float) 411 target.setFloatProperty(propName, ((Float) propVal).floatValue()); 412 else if (propVal instanceof Short) 413 target.setShortProperty(propName, ((Short) propVal).shortValue()); 414 else if (propVal instanceof Byte) 415 target.setByteProperty(propName, ((Byte) propVal).byteValue()); 416 } 417 418 /*** 419 * Create and set a <tt>RMsg</tt> from a <tt>javax.jms.MapMessage</tt>. 420 * 421 * @param source 422 * Source message. 423 * @return Unmarshalled message object. 424 * @see #unmarshal(javax.jms.MapMessage, RMapMessage) 425 */ 426 public static RMapMessage unmarshal(javax.jms.MapMessage source) 427 throws ConverterException 428 { 429 try 430 { 431 // Create message object 432 if (!source.propertyExists(MSG_NAME)) 433 throw new ConverterException("Property not found: " + MSG_NAME); 434 435 String msgName = source.getStringProperty(MSG_NAME); 436 RMapMessage target = Converter.createMsgObject(msgName); 437 438 unmarshal(source, target); 439 440 return target; 441 } 442 catch (Exception ex) 443 { 444 throw new ConverterException(ex); 445 } 446 } 447 448 /*** 449 * Create and set a <tt>RMsg</tt> from a <tt>javax.jms.MapMessage</tt>. 450 * 451 * @param source 452 * Source message. 453 * @param target 454 * Target message object. 455 */ 456 public static void unmarshal(MapMessage source, RMapMessage target) 457 throws ConverterException 458 { 459 try 460 { 461 if (!getTibcoJmsMsgExt()) 462 regularUnmarshal(source, target); 463 else 464 tibUnmarshal(source, target); 465 } 466 catch (Exception ex) 467 { 468 throw new ConverterException(ex); 469 } 470 } 471 472 public static void addProperties(final Message outMsg, final Map props) 473 throws JMSException 474 { 475 if (props == null || props.isEmpty()) 476 return; 477 478 for (Iterator iter = props.entrySet().iterator(); iter.hasNext();) 479 { 480 Map.Entry entry = (Map.Entry) iter.next(); 481 Object propName = entry.getKey(); 482 if (!(propName instanceof String)) 483 { 484 continue; 485 } 486 Object propVal = entry.getValue(); 487 addProperty(outMsg, (String) propName, propVal); 488 } 489 } 490 491 private static void tibUnmarshal(MapMessage source, RMapMessage target) 492 throws ConverterException 493 { 494 Enumeration en = null; 495 try 496 { 497 en = source.getMapNames(); 498 } 499 catch (JMSException ex) 500 { 501 throw new ConverterException(ex); 502 } 503 504 for (; en != null && en.hasMoreElements();) 505 { 506 String name = (String) en.nextElement(); 507 try 508 { 509 Object val = source.getObject(name); 510 RFld targetFld = target.getFieldIfExists(name); 511 if (targetFld != null) 512 { 513 // Skip if target field is locked 514 if (targetFld.isLocked()) 515 continue; 516 517 RFldType targetFldType = targetFld.getType(); 518 if (targetFldType == RFldType.DECIMAL) 519 { 520 RFldDecimal realFld = (RFldDecimal) targetFld; 521 realFld.set(source.getObject(name)); 522 } 523 else if (targetFldType == RFldType.DATETIME) 524 { 525 String sVal = val.toString(); 526 targetFld.set(RDateFormat.getInstance().parse(sVal)); 527 } 528 else if (targetFldType.isComplex()) 529 { 530 setComplex((MapMessage) val, targetFld); 531 } 532 else 533 { 534 targetFld.set(val); 535 } 536 } 537 } 538 catch (Exception ex) 539 { 540 throw new ConverterException("Error converting field: " + name, 541 ex); 542 } 543 } 544 } 545 546 private static void regularUnmarshal(MapMessage source, RMapMessage target) 547 throws ConverterException 548 { 549 try 550 { 551 // First pass - set all JMS supported fields 552 RFld[] flds = target.getFieldsAsArray(); 553 for (int i = flds.length - 1; i >= 0; --i) 554 { 555 RFldInterface srcFld = flds[i]; 556 String fldName = srcFld.getName(); 557 if (source.itemExists(fldName)) 558 { 559 Object fldValue = source.getObject(fldName); 560 if (fldValue != null) 561 srcFld.set(fldValue); 562 } 563 } 564 565 // Second pass - set all non-JMS supported fields 566 if (source.itemExists(XML_FIELD_NAME)) 567 { 568 String xml = source.getString(XML_FIELD_NAME); 569 if (xml != null) 570 ConverterXML.unmarshal(xml, target); 571 } 572 } 573 catch (Exception ex) 574 { 575 throw new ConverterException(ex); 576 } 577 } 578 579 private static void setComplex(MapMessage source, RFld target) 580 throws ConverterException 581 { 582 try 583 { 584 RFldType type = target.getType(); 585 if (type == RFldType.BEAN) 586 { 587 RFldBean realFld = (RFldBean) target; 588 realFld.set(ConverterBeanAndJMS.unmarshal(source)); 589 } 590 else if (type == RFldType.BEANLIST) 591 { 592 RFldBeanList realFld = (RFldBeanList) target; 593 int len = source.getInt("length"); 594 List lst = new ArrayList(len); 595 for (int i = 0; i < len; ++i) 596 { 597 MapMessage val = (MapMessage) source.getObject(String 598 .valueOf(i)); 599 lst.add(ConverterBeanAndJMS.unmarshal(val)); 600 } 601 realFld.set(lst); 602 } 603 else if (type == RFldType.MSGOBJ) 604 { 605 RFldMsgObj realFld = (RFldMsgObj) target; 606 if (realFld.isValSet()) 607 { 608 realFld.getValue().resetFields(); 609 ConverterJMS.unmarshal(source, (RMapMessage) target 610 .getValueAsObject()); 611 } 612 else 613 { 614 RMsg msg = (RMsg) Converter.createMsgObject(realFld 615 .getClassObject()); 616 ConverterJMS.unmarshal(source, msg); 617 realFld.set(msg); 618 } 619 } 620 else if (type == RFldType.MSGOBJARRAY) 621 { 622 RFldMsgObjArray realFld = (RFldMsgObjArray) target; 623 int len = source.getInt("length"); 624 RMsg[] elements = new RMsg[len]; 625 for (int i = 0; i < len; ++i) 626 { 627 elements[i] = (RMsg) unmarshal((MapMessage) source 628 .getObject(String.valueOf(i))); 629 } 630 realFld.set(elements); 631 } 632 else if (type == RFldType.MSGOBJHASHTABLE) 633 { 634 RFldMsgObjHashtable realFld = (RFldMsgObjHashtable) target; 635 java.util.Hashtable elements = new java.util.Hashtable(); 636 for (Enumeration e = source.getMapNames(); e.hasMoreElements();) 637 { 638 String key = (String) e.nextElement(); 639 MapMessage elem = (MapMessage) source.getObject(key); 640 elements.put(key, ConverterJMS.unmarshal(elem)); 641 } 642 realFld.set(elements); 643 } 644 else if (type == RFldType.DATEARRAY) 645 { 646 RFldDatetimeArray realFld = (RFldDatetimeArray) target; 647 int len = source.getInt("length"); 648 Date[] elements = new Date[len]; 649 for (int i = 0; i < len; ++i) 650 { 651 String sDate = (String) source.getObject(String.valueOf(i)); 652 elements[i] = RDateFormat.getInstance().parse(sDate); 653 } 654 realFld.set(elements); 655 } 656 else if (type == RFldType.STRINGARRAY) 657 { 658 RFldStringArray realFld = (RFldStringArray) target; 659 int len = source.getInt("length"); 660 String[] elements = new String[len]; 661 for (int i = 0; i < len; ++i) 662 { 663 elements[i] = (String) source.getObject(String.valueOf(i)); 664 } 665 realFld.set(elements); 666 } 667 else if (type == RFldType.STRINGLIST) 668 { 669 RFldStringList realFld = (RFldStringList) target; 670 int len = source.getInt("length"); 671 java.util.List elements = new java.util.ArrayList(len); 672 for (int i = 0; i < len; ++i) 673 { 674 elements.add(source.getObject(String.valueOf(i))); 675 } 676 realFld.set(elements); 677 } 678 else if (type == RFldType.STRINGHASHTABLE) 679 { 680 RFldStringHashtable realFld = (RFldStringHashtable) target; 681 java.util.Hashtable elements = new java.util.Hashtable(); 682 for (Enumeration e = source.getMapNames(); e.hasMoreElements();) 683 { 684 String key = (String) e.nextElement(); 685 String elem = (String) source.getObject(key); 686 elements.put(key, elem); 687 } 688 realFld.set(elements); 689 } 690 else 691 throw new ConverterException("Invalid field type: " 692 + type.toString()); 693 } 694 catch (Exception ex) 695 { 696 throw new ConverterException(ex); 697 } 698 } 699 700 /*** 701 * Name of <tt>String</tt> property with the message name. 702 */ 703 public static final String MSG_NAME = "RMsgName"; 704 705 /*** 706 * Name of <tt>String</tt> field with the XML representation of non-JMS 707 * supported field types. 708 */ 709 public static final String XML_FIELD_NAME = "RMsgXML"; 710 711 /*** 712 * Flag to indicate the <tt>boolean</tt> value of the 713 * <tt>TIBCO_JMS_MSG_EXT</tt>- property of map messages. If this is 714 * <tt>true</tt> then all map messages created by this module have the 715 * <tt>TIBCO_JMS_MSG_EXT</tt> property set to <tt>true</tt>. 716 */ 717 private static boolean tibcoJmsMsgExt_ = true; 718 }

This page was automatically generated by Maven