001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.jms.message;
031:
032: import com.caucho.jms.connection.JmsSession;
033: import com.caucho.hessian.io.*;
034: import com.caucho.vfs.*;
035: import com.caucho.util.*;
036:
037: import javax.jms.*;
038: import java.lang.ref.WeakReference;
039: import java.io.*;
040: import java.util.*;
041: import java.util.logging.Level;
042: import java.util.logging.Logger;
043:
044: /**
045: * A basic message.
046: */
047: public class MessageImpl implements Message {
048: protected static final Logger log = Logger
049: .getLogger(MessageImpl.class.getName());
050: protected static final L10N L = new L10N(MessageImpl.class);
051:
052: private static final HashSet<String> _reserved;
053:
054: private volatile WeakReference<JmsSession> _sessionRef;
055:
056: private String _messageId;
057: private String _correlationId;
058:
059: private long _timestamp;
060: private long _expiration;
061:
062: private Destination _destination;
063: private Destination _replyTo;
064:
065: private int _deliveryMode = DeliveryMode.PERSISTENT;
066: private boolean _isRedelivered;
067:
068: private String _messageType;
069: private int _priority = 4;
070:
071: private HashMap<String, Object> _properties;
072:
073: private boolean _isHeaderWriteable = true;
074: private boolean _isBodyWriteable = true;
075:
076: public MessageImpl() {
077: }
078:
079: /**
080: * Create a message, copying the properties
081: */
082: public MessageImpl(Message msg) throws JMSException {
083: _messageId = msg.getJMSMessageID();
084: _correlationId = msg.getJMSCorrelationID();
085:
086: _timestamp = msg.getJMSTimestamp();
087: _expiration = msg.getJMSExpiration();
088:
089: _destination = msg.getJMSDestination();
090: _replyTo = msg.getJMSReplyTo();
091:
092: _deliveryMode = msg.getJMSDeliveryMode();
093: _isRedelivered = msg.getJMSRedelivered();
094:
095: _messageType = msg.getJMSType();
096: _priority = msg.getJMSPriority();
097:
098: Enumeration e = msg.getPropertyNames();
099:
100: while (e.hasMoreElements()) {
101: String name = (String) e.nextElement();
102:
103: setObjectProperty(name, msg.getObjectProperty(name));
104: }
105:
106: _isHeaderWriteable = false;
107: _isBodyWriteable = false;
108: }
109:
110: public MessageImpl(MessageImpl msg) {
111: if (msg._properties != null) {
112: _properties = new HashMap<String, Object>(msg._properties);
113: }
114:
115: _messageId = msg._messageId;
116: _correlationId = msg._correlationId;
117:
118: _timestamp = msg._timestamp;
119: _expiration = msg._expiration;
120:
121: _destination = msg._destination;
122: _replyTo = msg._replyTo;
123:
124: _deliveryMode = msg._deliveryMode;
125: _isRedelivered = msg._isRedelivered;
126:
127: _messageType = msg._messageType;
128: _priority = msg._priority;
129:
130: _isHeaderWriteable = false;
131: _isBodyWriteable = false;
132: }
133:
134: /**
135: * Sets the session.
136: */
137: public void setSession(JmsSession session) {
138: _sessionRef = new WeakReference<JmsSession>(session);
139: }
140:
141: /**
142: * Returns the type enumeration.
143: */
144: public MessageType getType() {
145: return MessageType.NULL;
146: }
147:
148: /**
149: * Returns the message id.
150: */
151: public String getJMSMessageID() {
152: return _messageId;
153: }
154:
155: /**
156: * Sets the message id.
157: *
158: * @param id the new message id
159: */
160: public void setJMSMessageID(String id) {
161: _messageId = id;
162: }
163:
164: /**
165: * Returns the time the message was sent.
166: */
167: public long getJMSTimestamp() throws JMSException {
168: return _timestamp;
169: }
170:
171: /**
172: * Sets the time the message was sent.
173: *
174: * @param time the message timestamp
175: */
176: public void setJMSTimestamp(long time) throws JMSException {
177: _timestamp = time;
178: }
179:
180: /**
181: * Returns the correlation id.
182: */
183: public byte[] getJMSCorrelationIDAsBytes() throws JMSException {
184: try {
185: if (_correlationId == null)
186: return null;
187: else
188: return _correlationId.getBytes("UTF8");
189: } catch (Throwable e) {
190: log.log(Level.WARNING, e.toString(), e);
191:
192: return null;
193: }
194: }
195:
196: /**
197: * Sets the correlation id.
198: *
199: * @param id the correlation id
200: */
201: public void setJMSCorrelationIDAsBytes(byte[] id)
202: throws JMSException {
203: try {
204: _correlationId = new String(id, 0, id.length, "UTF8");
205: } catch (Exception e) {
206: log.log(Level.WARNING, e.toString(), e);
207: }
208: }
209:
210: /**
211: * Returns the correlation id.
212: */
213: public String getJMSCorrelationID() throws JMSException {
214: return _correlationId;
215: }
216:
217: /**
218: * Sets the correlation id.
219: *
220: * @param id the correlation id
221: */
222: public void setJMSCorrelationID(String id) throws JMSException {
223: _correlationId = id;
224: }
225:
226: /**
227: * Gets the reply-to destination
228: */
229: public Destination getJMSReplyTo() throws JMSException {
230: return _replyTo;
231: }
232:
233: /**
234: * Sets the reply-to destination
235: *
236: * @param replyTo the destination
237: */
238: public void setJMSReplyTo(Destination replyTo) throws JMSException {
239: _replyTo = replyTo;
240: }
241:
242: /**
243: * Gets the destination
244: */
245: public Destination getJMSDestination() throws JMSException {
246: return _destination;
247: }
248:
249: /**
250: * Sets the reply-to destination
251: *
252: * @param destination the destination
253: */
254: public void setJMSDestination(Destination destination)
255: throws JMSException {
256: _destination = destination;
257: }
258:
259: /**
260: * Gets the delivery model
261: */
262: public int getJMSDeliveryMode() throws JMSException {
263: return _deliveryMode;
264: }
265:
266: /**
267: * Sets the delivery mode
268: *
269: * @param deliveryMode the delivery mode
270: */
271: public void setJMSDeliveryMode(int deliveryMode)
272: throws JMSException {
273: _deliveryMode = deliveryMode;
274: }
275:
276: /**
277: * Returns if the message is being redelivered.
278: */
279: public boolean getJMSRedelivered() {
280: return _isRedelivered;
281: }
282:
283: /**
284: * Sets if the message is being redelivered.
285: *
286: * @param deliveryMode the delivery mode
287: */
288: public void setJMSRedelivered(boolean isRedelivered) {
289: _isRedelivered = isRedelivered;
290: }
291:
292: /**
293: * Returns the message type
294: */
295: public String getJMSType() throws JMSException {
296: return _messageType;
297: }
298:
299: /**
300: * Sets the message type.
301: *
302: * @param type the delivery mode
303: */
304: public void setJMSType(String type) throws JMSException {
305: _messageType = type;
306: }
307:
308: /**
309: * Returns the message expiration time.
310: */
311: public long getJMSExpiration() throws JMSException {
312: return _expiration;
313: }
314:
315: /**
316: * Sets the message expiration type.
317: *
318: * @param time the expiration time
319: */
320: public void setJMSExpiration(long time) throws JMSException {
321: _expiration = time;
322: }
323:
324: /**
325: * Returns the message priority.
326: */
327: public int getJMSPriority() throws JMSException {
328: return _priority;
329: }
330:
331: /**
332: * Sets the message priority.
333: *
334: * @param priority the priority
335: */
336: public void setJMSPriority(int priority) throws JMSException {
337: _priority = priority;
338: }
339:
340: /**
341: * Clears the message properties, making them writeable.
342: */
343: public void clearProperties() throws JMSException {
344: if (_properties != null)
345: _properties.clear();
346: _isHeaderWriteable = true;
347: }
348:
349: /**
350: * Returns true if the property exists.
351: */
352: public boolean propertyExists(String name) throws JMSException {
353: if (_properties == null)
354: return false;
355:
356: return _properties.keySet().contains(name);
357: }
358:
359: /**
360: * Returns a boolean property with the given name.
361: */
362: public boolean getBooleanProperty(String name) throws JMSException {
363: return ObjectConverter.toBoolean(getObjectProperty(name));
364: }
365:
366: /**
367: * Returns a property as a byte
368: */
369: public byte getByteProperty(String name) throws JMSException {
370: return ObjectConverter.toByte(getObjectProperty(name));
371: }
372:
373: /**
374: * Returns a property as a short
375: */
376: public short getShortProperty(String name) throws JMSException {
377: return ObjectConverter.toShort(getObjectProperty(name));
378: }
379:
380: /**
381: * Returns a property as an integer
382: */
383: public int getIntProperty(String name) throws JMSException {
384: return ObjectConverter.toInt(getObjectProperty(name));
385: }
386:
387: /**
388: * Returns a property as a long
389: */
390: public long getLongProperty(String name) throws JMSException {
391: return ObjectConverter.toLong(getObjectProperty(name));
392: }
393:
394: /**
395: * Returns a property as a float
396: */
397: public float getFloatProperty(String name) throws JMSException {
398: return ObjectConverter.toFloat(getObjectProperty(name));
399: }
400:
401: /**
402: * Returns a property as a double
403: */
404: public double getDoubleProperty(String name) throws JMSException {
405: return ObjectConverter.toDouble(getObjectProperty(name));
406: }
407:
408: /**
409: * Returns a string property.
410: */
411: public String getStringProperty(String name) throws JMSException {
412: Object prop = getObjectProperty(name);
413:
414: if (prop == null)
415: return null;
416:
417: return String.valueOf(prop);
418: }
419:
420: /**
421: * Returns a string property.
422: */
423: public Object getObjectProperty(String name) throws JMSException {
424: if (_properties == null || name == null)
425: return null;
426: else
427: return _properties.get(name);
428: }
429:
430: /**
431: * Returns an enumeration of the message's properties.
432: */
433: public Enumeration getPropertyNames() throws JMSException {
434: if (_properties == null)
435: return NullEnumeration.create();
436: else
437: return Collections.enumeration(_properties.keySet());
438: }
439:
440: /**
441: * Sets a boolean property.
442: *
443: * @param name the property name
444: * @param value the property's value
445: */
446: public void setBooleanProperty(String name, boolean value)
447: throws JMSException {
448: setObjectProperty(name, new Boolean(value));
449: }
450:
451: /**
452: * Sets a byte property.
453: *
454: * @param name the property name
455: * @param value the property's value
456: */
457: public void setByteProperty(String name, byte value)
458: throws JMSException {
459: setObjectProperty(name, new Byte(value));
460: }
461:
462: /**
463: * Sets a short property.
464: *
465: * @param name the property name
466: * @param value the property's value
467: */
468: public void setShortProperty(String name, short value)
469: throws JMSException {
470: setObjectProperty(name, new Short(value));
471: }
472:
473: /**
474: * Sets an integer property.
475: *
476: * @param name the property name
477: * @param value the property's value
478: */
479: public void setIntProperty(String name, int value)
480: throws JMSException {
481: setObjectProperty(name, new Integer(value));
482: }
483:
484: /**
485: * Sets a long property.
486: *
487: * @param name the property name
488: * @param value the property's value
489: */
490: public void setLongProperty(String name, long value)
491: throws JMSException {
492: setObjectProperty(name, new Long(value));
493: }
494:
495: /**
496: * Sets a float property.
497: *
498: * @param name the property name
499: * @param value the property's value
500: */
501: public void setFloatProperty(String name, float value)
502: throws JMSException {
503: setObjectProperty(name, new Float(value));
504: }
505:
506: /**
507: * Sets a double property.
508: *
509: * @param name the property name
510: * @param value the property's value
511: */
512: public void setDoubleProperty(String name, double value)
513: throws JMSException {
514: setObjectProperty(name, new Double(value));
515: }
516:
517: /**
518: * Sets a string property.
519: *
520: * @param name the property name
521: * @param value the property's value
522: */
523: public void setStringProperty(String name, String value)
524: throws JMSException {
525: setObjectProperty(name, value);
526: }
527:
528: /**
529: * Sets an object property.
530: *
531: * @param name the property name
532: * @param value the property's value
533: */
534: public void setObjectProperty(String name, Object value)
535: throws JMSException {
536: checkPropertyWriteable();
537:
538: if (name == null)
539: throw new NullPointerException();
540: else if ("".equals(name))
541: throw new IllegalArgumentException();
542: if (isReserved(name))
543: throw new JMSException(L.l(
544: "'{0}' is a reserved property name.", name));
545:
546: if (!(value == null || value instanceof Number
547: || value instanceof String || value instanceof Boolean))
548: throw new MessageFormatException(L.l(
549: "{0} is an illegal object property value", value
550: .getClass().getName()));
551:
552: if (_properties == null)
553: _properties = new HashMap<String, Object>();
554:
555: _properties.put(name, value);
556: }
557:
558: /**
559: * Acknowledge receipt of this message.
560: */
561: public void acknowledge() throws JMSException {
562: WeakReference<JmsSession> sessionRef = _sessionRef;
563: _sessionRef = null;
564:
565: JmsSession session;
566:
567: if (sessionRef != null && (session = sessionRef.get()) != null) {
568: session.acknowledge();
569: }
570: }
571:
572: /**
573: * Clears the body, setting write mode.
574: */
575: public void clearBody() throws JMSException {
576: _isBodyWriteable = true;
577: }
578:
579: /**
580: * Sets the body for reading.
581: */
582: public void setReceive() throws JMSException {
583: _isHeaderWriteable = false;
584: _isBodyWriteable = false;
585: }
586:
587: /**
588: * Sets the body for reading.
589: */
590: protected void setBodyReadOnly() {
591: _isBodyWriteable = false;
592: }
593:
594: /**
595: * Returns the properties.
596: */
597: public HashMap<String, Object> getProperties() {
598: return _properties;
599: }
600:
601: public MessageImpl copy() {
602: MessageImpl msg = new MessageImpl();
603:
604: copy(msg);
605:
606: return msg;
607: }
608:
609: /**
610: * Serialize the properties to an input stream.
611: */
612: public InputStream propertiesToInputStream() throws IOException {
613: if (_properties == null || _properties.size() == 0)
614: return null;
615:
616: TempOutputStream out = new TempOutputStream();
617:
618: writeProperties(out);
619:
620: out.close();
621:
622: return out.openRead();
623: }
624:
625: /**
626: * Serialize the properties to an input stream.
627: */
628: public void writeProperties(OutputStream os) throws IOException {
629: if (_properties == null || _properties.size() == 0)
630: return;
631:
632: Hessian2Output out = new Hessian2Output(os);
633:
634: out.writeString(_messageId);
635: out.writeBoolean(_isRedelivered);
636: out.writeInt(_priority);
637: out.writeLong(_timestamp);
638: out.writeInt(_deliveryMode);
639: if (_destination instanceof java.io.Serializable)
640: out.writeObject(_destination);
641: else
642: out.writeObject(null);
643:
644: if (_replyTo instanceof java.io.Serializable)
645: out.writeObject(_replyTo);
646: else
647: out.writeObject(null);
648:
649: for (Map.Entry<String, Object> entry : _properties.entrySet()) {
650: out.writeString(entry.getKey());
651: out.writeObject(entry.getValue());
652: }
653:
654: out.close();
655: }
656:
657: /**
658: * Read the properties from an input stream.
659: */
660: public void readProperties(InputStream is) throws IOException,
661: JMSException {
662: if (is == null)
663: return;
664:
665: Hessian2Input in = new Hessian2Input(is);
666:
667: _messageId = in.readString();
668: _isRedelivered = in.readBoolean();
669: _priority = in.readInt();
670: _timestamp = in.readLong();
671: _deliveryMode = in.readInt();
672: _destination = (Destination) in.readObject();
673: _replyTo = (Destination) in.readObject();
674:
675: while (!in.isEnd()) {
676: String key = in.readString();
677: Object value = in.readObject();
678:
679: setObjectProperty(key, value);
680: }
681:
682: in.close();
683: }
684:
685: /**
686: * Serialize the body to an input stream.
687: */
688: public InputStream bodyToInputStream() throws IOException {
689: return null;
690: }
691:
692: /**
693: * Serialize the body to an output stream.
694: */
695: public void writeBody(OutputStream os) throws IOException {
696: }
697:
698: /**
699: * Read the body from an input stream.
700: */
701: public void readBody(InputStream is) throws IOException,
702: JMSException {
703: }
704:
705: protected void checkHeaderWriteable() throws JMSException {
706: if (!_isHeaderWriteable)
707: throw new MessageNotWriteableException(L
708: .l("received messages can't be written."));
709: }
710:
711: protected void checkPropertyWriteable() throws JMSException {
712: if (!_isHeaderWriteable)
713: throw new MessageNotWriteableException(
714: L
715: .l("properties for received messages are read-only."));
716: }
717:
718: protected void checkBodyWriteable() throws JMSException {
719: if (!_isBodyWriteable)
720: throw new MessageNotWriteableException(L
721: .l("received messages can't be written."));
722: }
723:
724: protected void checkBodyReadable() throws JMSException {
725: if (_isBodyWriteable)
726: throw new MessageNotReadableException(
727: L
728: .l("write-only messages can't be read until reset() is called."));
729: }
730:
731: protected void copy(MessageImpl newMsg) {
732: if (_properties != null) {
733: newMsg._properties = new HashMap<String, Object>(
734: _properties);
735: }
736:
737: newMsg._messageId = _messageId;
738: newMsg._correlationId = _correlationId;
739:
740: newMsg._timestamp = _timestamp;
741: newMsg._expiration = _expiration;
742:
743: newMsg._destination = _destination;
744: newMsg._replyTo = _replyTo;
745:
746: newMsg._deliveryMode = _deliveryMode;
747: newMsg._isRedelivered = _isRedelivered;
748:
749: newMsg._messageType = _messageType;
750: newMsg._priority = _priority;
751: }
752:
753: public String toString() {
754: if (_messageId != null)
755: return getClass().getSimpleName() + "[" + _messageId + "]";
756: else if (Alarm.isTest())
757: return getClass().getSimpleName() + "[]";
758: else
759: return getClass().getSimpleName() + "@"
760: + System.identityHashCode(this );
761: }
762:
763: public static boolean isReserved(String name) {
764: return _reserved.contains(name.toUpperCase());
765: }
766:
767: static {
768: _reserved = new HashSet<String>();
769: _reserved.add("TRUE");
770: _reserved.add("FALSE");
771: _reserved.add("NULL");
772: _reserved.add("NOT");
773: _reserved.add("AND");
774: _reserved.add("OR");
775: _reserved.add("BETWEEN");
776: _reserved.add("LIKE");
777: _reserved.add("IN");
778: _reserved.add("IS");
779: _reserved.add("ESCAPE");
780: }
781: }
|