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