KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > presumo > jms > message > JmsMessage


1 /**
2  * This file is part of Presumo.
3  *
4  * Presumo is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * Presumo is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Presumo; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  *
19  * Copyright 2001 Dan Greff
20  */

21 package com.presumo.jms.message;
22
23 import com.presumo.jms.client.JmsDestination;
24 import com.presumo.jms.client.JmsTopic;
25 import com.presumo.jms.client.JmsSession;
26
27 import java.util.BitSet JavaDoc;
28 import java.util.Enumeration JavaDoc;
29 import java.util.TimeZone JavaDoc;
30
31 import java.io.ByteArrayInputStream JavaDoc;
32 import java.io.ByteArrayOutputStream JavaDoc;
33 import java.io.DataOutput JavaDoc;
34 import java.io.DataOutputStream JavaDoc;
35 import java.io.DataInput JavaDoc;
36 import java.io.DataInputStream JavaDoc;
37 import java.io.Externalizable JavaDoc;
38 import java.io.IOException JavaDoc;
39 import java.io.ObjectInput JavaDoc;
40 import java.io.ObjectOutput JavaDoc;
41
42 import javax.jms.Message JavaDoc;
43 import javax.jms.JMSException JavaDoc;
44 import javax.jms.Destination JavaDoc;
45 import javax.jms.MessageFormatException JavaDoc;
46 import javax.jms.MessageNotWriteableException JavaDoc;
47
48
49 /**
50  * <p>Implementation of javax.jms.Message.</p>
51  *
52  * @author Dan Greff
53  */

54 public class JmsMessage
55     implements Message JavaDoc, Externalizable JavaDoc, Cloneable JavaDoc
56 {
57   protected boolean readOnly = false;
58
59   private MessageHeader header;
60   private PrimitiveMap properties;
61
62   private boolean local; // Used to implement noLocal functionality
63
private int sendingTargetID = -1; // Used to prevent message backtracking
64
private AckHelper ackHelper; // Used to keep track of acknowledgements
65
private JmsSession sessionCallback;
66   private BitSet JavaDoc routingMask;
67   
68     /////////////////////////////////////////////////////////////////////////
69
// Constructors //
70
/////////////////////////////////////////////////////////////////////////
71

72   public JmsMessage()
73   {
74     header = new MessageHeader();
75     properties = new PrimitiveMap();
76   }
77
78   public JmsMessage(String JavaDoc routername)
79   {
80     header = new MessageHeader();
81     properties = new PrimitiveMap();
82
83     header.setJMSMessageID(new MessageID(routername));
84   }
85   
86   public JmsMessage(byte [] buf, int offset, int length)
87   {
88     header = new MessageHeader();
89     properties = new PrimitiveMap();
90    
91     try {
92       ByteArrayInputStream JavaDoc byteStream;
93       byteStream = new ByteArrayInputStream JavaDoc(buf, offset, length);
94       DataInputStream JavaDoc dataStream = new DataInputStream JavaDoc(byteStream);
95       this.unmarshal(dataStream);
96       dataStream.close();
97       byteStream.close();
98     } catch (IOException JavaDoc ioe) {}
99   }
100
101     /////////////////////////////////////////////////////////////////////////
102
// Public Methods //
103
/////////////////////////////////////////////////////////////////////////
104

105   /**
106    * Implementation of cloneable interface. Simply does the default shallow
107    * clone on purpose. This is needed to make acknowledge() work. This
108    * implementation will clone a message and then set acknowledgment info
109    * on the clone. The data structures within this message implementation
110    * are set up so that the shallow clone will not duplicate the data but
111    * only references to it. As a result there will not be multiple copies
112    * of the actual message data (header, properties, body, etc...) in memory.
113    *
114    * Since the data is not copied, there is really no advantage to cloning
115    * a message within JMS application code and one should not do so within
116    * a JMS application. The JMS specification does not specify a standard
117    * behavior in response to a clone.
118    */

119   public final Object JavaDoc clone()
120   {
121     try {
122       return super.clone();
123     } catch (CloneNotSupportedException JavaDoc e) { e.printStackTrace(); }
124     return null;
125   }
126
127   public int hashCode()
128   {
129     return header.jmsMessageID.hashCode();
130   }
131
132   public boolean equals(Object JavaDoc obj)
133   {
134     if ( (obj != null) && (obj instanceof JmsMessage) ) {
135       JmsMessage msg = (JmsMessage) obj;
136       return header.jmsMessageID.equals(msg.header.jmsMessageID);
137     }
138     return false;
139   }
140
141   /**
142    * Overides Object.toString() to display the contents of the Message
143    * header and properties.
144    */

145   public String JavaDoc toString()
146   {
147     return super.toString() + "\n" +header.toString() + properties.toString();
148   }
149   
150
151   /**
152    * Utility function to convert the message to a byte array.
153    */

154   public final byte[] toByteArray()
155   {
156     byte [] result = null;
157     try {
158
159       ByteArrayOutputStream JavaDoc byteStream = new ByteArrayOutputStream JavaDoc();
160       DataOutputStream JavaDoc dataStream = new DataOutputStream JavaDoc(byteStream);
161       this.marshal(dataStream);
162       dataStream.flush();
163       result = byteStream.toByteArray();
164       dataStream.close();
165       byteStream.close();
166  
167     } catch (IOException JavaDoc ioe) {}
168     return result;
169   }
170   
171   /**
172    * Implemented so messages can be serialized.
173    */

174   public final void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc
175   {
176     marshal(out);
177   }
178   
179   /**
180    * Implemented so messages can be serialized.
181    */

182   public final void readExternal(ObjectInput JavaDoc in) throws IOException JavaDoc
183   {
184     unmarshal(in);
185   }
186   
187   /**
188    * Custom data marshaling mechanism.
189    */

190   public void marshal(DataOutput JavaDoc out) throws IOException JavaDoc
191   {
192     header.marshal(out);
193     properties.marshal(out);
194   }
195   
196   /**
197    * Reads in state saved via the custom marshaling mechanism
198    */

199   public void unmarshal(DataInput JavaDoc in) throws IOException JavaDoc
200   {
201     header.unmarshal(in);
202    
203     // Persistent messages must have a AckHelper to handle
204
// acknowledgements properly
205
if (header.jmsDeliveryMode == javax.jms.DeliveryMode.PERSISTENT)
206       this.ackHelper = new AckHelper(this);
207
208     properties.unmarshal(in);
209   }
210   
211
212     /////////////////////////////////////////////////////////////////////////
213
// Public Methods implementing javax.jms.Message //
214
/////////////////////////////////////////////////////////////////////////
215

216   public void acknowledge()
217   {
218     if (sessionCallback != null) {
219       sessionCallback.acknowledge();
220     }
221   }
222
223   public void clearBody() throws JMSException JavaDoc
224   {
225     checkWrite();
226   }
227   
228     /////////////////////////////////////////////////////////////////////////
229
// javax.jms.Message Header Accessors //
230
/////////////////////////////////////////////////////////////////////////
231

232   public final void setJMSMessageID(String JavaDoc messageID)
233   {
234     header.jmsMessageID = MessageID.unmarshal(messageID);
235   }
236
237   public final void setJMSTimestamp(long timestamp)
238   {
239     header.setJMSTimestamp(timestamp);
240   }
241  
242   public final String JavaDoc getJMSMessageID()
243   {
244     return header.jmsMessageID.toString();
245   }
246
247   public final long getJMSTimestamp()
248   {
249     return header.jmsTimestamp;
250   }
251
252   public final byte[] getJMSCorrelationIDAsBytes() throws JMSException JavaDoc
253   {
254     byte [] result = null;
255     try {
256
257       ByteArrayOutputStream JavaDoc byteStream = new ByteArrayOutputStream JavaDoc();
258       DataOutputStream JavaDoc dataStream = new DataOutputStream JavaDoc(byteStream);
259       header.jmsCorrelationID.marshal(dataStream);
260       dataStream.flush();
261       result = byteStream.toByteArray();
262       dataStream.close();
263       byteStream.close();
264  
265     } catch (IOException JavaDoc ioe) {}
266     return result;
267   }
268
269   public final void setJMSCorrelationIDAsBytes(byte[] correlationID)
270     throws JMSException JavaDoc
271   {
272     try {
273       ByteArrayInputStream JavaDoc byteStream;
274       byteStream = new ByteArrayInputStream JavaDoc(correlationID);
275       DataInputStream JavaDoc dataStream = new DataInputStream JavaDoc(byteStream);
276       header.setJMSCorrelationID(MessageID.unmarshal(dataStream));
277       dataStream.close();
278       byteStream.close();
279     } catch (IOException JavaDoc ioe) {
280       JMSException JavaDoc jmsex = new JMSException JavaDoc("Correlation ID is corrupt");
281       jmsex.setLinkedException(ioe);
282       throw jmsex;
283     }
284   }
285
286   public final String JavaDoc getJMSCorrelationID() throws JMSException JavaDoc
287   {
288     return header.jmsCorrelationID.toString();
289   }
290
291   public final void setJMSCorrelationID(String JavaDoc correlationID)
292   {
293     header.setJMSCorrelationID(MessageID.unmarshal(correlationID));
294   }
295
296   public final Destination getJMSReplyTo() throws JMSException JavaDoc
297   {
298     if (header.jmsReplyTo == null)
299       return null;
300     if (header.jmsReplyTo.startsWith(JmsTopic.TOPIC_PREFIX))
301       return new JmsTopic(header.jmsReplyTo);
302     
303     // TODO:: p2p
304
// return new JmsQueue(header.jmsReplyTo);
305
throw new RuntimeException JavaDoc("fix me");
306   }
307
308   public final void setJMSReplyTo(Destination replyTo)
309   {
310     header.setJMSReplyTo(replyTo);
311   }
312
313   public final Destination getJMSDestination() throws JMSException JavaDoc
314   {
315     if (header.jmsDestination == null)
316       return null;
317     if (header.jmsDestination.startsWith(JmsTopic.TOPIC_PREFIX))
318       return new JmsTopic(header.jmsDestination);
319     
320     // TODO:: p2p
321
//return new JmsQueue(header.jmsDestination);
322
throw new RuntimeException JavaDoc("fix me");
323   }
324
325   public final void setJMSDestination(Destination destination)
326   {
327     header.setJMSDestination(destination);
328   }
329
330   public final int getJMSDeliveryMode()
331   {
332     return header.jmsDeliveryMode;
333   }
334   
335   public final void setJMSDeliveryMode(int deliveryMode)
336   {
337     header.setJMSDeliveryMode(deliveryMode);
338
339     // Persistent messages need an AckHelper to keep track of acks
340
if (deliveryMode == javax.jms.DeliveryMode.PERSISTENT)
341       this.ackHelper = new AckHelper(this);
342   }
343
344   public final boolean getJMSRedelivered()
345   {
346     return header.jmsRedelivered;
347   }
348
349   public final void setJMSRedelivered(boolean redelivered)
350   {
351     header.setJMSRedelivered(redelivered);
352   }
353
354   public final String JavaDoc getJMSType()
355   {
356     return header.jmsType;
357   }
358
359   public final void setJMSType(String JavaDoc type)
360   {
361     header.setJMSType(type);
362   }
363
364   public final long getJMSExpiration()
365   {
366     return header.jmsExpiration;
367   }
368
369   public final void setJMSExpiration(long expiration)
370   {
371     header.setJMSExpiration(expiration);
372   }
373
374   public final int getJMSPriority()
375   {
376     return header.jmsPriority;
377   }
378
379   public final void setJMSPriority(int priority)
380   {
381     header.setJMSPriority(priority);
382   }
383
384     /////////////////////////////////////////////////////////////////////////
385
// javax.jms.Message Property Accessors //
386
/////////////////////////////////////////////////////////////////////////
387

388   public final void clearProperties() throws JMSException JavaDoc
389   {
390     checkWrite();
391     properties.clear();
392   }
393
394   public final boolean propertyExists(String JavaDoc name) throws JMSException JavaDoc
395   {
396     return properties.primitiveExists(name);
397   }
398   
399   public final boolean getBooleanProperty(String JavaDoc name) throws JMSException JavaDoc
400   {
401     return properties.getBoolean(name);
402   }
403  
404   public final byte getByteProperty(String JavaDoc name)
405     throws JMSException JavaDoc, NumberFormatException JavaDoc
406   {
407     return properties.getByte(name);
408   }
409     
410   public final short getShortProperty(String JavaDoc name)
411     throws JMSException JavaDoc, NumberFormatException JavaDoc
412   {
413     return properties.getShort(name);
414   }
415    
416   public final int getIntProperty(String JavaDoc name)
417     throws JMSException JavaDoc, NumberFormatException JavaDoc
418   {
419     return properties.getInt(name);
420   }
421
422   public final long getLongProperty(String JavaDoc name)
423     throws JMSException JavaDoc, NumberFormatException JavaDoc
424   {
425     return properties.getLong(name);
426   }
427
428   public final float getFloatProperty(String JavaDoc name)
429     throws JMSException JavaDoc, NumberFormatException JavaDoc
430   {
431     return properties.getFloat(name);
432   }
433
434   public final double getDoubleProperty(String JavaDoc name)
435     throws JMSException JavaDoc, NumberFormatException JavaDoc
436   {
437     return properties.getDouble(name);
438   }
439
440   public final String JavaDoc getStringProperty(String JavaDoc name) throws JMSException JavaDoc
441   {
442     return properties.getString(name);
443   }
444
445   public final Object JavaDoc getObjectProperty(String JavaDoc name)
446   {
447     // This makes the router work because it's filter accesses
448
// the destination. Usually, the message header is not
449
// queryable from a filter.
450
if (name.equals(JmsDestination.DESTINATION_PROPERTY_NAME))
451       return header.jmsDestination;
452     
453     return properties.getObject(name);
454   }
455
456   public final Enumeration JavaDoc getPropertyNames() throws JMSException JavaDoc
457   {
458     return properties.getPrimitiveNames();
459   }
460
461
462   public final void setBooleanProperty(String JavaDoc name, boolean value) throws JMSException JavaDoc
463   {
464     checkWrite();
465     properties.setBoolean(name, value);
466   }
467
468   public final void setByteProperty(String JavaDoc name, byte value) throws JMSException JavaDoc
469   {
470     checkWrite();
471     properties.setByte(name, value);
472   }
473
474   public final void setShortProperty(String JavaDoc name, short value) throws JMSException JavaDoc
475   {
476     checkWrite();
477     properties.setShort(name, value);
478   }
479
480   public final void setIntProperty(String JavaDoc name, int value) throws JMSException JavaDoc
481   {
482     checkWrite();
483     properties.setInt(name, value);
484   }
485
486   public final void setLongProperty(String JavaDoc name, long value) throws JMSException JavaDoc
487   {
488     checkWrite();
489     properties.setLong(name, value);
490   }
491
492   public final void setFloatProperty(String JavaDoc name, float value) throws JMSException JavaDoc
493   {
494     checkWrite();
495     properties.setFloat(name, value);
496   }
497
498   public final void setDoubleProperty(String JavaDoc name, double value) throws JMSException JavaDoc
499   {
500     checkWrite();
501     properties.setDouble(name, value);
502   }
503
504   public final void setStringProperty(String JavaDoc name, String JavaDoc value) throws JMSException JavaDoc
505   {
506     checkWrite();
507     properties.setString(name, value);
508   }
509
510   public final void setObjectProperty(String JavaDoc name, Object JavaDoc value) throws JMSException JavaDoc
511   {
512     checkWrite();
513     properties.setObject(name, value);
514   }
515
516
517     /////////////////////////////////////////////////////////////////////////
518
// Public Methods specific to this JMS implementation //
519
/////////////////////////////////////////////////////////////////////////
520

521   public void setRoutingMask(BitSet JavaDoc mask) { routingMask = mask; }
522   public BitSet JavaDoc getRoutingMask() { return routingMask; }
523
524   public void setSessionCallback(JmsSession session) { this.sessionCallback = session; }
525
526   public final void setSendingTargetID(int id) { this.sendingTargetID = id; }
527   public final int getSendingTargetID() { return this.sendingTargetID; }
528   
529   public final void setLocal(boolean val) { this.local = val; }
530   public final boolean isLocal() { return this.local; }
531
532
533   /**
534    * Used by internal routing to keep track of message state through
535    * the system.
536    *
537    * @return AckHelper associated with this message if PERSISTENT, or
538    * null if the message is not persistent.
539    */

540   public final AckHelper getAckHelper() { return this.ackHelper; }
541
542   /**
543    * @secret
544    */

545   public final void setJMSSystemMsgType(int type)
546   {
547     header.setJMSSystemMsgType(type);
548   }
549
550   /**
551    * @secret
552    */

553   public final int getJMSSystemMsgType()
554   {
555     return header.jmsSystemMsgType;
556   }
557   
558   /**
559    * @secret
560    */

561   public final void setReadOnly()
562   {
563     readOnly = true;
564   }
565   
566     ///////////////////////////////////////////////////////////////////////////
567
// Package Methods //
568
///////////////////////////////////////////////////////////////////////////
569

570
571   /**
572    * Used by MessageEncoder to identify message types.
573    */

574   byte getMarshalingID()
575   {
576     return MessageEncoder.MESSAGE;
577   }
578   
579
580     ///////////////////////////////////////////////////////////////////////////
581
// Protected Methods //
582
///////////////////////////////////////////////////////////////////////////
583

584   protected void checkWrite() throws JMSException JavaDoc
585   {
586     if (this.readOnly) {
587       JMSException JavaDoc jmse = new
588             MessageNotWriteableException JavaDoc("This Message is readOnly");
589       throw jmse;
590     }
591   }
592   
593 }
594
Popular Tags