Source code: org/activemq/message/ActiveMQMessage.java
1 /**
2 *
3 * Copyright 2004 Protique Ltd
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 **/
18
19 package org.activemq.message;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.DataInput;
24 import java.io.DataInputStream;
25 import java.io.DataOutput;
26 import java.io.DataOutputStream;
27 import java.io.IOException;
28 import java.util.Collections;
29 import java.util.Enumeration;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.Map;
33 import java.util.List;
34 import java.util.ArrayList;
35 import java.util.StringTokenizer;
36
37 import javax.jms.DeliveryMode;
38 import javax.jms.Destination;
39 import javax.jms.JMSException;
40 import javax.jms.Message;
41 import javax.jms.MessageFormatException;
42 import javax.jms.MessageNotWriteableException;
43
44 import org.activemq.io.util.ByteArray;
45 import org.activemq.io.util.ByteArrayCompression;
46 import org.activemq.io.util.MemoryManageable;
47 import org.activemq.service.MessageIdentity;
48 import org.activemq.util.IdGenerator;
49
50 /**
51 * The <CODE>Message</CODE> interface is the root interface of all JMS
52 * messages. It defines the message header and the <CODE>acknowledge</CODE>
53 * method used for all messages.
54 * <p/>
55 * <P>Most message-oriented middleware (MOM) products treat messages as
56 * lightweight entities that consist
57 * of a header and a payload. The header contains fields used for message
58 * routing and identification; the payload contains the application data
59 * being sent.
60 * <p/>
61 * <P>Within this general form, the definition of a message varies
62 * significantly across products. It would be quite difficult for the JMS API
63 * to support all of these message models.
64 * <p/>
65 * <P>With this in mind, the JMS message model has the following goals:
66 * <UL>
67 * <LI>Provide a single, unified message API
68 * <LI>Provide an API suitable for creating messages that match the
69 * format used by provider-native messaging applications
70 * <LI>Support the development of heterogeneous applications that span
71 * operating systems, machine architectures, and computer languages
72 * <LI>Support messages containing objects in the Java programming language
73 * ("Java objects")
74 * <LI>Support messages containing Extensible Markup Language (XML) pages
75 * </UL>
76 * <p/>
77 * <P>JMS messages are composed of the following parts:
78 * <UL>
79 * <LI>Header - All messages support the same set of header fields.
80 * Header fields contain values used by both clients and providers to
81 * identify and route messages.
82 * <LI>Properties - Each message contains a built-in facility for supporting
83 * application-defined property values. Properties provide an efficient
84 * mechanism for supporting application-defined message filtering.
85 * <LI>Body - The JMS API defines several types of message body, which cover
86 * the majority of messaging styles currently in use.
87 * </UL>
88 * <p/>
89 * <H4>Message Bodies</H4>
90 * <p/>
91 * <P>The JMS API defines five types of message body:
92 * <UL>
93 * <LI>Stream - A <CODE>StreamMessage</CODE> object's message body contains
94 * a stream of primitive values in the Java programming
95 * language ("Java primitives"). It is filled and read sequentially.
96 * <LI>Map - A <CODE>MapMessage</CODE> object's message body contains a set
97 * of name-value pairs, where names are <CODE>String</CODE>
98 * objects, and values are Java primitives. The entries can be accessed
99 * sequentially or randomly by name. The order of the entries is
100 * undefined.
101 * <LI>Text - A <CODE>TextMessage</CODE> object's message body contains a
102 * <CODE>java.lang.String</CODE> object. This message type can be used
103 * to transport plain-text messages, and XML messages.
104 * <LI>Object - An <CODE>ObjectMessage</CODE> object's message body contains
105 * a <CODE>Serializable</CODE> Java object.
106 * <LI>Bytes - A <CODE>BytesMessage</CODE> object's message body contains a
107 * stream of uninterpreted bytes. This message type is for
108 * literally encoding a body to match an existing message format. In
109 * many cases, it is possible to use one of the other body types,
110 * which are easier to use. Although the JMS API allows the use of
111 * message properties with byte messages, they are typically not used,
112 * since the inclusion of properties may affect the format.
113 * </UL>
114 * <p/>
115 * <H4>Message Headers</H4>
116 * <p/>
117 * <P>The <CODE>JMSCorrelationID</CODE> header field is used for linking one
118 * message with
119 * another. It typically links a reply message with its requesting message.
120 * <p/>
121 * <P><CODE>JMSCorrelationID</CODE> can hold a provider-specific message ID,
122 * an application-specific <CODE>String</CODE> object, or a provider-native
123 * <CODE>byte[]</CODE> value.
124 * <p/>
125 * <H4>Message Properties</H4>
126 * <p/>
127 * <P>A <CODE>Message</CODE> object contains a built-in facility for supporting
128 * application-defined property values. In effect, this provides a mechanism
129 * for adding application-specific header fields to a message.
130 * <p/>
131 * <P>Properties allow an application, via message selectors, to have a JMS
132 * provider select, or filter, messages on its behalf using
133 * application-specific criteria.
134 * <p/>
135 * <P>Property names must obey the rules for a message selector identifier.
136 * Property names must not be null, and must not be empty strings. If a property
137 * name is set and it is either null or an empty string, an
138 * <CODE>IllegalArgumentException</CODE> must be thrown.
139 * <p/>
140 * <P>Property values can be <CODE>boolean</CODE>, <CODE>byte</CODE>,
141 * <CODE>short</CODE>, <CODE>int</CODE>, <CODE>long</CODE>, <CODE>float</CODE>,
142 * <CODE>double</CODE>, and <CODE>String</CODE>.
143 * <p/>
144 * <P>Property values are set prior to sending a message. When a client
145 * receives a message, its properties are in read-only mode. If a
146 * client attempts to set properties at this point, a
147 * <CODE>MessageNotWriteableException</CODE> is thrown. If
148 * <CODE>clearProperties</CODE> is called, the properties can now be both
149 * read from and written to. Note that header fields are distinct from
150 * properties. Header fields are never in read-only mode.
151 * <p/>
152 * <P>A property value may duplicate a value in a message's body, or it may
153 * not. Although JMS does not define a policy for what should or should not
154 * be made a property, application developers should note that JMS providers
155 * will likely handle data in a message's body more efficiently than data in
156 * a message's properties. For best performance, applications should use
157 * message properties only when they need to customize a message's header.
158 * The primary reason for doing this is to support customized message
159 * selection.
160 * <p/>
161 * <P>Message properties support the following conversion table. The marked
162 * cases must be supported. The unmarked cases must throw a
163 * <CODE>JMSException</CODE>. The <CODE>String</CODE>-to-primitive conversions
164 * may throw a runtime exception if the
165 * primitive's <CODE>valueOf</CODE> method does not accept the
166 * <CODE>String</CODE> as a valid representation of the primitive.
167 * <p/>
168 * <P>A value written as the row type can be read as the column type.
169 * <p/>
170 * <PRE>
171 * | | boolean byte short int long float double String
172 * |----------------------------------------------------------
173 * |boolean | X X
174 * |byte | X X X X X
175 * |short | X X X X
176 * |int | X X X
177 * |long | X X
178 * |float | X X X
179 * |double | X X
180 * |String | X X X X X X X X
181 * |----------------------------------------------------------
182 * </PRE>
183 * <p/>
184 * <P>In addition to the type-specific set/get methods for properties, JMS
185 * provides the <CODE>setObjectProperty</CODE> and
186 * <CODE>getObjectProperty</CODE> methods. These support the same set of
187 * property types using the objectified primitive values. Their purpose is
188 * to allow the decision of property type to made at execution time rather
189 * than at compile time. They support the same property value conversions.
190 * <p/>
191 * <P>The <CODE>setObjectProperty</CODE> method accepts values of class
192 * <CODE>Boolean</CODE>, <CODE>Byte</CODE>, <CODE>Short</CODE>,
193 * <CODE>Integer</CODE>, <CODE>Long</CODE>, <CODE>Float</CODE>,
194 * <CODE>Double</CODE>, and <CODE>String</CODE>. An attempt
195 * to use any other class must throw a <CODE>JMSException</CODE>.
196 * <p/>
197 * <P>The <CODE>getObjectProperty</CODE> method only returns values of class
198 * <CODE>Boolean</CODE>, <CODE>Byte</CODE>, <CODE>Short</CODE>,
199 * <CODE>Integer</CODE>, <CODE>Long</CODE>, <CODE>Float</CODE>,
200 * <CODE>Double</CODE>, and <CODE>String</CODE>.
201 * <p/>
202 * <P>The order of property values is not defined. To iterate through a
203 * message's property values, use <CODE>getPropertyNames</CODE> to retrieve
204 * a property name enumeration and then use the various property get methods
205 * to retrieve their values.
206 * <p/>
207 * <P>A message's properties are deleted by the <CODE>clearProperties</CODE>
208 * method. This leaves the message with an empty set of properties.
209 * <p/>
210 * <P>Getting a property value for a name which has not been set returns a
211 * null value. Only the <CODE>getStringProperty</CODE> and
212 * <CODE>getObjectProperty</CODE> methods can return a null value.
213 * Attempting to read a null value as a primitive type must be treated as
214 * calling the primitive's corresponding <CODE>valueOf(String)</CODE>
215 * conversion method with a null value.
216 * <p/>
217 * <P>The JMS API reserves the <CODE>JMSX</CODE> property name prefix for JMS
218 * defined properties.
219 * The full set of these properties is defined in the Java Message Service
220 * specification. New JMS defined properties may be added in later versions
221 * of the JMS API. Support for these properties is optional. The
222 * <CODE>String[] ConnectionMetaData.getJMSXPropertyNames</CODE> method
223 * returns the names of the JMSX properties supported by a connection.
224 * <p/>
225 * <P>JMSX properties may be referenced in message selectors whether or not
226 * they are supported by a connection. If they are not present in a
227 * message, they are treated like any other absent property.
228 * <p/>
229 * <P>JMSX properties defined in the specification as "set by provider on
230 * send" are available to both the producer and the consumers of the message.
231 * JMSX properties defined in the specification as "set by provider on
232 * receive" are available only to the consumers.
233 * <p/>
234 * <P><CODE>JMSXGroupID</CODE> and <CODE>JMSXGroupSeq</CODE> are standard
235 * properties that clients
236 * should use if they want to group messages. All providers must support them.
237 * Unless specifically noted, the values and semantics of the JMSX properties
238 * are undefined.
239 * <p/>
240 * <P>The JMS API reserves the <CODE>JMS_<I>vendor_name</I></CODE> property
241 * name prefix for provider-specific properties. Each provider defines its own
242 * value for <CODE><I>vendor_name</I></CODE>. This is the mechanism a JMS
243 * provider uses to make its special per-message services available to a JMS
244 * client.
245 * <p/>
246 * <P>The purpose of provider-specific properties is to provide special
247 * features needed to integrate JMS clients with provider-native clients in a
248 * single JMS application. They should not be used for messaging between JMS
249 * clients.
250 * <p/>
251 * <H4>Provider Implementations of JMS Message Interfaces</H4>
252 * <p/>
253 * <P>The JMS API provides a set of message interfaces that define the JMS
254 * message
255 * model. It does not provide implementations of these interfaces.
256 * <p/>
257 * <P>Each JMS provider supplies a set of message factories with its
258 * <CODE>Session</CODE> object for creating instances of messages. This allows
259 * a provider to use message implementations tailored to its specific needs.
260 * <p/>
261 * <P>A provider must be prepared to accept message implementations that are
262 * not its own. They may not be handled as efficiently as its own
263 * implementation; however, they must be handled.
264 * <p/>
265 * <P>Note the following exception case when a provider is handling a foreign
266 * message implementation. If the foreign message implementation contains a
267 * <CODE>JMSReplyTo</CODE> header field that is set to a foreign destination
268 * implementation, the provider is not required to handle or preserve the
269 * value of this header field.
270 * <p/>
271 * <H4>Message Selectors</H4>
272 * <p/>
273 * <P>A JMS message selector allows a client to specify, by
274 * header field references and property references, the
275 * messages it is interested in. Only messages whose header
276 * and property values
277 * match the
278 * selector are delivered. What it means for a message not to be delivered
279 * depends on the <CODE>MessageConsumer</CODE> being used (see
280 * {@link javax.jms.QueueReceiver QueueReceiver} and
281 * {@link javax.jms.TopicSubscriber TopicSubscriber}).
282 * <p/>
283 * <P>Message selectors cannot reference message body values.
284 * <p/>
285 * <P>A message selector matches a message if the selector evaluates to
286 * true when the message's header field values and property values are
287 * substituted for their corresponding identifiers in the selector.
288 * <p/>
289 * <P>A message selector is a <CODE>String</CODE> whose syntax is based on a
290 * subset of
291 * the SQL92 conditional expression syntax. If the value of a message selector
292 * is an empty string, the value is treated as a null and indicates that there
293 * is no message selector for the message consumer.
294 * <p/>
295 * <P>The order of evaluation of a message selector is from left to right
296 * within precedence level. Parentheses can be used to change this order.
297 * <p/>
298 * <P>Predefined selector literals and operator names are shown here in
299 * uppercase; however, they are case insensitive.
300 * <p/>
301 * <P>A selector can contain:
302 * <p/>
303 * <UL>
304 * <LI>Literals:
305 * <UL>
306 * <LI>A string literal is enclosed in single quotes, with a single quote
307 * represented by doubled single quote; for example,
308 * <CODE>'literal'</CODE> and <CODE>'literal''s'</CODE>. Like
309 * string literals in the Java programming language, these use the
310 * Unicode character encoding.
311 * <LI>An exact numeric literal is a numeric value without a decimal
312 * point, such as <CODE>57</CODE>, <CODE>-957</CODE>, and
313 * <CODE>+62</CODE>; numbers in the range of <CODE>long</CODE> are
314 * supported. Exact numeric literals use the integer literal
315 * syntax of the Java programming language.
316 * <LI>An approximate numeric literal is a numeric value in scientific
317 * notation, such as <CODE>7E3</CODE> and <CODE>-57.9E2</CODE>, or a
318 * numeric value with a decimal, such as <CODE>7.</CODE>,
319 * <CODE>-95.7</CODE>, and <CODE>+6.2</CODE>; numbers in the range of
320 * <CODE>double</CODE> are supported. Approximate literals use the
321 * floating-point literal syntax of the Java programming language.
322 * <LI>The boolean literals <CODE>TRUE</CODE> and <CODE>FALSE</CODE>.
323 * </UL>
324 * <LI>Identifiers:
325 * <UL>
326 * <LI>An identifier is an unlimited-length sequence of letters
327 * and digits, the first of which must be a letter. A letter is any
328 * character for which the method <CODE>Character.isJavaLetter</CODE>
329 * returns true. This includes <CODE>'_'</CODE> and <CODE>'$'</CODE>.
330 * A letter or digit is any character for which the method
331 * <CODE>Character.isJavaLetterOrDigit</CODE> returns true.
332 * <LI>Identifiers cannot be the names <CODE>NULL</CODE>,
333 * <CODE>TRUE</CODE>, and <CODE>FALSE</CODE>.
334 * <LI>Identifiers cannot be <CODE>NOT</CODE>, <CODE>AND</CODE>,
335 * <CODE>OR</CODE>, <CODE>BETWEEN</CODE>, <CODE>LIKE</CODE>,
336 * <CODE>IN</CODE>, <CODE>IS</CODE>, or <CODE>ESCAPE</CODE>.
337 * <LI>Identifiers are either header field references or property
338 * references. The type of a property value in a message selector
339 * corresponds to the type used to set the property. If a property
340 * that does not exist in a message is referenced, its value is
341 * <CODE>NULL</CODE>.
342 * <LI>The conversions that apply to the get methods for properties do not
343 * apply when a property is used in a message selector expression.
344 * For example, suppose you set a property as a string value, as in the
345 * following:
346 * <PRE>myMessage.setStringProperty("NumberOfOrders", "2");</PRE>
347 * The following expression in a message selector would evaluate to
348 * false, because a string cannot be used in an arithmetic expression:
349 * <PRE>"NumberOfOrders > 1"</PRE>
350 * <LI>Identifiers are case-sensitive.
351 * <LI>Message header field references are restricted to
352 * <CODE>JMSDeliveryMode</CODE>, <CODE>JMSPriority</CODE>,
353 * <CODE>JMSMessageID</CODE>, <CODE>JMSTimestamp</CODE>,
354 * <CODE>JMSCorrelationID</CODE>, and <CODE>JMSType</CODE>.
355 * <CODE>JMSMessageID</CODE>, <CODE>JMSCorrelationID</CODE>, and
356 * <CODE>JMSType</CODE> values may be null and if so are treated as a
357 * <CODE>NULL</CODE> value.
358 * <LI>Any name beginning with <CODE>'JMSX'</CODE> is a JMS defined
359 * property name.
360 * <LI>Any name beginning with <CODE>'JMS_'</CODE> is a provider-specific
361 * property name.
362 * <LI>Any name that does not begin with <CODE>'JMS'</CODE> is an
363 * application-specific property name.
364 * </UL>
365 * <LI>White space is the same as that defined for the Java programming
366 * language: space, horizontal tab, form feed, and line terminator.
367 * <LI>Expressions:
368 * <UL>
369 * <LI>A selector is a conditional expression; a selector that evaluates
370 * to <CODE>true</CODE> matches; a selector that evaluates to
371 * <CODE>false</CODE> or unknown does not match.
372 * <LI>Arithmetic expressions are composed of themselves, arithmetic
373 * operations, identifiers (whose value is treated as a numeric
374 * literal), and numeric literals.
375 * <LI>Conditional expressions are composed of themselves, comparison
376 * operations, and logical operations.
377 * </UL>
378 * <LI>Standard bracketing <CODE>()</CODE> for ordering expression evaluation
379 * is supported.
380 * <LI>Logical operators in precedence order: <CODE>NOT</CODE>,
381 * <CODE>AND</CODE>, <CODE>OR</CODE>
382 * <LI>Comparison operators: <CODE>=</CODE>, <CODE>></CODE>, <CODE>>=</CODE>,
383 * <CODE><</CODE>, <CODE><=</CODE>, <CODE><></CODE> (not equal)
384 * <UL>
385 * <LI>Only like type values can be compared. One exception is that it
386 * is valid to compare exact numeric values and approximate numeric
387 * values; the type conversion required is defined by the rules of
388 * numeric promotion in the Java programming language. If the
389 * comparison of non-like type values is attempted, the value of the
390 * operation is false. If either of the type values evaluates to
391 * <CODE>NULL</CODE>, the value of the expression is unknown.
392 * <LI>String and boolean comparison is restricted to <CODE>=</CODE> and
393 * <CODE><></CODE>. Two strings are equal
394 * if and only if they contain the same sequence of characters.
395 * </UL>
396 * <LI>Arithmetic operators in precedence order:
397 * <UL>
398 * <LI><CODE>+</CODE>, <CODE>-</CODE> (unary)
399 * <LI><CODE>*</CODE>, <CODE>/</CODE> (multiplication and division)
400 * <LI><CODE>+</CODE>, <CODE>-</CODE> (addition and subtraction)
401 * <LI>Arithmetic operations must use numeric promotion in the Java
402 * programming language.
403 * </UL>
404 * <LI><CODE><I>arithmetic-expr1</I> [NOT] BETWEEN <I>arithmetic-expr2</I>
405 * AND <I>arithmetic-expr3</I></CODE> (comparison operator)
406 * <UL>
407 * <LI><CODE>"age BETWEEN 15 AND 19"</CODE> is
408 * equivalent to
409 * <CODE>"age >= 15 AND age <= 19"</CODE>
410 * <LI><CODE>"age NOT BETWEEN 15 AND 19"</CODE>
411 * is equivalent to
412 * <CODE>"age < 15 OR age > 19"</CODE>
413 * </UL>
414 * <LI><CODE><I>identifier</I> [NOT] IN (<I>string-literal1</I>,
415 * <I>string-literal2</I>,...)</CODE> (comparison operator where
416 * <CODE><I>identifier</I></CODE> has a <CODE>String</CODE> or
417 * <CODE>NULL</CODE> value)
418 * <UL>
419 * <LI><CODE>"Country IN (' UK', 'US', 'France')"</CODE>
420 * is true for
421 * <CODE>'UK'</CODE> and false for <CODE>'Peru'</CODE>; it is
422 * equivalent to the expression
423 * <CODE>"(Country = ' UK') OR (Country = ' US') OR (Country = ' France')"</CODE>
424 * <LI><CODE>"Country NOT IN (' UK', 'US', 'France')"</CODE>
425 * is false for <CODE>'UK'</CODE> and true for <CODE>'Peru'</CODE>; it
426 * is equivalent to the expression
427 * <CODE>"NOT ((Country = ' UK') OR (Country = ' US') OR (Country = ' France'))"</CODE>
428 * <LI>If identifier of an <CODE>IN</CODE> or <CODE>NOT IN</CODE>
429 * operation is <CODE>NULL</CODE>, the value of the operation is
430 * unknown.
431 * </UL>
432 * <LI><CODE><I>identifier</I> [NOT] LIKE <I>pattern-value</I> [ESCAPE
433 * <I>escape-character</I>]</CODE> (comparison operator, where
434 * <CODE><I>identifier</I></CODE> has a <CODE>String</CODE> value;
435 * <CODE><I>pattern-value</I></CODE> is a string literal where
436 * <CODE>'_'</CODE> stands for any single character; <CODE>'%'</CODE>
437 * stands for any sequence of characters, including the empty sequence;
438 * and all other characters stand for themselves. The optional
439 * <CODE><I>escape-character</I></CODE> is a single-character string
440 * literal whose character is used to escape the special meaning of the
441 * <CODE>'_'</CODE> and <CODE>'%'</CODE> in
442 * <CODE><I>pattern-value</I></CODE>.)
443 * <UL>
444 * <LI><CODE>"phone LIKE '12%3'"</CODE> is true for
445 * <CODE>'123'</CODE> or <CODE>'12993'</CODE> and false for
446 * <CODE>'1234'</CODE>
447 * <LI><CODE>"word LIKE 'l_se'"</CODE> is true for
448 * <CODE>'lose'</CODE> and false for <CODE>'loose'</CODE>
449 * <LI><CODE>"underscored LIKE '\_%' ESCAPE '\'"</CODE>
450 * is true for <CODE>'_foo'</CODE> and false for <CODE>'bar'</CODE>
451 * <LI><CODE>"phone NOT LIKE '12%3'"</CODE> is false for
452 * <CODE>'123'</CODE> or <CODE>'12993'</CODE> and true for
453 * <CODE>'1234'</CODE>
454 * <LI>If <CODE><I>identifier</I></CODE> of a <CODE>LIKE</CODE> or
455 * <CODE>NOT LIKE</CODE> operation is <CODE>NULL</CODE>, the value
456 * of the operation is unknown.
457 * </UL>
458 * <LI><CODE><I>identifier</I> IS NULL</CODE> (comparison operator that tests
459 * for a null header field value or a missing property value)
460 * <UL>
461 * <LI><CODE>"prop_name IS NULL"</CODE>
462 * </UL>
463 * <LI><CODE><I>identifier</I> IS NOT NULL</CODE> (comparison operator that
464 * tests for the existence of a non-null header field value or a property
465 * value)
466 * <UL>
467 * <LI><CODE>"prop_name IS NOT NULL"</CODE>
468 * </UL>
469 * <p/>
470 * <P>JMS providers are required to verify the syntactic correctness of a
471 * message selector at the time it is presented. A method that provides a
472 * syntactically incorrect selector must result in a <CODE>JMSException</CODE>.
473 * JMS providers may also optionally provide some semantic checking at the time
474 * the selector is presented. Not all semantic checking can be performed at
475 * the time a message selector is presented, because property types are not known.
476 * <p/>
477 * <P>The following message selector selects messages with a message type
478 * of car and color of blue and weight greater than 2500 pounds:
479 * <p/>
480 * <PRE>"JMSType = 'car' AND color = 'blue' AND weight > 2500"</PRE>
481 * <p/>
482 * <H4>Null Values</H4>
483 * <p/>
484 * <P>As noted above, property values may be <CODE>NULL</CODE>. The evaluation
485 * of selector expressions containing <CODE>NULL</CODE> values is defined by
486 * SQL92 <CODE>NULL</CODE> semantics. A brief description of these semantics
487 * is provided here.
488 * <p/>
489 * <P>SQL treats a <CODE>NULL</CODE> value as unknown. Comparison or arithmetic
490 * with an unknown value always yields an unknown value.
491 * <p/>
492 * <P>The <CODE>IS NULL</CODE> and <CODE>IS NOT NULL</CODE> operators convert
493 * an unknown value into the respective <CODE>TRUE</CODE> and
494 * <CODE>FALSE</CODE> values.
495 * <p/>
496 * <P>The boolean operators use three-valued logic as defined by the
497 * following tables:
498 * <p/>
499 * <P><B>The definition of the <CODE>AND</CODE> operator</B>
500 * <p/>
501 * <PRE>
502 * | AND | T | F | U
503 * +------+-------+-------+-------
504 * | T | T | F | U
505 * | F | F | F | F
506 * | U | U | F | U
507 * +------+-------+-------+-------
508 * </PRE>
509 * <p/>
510 * <P><B>The definition of the <CODE>OR</CODE> operator</B>
511 * <p/>
512 * <PRE>
513 * | OR | T | F | U
514 * +------+-------+-------+--------
515 * | T | T | T | T
516 * | F | T | F | U
517 * | U | T | U | U
518 * +------+-------+-------+-------
519 * </PRE>
520 * <p/>
521 * <P><B>The definition of the <CODE>NOT</CODE> operator</B>
522 * <p/>
523 * <PRE>
524 * | NOT
525 * +------+------
526 * | T | F
527 * | F | T
528 * | U | U
529 * +------+-------
530 * </PRE>
531 * <p/>
532 * <H4>Special Notes</H4>
533 * <p/>
534 * <P>When used in a message selector, the <CODE>JMSDeliveryMode</CODE> header
535 * field is treated as having the values <CODE>'PERSISTENT'</CODE> and
536 * <CODE>'NON_PERSISTENT'</CODE>.
537 * <p/>
538 * <P>Date and time values should use the standard <CODE>long</CODE>
539 * millisecond value. When a date or time literal is included in a message
540 * selector, it should be an integer literal for a millisecond value. The
541 * standard way to produce millisecond values is to use
542 * <CODE>java.util.Calendar</CODE>.
543 * <p/>
544 * <P>Although SQL supports fixed decimal comparison and arithmetic, JMS
545 * message selectors do not. This is the reason for restricting exact
546 * numeric literals to those without a decimal (and the addition of
547 * numerics with a decimal as an alternate representation for
548 * approximate numeric values).
549 * <p/>
550 * <P>SQL comments are not supported.
551 *
552 * @version $Revision: 1.1.1.1 $
553 * @see javax.jms.MessageConsumer#receive()
554 * @see javax.jms.MessageConsumer#receive(long)
555 * @see javax.jms.MessageConsumer#receiveNoWait()
556 * @see javax.jms.MessageListener#onMessage(Message)
557 * @see javax.jms.BytesMessage
558 * @see javax.jms.MapMessage
559 * @see javax.jms.ObjectMessage
560 * @see javax.jms.StreamMessage
561 * @see javax.jms.TextMessage
562 */
563
564 public class ActiveMQMessage extends AbstractPacket implements Message, Comparable, MemoryManageable, BodyPacket {
565
566 /**
567 * The message producer's default delivery mode is <CODE>PERSISTENT</CODE>.
568 *
569 * @see DeliveryMode#PERSISTENT
570 */
571 static final int DEFAULT_DELIVERY_MODE = DeliveryMode.PERSISTENT;
572
573 /**
574 * The message producer's default priority is 4.
575 */
576 static final int DEFAULT_PRIORITY = 4;
577
578 /**
579 * The message producer's default time to live is unlimited; the message
580 * never expires.
581 */
582 static final long DEFAULT_TIME_TO_LIVE = 0;
583
584 /**
585 * message property types
586 */
587 final static byte EOF = 2;
588 final static byte BYTES = 3;
589 final static byte STRING = 4;
590 final static byte BOOLEAN = 5;
591 final static byte CHAR = 6;
592 final static byte BYTE = 7;
593 final static byte SHORT = 8;
594 final static byte INT = 9;
595 final static byte LONG = 10;
596 final static byte FLOAT = 11;
597 final static byte DOUBLE = 12;
598 final static byte NULL = 13;
599
600 /**
601 * Message flag indexes (used for writing/reading to/from a Stream
602 */
603
604 public static final int CORRELATION_INDEX = 2;
605 public static final int TYPE_INDEX = 3;
606 public static final int BROKER_NAME_INDEX = 4;
607 public static final int CLUSTER_NAME_INDEX = 5;
608 public static final int TRANSACTION_ID_INDEX = 6;
609 public static final int REPLY_TO_INDEX = 7;
610 public static final int TIMESTAMP_INDEX = 8;
611 public static final int EXPIRATION_INDEX = 9;
612 public static final int REDELIVERED_INDEX = 10;
613 public static final int XA_TRANS_INDEX = 11;
614 public static final int CID_INDEX = 12;
615 public static final int PROPERTIES_INDEX = 13;
616 public static final int DISPATCHED_FROM_DLQ_INDEX = 14;
617 public static final int PAYLOAD_INDEX = 15;
618 public static final int EXTERNAL_MESSAGE_ID_INDEX = 16;
619 public static final int MESSAGE_PART_INDEX = 17;
620 public static final int CACHED_VALUES_INDEX = 18;
621 public static final int CACHED_DESTINATION_INDEX = 19;
622 public static final int LONG_SEQUENCE_INDEX = 20;
623
624
625
626 private static final String DELIVERY_COUNT_NAME = "JMSXDeliveryCount";
627 /**
628 * <code>readOnlyMessage</code> denotes if the message is read only
629 */
630 protected boolean readOnlyMessage;
631
632 private String jmsMessageID;
633 private String jmsClientID;
634 private String jmsCorrelationID;
635 private String producerKey;
636 private ActiveMQDestination jmsDestination;
637 private ActiveMQDestination jmsReplyTo;
638 private int jmsDeliveryMode = DEFAULT_DELIVERY_MODE;
639 private boolean jmsRedelivered;
640 private String jmsType;
641 private long jmsExpiration;
642 private int jmsPriority = DEFAULT_PRIORITY;
643 private long jmsTimestamp;
644 private Map properties;
645 private boolean readOnlyProperties;
646 private String entryBrokerName;
647 private String entryClusterName;
648 private int[] consumerNos; //these are set by the broker, and only relevant to consuming connections
649 private Object transactionId;
650 private boolean xaTransacted;
651 private String consumerIdentifier; //this is only used on the Client for acknowledging receipt of a message
652 private boolean messageConsumed;//only used on the client - to denote if its been delivered and read
653 private boolean transientConsumed;//only used on the client - to denote if its been delivered and read
654 private long sequenceNumber;//the sequence for this message from the producerId
655 private int deliveryCount = 1;//number of times the message has been delivered
656 private boolean dispatchedFromDLQ;
657 private MessageAcknowledge messageAcknowledge;
658 private ByteArray bodyAsBytes;
659 private MessageIdentity jmsMessageIdentity;
660 private short messsageHandle;//refers to the id of the MessageProducer that sent the message
661 private boolean externalMessageId;//is the messageId set from another JMS implementation ?
662 private boolean messagePart;//is the message split into multiple packets
663 private short numberOfParts;
664 private short partNumber;
665 private String parentMessageID;//if split into multiple parts - the 'real' or first messageId
666
667
668 /**
669 * Retrieve if a JMS Message type or not
670 *
671 * @return true if it is a JMS Message
672 */
673 public boolean isJMSMessage() {
674 return true;
675 }
676
677
678 /**
679 * @return pretty print of this Message
680 */
681 public String toString() {
682 return super.toString() + " ActiveMQMessage{ " +
683 ", jmsMessageID = " + jmsMessageID +
684 ", bodyAsBytes = " + bodyAsBytes +
685 ", readOnlyMessage = " + readOnlyMessage +
686 ", jmsClientID = '" + jmsClientID + "' " +
687 ", jmsCorrelationID = '" + jmsCorrelationID + "' " +
688 ", jmsDestination = " + jmsDestination +
689 ", jmsReplyTo = " + jmsReplyTo +
690 ", jmsDeliveryMode = " + jmsDeliveryMode +
691 ", jmsRedelivered = " + jmsRedelivered +
692 ", jmsType = '" + jmsType + "' " +
693 ", jmsExpiration = " + jmsExpiration +
694 ", jmsPriority = " + jmsPriority +
695 ", jmsTimestamp = " + jmsTimestamp +
696 ", properties = " + properties +
697 ", readOnlyProperties = " + readOnlyProperties +
698 ", entryBrokerName = '" + entryBrokerName + "' " +
699 ", entryClusterName = '" + entryClusterName + "' " +
700 ", consumerNos = " + toString(consumerNos) +
701 ", transactionId = '" + transactionId + "' " +
702 ", xaTransacted = " + xaTransacted +
703 ", consumerIdentifer = '" + consumerIdentifier + "' " +
704 ", messageConsumed = " + messageConsumed +
705 ", transientConsumed = " + transientConsumed +
706 ", sequenceNumber = " + sequenceNumber +
707 ", deliveryCount = " + deliveryCount +
708 ", dispatchedFromDLQ = " + dispatchedFromDLQ +
709 ", messageAcknowledge = " + messageAcknowledge +
710 ", jmsMessageIdentity = " + jmsMessageIdentity +
711 ", producerKey = " + producerKey +
712 " }";
713 }
714
715 protected String toString(int[] consumerNos) {
716 if (consumerNos == null) {
717 return "null";
718 }
719 StringBuffer buffer = new StringBuffer("[");
720 for (int i = 0; i < consumerNos.length; i++) {
721 int consumerNo = consumerNos[i];
722 if (i > 0) {
723 buffer.append(", ");
724 }
725 buffer.append(Integer.toString(i));
726 }
727 buffer.append("]");
728 return buffer.toString();
729 }
730
731
732 /**
733 * @return Returns the messageAcknowledge.
734 *
735 * @Transient
736 */
737 public MessageAcknowledge getMessageAcknowledge() {
738 return messageAcknowledge;
739 }
740
741 /**
742 * @param messageAcknowledge The messageAcknowledge to set.
743 */
744 public void setMessageAcknowledge(MessageAcknowledge messageAcknowledge) {
745 this.messageAcknowledge = messageAcknowledge;
746 }
747
748 /**
749 * Return the type of Packet
750 *
751 * @return integer representation of the type of Packet
752 */
753
754 public int getPacketType() {
755 return ACTIVEMQ_MESSAGE;
756 }
757
758
759 /**
760 * set the message readOnly
761 *
762 * @param value
763 */
764 public void setReadOnly(boolean value) {
765 this.readOnlyProperties = value;
766 this.readOnlyMessage = value;
767 }
768
769 /**
770 * test to see if a particular Consumer at a Connection
771 * is meant to receive this Message
772 *
773 * @param consumerNumber
774 * @return true if a target
775 */
776
777 public boolean isConsumerTarget(int consumerNumber) {
778 if (consumerNos != null) {
779 for (int i = 0; i < consumerNos.length; i++) {
780 if (consumerNos[i] == consumerNumber) {
781 return true;
782 }
783 }
784 }
785 return false;
786 }
787
788 /**
789 * @return consumer Nos as a String
790 */
791 public String getConsumerNosAsString() {
792 String result = "";
793 if (consumerNos != null) {
794 for (int i = 0; i < consumerNos.length; i++) {
795 if (i > 0) {
796 result += ",";
797 }
798 result += consumerNos[i];
799 }
800 }
801 return result;
802 }
803
804 /**
805 * Sets the consumer numbers using a String format
806 */
807 public void setConsumerNosAsString(String value) {
808 if (value == null) {
809 setConsumerNos(null);
810 }
811 else {
812 List values = new ArrayList();
813 StringTokenizer enm = new StringTokenizer(value, ",");
814 while (enm.hasMoreElements()) {
815 String token = enm.nextToken();
816 values.add(token);
817 }
818
819 int[] answer = new int[values.size()];
820 int i = 0;
821 for (Iterator iter = values.iterator(); iter.hasNext();) {
822 String text = (String) iter.next();
823 answer[i++] = Integer.parseInt(text.trim());
824 }
825 setConsumerNos(answer);
826 }
827 }
828
829
830 /**
831 * @return true if the message is non-persistent or intended for a temporary destination
832 */
833 public boolean isTemporary() {
834 return jmsDeliveryMode == DeliveryMode.NON_PERSISTENT ||
835 (jmsDestination != null && jmsDestination.isTemporary());
836 }
837
838 /**
839 * @return Returns hash code for this instance
840 */
841
842 public int hashCode() {
843 return this.getJMSMessageID() != null ? this.getJMSMessageID().hashCode() : super.hashCode();
844 }
845
846 /**
847 * Returns true if this instance is equivalent to obj
848 *
849 * @param obj the other instance to test
850 * @return true/false
851 */
852
853 public boolean equals(Object obj) {
854 boolean result = obj == this;
855 if (!result && obj != null && obj instanceof ActiveMQMessage) {
856 ActiveMQMessage other = (ActiveMQMessage) obj;
857 //the call getJMSMessageID() will initialize the messageID
858 //if it hasn't already been set
859 result = this.getJMSMessageID() == other.getJMSMessageID();
860 if (!result){
861 if (this.jmsMessageID != null && this.jmsMessageID.length() > 0 ||
862 other.jmsMessageID != null && other.jmsMessageID.length() > 0){
863 if (this.jmsMessageID != null && other.jmsMessageID != null){
864 result = this.jmsMessageID.equals(other.jmsMessageID);
865 }
866 }else{
867 result = this.getId() == other.getId();
868 }
869 }
870 }
871 return result;
872 }
873
874 /**
875 * @param o object to compare
876 * @return 1 if this > o else 0 if they are equal or -1 if this < o
877 */
878 public int compareTo(Object o) {
879 if (o instanceof ActiveMQMessage) {
880 return compareTo((ActiveMQMessage) o);
881 }
882 return -1;
883 }
884
885 /**
886 * Sorted by destination and then messageId
887 *
888 * @param that another message to compare against
889 * @return 1 if this > that else 0 if they are equal or -1 if this < that
890 */
891 public int compareTo(ActiveMQMessage that) {
892 int answer = 1;
893
894 if (that != null && this.jmsDestination != null && that.jmsDestination != null) {
895 answer = this.jmsDestination.compareTo(that.jmsDestination);
896 if (answer == 0) {
897 if (this.jmsMessageID != null && that.jmsMessageID != null) {
898 answer = IdGenerator.compare(this.jmsMessageID, that.jmsMessageID);
899 }
900 else {
901 answer = 1;
902 }
903 }
904 }
905 return answer;
906 }
907
908
909 /**
910 * @return Returns a shallow copy of the message instance
911 * @throws JMSException
912 */
913
914 public ActiveMQMessage shallowCopy() throws JMSException {
915 ActiveMQMessage other = new ActiveMQMessage();
916 this.initializeOther(other);
917 return other;
918 }
919
920 /**
921 * @return Returns a deep copy of the message - note the header fields are only shallow copied
922 * @throws JMSException
923 */
924
925 public ActiveMQMessage deepCopy() throws JMSException {
926 return shallowCopy();
927 }
928
929
930 /**
931 * Indicates if the Message has expired
932 *
933 * @param currentTime -
934 * the current time in milliseconds
935 * @return true if the message can be expired
936 */
937 public boolean isExpired(long currentTime) {
938 boolean result = false;
939 long expiration = this.jmsExpiration;
940 if (jmsExpiration > 0 && jmsExpiration < currentTime) {
941 result = true;
942 }
943 return result;
944 }
945
946 /**
947 * @return true if the message is expired
948 */
949 public boolean isExpired() {
950 return !dispatchedFromDLQ && jmsExpiration > 0 && isExpired(System.currentTimeMillis());
951 }
952
953 /**
954 * @return true if an advisory message
955 */
956 public boolean isAdvisory(){
957 return jmsDestination != null && jmsDestination.isAdvisory();
958 }
959
960 /**
961 * Initializes another message with current values from this instance
962 *
963 * @param other the other ActiveMQMessage to initialize
964 */
965 protected void initializeOther(ActiveMQMessage other) {
966 super.initializeOther(other);
967 other.jmsMessageID = this.jmsMessageID;
968 other.jmsClientID = this.jmsClientID;
969 other.jmsCorrelationID = this.jmsCorrelationID;
970 other.jmsDestination = this.jmsDestination;
971 other.jmsReplyTo = this.jmsReplyTo;
972 other.jmsDeliveryMode = this.jmsDeliveryMode;
973 other.jmsRedelivered = this.jmsRedelivered;
974 other.jmsType = this.jmsType;
975 other.jmsExpiration = this.jmsExpiration;
976 other.jmsPriority = this.jmsPriority;
977 other.jmsTimestamp = this.jmsTimestamp;
978 other.properties = this.properties != null ? new HashMap(this.properties) : null;
979 other.readOnlyProperties = this.readOnlyProperties;
980 other.readOnlyMessage = this.readOnlyMessage;
981 other.entryBrokerName = this.entryBrokerName;
982 other.entryClusterName = this.entryClusterName;
983 other.consumerNos = this.consumerNos;
984 other.transactionId = this.transactionId;
985 other.xaTransacted = this.xaTransacted;
986 other.bodyAsBytes = this.bodyAsBytes;
987 other.messageAcknowledge = this.messageAcknowledge;
988 other.jmsMessageIdentity = this.jmsMessageIdentity;
989 other.sequenceNumber = this.sequenceNumber;
990 other.deliveryCount = this.deliveryCount;
991 other.dispatchedFromDLQ = this.dispatchedFromDLQ;
992 other.messsageHandle = this.messsageHandle;
993 other.consumerIdentifier = this.consumerIdentifier;
994 other.externalMessageId = this.externalMessageId;
995 other.producerKey = this.producerKey;
996 other.messagePart = this.messagePart;
997 other.numberOfParts = this.numberOfParts;
998 other.partNumber = this.partNumber;
999 other.parentMessageID = this.parentMessageID;
1000 }
1001
1002
1003 /**
1004 * Gets the message ID.
1005 * <p/>
1006 * <P>The <CODE>JMSMessageID</CODE> header field contains a value that
1007 * uniquely identifies each message sent by a provider.
1008 * <p/>
1009 * <P>When a message is sent, <CODE>JMSMessageID</CODE> can be ignored.
1010 * When the <CODE>send</CODE> or <CODE>publish</CODE> method returns, it
1011 * contains a provider-assigned value.
1012 * <p/>
1013 * <P>A <CODE>JMSMessageID</CODE> is a <CODE>String</CODE> value that
1014 * should function as a
1015 * unique key for identifying messages in a historical repository.
1016 * The exact scope of uniqueness is provider-defined. It should at
1017 * least cover all messages for a specific installation of a
1018 * provider, where an installation is some connected set of message
1019 * routers.
1020 * <p/>
1021 * <P>All <CODE>JMSMessageID</CODE> values must start with the prefix
1022 * <CODE>'ID:'</CODE>.
1023 * Uniqueness of message ID values across different providers is
1024 * not required.
1025 * <p/>
1026 * <P>Since message IDs take some effort to create and increase a
1027 * message's size, some JMS providers may be able to optimize message
1028 * overhead if they are given a hint that the message ID is not used by
1029 * an application. By calling the
1030 * <CODE>MessageProducer.setDisableMessageID</CODE> method, a JMS client
1031 * enables this potential optimization for all messages sent by that
1032 * message producer. If the JMS provider accepts this
1033 * hint, these messages must have the message ID set to null; if the
1034 * provider ignores the hint, the message ID must be set to its normal
1035 * unique value.
1036 *
1037 * @return the message ID
1038 * @see javax.jms.Message#setJMSMessageID(String)
1039 * @see javax.jms.MessageProducer#setDisableMessageID(boolean)
1040 */
1041
1042 public String getJMSMessageID() {
1043 if (jmsMessageID == null && producerKey != null){
1044 jmsMessageID = producerKey + sequenceNumber;
1045 }
1046 return jmsMessageID;
1047 }
1048
1049
1050 /**
1051 * Sets the message ID.
1052 * <p/>
1053 * <P>JMS providers set this field when a message is sent. This method
1054 * can be used to change the value for a message that has been received.
1055 *
1056 * @param id the ID of the message
1057 * @see javax.jms.Message#getJMSMessageID()
1058 */
1059
1060 public void setJMSMessageID(String id) {
1061 this.jmsMessageID = id;
1062 this.jmsMessageIdentity = null;
1063 }
1064
1065 /**
1066 * Another way to get the Message id.
1067 *
1068 * @Transient
1069 */
1070 public Object getMemoryId() {
1071 return getJMSMessageID();
1072 }
1073
1074 /**
1075 * Gets the message timestamp.
1076 * <p/>
1077 * <P>The <CODE>JMSTimestamp</CODE> header field contains the time a
1078 * message was
1079 * handed off to a provider to be sent. It is not the time the
1080 * message was actually transmitted, because the actual send may occur
1081 * later due to transactions or other client-side queueing of messages.
1082 * <p/>
1083 * <P>When a message is sent, <CODE>JMSTimestamp</CODE> is ignored. When
1084 * the <CODE>send</CODE> or <CODE>publish</CODE>
1085 * method returns, it contains a time value somewhere in the interval
1086 * between the call and the return. The value is in the format of a normal
1087 * millis time value in the Java programming language.
1088 * <p/>
1089 * <P>Since timestamps take some effort to create and increase a
1090 * message's size, some JMS providers may be able to optimize message
1091 * overhead if they are given a hint that the timestamp is not used by an
1092 * application. By calling the
1093 * <CODE>MessageProducer.setDisableMessageTimestamp</CODE> method, a JMS
1094 * client enables this potential optimization for all messages sent by
1095 * that message producer. If the JMS provider accepts this
1096 * hint, these messages must have the timestamp set to zero; if the
1097 * provider ignores the hint, the timestamp must be set to its normal
1098 * value.
1099 *
1100 * @return the message timestamp
1101 * @see javax.jms.Message#setJMSTimestamp(long)
1102 * @see javax.jms.MessageProducer#setDisableMessageTimestamp(boolean)
1103 */
1104
1105 public long getJMSTimestamp() {
1106 return jmsTimestamp;
1107 }
1108
1109
1110 /**
1111 * Sets the message timestamp.
1112 * <p/>
1113 * <P>JMS providers set this field when a message is sent. This method
1114 * can be used to change the value for a message that has been received.
1115 *
1116 * @param timestamp the timestamp for this message
1117 * @see javax.jms.Message#getJMSTimestamp()
1118 */
1119
1120 public void setJMSTimestamp(long timestamp) {
1121 this.jmsTimestamp = timestamp;
1122 }
1123
1124
1125 /**
1126 * Gets the correlation ID as an array of bytes for the message.
1127 * <p/>
1128 * <P>The use of a <CODE>byte[]</CODE> value for
1129 * <CODE>JMSCorrelationID</CODE> is non-portable.
1130 *
1131 * @return the correlation ID of a message as an array of bytes
1132 * @see javax.jms.Message#setJMSCorrelationID(String)
1133 * @see javax.jms.Message#getJMSCorrelationID()
1134 * @see javax.jms.Message#setJMSCorrelationIDAsBytes(byte[])
1135 *
1136 * @Transient
1137 */
1138 public byte[] getJMSCorrelationIDAsBytes() {
1139 return this.jmsCorrelationID != null ? this.jmsCorrelationID.getBytes() : null;
1140 }
1141
1142
1143 /**
1144 * Sets the correlation ID as an array of bytes for the message.
1145 * <p/>
1146 * <P>The array is copied before the method returns, so
1147 * future modifications to the array will not alter this message header.
1148 * <p/>
1149 * <P>If a provider supports the native concept of correlation ID, a
1150 * JMS client may need to assign specific <CODE>JMSCorrelationID</CODE>
1151 * values to match those expected by native messaging clients.
1152 * JMS providers without native correlation ID values are not required to
1153 * support this method and its corresponding get method; their
1154 * implementation may throw a
1155 * <CODE>java.lang.UnsupportedOperationException</CODE>.
1156 * <p/>
1157 * <P>The use of a <CODE>byte[]</CODE> value for
1158 * <CODE>JMSCorrelationID</CODE> is non-portable.
1159 *
1160 * @param correlationID the correlation ID value as an array of bytes
1161 * @see javax.jms.Message#setJMSCorrelationID(String)
1162 * @see javax.jms.Message#getJMSCorrelationID()
1163 * @see javax.jms.Message#getJMSCorrelationIDAsBytes()
1164 */
1165
1166 public void setJMSCorrelationIDAsBytes(byte[] correlationID) {
1167 if (correlationID == null) {
1168 this.jmsCorrelationID = null;
1169 }
1170 else {
1171 this.jmsCorrelationID = new String(correlationID);
1172 }
1173 }
1174
1175
1176 /**
1177 * Sets the correlation ID for the message.
1178 * <p/>
1179 * <P>A client can use the <CODE>JMSCorrelationID</CODE> header field to
1180 * link one message with another. A typical use is to link a response
1181 * message with its request message.
1182 * <p/>
1183 * <P><CODE>JMSCorrelationID</CODE> can hold one of the following:
1184 * <UL>
1185 * <LI>A provider-specific message ID
1186 * <LI>An application-specific <CODE>String</CODE>
1187 * <LI>A provider-native <CODE>byte[]</CODE> value
1188 * </UL>
1189 * <p/>
1190 * <P>Since each message sent by a JMS provider is assigned a message ID
1191 * value, it is convenient to link messages via message ID. All message ID
1192 * values must start with the <CODE>'ID:'</CODE> prefix.
1193 * <p/>
1194 * <P>In some cases, an application (made up of several clients) needs to
1195 * use an application-specific value for linking messages. For instance,
1196 * an application may use <CODE>JMSCorrelationID</CODE> to hold a value
1197 * referencing some external information. Application-specified values
1198 * must not start with the <CODE>'ID:'</CODE> prefix; this is reserved for
1199 * provider-generated message ID values.
1200 * <p/>
1201 * <P>If a provider supports the native concept of correlation ID, a JMS
1202 * client may need to assign specific <CODE>JMSCorrelationID</CODE> values
1203 * to match those expected by clients that do not use the JMS API. A
1204 * <CODE>byte[]</CODE> value is used for this
1205 * purpose. JMS providers without native correlation ID values are not
1206 * required to support <CODE>byte[]</CODE> values. The use of a
1207 * <CODE>byte[]</CODE> value for <CODE>JMSCorrelationID</CODE> is
1208 * non-portable.
1209 *
1210 * @param correlationID the message ID of a message being referred to
1211 * @see javax.jms.Message#getJMSCorrelationID()
1212 * @see javax.jms.Message#getJMSCorrelationIDAsBytes()
1213 * @see javax.jms.Message#setJMSCorrelationIDAsBytes(byte[])
1214 */
1215
1216 public void setJMSCorrelationID(String correlationID) {
1217 this.jmsCorrelationID = correlationID;
1218 }
1219
1220
1221 /**
1222 * Gets the correlation ID for the message.
1223 * <p/>
1224 * <P>This method is used to return correlation ID values that are
1225 * either provider-specific message IDs or application-specific
1226 * <CODE>String</CODE> values.
1227 *
1228 * @return the correlation ID of a message as a <CODE>String</CODE>
1229 * @see javax.jms.Message#setJMSCorrelationID(String)
1230 * @see javax.jms.Message#getJMSCorrelationIDAsBytes()
1231 * @see javax.jms.Message#setJMSCorrelationIDAsBytes(byte[])
1232 */
1233
1234 public String getJMSCorrelationID() {
1235 return this.jmsCorrelationID;
1236 }
1237
1238
1239 /**
1240 * Gets the <CODE>Destination</CODE> object to which a reply to this
1241 * message should be sent.
1242 *
1243 * @return <CODE>Destination</CODE> to which to send a response to this
1244 * message
1245 * @see javax.jms.Message#setJMSReplyTo(Destination)
1246 */
1247
1248 public Destination getJMSReplyTo() {
1249 return this.jmsReplyTo;
1250
1251 }
1252
1253
1254 /**
1255 * Sets the <CODE>Destination</CODE> object to which a reply to this
1256 * message should be sent.
1257 * <p/>
1258 * <P>The <CODE>JMSReplyTo</CODE> header field contains the destination
1259 * where a reply
1260 * to the current message should be sent. If it is null, no reply is
1261 * expected. The destination may be either a <CODE>Queue</CODE> object or
1262 * a <CODE>Topic</CODE> object.
1263 * <p/>
1264 * <P>Messages sent with a null <CODE>JMSReplyTo</CODE> value may be a
1265 * notification of some event, or they may just be some data the sender
1266 * thinks is of interest.
1267 * <p/>
1268 * <P>Messages with a <CODE>JMSReplyTo</CODE> value typically expect a
1269 * response. A response is optional; it is up to the client to decide.
1270 * These messages are called requests. A message sent in response to a
1271 * request is called a reply.
1272 * <p/>
1273 * <P>In some cases a client may wish to match a request it sent earlier
1274 * with a reply it has just received. The client can use the
1275 * <CODE>JMSCorrelationID</CODE> header field for this purpose.
1276 *
1277 * @param replyTo <CODE>Destination</CODE> to which to send a response to
1278 * this message
1279 * @see javax.jms.Message#getJMSReplyTo()
1280 */
1281
1282 public void setJMSReplyTo(Destination replyTo) {
1283 this.jmsReplyTo = (ActiveMQDestination) replyTo;
1284 }
1285
1286
1287 /**
1288 * Gets the <CODE>Destination</CODE> object for this message.
1289 * <p/>
1290 * <P>The <CODE>JMSDestination</CODE> header field contains the
1291 * destination to which the message is being sent.
1292 * <p/>
1293 * <P>When a message is sent, this field is ignored. After completion
1294 * of the <CODE>send</CODE> or <CODE>publish</CODE> method, the field
1295 * holds the destination specified by the method.
1296 * <p/>
1297 * <P>When a message is received, its <CODE>JMSDestination</CODE> value
1298 * must be equivalent to the value assigned when it was sent.
1299 *
1300 * @return the destination of this message
1301 * @see javax.jms.Message#setJMSDestination(Destination)
1302 */
1303
1304 public Destination getJMSDestination() {
1305 return this.jmsDestination;
1306 }
1307
1308
1309 /**
1310 * Sets the <CODE>Destination</CODE> object for this message.
1311 * <p/>
1312 * <P>JMS providers set this field when a message is sent. This method
1313 * can be used to change the value for a message that has been received.
1314 *
1315 * @param destination the destination for this message
1316 * @see javax.jms.Message#getJMSDestination()
1317 */
1318
1319 public void setJMSDestination(Destination destination) {
1320 this.jmsDestination = (ActiveMQDestination) destination;
1321 }
1322
1323
1324 /**
1325 * Gets the <CODE>DeliveryMode</CODE> value specified for this message.
1326 *
1327 * @return the delivery mode for this message
1328 * @see javax.jms.Message#setJMSDeliveryMode(int)
1329 * @see javax.jms.DeliveryMode
1330 */
1331
1332 public int getJMSDeliveryMode() {
1333 return this.jmsDeliveryMode;
1334 }
1335
1336
1337 /**
1338 * Sets the <CODE>DeliveryMode</CODE> value for this message.
1339 * <p/>
1340 * <P>JMS providers set this field when a message is sent. This method
1341 * can be used to change the value for a message that has been received.
1342 *
1343 * @param deliveryMode the delivery mode for this message
1344 * @see javax.jms.Message#getJMSDeliveryMode()
1345 * @see javax.jms.DeliveryMode
1346 */
1347
1348 public void setJMSDeliveryMode(int deliveryMode) {
1349 this.jmsDeliveryMode = deliveryMode;
1350 }
1351
1352
1353 /**
1354 * Gets an indication of whether this message is being redelivered.
1355 * <p/>
1356 * <P>If a client receives a message with the <CODE>JMSRedelivered</CODE>
1357 * field set,
1358 * it is likely, but not guaranteed, that this message was delivered
1359 * earlier but that its receipt was not acknowledged
1360 * at that time.
1361 *
1362 * @return true if this message is being redelivered
1363 * @see javax.jms.Message#setJMSRedelivered(boolean)
1364 */
1365
1366 public boolean getJMSRedelivered() {
1367 return this.jmsRedelivered;
1368 }
1369
1370
1371 /**
1372 * Specifies whether this message is being redelivered.
1373 * <p/>
1374 * <P>This field is set at the time the message is delivered. This
1375 * method can be used to change the value for a message that has
1376 * been received.
1377 *
1378 * @param redelivered an indication of whether this message is being
1379 * redelivered
1380 * @see javax.jms.Message#getJMSRedelivered()
1381 */
1382
1383 public void setJMSRedelivered(boolean redelivered) {
1384 this.jmsRedelivered = redelivered;
1385 }
1386
1387
1388 /**
1389 * Gets the message type identifier supplied by the client when the
1390 * message was sent.
1391 *
1392 * @return the message type
1393 * @see javax.jms.Message#setJMSType(String)
1394 */
1395
1396 public String getJMSType() {
1397 return this.jmsType;
1398 }
1399
1400 /**
1401 * Sets the message type.
1402 * <p/>
1403 * <P>Some JMS providers use a message repository that contains the
1404 * definitions of messages sent by applications. The <CODE>JMSType</CODE>
1405 * header field may reference a message's definition in the provider's
1406 * repository.
1407 * <p/>
1408 * <P>The JMS API does not define a standard message definition repository,
1409 * nor does it define a naming policy for the definitions it contains.
1410 * <p/>
1411 * <P>Some messaging systems require that a message type definition for
1412 * each application message be created and that each message specify its
1413 * type. In order to work with such JMS providers, JMS clients should
1414 * assign a value to <CODE>JMSType</CODE>, whether the application makes
1415 * use of it or not. This ensures that the field is properly set for those
1416 * providers that require it.
1417 * <p/>
1418 * <P>To ensure portability, JMS clients should use symbolic values for
1419 * <CODE>JMSType</CODE> that can be configured at installation time to the
1420 * values defined in the current provider's message repository. If string
1421 * literals are used, they may not be valid type names for some JMS
1422 * providers.
1423 *
1424