| MessageUtility.java |
package org.mockejb.jms;
import javax.jms.*;
import java.util.Enumeration;
/**
* Collection of utility methods.
*
* @author D11
* Dimitar Gospodinov
*/
public final class MessageUtility {
/**
* Objects can not be created.
*/
private MessageUtility() {
// Does nothing
}
/**
* Compares two strings. Allows <code>null</code> values.
* @param s1
* @param s2
* @return <code>true</code> if <code>s1</code> and
* <code>s2</code> are <code>null</code> or
* <code>s1.equals(s2)</code> evaluates to <code>true</code>.
* In all other cases returns <code>false</code>.
*/
public static boolean compare(String s1, String s2) {
if (s1 == null && s2 == null) {
return true;
}
if (s1 != null && s2 != null) {
return s1.equals(s2);
}
return false;
}
/**
* Compares two byte arrays. Disallow <code>null</code> values.
* @param bytes1
* @param bytes2
* @return <code>true</code> if <code>bytes1</code> and
* <code>bytes2</code> have the same lengths and content.
* In all other cases returns <code>false</code>.
*/
public static boolean compare(byte[] bytes1, byte[] bytes2) {
if (bytes1.length != bytes2.length) {
return false;
}
for (int i = 0; i < bytes1.length; i++) {
if (bytes1[i] != bytes2[i]) {
return false;
}
}
return true;
}
/**
* Compares two messages. Messages are considered equal if
* they have the same header values and properties.
* @param msg1
* @param msg2
* @return <code>true</code> if all header fields in <code>msg1</code>
* have the same values as the corresponded header fields in
* <code>msg2</code>, and all properties from <code>msg1</code>
* exists and have the same values in <code>msg2</code>, and
* <code>msg2</code> does not have properties that do not exist in
* <code>msg1</code>.
* @throws JMSException
*/
public static boolean compare(Message msg1, Message msg2)
throws JMSException {
// Compare header fields
if (compare(msg1.getJMSCorrelationID(), msg2.getJMSCorrelationID())
&& msg1.getJMSDeliveryMode() == msg2.getJMSDeliveryMode()
&& msg1.getJMSDestination() == msg2.getJMSDestination()
&& msg1.getJMSExpiration() == msg2.getJMSExpiration()
&& compare(msg1.getJMSMessageID(), msg2.getJMSMessageID())
&& msg1.getJMSPriority() == msg2.getJMSPriority()
&& msg1.getJMSReplyTo() == msg2.getJMSReplyTo()
&& msg1.getJMSTimestamp() == msg2.getJMSTimestamp()
&& compare(msg1.getJMSType(), msg2.getJMSType())
&& msg1.getJMSRedelivered() == msg2.getJMSRedelivered()) {
// Compare properties
Enumeration names = msg1.getPropertyNames();
int numOfProperties1 = 0;
while (names.hasMoreElements()) {
numOfProperties1++;
String name = (String) names.nextElement();
if (!msg2.propertyExists(name)) {
return false;
}
Object value1 = msg1.getObjectProperty(name);
Object value2 = msg2.getObjectProperty(name);
if ((value1 == null && value2 == null)
|| (value1 != null
&& value2 != null
&& value1.equals(value2))) {
continue;
}
return false;
}
// Determine number of properties in msg2
names = msg2.getPropertyNames();
int numOfProperties2 = 0;
while (names.hasMoreElements()
&& numOfProperties2 <= numOfProperties1) {
numOfProperties2++;
names.nextElement();
}
return numOfProperties1 == numOfProperties2;
}
return false;
}
/**
* Compares two bytes messages. Messages are considered equal if
* they have the same value for their bodies and their
* header fields and properties values are the same.
* @param msg1
* @param msg2
* @return <code>true</code> if the body of <code>msg1</code>
* has the same value as the body of <code>msg2</code>, and
* <code>compare((Message)msg1, msg2)</code> evaluates to <code>true</code>.
* In all other cases returns <code>false</code>.
* @throws JMSException
*/
public static boolean compare(BytesMessage msg1, BytesMessage msg2)
throws JMSException {
// Create copy of the messages to be compared so we can freely manipulate them
BytesMessageImpl m1 = new BytesMessageImpl(msg1);
BytesMessageImpl m2 = new BytesMessageImpl(msg2);
m1.reset();
m2.reset();
// Lengths are less than 2^31, otherwise m1 and m2 would not be created.
int length = (int) m1.getBodyLength();
if (length != (int) m2.getBodyLength()) {
return false;
}
while (length-- > 0) {
if (m1.readByte() != m2.readByte()) {
return false;
}
}
return compare((Message) m1, m2);
}
/**
* Compares two map messages. Messages are considered equal if
* they have the same value for their bodies and their
* header fields and properties values are the same.
* Bodies of map messages are considered equal if they contain
* the same set of name-value pairs.
* @param msg1
* @param msg2
* @return <code>true</code> if the body of <code>msg1</code>
* has the same value as the body of <code>msg2</code>, and
* <code>compare((Message)msg1, msg2)</code> evaluates to <code>true</code>.
* In all other cases returns <code>false</code>.
* @throws JMSException
*/
public static boolean compare(MapMessage msg1, MapMessage msg2)
throws JMSException {
// Compare properties
Enumeration names = msg1.getMapNames();
int numOfNames1 = 0;
while (names.hasMoreElements()) {
numOfNames1++;
String name = (String) names.nextElement();
if (!msg2.itemExists(name)) {
return false;
}
Object value1 = msg1.getObject(name);
Object value2 = msg2.getObject(name);
if ((value1 == null && value2 == null)
|| ((value1 != null && value2 != null)
&& ((value1 instanceof byte[]
&& value2 instanceof byte[]
&& compare((byte[]) value1, (byte[]) value2))
|| value1.equals(value2)))) {
continue;
}
return false;
}
// Determine number of properties in msg2
names = msg2.getMapNames();
int numOfNames2 = 0;
while (names.hasMoreElements() && numOfNames2 <= numOfNames1) {
numOfNames2++;
names.nextElement();
}
return numOfNames1 == numOfNames2 && compare((Message) msg1, msg2);
}
/**
* Compares two object messages. Messages are considered equal if
* they have the same value for their bodies and their
* header fields and properties values are the same.
* Bodies of object messages are considered the same if after
* deserialization <code>msg1.getObject().equals(msg2.getObject)</code> evaluates to
* <code>true</code> or both bodies are <code>null</code>.
* @param msg1
* @param msg2
* @return <code>true</code> if the body of <code>msg1</code>
* has the same value as the body of <code>msg2</code>, and
* <code>compare((Message)msg1, msg2)</code> evaluates to <code>true</code>.
* In all other cases returns <code>false</code>.
* @throws JMSException
*/
public static boolean compare(ObjectMessage msg1, ObjectMessage msg2)
throws JMSException {
Object o1 = msg1.getObject();
Object o2 = msg2.getObject();
if (o1 == null && o2 == null) {
return compare((Message) msg1, msg2);
}
if (o1 != null && o2 != null) {
return o1.equals(o2) && compare((Message) msg1, msg2);
}
return false;
}
/**
* Compares two stream messages. Messages are considered equal if
* they have the same value for their bodies and their
* header fields and properties values are the same.
* Bodies of stream messages are considered the same if they have
* the same number of elements and corresponding elements (elements that
* have the same position in the stream) are from the
* same type and have the same values.
* @param msg1
* @param msg2
* @return <code>true</code> if the body of <code>msg1</code>
* has the same value as the body of <code>msg2</code>, and
* <code>compare((Message)msg1, msg2)</code> evaluates to <code>true</code>.
* In all other cases returns <code>false</code>.
* @throws JMSException
*/
public static boolean compare(StreamMessage msg1, StreamMessage msg2)
throws JMSException {
StreamMessageImpl m1 = new StreamMessageImpl(msg1);
StreamMessageImpl m2 = new StreamMessageImpl(msg2);
Object[] data1 = m1.getStreamData();
Object[] data2 = m2.getStreamData();
if (data1.length != data2.length) {
return false;
}
for (int i = 0; i < data1.length; i++) {
if (data1[i] == null && data2[i] == null) {
continue;
}
if (data1[i] != null
&& data2[i] != null
&& ((data1[i] instanceof byte[]
&& data2[i] instanceof byte[]
&& compare((byte[]) data1[i], (byte[]) data2[i]))
|| data1[i].equals(data2[i]))) {
continue;
}
return false;
}
return compare((Message) m1, m2);
}
/**
* Compares two text messages. Messages are considered equal if
* they have the same value for their bodies and their
* header fields and properties values are the same.
* Bodies of text messages are considered the same if
* <code>msg1.getText().equals(msg2.getText())</code> evaluates to
* <code>true</code> or both bodies are <code>null</code>.
* @param msg1
* @param msg2
* @return <code>true</code> if the body of <code>msg1</code>
* has the same value as the body of <code>msg2</code>, and
* <code>compare((Message)msg1, msg2)</code> evaluates to <code>true</code>.
* In all other cases returns <code>false</code>.
* @throws JMSException
*/
public static boolean compare(TextMessage msg1, TextMessage msg2)
throws JMSException {
return compare(msg1.getText(), msg2.getText())
&& compare((Message) msg1, msg2);
}
/**
* Copies header, properties and body of <code>msg</code> to a new
* message of the same type.
* @param msg to be copied from
* @param reset <code>true</code> if the copy should be in read only mode. If <code>msg</code> is already in read-only
* mode this parameter is redundant.
* @return copy of <code>msg</code>
* @throws JMSException
*/
public static MessageImpl copyMessage(Message msg, boolean reset) throws JMSException {
MessageImpl result;
if (msg instanceof BytesMessage) {
result = new BytesMessageImpl((BytesMessage) msg);
} else if (msg instanceof MapMessage) {
result = new MapMessageImpl((MapMessage) msg);
} else if (msg instanceof ObjectMessage) {
result = new ObjectMessageImpl(((ObjectMessage) msg).getObject());
} else if (msg instanceof StreamMessage) {
result = new StreamMessageImpl((StreamMessage) msg);
} else if (msg instanceof TextMessage) {
result = new TextMessageImpl((TextMessage) msg);
} else {
result = new MessageImpl(msg);
}
if (reset) {
result.setPropertiesNotWriteable();
result.resetBody();
}
return result;
}
}