001: package org.mockejb.jms;
002:
003: import javax.jms.*;
004: import java.util.Enumeration;
005:
006: /**
007: * Collection of utility methods.
008: *
009: * @author D11
010: * Dimitar Gospodinov
011: */
012: public final class MessageUtility {
013:
014: /**
015: * Objects can not be created.
016: */
017: private MessageUtility() {
018: // Does nothing
019: }
020:
021: /**
022: * Compares two strings. Allows <code>null</code> values.
023: * @param s1
024: * @param s2
025: * @return <code>true</code> if <code>s1</code> and
026: * <code>s2</code> are <code>null</code> or
027: * <code>s1.equals(s2)</code> evaluates to <code>true</code>.
028: * In all other cases returns <code>false</code>.
029: */
030: public static boolean compare(String s1, String s2) {
031: if (s1 == null && s2 == null) {
032: return true;
033: }
034: if (s1 != null && s2 != null) {
035: return s1.equals(s2);
036: }
037: return false;
038: }
039:
040: /**
041: * Compares two byte arrays. Disallow <code>null</code> values.
042: * @param bytes1
043: * @param bytes2
044: * @return <code>true</code> if <code>bytes1</code> and
045: * <code>bytes2</code> have the same lengths and content.
046: * In all other cases returns <code>false</code>.
047: */
048: public static boolean compare(byte[] bytes1, byte[] bytes2) {
049: if (bytes1.length != bytes2.length) {
050: return false;
051: }
052: for (int i = 0; i < bytes1.length; i++) {
053: if (bytes1[i] != bytes2[i]) {
054: return false;
055: }
056: }
057: return true;
058: }
059:
060: /**
061: * Compares two messages. Messages are considered equal if
062: * they have the same header values and properties.
063: * @param msg1
064: * @param msg2
065: * @return <code>true</code> if all header fields in <code>msg1</code>
066: * have the same values as the corresponded header fields in
067: * <code>msg2</code>, and all properties from <code>msg1</code>
068: * exists and have the same values in <code>msg2</code>, and
069: * <code>msg2</code> does not have properties that do not exist in
070: * <code>msg1</code>.
071: * @throws JMSException
072: */
073: public static boolean compare(Message msg1, Message msg2)
074: throws JMSException {
075:
076: // Compare header fields
077:
078: if (compare(msg1.getJMSCorrelationID(), msg2
079: .getJMSCorrelationID())
080: && msg1.getJMSDeliveryMode() == msg2
081: .getJMSDeliveryMode()
082: && msg1.getJMSDestination() == msg2.getJMSDestination()
083: && msg1.getJMSExpiration() == msg2.getJMSExpiration()
084: && compare(msg1.getJMSMessageID(), msg2
085: .getJMSMessageID())
086: && msg1.getJMSPriority() == msg2.getJMSPriority()
087: && msg1.getJMSReplyTo() == msg2.getJMSReplyTo()
088: && msg1.getJMSTimestamp() == msg2.getJMSTimestamp()
089: && compare(msg1.getJMSType(), msg2.getJMSType())
090: && msg1.getJMSRedelivered() == msg2.getJMSRedelivered()) {
091:
092: // Compare properties
093: Enumeration names = msg1.getPropertyNames();
094: int numOfProperties1 = 0;
095: while (names.hasMoreElements()) {
096: numOfProperties1++;
097: String name = (String) names.nextElement();
098: if (!msg2.propertyExists(name)) {
099: return false;
100: }
101: Object value1 = msg1.getObjectProperty(name);
102: Object value2 = msg2.getObjectProperty(name);
103: if ((value1 == null && value2 == null)
104: || (value1 != null && value2 != null && value1
105: .equals(value2))) {
106: continue;
107: }
108: return false;
109: }
110: // Determine number of properties in msg2
111: names = msg2.getPropertyNames();
112: int numOfProperties2 = 0;
113: while (names.hasMoreElements()
114: && numOfProperties2 <= numOfProperties1) {
115:
116: numOfProperties2++;
117: names.nextElement();
118: }
119: return numOfProperties1 == numOfProperties2;
120: }
121: return false;
122: }
123:
124: /**
125: * Compares two bytes messages. Messages are considered equal if
126: * they have the same value for their bodies and their
127: * header fields and properties values are the same.
128: * @param msg1
129: * @param msg2
130: * @return <code>true</code> if the body of <code>msg1</code>
131: * has the same value as the body of <code>msg2</code>, and
132: * <code>compare((Message)msg1, msg2)</code> evaluates to <code>true</code>.
133: * In all other cases returns <code>false</code>.
134: * @throws JMSException
135: */
136: public static boolean compare(BytesMessage msg1, BytesMessage msg2)
137: throws JMSException {
138:
139: // Create copy of the messages to be compared so we can freely manipulate them
140: BytesMessageImpl m1 = new BytesMessageImpl(msg1);
141: BytesMessageImpl m2 = new BytesMessageImpl(msg2);
142:
143: m1.reset();
144: m2.reset();
145:
146: // Lengths are less than 2^31, otherwise m1 and m2 would not be created.
147: int length = (int) m1.getBodyLength();
148: if (length != (int) m2.getBodyLength()) {
149: return false;
150: }
151: while (length-- > 0) {
152: if (m1.readByte() != m2.readByte()) {
153: return false;
154: }
155: }
156: return compare((Message) m1, m2);
157: }
158:
159: /**
160: * Compares two map messages. Messages are considered equal if
161: * they have the same value for their bodies and their
162: * header fields and properties values are the same.
163: * Bodies of map messages are considered equal if they contain
164: * the same set of name-value pairs.
165: * @param msg1
166: * @param msg2
167: * @return <code>true</code> if the body of <code>msg1</code>
168: * has the same value as the body of <code>msg2</code>, and
169: * <code>compare((Message)msg1, msg2)</code> evaluates to <code>true</code>.
170: * In all other cases returns <code>false</code>.
171: * @throws JMSException
172: */
173: public static boolean compare(MapMessage msg1, MapMessage msg2)
174: throws JMSException {
175:
176: // Compare properties
177: Enumeration names = msg1.getMapNames();
178: int numOfNames1 = 0;
179: while (names.hasMoreElements()) {
180: numOfNames1++;
181: String name = (String) names.nextElement();
182: if (!msg2.itemExists(name)) {
183: return false;
184: }
185: Object value1 = msg1.getObject(name);
186: Object value2 = msg2.getObject(name);
187: if ((value1 == null && value2 == null)
188: || ((value1 != null && value2 != null) && ((value1 instanceof byte[]
189: && value2 instanceof byte[] && compare(
190: (byte[]) value1, (byte[]) value2)) || value1
191: .equals(value2)))) {
192: continue;
193: }
194: return false;
195: }
196: // Determine number of properties in msg2
197: names = msg2.getMapNames();
198: int numOfNames2 = 0;
199: while (names.hasMoreElements() && numOfNames2 <= numOfNames1) {
200: numOfNames2++;
201: names.nextElement();
202: }
203: return numOfNames1 == numOfNames2
204: && compare((Message) msg1, msg2);
205: }
206:
207: /**
208: * Compares two object messages. Messages are considered equal if
209: * they have the same value for their bodies and their
210: * header fields and properties values are the same.
211: * Bodies of object messages are considered the same if after
212: * deserialization <code>msg1.getObject().equals(msg2.getObject)</code> evaluates to
213: * <code>true</code> or both bodies are <code>null</code>.
214: * @param msg1
215: * @param msg2
216: * @return <code>true</code> if the body of <code>msg1</code>
217: * has the same value as the body of <code>msg2</code>, and
218: * <code>compare((Message)msg1, msg2)</code> evaluates to <code>true</code>.
219: * In all other cases returns <code>false</code>.
220: * @throws JMSException
221: */
222: public static boolean compare(ObjectMessage msg1, ObjectMessage msg2)
223: throws JMSException {
224:
225: Object o1 = msg1.getObject();
226: Object o2 = msg2.getObject();
227:
228: if (o1 == null && o2 == null) {
229: return compare((Message) msg1, msg2);
230: }
231: if (o1 != null && o2 != null) {
232: return o1.equals(o2) && compare((Message) msg1, msg2);
233: }
234: return false;
235: }
236:
237: /**
238: * Compares two stream messages. Messages are considered equal if
239: * they have the same value for their bodies and their
240: * header fields and properties values are the same.
241: * Bodies of stream messages are considered the same if they have
242: * the same number of elements and corresponding elements (elements that
243: * have the same position in the stream) are from the
244: * same type and have the same values.
245: * @param msg1
246: * @param msg2
247: * @return <code>true</code> if the body of <code>msg1</code>
248: * has the same value as the body of <code>msg2</code>, and
249: * <code>compare((Message)msg1, msg2)</code> evaluates to <code>true</code>.
250: * In all other cases returns <code>false</code>.
251: * @throws JMSException
252: */
253: public static boolean compare(StreamMessage msg1, StreamMessage msg2)
254: throws JMSException {
255:
256: StreamMessageImpl m1 = new StreamMessageImpl(msg1);
257: StreamMessageImpl m2 = new StreamMessageImpl(msg2);
258:
259: Object[] data1 = m1.getStreamData();
260: Object[] data2 = m2.getStreamData();
261:
262: if (data1.length != data2.length) {
263: return false;
264: }
265: for (int i = 0; i < data1.length; i++) {
266: if (data1[i] == null && data2[i] == null) {
267: continue;
268: }
269: if (data1[i] != null
270: && data2[i] != null
271: && ((data1[i] instanceof byte[]
272: && data2[i] instanceof byte[] && compare(
273: (byte[]) data1[i], (byte[]) data2[i])) || data1[i]
274: .equals(data2[i]))) {
275: continue;
276: }
277: return false;
278: }
279: return compare((Message) m1, m2);
280: }
281:
282: /**
283: * Compares two text messages. Messages are considered equal if
284: * they have the same value for their bodies and their
285: * header fields and properties values are the same.
286: * Bodies of text messages are considered the same if
287: * <code>msg1.getText().equals(msg2.getText())</code> evaluates to
288: * <code>true</code> or both bodies are <code>null</code>.
289: * @param msg1
290: * @param msg2
291: * @return <code>true</code> if the body of <code>msg1</code>
292: * has the same value as the body of <code>msg2</code>, and
293: * <code>compare((Message)msg1, msg2)</code> evaluates to <code>true</code>.
294: * In all other cases returns <code>false</code>.
295: * @throws JMSException
296: */
297: public static boolean compare(TextMessage msg1, TextMessage msg2)
298: throws JMSException {
299:
300: return compare(msg1.getText(), msg2.getText())
301: && compare((Message) msg1, msg2);
302: }
303:
304: /**
305: * Copies header, properties and body of <code>msg</code> to a new
306: * message of the same type.
307: * @param msg to be copied from
308: * @param reset <code>true</code> if the copy should be in read only mode. If <code>msg</code> is already in read-only
309: * mode this parameter is redundant.
310: * @return copy of <code>msg</code>
311: * @throws JMSException
312: */
313: public static MessageImpl copyMessage(Message msg, boolean reset)
314: throws JMSException {
315: MessageImpl result;
316: if (msg instanceof BytesMessage) {
317: result = new BytesMessageImpl((BytesMessage) msg);
318: } else if (msg instanceof MapMessage) {
319: result = new MapMessageImpl((MapMessage) msg);
320: } else if (msg instanceof ObjectMessage) {
321: result = new ObjectMessageImpl(((ObjectMessage) msg)
322: .getObject());
323: } else if (msg instanceof StreamMessage) {
324: result = new StreamMessageImpl((StreamMessage) msg);
325: } else if (msg instanceof TextMessage) {
326: result = new TextMessageImpl((TextMessage) msg);
327: } else {
328: result = new MessageImpl(msg);
329: }
330:
331: if (reset) {
332: result.setPropertiesNotWriteable();
333: result.resetBody();
334: }
335: return result;
336: }
337:
338: }
|