001: /*
002: * Copyright 2005 Joe Walker
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.directwebremoting.jms;
017:
018: import java.io.Serializable;
019: import java.util.Collections;
020: import java.util.Enumeration;
021: import java.util.HashMap;
022: import java.util.Map;
023:
024: import javax.jms.DeliveryMode;
025: import javax.jms.Destination;
026: import javax.jms.MapMessage;
027: import javax.jms.Message;
028: import javax.jms.ObjectMessage;
029: import javax.jms.TextMessage;
030:
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033: import org.directwebremoting.Hub;
034: import org.directwebremoting.event.MessageEvent;
035: import org.directwebremoting.extend.MarshallException;
036:
037: /**
038: * An implementation of all the {@link Message} types rolled into one.
039: * This allows DWR to not know what type of Message the user wishes to work with
040: * and to make the decision at runtime depending on how they choose to cast us.
041: * @author Joe Walker [joe at getahead dot ltd dot uk]
042: */
043: public class DwrMessage implements Message, MapMessage, TextMessage,
044: ObjectMessage {
045: /**
046: * Default ctor
047: */
048: public DwrMessage() {
049: }
050:
051: /**
052: * Ctor for setting up a {@link TextMessage}
053: */
054: public DwrMessage(String text) {
055: setText(text);
056: }
057:
058: /**
059: * Ctor for setting up an {@link ObjectMessage}
060: */
061: public DwrMessage(Serializable object) {
062: setObject(object);
063: }
064:
065: /**
066: * Ctor for propagation from the DWR {@link Hub}.
067: */
068: public DwrMessage(Hub hub, MessageEvent message) {
069: setMessageEvent(hub, message);
070: }
071:
072: /* (non-Javadoc)
073: * @see javax.jms.Message#acknowledge()
074: */
075: public void acknowledge() {
076: throw Unsupported.noManualAcknowledgment();
077: }
078:
079: /* (non-Javadoc)
080: * @see javax.jms.Message#clearBody()
081: */
082: public void clearBody() {
083: throw new IllegalStateException(
084: "Can raw JMS messages have bodies?");
085: }
086:
087: /* (non-Javadoc)
088: * @see javax.jms.Message#clearProperties()
089: */
090: public void clearProperties() {
091: properties.clear();
092: }
093:
094: /* (non-Javadoc)
095: * @see javax.jms.Message#getPropertyNames()
096: */
097: public Enumeration<String> getPropertyNames() {
098: return Collections.enumeration(properties.keySet());
099: }
100:
101: /* (non-Javadoc)
102: * @see javax.jms.Message#propertyExists(java.lang.String)
103: */
104: public boolean propertyExists(String name) {
105: return properties.containsKey(name);
106: }
107:
108: /* (non-Javadoc)
109: * @see javax.jms.Message#getBooleanProperty(java.lang.String)
110: */
111: public boolean getBooleanProperty(String name) {
112: return Boolean.parseBoolean(getStringProperty(name));
113: }
114:
115: /* (non-Javadoc)
116: * @see javax.jms.Message#getByteProperty(java.lang.String)
117: */
118: public byte getByteProperty(String name) {
119: return Byte.parseByte(getStringProperty(name));
120: }
121:
122: /* (non-Javadoc)
123: * @see javax.jms.Message#getDoubleProperty(java.lang.String)
124: */
125: public double getDoubleProperty(String name) {
126: return Double.parseDouble(getStringProperty(name));
127: }
128:
129: /* (non-Javadoc)
130: * @see javax.jms.Message#getFloatProperty(java.lang.String)
131: */
132: public float getFloatProperty(String name) {
133: return Float.parseFloat(getStringProperty(name));
134: }
135:
136: /* (non-Javadoc)
137: * @see javax.jms.Message#getIntProperty(java.lang.String)
138: */
139: public int getIntProperty(String name) {
140: return Integer.parseInt(getStringProperty(name));
141: }
142:
143: /* (non-Javadoc)
144: * @see javax.jms.Message#getLongProperty(java.lang.String)
145: */
146: public long getLongProperty(String name) {
147: return Long.parseLong(getStringProperty(name));
148: }
149:
150: /* (non-Javadoc)
151: * @see javax.jms.Message#getObjectProperty(java.lang.String)
152: */
153: public Object getObjectProperty(String name) {
154: return properties.get(name);
155: }
156:
157: /* (non-Javadoc)
158: * @see javax.jms.Message#getShortProperty(java.lang.String)
159: */
160: public short getShortProperty(String name) {
161: return Short.parseShort(getStringProperty(name));
162: }
163:
164: /* (non-Javadoc)
165: * @see javax.jms.Message#getStringProperty(java.lang.String)
166: */
167: public String getStringProperty(String name) {
168: return properties.get(name).toString();
169: }
170:
171: /* (non-Javadoc)
172: * @see javax.jms.Message#setBooleanProperty(java.lang.String, boolean)
173: */
174: public void setBooleanProperty(String name, boolean value) {
175: properties.put(name, value);
176: }
177:
178: /* (non-Javadoc)
179: * @see javax.jms.Message#setByteProperty(java.lang.String, byte)
180: */
181: public void setByteProperty(String name, byte value) {
182: properties.put(name, value);
183: }
184:
185: /* (non-Javadoc)
186: * @see javax.jms.Message#setDoubleProperty(java.lang.String, double)
187: */
188: public void setDoubleProperty(String name, double value) {
189: properties.put(name, value);
190: }
191:
192: /* (non-Javadoc)
193: * @see javax.jms.Message#setFloatProperty(java.lang.String, float)
194: */
195: public void setFloatProperty(String name, float value) {
196: properties.put(name, value);
197: }
198:
199: /* (non-Javadoc)
200: * @see javax.jms.Message#setIntProperty(java.lang.String, int)
201: */
202: public void setIntProperty(String name, int value) {
203: properties.put(name, value);
204: }
205:
206: /* (non-Javadoc)
207: * @see javax.jms.Message#setLongProperty(java.lang.String, long)
208: */
209: public void setLongProperty(String name, long value) {
210: properties.put(name, value);
211: }
212:
213: /* (non-Javadoc)
214: * @see javax.jms.Message#setObjectProperty(java.lang.String, java.lang.Object)
215: */
216: public void setObjectProperty(String name, Object value) {
217: properties.put(name, value);
218: }
219:
220: /* (non-Javadoc)
221: * @see javax.jms.Message#setShortProperty(java.lang.String, short)
222: */
223: public void setShortProperty(String name, short value) {
224: properties.put(name, value);
225: }
226:
227: /* (non-Javadoc)
228: * @see javax.jms.Message#setStringProperty(java.lang.String, java.lang.String)
229: */
230: public void setStringProperty(String name, String value) {
231: properties.put(name, value);
232: }
233:
234: /* (non-Javadoc)
235: * @see javax.jms.Message#getJMSCorrelationID()
236: */
237: public String getJMSCorrelationID() {
238: return correlationId;
239: }
240:
241: /* (non-Javadoc)
242: * @see javax.jms.Message#getJMSCorrelationIDAsBytes()
243: */
244: public byte[] getJMSCorrelationIDAsBytes() {
245: return correlationId.getBytes();
246: }
247:
248: /* (non-Javadoc)
249: * @see javax.jms.Message#getJMSDeliveryMode()
250: */
251: public int getJMSDeliveryMode() {
252: return deliveryMode;
253: }
254:
255: /* (non-Javadoc)
256: * @see javax.jms.Message#getJMSDestination()
257: */
258: public Destination getJMSDestination() {
259: return destination;
260: }
261:
262: /* (non-Javadoc)
263: * @see javax.jms.Message#getJMSExpiration()
264: */
265: public long getJMSExpiration() {
266: return expiration;
267: }
268:
269: /* (non-Javadoc)
270: * @see javax.jms.Message#getJMSMessageID()
271: */
272: public String getJMSMessageID() {
273: return messageId;
274: }
275:
276: /* (non-Javadoc)
277: * @see javax.jms.Message#getJMSPriority()
278: */
279: public int getJMSPriority() {
280: return priority;
281: }
282:
283: /* (non-Javadoc)
284: * @see javax.jms.Message#getJMSRedelivered()
285: */
286: public boolean getJMSRedelivered() {
287: return redelivered;
288: }
289:
290: /* (non-Javadoc)
291: * @see javax.jms.Message#getJMSReplyTo()
292: */
293: public Destination getJMSReplyTo() {
294: return replyTo;
295: }
296:
297: /* (non-Javadoc)
298: * @see javax.jms.Message#getJMSTimestamp()
299: */
300: public long getJMSTimestamp() {
301: return timestamp;
302: }
303:
304: /* (non-Javadoc)
305: * @see javax.jms.Message#getJMSType()
306: */
307: public String getJMSType() {
308: return type;
309: }
310:
311: /* (non-Javadoc)
312: * @see javax.jms.Message#setJMSCorrelationID(java.lang.String)
313: */
314: public void setJMSCorrelationID(String correlationID) {
315: this .correlationId = correlationID;
316: }
317:
318: /* (non-Javadoc)
319: * @see javax.jms.Message#setJMSCorrelationIDAsBytes(byte[])
320: */
321: public void setJMSCorrelationIDAsBytes(byte[] correlationID) {
322: this .correlationId = new String(correlationID);
323: }
324:
325: /* (non-Javadoc)
326: * @see javax.jms.Message#setJMSDeliveryMode(int)
327: */
328: public void setJMSDeliveryMode(int deliveryMode) {
329: this .deliveryMode = deliveryMode;
330: throw Unsupported.noTransactions();
331: }
332:
333: /* (non-Javadoc)
334: * @see javax.jms.Message#setJMSDestination(javax.jms.Destination)
335: */
336: public void setJMSDestination(Destination destination) {
337: this .destination = destination;
338: }
339:
340: /* (non-Javadoc)
341: * @see javax.jms.Message#setJMSExpiration(long)
342: */
343: public void setJMSExpiration(long expiration) {
344: this .expiration = expiration;
345: throw Unsupported.noMessageExpiry();
346: }
347:
348: /* (non-Javadoc)
349: * @see javax.jms.Message#setJMSMessageID(java.lang.String)
350: */
351: public void setJMSMessageID(String messageId) {
352: this .messageId = messageId;
353: }
354:
355: /* (non-Javadoc)
356: * @see javax.jms.Message#setJMSPriority(int)
357: */
358: public void setJMSPriority(int priority) {
359: this .priority = priority;
360: throw Unsupported.noMessagePriority();
361: }
362:
363: /* (non-Javadoc)
364: * @see javax.jms.Message#setJMSRedelivered(boolean)
365: */
366: public void setJMSRedelivered(boolean redelivered) {
367: this .redelivered = redelivered;
368: throw Unsupported.noTransactions();
369: }
370:
371: /* (non-Javadoc)
372: * @see javax.jms.Message#setJMSReplyTo(javax.jms.Destination)
373: */
374: public void setJMSReplyTo(Destination replyTo) {
375: this .replyTo = replyTo;
376: throw Unsupported.noPointToPoint();
377: }
378:
379: /* (non-Javadoc)
380: * @see javax.jms.Message#setJMSTimestamp(long)
381: */
382: public void setJMSTimestamp(long timestamp) {
383: this .timestamp = timestamp;
384: }
385:
386: /* (non-Javadoc)
387: * @see javax.jms.Message#setJMSType(java.lang.String)
388: */
389: public void setJMSType(String type) {
390: this .type = type;
391: }
392:
393: /**
394: * Holds a reference to a message that we are replying/referring to
395: */
396: private String correlationId;
397:
398: /**
399: * @see DeliveryMode
400: */
401: private int deliveryMode;
402:
403: /**
404: * The topic or queue that we are destined for
405: */
406: private Destination destination;
407:
408: /**
409: * How long until this message expires
410: */
411: private long expiration;
412:
413: /**
414: * All JMS messages need a unique id
415: */
416: private String messageId;
417:
418: /**
419: * @see Message#setJMSPriority(int)
420: */
421: private int priority;
422:
423: /**
424: * Perhaps we will support this when we support Gears?
425: */
426: private boolean redelivered;
427:
428: /**
429: * The topic or queue that message replies should be sent to
430: */
431: private Destination replyTo;
432:
433: /**
434: * @see Message#setJMSTimestamp(long)
435: */
436: private long timestamp;
437:
438: /**
439: * @see Message#setJMSType(String)
440: */
441: private String type;
442:
443: /**
444: * The hash of properties assigned to this message
445: */
446: private Map<String, Object> properties = new HashMap<String, Object>();
447:
448: // The methods from MapMessage
449:
450: /* (non-Javadoc)
451: * @see javax.jms.MapMessage#getMapNames()
452: */
453: public Enumeration<String> getMapNames() {
454: return Collections.enumeration(map.keySet());
455: }
456:
457: /* (non-Javadoc)
458: * @see javax.jms.MapMessage#itemExists(java.lang.String)
459: */
460: public boolean itemExists(String name) {
461: return map.containsKey(name);
462: }
463:
464: /* (non-Javadoc)
465: * @see javax.jms.MapMessage#getBoolean(java.lang.String)
466: */
467: public boolean getBoolean(String name) {
468: return Boolean.parseBoolean(getString(name));
469: }
470:
471: /* (non-Javadoc)
472: * @see javax.jms.MapMessage#getByte(java.lang.String)
473: */
474: public byte getByte(String name) {
475: return Byte.parseByte(getString(name));
476: }
477:
478: /* (non-Javadoc)
479: * @see javax.jms.MapMessage#getBytes(java.lang.String)
480: */
481: public byte[] getBytes(String name) {
482: return getString(name).getBytes();
483: }
484:
485: /* (non-Javadoc)
486: * @see javax.jms.MapMessage#getChar(java.lang.String)
487: */
488: public char getChar(String name) {
489: return getString(name).charAt(0);
490: }
491:
492: /* (non-Javadoc)
493: * @see javax.jms.MapMessage#getDouble(java.lang.String)
494: */
495: public double getDouble(String name) {
496: return Double.parseDouble(getString(name));
497: }
498:
499: /* (non-Javadoc)
500: * @see javax.jms.MapMessage#getFloat(java.lang.String)
501: */
502: public float getFloat(String name) {
503: return Float.parseFloat(getString(name));
504: }
505:
506: /* (non-Javadoc)
507: * @see javax.jms.MapMessage#getInt(java.lang.String)
508: */
509: public int getInt(String name) {
510: return Integer.parseInt(getString(name));
511: }
512:
513: /* (non-Javadoc)
514: * @see javax.jms.MapMessage#getLong(java.lang.String)
515: */
516: public long getLong(String name) {
517: return Long.parseLong(getString(name));
518: }
519:
520: /* (non-Javadoc)
521: * @see javax.jms.MapMessage#getShort(java.lang.String)
522: */
523: public short getShort(String name) {
524: return Short.parseShort(getString(name));
525: }
526:
527: /* (non-Javadoc)
528: * @see javax.jms.MapMessage#getString(java.lang.String)
529: */
530: public String getString(String name) {
531: return getObject(name).toString();
532: }
533:
534: /* (non-Javadoc)
535: * @see javax.jms.MapMessage#getObject(java.lang.String)
536: */
537: @SuppressWarnings("unchecked")
538: public Object getObject(String name) {
539: switch (source) {
540: case MAP:
541: return map.get(name);
542:
543: case MESSAGE_EVENT:
544: try {
545: return message.getData(Map.class);
546: } catch (MarshallException ex) {
547: return "";
548: }
549:
550: case NONE:
551: return "";
552:
553: case SERIALIZABLE:
554: return ((Map<String, Object>) object).get(name);
555:
556: case TEXT:
557: return "";
558:
559: default:
560: return "";
561: }
562: }
563:
564: /* (non-Javadoc)
565: * @see javax.jms.MapMessage#setBoolean(java.lang.String, boolean)
566: */
567: public void setBoolean(String name, boolean value) {
568: map.put(name, value);
569: setSource(Source.MAP);
570: }
571:
572: /* (non-Javadoc)
573: * @see javax.jms.MapMessage#setByte(java.lang.String, byte)
574: */
575: public void setByte(String name, byte value) {
576: map.put(name, value);
577: setSource(Source.MAP);
578: }
579:
580: /* (non-Javadoc)
581: * @see javax.jms.MapMessage#setBytes(java.lang.String, byte[])
582: */
583: public void setBytes(String name, byte[] value) {
584: map.put(name, value);
585: setSource(Source.MAP);
586: }
587:
588: /* (non-Javadoc)
589: * @see javax.jms.MapMessage#setBytes(java.lang.String, byte[], int, int)
590: */
591: public void setBytes(String name, byte[] value, int offset,
592: int length) {
593: byte[] data = new byte[length];
594: System.arraycopy(data, 0, value, offset, length);
595: map.put(name, data);
596: setSource(Source.MAP);
597: }
598:
599: /* (non-Javadoc)
600: * @see javax.jms.MapMessage#setChar(java.lang.String, char)
601: */
602: public void setChar(String name, char value) {
603: map.put(name, value);
604: setSource(Source.MAP);
605: }
606:
607: /* (non-Javadoc)
608: * @see javax.jms.MapMessage#setDouble(java.lang.String, double)
609: */
610: public void setDouble(String name, double value) {
611: map.put(name, value);
612: setSource(Source.MAP);
613: }
614:
615: /* (non-Javadoc)
616: * @see javax.jms.MapMessage#setFloat(java.lang.String, float)
617: */
618: public void setFloat(String name, float value) {
619: map.put(name, value);
620: setSource(Source.MAP);
621: }
622:
623: /* (non-Javadoc)
624: * @see javax.jms.MapMessage#setInt(java.lang.String, int)
625: */
626: public void setInt(String name, int value) {
627: map.put(name, value);
628: setSource(Source.MAP);
629: }
630:
631: /* (non-Javadoc)
632: * @see javax.jms.MapMessage#setLong(java.lang.String, long)
633: */
634: public void setLong(String name, long value) {
635: map.put(name, value);
636: setSource(Source.MAP);
637: }
638:
639: /* (non-Javadoc)
640: * @see javax.jms.MapMessage#setObject(java.lang.String, java.lang.Object)
641: */
642: public void setObject(String name, Object value) {
643: map.put(name, value);
644: setSource(Source.MAP);
645: }
646:
647: /* (non-Javadoc)
648: * @see javax.jms.MapMessage#setShort(java.lang.String, short)
649: */
650: public void setShort(String name, short value) {
651: map.put(name, value);
652: setSource(Source.MAP);
653: }
654:
655: /* (non-Javadoc)
656: * @see javax.jms.MapMessage#setString(java.lang.String, java.lang.String)
657: */
658: public void setString(String name, String value) {
659: map.put(name, value);
660: setSource(Source.MAP);
661: }
662:
663: // The methods from TextMessage
664:
665: /* (non-Javadoc)
666: * @see javax.jms.TextMessage#getText()
667: */
668: public String getText() {
669: switch (source) {
670: case MAP:
671: return null;
672:
673: case MESSAGE_EVENT:
674: try {
675: return message.getData(String.class);
676: } catch (MarshallException ex) {
677: return null;
678: }
679:
680: case NONE:
681: return null;
682:
683: case SERIALIZABLE:
684: return object.toString();
685:
686: case TEXT:
687: return text;
688:
689: default:
690: return null;
691: }
692: }
693:
694: /* (non-Javadoc)
695: * @see javax.jms.TextMessage#setText(java.lang.String)
696: */
697: public void setText(String text) {
698: this .text = text;
699: setSource(Source.TEXT);
700: }
701:
702: // The methods from ObjectMessage
703:
704: /* (non-Javadoc)
705: * @see javax.jms.ObjectMessage#getObject()
706: */
707: public Serializable getObject() {
708: switch (source) {
709: case MAP:
710: return null;
711:
712: case MESSAGE_EVENT:
713: return (Serializable) message.getRawData();
714:
715: case NONE:
716: return null;
717:
718: case SERIALIZABLE:
719: return object;
720:
721: case TEXT:
722: return text;
723:
724: default:
725: return null;
726: }
727: }
728:
729: /* (non-Javadoc)
730: * @see javax.jms.ObjectMessage#setObject(java.io.Serializable)
731: */
732: public void setObject(Serializable object) {
733: this .object = object;
734: setSource(Source.SERIALIZABLE);
735: }
736:
737: /**
738: * @param hub
739: * @param message
740: */
741: private void setMessageEvent(Hub hub, MessageEvent message) {
742: this .hub = hub;
743: this .message = message;
744: setSource(Source.MESSAGE_EVENT);
745: }
746:
747: /**
748: * We might want to warn people about gratuitous source type changes
749: */
750: private void setSource(Source source) {
751: if (this .source != null && this .source != source) {
752: log.warn("Changing source of message from " + this .source
753: + " to " + source);
754: }
755:
756: this .source = source;
757: }
758:
759: /**
760: * Where did the data for this message come from?
761: */
762: enum Source {
763: /**
764: * Use by the DWR Hub. Data is stored in hub and message
765: * @see #hub
766: * @see #message
767: */
768: MESSAGE_EVENT,
769:
770: /**
771: * There is no data, we have to assume headers only
772: */
773: NONE,
774:
775: /**
776: * Data is stored in text
777: * @see #text
778: */
779: TEXT,
780:
781: /**
782: * Data is stored in the map
783: * @see #map
784: */
785: MAP,
786:
787: /**
788: * Data is stored in the serializable object
789: * @see #object
790: */
791: SERIALIZABLE,
792:
793: /**
794: * Streamed data is not supported yet
795: */
796: // STREAM,
797: /**
798: * Binary data is not supported yet
799: */
800: // BYTES,
801: }
802:
803: /**
804: * What is the current source of our data
805: */
806: protected Source source = null;
807:
808: /**
809: * The object that we are wrapping
810: */
811: protected Serializable object;
812:
813: /**
814: * The message passed over JMS
815: */
816: protected String text;
817:
818: /**
819: * The map of contained objects
820: */
821: protected Map<String, Object> map = new HashMap<String, Object>();
822:
823: /**
824: * The Hub for when data is received from the client
825: */
826: protected Hub hub;
827:
828: /**
829: * The message straight out of the hub
830: */
831: protected MessageEvent message;
832:
833: /**
834: * The log stream
835: */
836: private static final Log log = LogFactory.getLog(DwrMessage.class);
837: }
|