You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ta...@apache.org on 2014/09/23 20:20:46 UTC
[22/27] Initial drop of donated AMQP Client Code.
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessage.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessage.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessage.java
new file mode 100644
index 0000000..8bee2e3
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessage.java
@@ -0,0 +1,643 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.qpid.jms.message;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import javax.jms.DeliveryMode;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.MessageFormatException;
+import javax.jms.MessageNotReadableException;
+import javax.jms.MessageNotWriteableException;
+
+import org.apache.qpid.jms.JmsConnection;
+import org.apache.qpid.jms.exceptions.JmsExceptionSupport;
+import org.apache.qpid.jms.message.facade.JmsMessageFacade;
+import org.apache.qpid.jms.meta.JmsMessageId;
+import org.apache.qpid.jms.util.TypeConversionSupport;
+
+public class JmsMessage implements javax.jms.Message {
+
+ protected transient Callable<Void> acknowledgeCallback;
+ protected transient JmsConnection connection;
+
+ protected final JmsMessageFacade facade;
+ protected boolean readOnlyBody;
+ protected boolean readOnlyProperties;
+
+ public JmsMessage(JmsMessageFacade facade) {
+ this.facade = facade;
+ }
+
+ public JmsMessage copy() throws JMSException {
+ JmsMessage other = new JmsMessage(facade.copy());
+ other.copy(this);
+ return other;
+ }
+
+ protected void copy(JmsMessage other) {
+ this.readOnlyBody = other.readOnlyBody;
+ this.readOnlyProperties = other.readOnlyBody;
+ this.acknowledgeCallback = other.acknowledgeCallback;
+ this.connection = other.connection;
+ }
+
+ @Override
+ public int hashCode() {
+ String id = null;
+ try {
+ id = getJMSMessageID();
+ } catch (JMSException e) {
+ }
+
+ if (id != null) {
+ return id.hashCode();
+ } else {
+ return super.hashCode();
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || o.getClass() != getClass()) {
+ return false;
+ }
+
+ JmsMessage msg = (JmsMessage) o;
+ JmsMessageId oMsg = null;
+ JmsMessageId thisMsg = null;
+
+ thisMsg = facade.getMessageId();
+ oMsg = msg.facade.getMessageId();
+
+ return thisMsg != null && oMsg != null && oMsg.equals(thisMsg);
+ }
+
+ @Override
+ public void acknowledge() throws JMSException {
+ if (acknowledgeCallback != null) {
+ try {
+ acknowledgeCallback.call();
+ } catch (Throwable e) {
+ throw JmsExceptionSupport.create(e);
+ }
+ }
+ }
+
+ @Override
+ public void clearBody() throws JMSException {
+ readOnlyBody = false;
+ facade.clearBody();
+ }
+
+ public boolean isReadOnlyBody() {
+ return this.readOnlyBody;
+ }
+
+ public void setReadOnlyBody(boolean readOnlyBody) {
+ this.readOnlyBody = readOnlyBody;
+ }
+
+ public void setReadOnlyProperties(boolean readOnlyProperties) {
+ this.readOnlyProperties = readOnlyProperties;
+ }
+
+ @Override
+ public String getJMSMessageID() throws JMSException {
+ if (facade.getMessageId() == null) {
+ return null;
+ }
+ return facade.getMessageId().toString();
+ }
+
+ @Override
+ public void setJMSMessageID(String value) throws JMSException {
+ if (value != null) {
+ JmsMessageId id = new JmsMessageId(value);
+ facade.setMessageId(id);
+ } else {
+ facade.setMessageId(null);
+ }
+ }
+
+ public void setJMSMessageID(JmsMessageId messageId) throws JMSException {
+ facade.setMessageId(messageId);
+ }
+
+ @Override
+ public long getJMSTimestamp() throws JMSException {
+ return facade.getTimestamp();
+ }
+
+ @Override
+ public void setJMSTimestamp(long timestamp) throws JMSException {
+ facade.setTimestamp(timestamp);
+ }
+
+ @Override
+ public String getJMSCorrelationID() throws JMSException {
+ return facade.getCorrelationId();
+ }
+
+ @Override
+ public void setJMSCorrelationID(String correlationId) throws JMSException {
+ facade.setCorrelationId(correlationId);
+ }
+
+ @Override
+ public byte[] getJMSCorrelationIDAsBytes() throws JMSException {
+ return facade.getCorrelationIdBytes();
+ }
+
+ @Override
+ public void setJMSCorrelationIDAsBytes(byte[] correlationId) throws JMSException {
+ facade.setCorrelationIdBytes(correlationId);
+ }
+
+ @Override
+ public Destination getJMSReplyTo() throws JMSException {
+ return facade.getReplyTo();
+ }
+
+ @Override
+ public void setJMSReplyTo(Destination destination) throws JMSException {
+ facade.setReplyTo(JmsMessageTransformation.transformDestination(connection, destination));
+ }
+
+ @Override
+ public Destination getJMSDestination() throws JMSException {
+ return facade.getDestination();
+ }
+
+ @Override
+ public void setJMSDestination(Destination destination) throws JMSException {
+ facade.setDestination(JmsMessageTransformation.transformDestination(connection, destination));
+ }
+
+ @Override
+ public int getJMSDeliveryMode() throws JMSException {
+ return facade.isPersistent() ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT;
+ }
+
+ @Override
+ public void setJMSDeliveryMode(int mode) throws JMSException {
+ facade.setPersistent(mode == DeliveryMode.PERSISTENT);
+ }
+
+ @Override
+ public boolean getJMSRedelivered() throws JMSException {
+ return this.isRedelivered();
+ }
+
+ @Override
+ public void setJMSRedelivered(boolean redelivered) throws JMSException {
+ this.setRedelivered(redelivered);
+ }
+
+ @Override
+ public String getJMSType() throws JMSException {
+ return facade.getType();
+ }
+
+ @Override
+ public void setJMSType(String type) throws JMSException {
+ facade.setType(type);
+ }
+
+ @Override
+ public long getJMSExpiration() throws JMSException {
+ return facade.getExpiration();
+ }
+
+ @Override
+ public void setJMSExpiration(long expiration) throws JMSException {
+ facade.setExpiration(expiration);
+ }
+
+ @Override
+ public int getJMSPriority() throws JMSException {
+ return facade.getPriority();
+ }
+
+ @Override
+ public void setJMSPriority(int priority) throws JMSException {
+ byte scaled = 0;
+
+ if (priority < 0) {
+ scaled = 0;
+ } else if (priority > 9) {
+ scaled = 9;
+ } else {
+ scaled = (byte) priority;
+ }
+
+ facade.setPriority(scaled);
+ }
+
+ @Override
+ public void clearProperties() throws JMSException {
+ facade.clearProperties();
+ }
+
+ @Override
+ public boolean propertyExists(String name) throws JMSException {
+ return JmsMessagePropertyIntercepter.propertyExists(facade, name);
+ }
+
+ /**
+ * Returns an unmodifiable Map containing the properties contained within the message.
+ *
+ * @return unmodifiable Map of the current properties in the message.
+ *
+ * @throws JMSException if there is an error accessing the message properties.
+ */
+ public Map<String, Object> getProperties() throws JMSException {
+ return Collections.unmodifiableMap(facade.getProperties());
+ }
+
+ /**
+ * Allows for a direct put of an Object value into the message properties.
+ *
+ * This method bypasses the normal JMS type checking for properties being set on
+ * the message and should be used with great care.
+ *
+ * @param key
+ * the property name to use when setting the value.
+ * @param value
+ * the value to insert into the message properties.
+ *
+ * @throws JMSException if an error occurs while accessing the Message properties.
+ */
+ public void setProperty(String key, Object value) throws JMSException {
+ this.facade.setProperty(key, value);
+ }
+
+ /**
+ * Returns the Object value referenced by the given key.
+ *
+ * @param key
+ * the name of the property being accessed.
+ *
+ * @return the value stored at the given location or null if non set.
+ *
+ * @throws JMSException if an error occurs while accessing the Message properties.
+ */
+ public Object getProperty(String key) throws JMSException {
+ return this.facade.getProperty(key);
+ }
+
+ @Override
+ public Enumeration<?> getPropertyNames() throws JMSException {
+ Set<String> result = new HashSet<String>(facade.getProperties().keySet());
+ return Collections.enumeration(result);
+ }
+
+ /**
+ * return all property names, including standard JMS properties and JMSX
+ * properties
+ *
+ * @return Enumeration of all property names on this message
+ * @throws JMSException
+ */
+ public Enumeration<?> getAllPropertyNames() throws JMSException {
+ Set<String> result = new HashSet<String>(facade.getProperties().keySet());
+ result.addAll(JmsMessagePropertyIntercepter.getAllPropertyNames());
+ return Collections.enumeration(result);
+ }
+
+ @Override
+ public void setObjectProperty(String name, Object value) throws JMSException {
+ checkReadOnlyProperties();
+ checkPropertyNameIsValid(name);
+ checkValidObject(value);
+ JmsMessagePropertyIntercepter.setProperty(facade, name, value);
+ }
+
+ public void setProperties(Map<String, Object> properties) throws JMSException {
+ for (Iterator<Map.Entry<String, Object>> iter = properties.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry<String, Object> entry = iter.next();
+ setObjectProperty(entry.getKey(), entry.getValue());
+ }
+ }
+
+ protected void checkValidObject(Object value) throws MessageFormatException {
+ boolean valid = value instanceof Boolean ||
+ value instanceof Byte ||
+ value instanceof Short ||
+ value instanceof Integer ||
+ value instanceof Long ||
+ value instanceof Float ||
+ value instanceof Double ||
+ value instanceof Character ||
+ value instanceof String ||
+ value == null;
+
+ if (!valid) {
+ throw new MessageFormatException("Only objectified primitive objects and String types are allowed but was: " + value + " type: " + value.getClass());
+ }
+ }
+
+ @Override
+ public Object getObjectProperty(String name) throws JMSException {
+ if (name == null) {
+ throw new NullPointerException("Property name cannot be null");
+ }
+
+ return JmsMessagePropertyIntercepter.getProperty(facade, name);
+ }
+
+ @Override
+ public boolean getBooleanProperty(String name) throws JMSException {
+ Object value = getObjectProperty(name);
+ if (value == null) {
+ return false;
+ }
+ Boolean rc = (Boolean) TypeConversionSupport.convert(value, Boolean.class);
+ if (rc == null) {
+ throw new MessageFormatException("Property " + name + " was a " + value.getClass().getName() + " and cannot be read as a boolean");
+ }
+ return rc.booleanValue();
+ }
+
+ @Override
+ public byte getByteProperty(String name) throws JMSException {
+ Object value = getObjectProperty(name);
+ if (value == null) {
+ throw new NumberFormatException("property " + name + " was null");
+ }
+ Byte rc = (Byte) TypeConversionSupport.convert(value, Byte.class);
+ if (rc == null) {
+ throw new MessageFormatException("Property " + name + " was a " + value.getClass().getName() + " and cannot be read as a byte");
+ }
+ return rc.byteValue();
+ }
+
+ @Override
+ public short getShortProperty(String name) throws JMSException {
+ Object value = getObjectProperty(name);
+ if (value == null) {
+ throw new NumberFormatException("property " + name + " was null");
+ }
+ Short rc = (Short) TypeConversionSupport.convert(value, Short.class);
+ if (rc == null) {
+ throw new MessageFormatException("Property " + name + " was a " + value.getClass().getName() + " and cannot be read as a short");
+ }
+ return rc.shortValue();
+ }
+
+ @Override
+ public int getIntProperty(String name) throws JMSException {
+ Object value = getObjectProperty(name);
+ if (value == null) {
+ throw new NumberFormatException("property " + name + " was null");
+ }
+ Integer rc = (Integer) TypeConversionSupport.convert(value, Integer.class);
+ if (rc == null) {
+ throw new MessageFormatException("Property " + name + " was a " + value.getClass().getName() + " and cannot be read as an integer");
+ }
+ return rc.intValue();
+ }
+
+ @Override
+ public long getLongProperty(String name) throws JMSException {
+ Object value = getObjectProperty(name);
+ if (value == null) {
+ throw new NumberFormatException("property " + name + " was null");
+ }
+ Long rc = (Long) TypeConversionSupport.convert(value, Long.class);
+ if (rc == null) {
+ throw new MessageFormatException("Property " + name + " was a " + value.getClass().getName() + " and cannot be read as a long");
+ }
+ return rc.longValue();
+ }
+
+ @Override
+ public float getFloatProperty(String name) throws JMSException {
+ Object value = getObjectProperty(name);
+ if (value == null) {
+ throw new NullPointerException("property " + name + " was null");
+ }
+ Float rc = (Float) TypeConversionSupport.convert(value, Float.class);
+ if (rc == null) {
+ throw new MessageFormatException("Property " + name + " was a " + value.getClass().getName() + " and cannot be read as a float");
+ }
+ return rc.floatValue();
+ }
+
+ @Override
+ public double getDoubleProperty(String name) throws JMSException {
+ Object value = getObjectProperty(name);
+ if (value == null) {
+ throw new NullPointerException("property " + name + " was null");
+ }
+ Double rc = (Double) TypeConversionSupport.convert(value, Double.class);
+ if (rc == null) {
+ throw new MessageFormatException("Property " + name + " was a " + value.getClass().getName() + " and cannot be read as a double");
+ }
+ return rc.doubleValue();
+ }
+
+ @Override
+ public String getStringProperty(String name) throws JMSException {
+ Object value = getObjectProperty(name);
+ if (value == null) {
+ return null;
+ }
+ String rc = (String) TypeConversionSupport.convert(value, String.class);
+ if (rc == null) {
+ throw new MessageFormatException("Property " + name + " was a " + value.getClass().getName() + " and cannot be read as a String");
+ }
+ return rc;
+ }
+
+ @Override
+ public void setBooleanProperty(String name, boolean value) throws JMSException {
+ setObjectProperty(name, Boolean.valueOf(value));
+ }
+
+ @Override
+ public void setByteProperty(String name, byte value) throws JMSException {
+ setObjectProperty(name, Byte.valueOf(value));
+ }
+
+ @Override
+ public void setShortProperty(String name, short value) throws JMSException {
+ setObjectProperty(name, Short.valueOf(value));
+ }
+
+ @Override
+ public void setIntProperty(String name, int value) throws JMSException {
+ setObjectProperty(name, Integer.valueOf(value));
+ }
+
+ @Override
+ public void setLongProperty(String name, long value) throws JMSException {
+ setObjectProperty(name, Long.valueOf(value));
+ }
+
+ @Override
+ public void setFloatProperty(String name, float value) throws JMSException {
+ setObjectProperty(name, new Float(value));
+ }
+
+ @Override
+ public void setDoubleProperty(String name, double value) throws JMSException {
+ setObjectProperty(name, new Double(value));
+ }
+
+ @Override
+ public void setStringProperty(String name, String value) throws JMSException {
+ setObjectProperty(name, value);
+ }
+
+ public Callable<Void> getAcknowledgeCallback() {
+ return acknowledgeCallback;
+ }
+
+ public void setAcknowledgeCallback(Callable<Void> acknowledgeCallback) {
+ this.acknowledgeCallback = acknowledgeCallback;
+ }
+
+ /**
+ * Send operation event listener. Used to get the message ready to be sent.
+ *
+ * @throws JMSException
+ */
+ public void onSend() throws JMSException {
+ setReadOnlyBody(true);
+ setReadOnlyProperties(true);
+ facade.onSend();
+ }
+
+ public JmsConnection getConnection() {
+ return connection;
+ }
+
+ public void setConnection(JmsConnection connection) {
+ this.connection = connection;
+ }
+
+ public boolean isExpired() throws JMSException {
+ long expireTime = facade.getExpiration();
+ return expireTime > 0 && System.currentTimeMillis() > expireTime;
+ }
+
+ public void incrementRedeliveryCount() {
+ facade.setRedeliveryCounter(facade.getRedeliveryCounter() + 1);
+ }
+
+ public JmsMessageFacade getFacade() {
+ return this.facade;
+ }
+
+ public boolean isRedelivered() throws JMSException {
+ return facade.isRedelivered();
+ }
+
+ public void setRedelivered(boolean redelivered) throws JMSException {
+ if (redelivered) {
+ if (!isRedelivered()) {
+ facade.setRedeliveryCounter(1);
+ }
+ } else {
+ if (isRedelivered()) {
+ facade.setRedeliveryCounter(0);
+ }
+ }
+ }
+
+ protected void checkReadOnlyProperties() throws MessageNotWriteableException {
+ if (readOnlyProperties) {
+ throw new MessageNotWriteableException("Message properties are read-only");
+ }
+ }
+
+ protected void checkReadOnlyBody() throws MessageNotWriteableException {
+ if (readOnlyBody) {
+ throw new MessageNotWriteableException("Message body is read-only");
+ }
+ }
+
+ protected void checkWriteOnlyBody() throws MessageNotReadableException {
+ if (!readOnlyBody) {
+ throw new MessageNotReadableException("Message body is write-only");
+ }
+ }
+
+ private void checkPropertyNameIsValid(String propertyName) throws IllegalArgumentException {
+ if (propertyName == null) {
+ throw new IllegalArgumentException("Property name must not be null");
+ } else if (propertyName.length() == 0) {
+ throw new IllegalArgumentException("Property name must not be the empty string");
+ }
+
+ checkIdentifierFormat(propertyName);
+ }
+
+ private void checkIdentifierFormat(String identifier) throws IllegalArgumentException {
+ checkIdentifierLetterAndDigitRequirements(identifier);
+ checkIdentifierIsntNullTrueFalse(identifier);
+ checkIdentifierIsntLogicOperator(identifier);
+ }
+
+ private void checkIdentifierIsntLogicOperator(String identifier) {
+ // Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or ESCAPE.
+ if ("NOT".equals(identifier) || "AND".equals(identifier) || "OR".equals(identifier) ||
+ "BETWEEN".equals(identifier) || "LIKE".equals(identifier) || "IN".equals(identifier) ||
+ "IS".equals(identifier) || "ESCAPE".equals(identifier)) {
+
+ throw new IllegalArgumentException("Identifier not allowed in JMS: '" + identifier + "'");
+ }
+ }
+
+ private void checkIdentifierIsntNullTrueFalse(String identifier) {
+ // Identifiers cannot be the names NULL, TRUE, and FALSE.
+ if ("NULL".equals(identifier) || "TRUE".equals(identifier) || "FALSE".equals(identifier)) {
+ throw new IllegalArgumentException("Identifier not allowed in JMS: '" + identifier + "'");
+ }
+ }
+
+ private void checkIdentifierLetterAndDigitRequirements(String identifier) {
+ // An identifier is an unlimited-length sequence of letters and digits, the first of
+ // which must be a letter. A letter is any character for which the method
+ // Character.isJavaLetter returns true. This includes '_' and '$'. A letter or digit
+ // is any character for which the method Character.isJavaLetterOrDigit returns true.
+ char startChar = identifier.charAt(0);
+ if (!(Character.isJavaIdentifierStart(startChar))) {
+ throw new IllegalArgumentException("Identifier does not begin with a valid JMS identifier start character: '" + identifier + "' ");
+ }
+
+ // JMS part character
+ int length = identifier.length();
+ for (int i = 1; i < length; i++) {
+ char ch = identifier.charAt(i);
+ if (!(Character.isJavaIdentifierPart(ch))) {
+ throw new IllegalArgumentException("Identifier contains invalid JMS identifier character '" + ch + "': '" + identifier + "' ");
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessageFactory.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessageFactory.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessageFactory.java
new file mode 100644
index 0000000..91c148c
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessageFactory.java
@@ -0,0 +1,133 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.qpid.jms.message;
+
+import java.io.Serializable;
+
+import javax.jms.JMSException;
+
+/**
+ * Interface that a Provider should implement to provide a Provider
+ * Specific JmsMessage implementation that optimizes the exchange of
+ * message properties and payload between the JMS Message API and the
+ * underlying Provider Message implementations.
+ */
+public interface JmsMessageFactory {
+
+ /**
+ * Creates an instance of a basic JmsMessage object. The provider may
+ * either create the Message with the default generic internal message
+ * implementation or create a Provider specific instance that optimizes
+ * the access and marshaling of the message.
+ *
+ * @return a newly created and initialized JmsMessage instance.
+ *
+ * @throws JMSException if the provider cannot create the message for some reason.
+ */
+ JmsMessage createMessage() throws JMSException;
+
+ /**
+ * Creates an instance of a basic JmsTextMessage object. The provider may
+ * either create the Message with the default generic internal message
+ * implementation or create a Provider specific instance that optimizes
+ * the access and marshaling of the message.
+ *
+ * @param payload
+ * The value to initially assign to the Message body, or null if empty to start.
+ *
+ * @returns a newly created and initialized JmsTextMessage instance.
+ *
+ * @throws JMSException if the provider cannot create the message for some reason.
+ */
+ JmsTextMessage createTextMessage(String payload) throws JMSException;
+
+ /**
+ * Creates an instance of a basic JmsTextMessage object. The provider may
+ * either create the Message with the default generic internal message
+ * implementation or create a Provider specific instance that optimizes
+ * the access and marshaling of the message.
+ *
+ * @returns a newly created and initialized JmsTextMessage instance.
+ *
+ * @throws JMSException if the provider cannot create the message for some reason.
+ */
+ JmsTextMessage createTextMessage() throws JMSException;
+
+ /**
+ * Creates an instance of a basic JmsBytesMessage object. The provider may
+ * either create the Message with the default generic internal message
+ * implementation or create a Provider specific instance that optimizes
+ * the access and marshaling of the message.
+ *
+ * @returns a newly created and initialized JmsTextMessage instance.
+ *
+ * @throws JMSException if the provider cannot create the message for some reason.
+ */
+ JmsBytesMessage createBytesMessage() throws JMSException;
+
+ /**
+ * Creates an instance of a basic JmsMapMessage object. The provider may
+ * either create the Message with the default generic internal message
+ * implementation or create a Provider specific instance that optimizes
+ * the access and marshaling of the message.
+ *
+ * @returns a newly created and initialized JmsTextMessage instance.
+ *
+ * @throws JMSException if the provider cannot create the message for some reason.
+ */
+ JmsMapMessage createMapMessage() throws JMSException;
+
+ /**
+ * Creates an instance of a basic JmsStreamMessage object. The provider may
+ * either create the Message with the default generic internal message
+ * implementation or create a Provider specific instance that optimizes
+ * the access and marshaling of the message.
+ *
+ * @returns a newly created and initialized JmsTextMessage instance.
+ *
+ * @throws JMSException if the provider cannot create the message for some reason.
+ */
+ JmsStreamMessage createStreamMessage() throws JMSException;
+
+ /**
+ * Creates an instance of a basic JmsObjectMessage object. The provider may
+ * either create the Message with the default generic internal message
+ * implementation or create a Provider specific instance that optimizes
+ * the access and marshaling of the message.
+ *
+ * @param payload
+ * The value to initially assign to the Message body, or null if empty to start.
+ *
+ * @returns a newly created and initialized JmsObjectMessage instance.
+ *
+ * @throws JMSException if the provider cannot create the message for some reason.
+ */
+ JmsObjectMessage createObjectMessage(Serializable payload) throws JMSException;
+
+ /**
+ * Creates an instance of a basic JmsObjectMessage object. The provider may
+ * either create the Message with the default generic internal message
+ * implementation or create a Provider specific instance that optimizes
+ * the access and marshaling of the message.
+ *
+ * @returns a newly created and initialized JmsObjectMessage instance.
+ *
+ * @throws JMSException if the provider cannot create the message for some reason.
+ */
+ JmsObjectMessage createObjectMessage() throws JMSException;
+
+}
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessagePropertyIntercepter.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessagePropertyIntercepter.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessagePropertyIntercepter.java
new file mode 100644
index 0000000..863f420
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessagePropertyIntercepter.java
@@ -0,0 +1,622 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.qpid.jms.message;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.jms.DeliveryMode;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+
+import org.apache.qpid.jms.JmsDestination;
+import org.apache.qpid.jms.exceptions.JmsExceptionSupport;
+import org.apache.qpid.jms.message.facade.JmsMessageFacade;
+import org.apache.qpid.jms.meta.JmsMessageId;
+import org.apache.qpid.jms.util.TypeConversionSupport;
+
+/**
+ * Utility class used to intercept calls to Message property gets and sets and map the
+ * correct fields in the underlying JmsMessageFacade to the property name being operated on.
+ */
+public class JmsMessagePropertyIntercepter {
+
+ private static final Map<String, PropertyIntercepter> PROPERTY_INTERCEPTERS =
+ new HashMap<String, PropertyIntercepter>();
+
+ /**
+ * Interface for a Property intercepter object used to write JMS style
+ * properties that are part of the JMS Message object members or perform
+ * some needed conversion action before some named property is read or
+ * written. If a property is not writable then the intercepter should
+ * throw an JMSException to indicate the error.
+ */
+ interface PropertyIntercepter {
+
+ /**
+ * Called when the names property is queried from an JMS Message object.
+ *
+ * @param message
+ * The message being acted upon.
+ *
+ * @return the correct property value from the given Message.
+ *
+ * @throws JMSException if an error occurs while accessing the property
+ */
+ Object getProperty(JmsMessageFacade message) throws JMSException;
+
+ /**
+ * Called when the names property is assigned from an JMS Message object.
+ *
+ * @param message
+ * The message instance being acted upon.
+ * @param value
+ * The value to assign to the intercepted property.
+ *
+ * @throws JMSException if an error occurs writing the property.
+ */
+ void setProperty(JmsMessageFacade message, Object value) throws JMSException;
+
+ /**
+ * Indicates if the intercepted property has a value currently assigned.
+ *
+ * @param message
+ * The message instance being acted upon.
+ *
+ * @return true if the intercepted property has a value assigned to it.
+ */
+ boolean propertyExists(JmsMessageFacade message);
+
+ }
+
+ static {
+ PROPERTY_INTERCEPTERS.put("JMSXDeliveryCount", new PropertyIntercepter() {
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ Integer rc = (Integer) TypeConversionSupport.convert(value, Integer.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSXDeliveryCount cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setRedeliveryCounter(rc.intValue() - 1);
+ }
+
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ return Integer.valueOf(message.getRedeliveryCounter() + 1);
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return true;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSDestination", new PropertyIntercepter() {
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ JmsDestination rc = (JmsDestination) TypeConversionSupport.convert(value, JmsDestination.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSDestination cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setDestination(rc);
+ }
+
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ Destination dest = message.getDestination();
+ if (dest == null) {
+ return null;
+ }
+ return dest.toString();
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return message.getDestination() != null;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSReplyTo", new PropertyIntercepter() {
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ JmsDestination rc = (JmsDestination) TypeConversionSupport.convert(value, JmsDestination.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSReplyTo cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setReplyTo(rc);
+ }
+
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ if (message.getReplyTo() == null) {
+ return null;
+ }
+ return message.getReplyTo().toString();
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return message.getReplyTo() != null;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSType", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ return message.getType();
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ String rc = (String) TypeConversionSupport.convert(value, String.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSType cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setType(rc);
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return message.getType() != null;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSDeliveryMode", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ return message.isPersistent() ? "PERSISTENT" : "NON_PERSISTENT";
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ Integer rc = null;
+ try {
+ rc = (Integer) TypeConversionSupport.convert(value, Integer.class);
+ } catch (NumberFormatException nfe) {
+ if (value instanceof String) {
+ if (((String) value).equalsIgnoreCase("PERSISTENT")) {
+ rc = DeliveryMode.PERSISTENT;
+ } else if (((String) value).equalsIgnoreCase("NON_PERSISTENT")) {
+ rc = DeliveryMode.NON_PERSISTENT;
+ } else {
+ throw nfe;
+ }
+ }
+ }
+ if (rc == null) {
+ Boolean bool = (Boolean) TypeConversionSupport.convert(value, Boolean.class);
+ if (bool == null) {
+ throw new JMSException("Property JMSDeliveryMode cannot be set from a " + value.getClass().getName() + ".");
+ } else {
+ message.setPersistent(bool.booleanValue());
+ }
+ } else {
+ message.setPersistent(rc == DeliveryMode.PERSISTENT);
+ }
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return true;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSPriority", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ return Integer.valueOf(message.getPriority());
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ Integer rc = (Integer) TypeConversionSupport.convert(value, Integer.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSPriority cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setPriority(rc.byteValue());
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return true;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSMessageID", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ if (message.getMessageId() == null) {
+ return null;
+ }
+ return message.getMessageId().toString();
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ String rc = (String) TypeConversionSupport.convert(value, String.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSMessageID cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setMessageId(new JmsMessageId(rc));
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return message.getMessageId() != null;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSTimestamp", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ return Long.valueOf(message.getTimestamp());
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ Long rc = (Long) TypeConversionSupport.convert(value, Long.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSTimestamp cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setTimestamp(rc.longValue());
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return true;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSCorrelationID", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ return message.getCorrelationId();
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ String rc = (String) TypeConversionSupport.convert(value, String.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSCorrelationID cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setCorrelationId(rc);
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return message.getCorrelationId() != null;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSExpiration", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ return Long.valueOf(message.getExpiration());
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ Long rc = (Long) TypeConversionSupport.convert(value, Long.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSExpiration cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setExpiration(rc.longValue());
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return true;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSRedelivered", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ return Boolean.valueOf(message.isRedelivered());
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ Boolean rc = (Boolean) TypeConversionSupport.convert(value, Boolean.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSRedelivered cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setRedelivered(rc.booleanValue());
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return true;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSXGroupID", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ return message.getGroupId();
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ String rc = (String) TypeConversionSupport.convert(value, String.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSXGroupID cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setGroupId(rc);
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return message.getGroupId() != null;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSXGroupSeq", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ return message.getGroupSequence();
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ Integer rc = (Integer) TypeConversionSupport.convert(value, Integer.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSXGroupSeq cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setGroupSequence(rc.intValue());
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return true;
+ }
+ });
+ PROPERTY_INTERCEPTERS.put("JMSXUserID", new PropertyIntercepter() {
+ @Override
+ public Object getProperty(JmsMessageFacade message) throws JMSException {
+ Object userId = message.getUserId();
+ if (userId == null) {
+ try {
+ userId = message.getProperty("JMSXUserID");
+ } catch (Exception e) {
+ throw JmsExceptionSupport.create(e);
+ }
+ }
+
+ return userId;
+ }
+
+ @Override
+ public void setProperty(JmsMessageFacade message, Object value) throws JMSException {
+ String rc = (String) TypeConversionSupport.convert(value, String.class);
+ if (rc == null) {
+ throw new JMSException("Property JMSXUserID cannot be set from a " + value.getClass().getName() + ".");
+ }
+ message.setUserId(rc);
+ }
+
+ @Override
+ public boolean propertyExists(JmsMessageFacade message) {
+ return message.getUserId() != null;
+ }
+ });
+ }
+
+ /**
+ * Static get method that takes a property name and gets the value either via
+ * a registered property get object or through the JmsMessageFacade getProperty
+ * method.
+ *
+ * @param message
+ * the JmsMessageFacade instance to read from
+ * @param name
+ * the property name that is being requested.
+ *
+ * @return the correct value either mapped to an Message attribute of a Message property.
+ *
+ * @throws JMSException if an error occurs while reading the defined property.
+ */
+ public static Object getProperty(JmsMessageFacade message, String name) throws JMSException {
+ Object value = null;
+
+ PropertyIntercepter jmsPropertyExpression = PROPERTY_INTERCEPTERS.get(name);
+ if (jmsPropertyExpression != null) {
+ value = jmsPropertyExpression.getProperty(message);
+ } else {
+ value = message.getProperty(name);
+ }
+
+ return value;
+ }
+
+ /**
+ * Static set method that takes a property name and sets the value either via
+ * a registered property set object or through the JmsMessageFacade setProperty
+ * method.
+ *
+ * @param message
+ * the JmsMessageFacade instance to write to.
+ * @param name
+ * the property name that is being written.
+ * @param value
+ * the new value to assign for the named property.
+ *
+ * @throws JMSException if an error occurs while writing the defined property.
+ */
+ public static void setProperty(JmsMessageFacade message, String name, Object value) throws JMSException {
+ PropertyIntercepter jmsPropertyExpression = PROPERTY_INTERCEPTERS.get(name);
+ if (jmsPropertyExpression != null) {
+ jmsPropertyExpression.setProperty(message, value);
+ } else {
+ message.setProperty(name, value);
+ }
+ }
+
+ /**
+ * Static inspection method to determine if a named property exists for a given message.
+ *
+ * @param message
+ * the JmsMessageFacade instance to read from
+ * @param name
+ * the property name that is being inspected.
+ *
+ * @return true if the message contains the given property.
+ *
+ * @throws JMSException if an error occurs while validating the defined property.
+ */
+ public static boolean propertyExists(JmsMessageFacade message, String name) throws JMSException {
+ PropertyIntercepter jmsPropertyExpression = PROPERTY_INTERCEPTERS.get(name);
+ if (jmsPropertyExpression != null) {
+ return jmsPropertyExpression.propertyExists(message);
+ } else {
+ return message.propertyExists(name);
+ }
+ }
+
+ /**
+ * For each of the currently configured message property intercepter instance a
+ * string key value is inserted into an Set and returned.
+ *
+ * @return a Set<String> containing the names of all intercepted properties.
+ */
+ public static Set<String> getAllPropertyNames() {
+ return PROPERTY_INTERCEPTERS.keySet();
+ }
+
+ /**
+ * For each of the currently configured message property intercepter instance a
+ * string key value is inserted into an Set and returned if the property has a
+ * value and is available for a read operation.
+ *
+ * @return a Set<String> containing the names of all intercepted properties with a value.
+ */
+ public static Set<String> getPropertyNames(JmsMessageFacade message) {
+ Set<String> names = new HashSet<String>();
+ for (Entry<String, PropertyIntercepter> entry : PROPERTY_INTERCEPTERS.entrySet()) {
+ if (entry.getValue().propertyExists(message)) {
+ names.add(entry.getKey());
+ }
+ }
+ return names;
+ }
+
+ /**
+ * Allows for the additional PropertyIntercepter instances to be added to the global set.
+ *
+ * @param propertyName
+ * The name of the Message property that will be intercepted.
+ * @param getter
+ * The PropertyIntercepter instance that should be used for the named property.
+ */
+ public static void addPropertySetter(String propertyName, PropertyIntercepter getter) {
+ PROPERTY_INTERCEPTERS.put(propertyName, getter);
+ }
+
+ /**
+ * Given a property name, remove the configured intercepter that has been assigned to
+ * intercept the queries for that property value.
+ *
+ * @param propertyName
+ * The name of the PropertyIntercepter to remove.
+ *
+ * @return true if a getter was removed from the global set.
+ */
+ public boolean removePropertySetter(String propertyName) {
+ if (PROPERTY_INTERCEPTERS.remove(propertyName) != null) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private final String name;
+ private final PropertyIntercepter jmsPropertyExpression;
+
+ /**
+ * Creates an new property getter instance that is assigned to read the named value.
+ *
+ * @param name
+ * the property value that this getter is assigned to lookup.
+ */
+ public JmsMessagePropertyIntercepter(String name) {
+ this.name = name;
+ this.jmsPropertyExpression = PROPERTY_INTERCEPTERS.get(name);
+ }
+
+ /**
+ * Gets the correct property value from the JmsMessageFacade instance based on
+ * the predefined property mappings.
+ *
+ * @param message
+ * the JmsMessageFacade whose property is being read.
+ *
+ * @return the correct value either mapped to an Message attribute of a Message property.
+ *
+ * @throws JMSException if an error occurs while reading the defined property.
+ */
+ public Object get(JmsMessageFacade message) throws JMSException {
+ if (jmsPropertyExpression != null) {
+ return jmsPropertyExpression.getProperty(message);
+ }
+
+ return message.getProperty(name);
+ }
+
+ /**
+ * Sets the correct property value from the JmsMessageFacade instance based on
+ * the predefined property mappings.
+ *
+ * @param message
+ * the JmsMessageFacade whose property is being read.
+ * @param value
+ * the value to be set on the intercepted JmsMessageFacade property.
+ *
+ * @throws JMSException if an error occurs while reading the defined property.
+ */
+ public void set(JmsMessageFacade message, Object value) throws JMSException {
+ if (jmsPropertyExpression != null) {
+ jmsPropertyExpression.setProperty(message, value);
+ } else {
+ message.setProperty(name, value);
+ }
+ }
+
+ /**
+ * @return the property name that is being intercepted for the JmsMessageFacade.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o == null || !this.getClass().equals(o.getClass())) {
+ return false;
+ }
+ return name.equals(((JmsMessagePropertyIntercepter) o).name);
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessageTransformation.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessageTransformation.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessageTransformation.java
new file mode 100644
index 0000000..404cabd
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsMessageTransformation.java
@@ -0,0 +1,198 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.qpid.jms.message;
+
+import java.util.Enumeration;
+
+import javax.jms.BytesMessage;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.MapMessage;
+import javax.jms.Message;
+import javax.jms.MessageEOFException;
+import javax.jms.ObjectMessage;
+import javax.jms.Queue;
+import javax.jms.StreamMessage;
+import javax.jms.TemporaryQueue;
+import javax.jms.TemporaryTopic;
+import javax.jms.TextMessage;
+import javax.jms.Topic;
+
+import org.apache.qpid.jms.JmsConnection;
+import org.apache.qpid.jms.JmsDestination;
+import org.apache.qpid.jms.JmsQueue;
+import org.apache.qpid.jms.JmsTemporaryQueue;
+import org.apache.qpid.jms.JmsTemporaryTopic;
+import org.apache.qpid.jms.JmsTopic;
+
+/**
+ * A helper class for converting normal JMS interfaces into the QpidJMS specific
+ * versions.
+ */
+public final class JmsMessageTransformation {
+
+ private JmsMessageTransformation() {
+ }
+
+ /**
+ * Creates a an available JMS message from another provider.
+ *
+ * @param destination
+ * - Destination to be converted into Jms's implementation.
+ * @return JmsDestination - Jms's implementation of the
+ * destination.
+ * @throws JMSException
+ * @throws JMSException
+ * if an error occurs
+ */
+ public static JmsDestination transformDestination(JmsConnection connection, Destination destination) throws JMSException {
+ JmsDestination result = null;
+
+ if (destination != null) {
+ if (destination instanceof JmsDestination) {
+ return (JmsDestination) destination;
+
+ } else {
+ if (destination instanceof TemporaryQueue) {
+ result = new JmsTemporaryQueue(((TemporaryQueue) destination).getQueueName());
+ } else if (destination instanceof TemporaryTopic) {
+ result = new JmsTemporaryTopic(((TemporaryTopic) destination).getTopicName());
+ } else if (destination instanceof Queue) {
+ result = new JmsQueue(((Queue) destination).getQueueName());
+ } else if (destination instanceof Topic) {
+ result = new JmsTopic(((Topic) destination).getTopicName());
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Creates a fast shallow copy of the current JmsMessage or creates a
+ * whole new message instance from an available JMS message from another
+ * provider.
+ *
+ * @param message
+ * - Message to be converted into Jms's implementation.
+ * @param connection
+ * @return JmsMessage - Jms's implementation object of the
+ * message.
+ * @throws JMSException
+ * if an error occurs
+ */
+ public static JmsMessage transformMessage(JmsConnection connection, Message message) throws JMSException {
+ if (message instanceof JmsMessage) {
+ return ((JmsMessage) message).copy();
+ } else {
+ JmsMessage activeMessage = null;
+ JmsMessageFactory factory = connection.getMessageFactory();
+
+ if (message instanceof BytesMessage) {
+ BytesMessage bytesMsg = (BytesMessage) message;
+ bytesMsg.reset();
+ JmsBytesMessage msg = factory.createBytesMessage();
+ try {
+ for (;;) {
+ // Reads a byte from the message stream until the stream
+ // is empty
+ msg.writeByte(bytesMsg.readByte());
+ }
+ } catch (MessageEOFException e) {
+ // if an end of message stream as expected
+ } catch (JMSException e) {
+ }
+
+ activeMessage = msg;
+ } else if (message instanceof MapMessage) {
+ MapMessage mapMsg = (MapMessage) message;
+ JmsMapMessage msg = factory.createMapMessage();
+ Enumeration<?> iter = mapMsg.getMapNames();
+
+ while (iter.hasMoreElements()) {
+ String name = iter.nextElement().toString();
+ msg.setObject(name, mapMsg.getObject(name));
+ }
+
+ activeMessage = msg;
+ } else if (message instanceof ObjectMessage) {
+ ObjectMessage objMsg = (ObjectMessage) message;
+ JmsObjectMessage msg = factory.createObjectMessage();
+ msg.setObject(objMsg.getObject());
+ activeMessage = msg;
+ } else if (message instanceof StreamMessage) {
+ StreamMessage streamMessage = (StreamMessage) message;
+ streamMessage.reset();
+ JmsStreamMessage msg = factory.createStreamMessage();
+ Object obj = null;
+
+ try {
+ while ((obj = streamMessage.readObject()) != null) {
+ msg.writeObject(obj);
+ }
+ } catch (MessageEOFException e) {
+ // if an end of message stream as expected
+ } catch (JMSException e) {
+ }
+
+ activeMessage = msg;
+ } else if (message instanceof TextMessage) {
+ TextMessage textMsg = (TextMessage) message;
+ JmsTextMessage msg = factory.createTextMessage();
+ msg.setText(textMsg.getText());
+ activeMessage = msg;
+ } else {
+ activeMessage = factory.createTextMessage();
+ }
+
+ copyProperties(connection, message, activeMessage);
+
+ return activeMessage;
+ }
+ }
+
+ /**
+ * Copies the standard JMS and user defined properties from the givem
+ * message to the specified message
+ *
+ * @param fromMessage
+ * the message to take the properties from
+ * @param toMessage
+ * the message to add the properties to
+ * @throws JMSException
+ */
+ public static void copyProperties(JmsConnection connection, Message fromMessage, Message toMessage) throws JMSException {
+ toMessage.setJMSMessageID(fromMessage.getJMSMessageID());
+ toMessage.setJMSCorrelationID(fromMessage.getJMSCorrelationID());
+ toMessage.setJMSReplyTo(transformDestination(connection, fromMessage.getJMSReplyTo()));
+ toMessage.setJMSDestination(transformDestination(connection, fromMessage.getJMSDestination()));
+ toMessage.setJMSDeliveryMode(fromMessage.getJMSDeliveryMode());
+ toMessage.setJMSRedelivered(fromMessage.getJMSRedelivered());
+ toMessage.setJMSType(fromMessage.getJMSType());
+ toMessage.setJMSExpiration(fromMessage.getJMSExpiration());
+ toMessage.setJMSPriority(fromMessage.getJMSPriority());
+ toMessage.setJMSTimestamp(fromMessage.getJMSTimestamp());
+
+ Enumeration<?> propertyNames = fromMessage.getPropertyNames();
+
+ while (propertyNames.hasMoreElements()) {
+ String name = propertyNames.nextElement().toString();
+ Object obj = fromMessage.getObjectProperty(name);
+ toMessage.setObjectProperty(name, obj);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsObjectMessage.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsObjectMessage.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsObjectMessage.java
new file mode 100644
index 0000000..e439764
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsObjectMessage.java
@@ -0,0 +1,111 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.qpid.jms.message;
+
+import java.io.Serializable;
+
+import javax.jms.JMSException;
+import javax.jms.MessageFormatException;
+import javax.jms.ObjectMessage;
+
+import org.apache.qpid.jms.message.facade.JmsObjectMessageFacade;
+
+/**
+ * An <CODE>ObjectMessage</CODE> object is used to send a message that contains a serializable
+ * object in the Java programming language ("Java object"). It inherits from the
+ * <CODE>Message</CODE> interface and adds a body containing a single reference to an object.
+ * Only <CODE>Serializable</CODE> Java objects can be used.
+ * <p/>
+ * <p/>
+ * If a collection of Java objects must be sent, one of the <CODE>Collection</CODE> classes
+ * provided since JDK 1.2 can be used.
+ * <p/>
+ * <p/>
+ * When a client receives an <CODE>ObjectMessage</CODE>, it is in read-only mode. If a client
+ * attempts to write to the message at this point, a <CODE>MessageNotWriteableException</CODE>
+ * is thrown. If <CODE>clearBody</CODE> is called, the message can now be both read from and
+ * written to.
+ *
+ * @see javax.jms.Session#createObjectMessage()
+ * @see javax.jms.Session#createObjectMessage(Serializable)
+ * @see javax.jms.BytesMessage
+ * @see javax.jms.MapMessage
+ * @see javax.jms.Message
+ * @see javax.jms.StreamMessage
+ * @see javax.jms.TextMessage
+ */
+public class JmsObjectMessage extends JmsMessage implements ObjectMessage {
+
+ private final JmsObjectMessageFacade facade;
+
+ public JmsObjectMessage(JmsObjectMessageFacade facade) {
+ super(facade);
+ this.facade = facade;
+ }
+
+ @Override
+ public JmsObjectMessage copy() throws JMSException {
+ JmsObjectMessage other = new JmsObjectMessage(facade.copy());
+ other.copy(this);
+ return other;
+ }
+
+ /**
+ * Sets the serializable object containing this message's data. It is important to note that
+ * an <CODE>ObjectMessage</CODE> contains a snapshot of the object at the time
+ * <CODE>setObject()</CODE> is called; subsequent modifications of the object will have no
+ * effect on the <CODE>ObjectMessage</CODE> body.
+ *
+ * @param newObject
+ * the message's data
+ * @throws JMSException
+ * if the JMS provider fails to set the object due to some internal error.
+ * @throws javax.jms.MessageFormatException
+ * if object serialization fails.
+ * @throws javax.jms.MessageNotWriteableException
+ * if the message is in read-only mode.
+ */
+ @Override
+ public void setObject(Serializable newObject) throws JMSException {
+ checkReadOnlyBody();
+ try {
+ this.facade.setObject(newObject);
+ } catch (Exception e) {
+ throw new MessageFormatException("Failed to serialize object");
+ }
+ }
+
+ /**
+ * Gets the serializable object containing this message's data. The default value is null.
+ *
+ * @return the serializable object containing this message's data
+ * @throws JMSException
+ */
+ @Override
+ public Serializable getObject() throws JMSException {
+ try {
+ return this.facade.getObject();
+ } catch (Exception e) {
+ throw new MessageFormatException("Failed to read object");
+ }
+ }
+
+ @Override
+ public String toString() {
+ return super.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsOutboundMessageDispatch.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsOutboundMessageDispatch.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsOutboundMessageDispatch.java
new file mode 100644
index 0000000..c77739b
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsOutboundMessageDispatch.java
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.qpid.jms.message;
+
+import org.apache.qpid.jms.JmsDestination;
+import org.apache.qpid.jms.meta.JmsProducerId;
+
+/**
+ * Envelope that wraps the objects involved in a Message send operation.
+ */
+public class JmsOutboundMessageDispatch {
+
+ private JmsProducerId producerId;
+ private JmsMessage message;
+ private JmsDestination destination;
+ private boolean sendAsync;
+
+ public JmsDestination getDestination() {
+ return destination;
+ }
+
+ public void setDestination(JmsDestination destination) {
+ this.destination = destination;
+ }
+
+ public JmsMessage getMessage() {
+ return message;
+ }
+
+ public void setMessage(JmsMessage message) {
+ this.message = message;
+ }
+
+ public JmsProducerId getProducerId() {
+ return producerId;
+ }
+
+ public void setProducerId(JmsProducerId producerId) {
+ this.producerId = producerId;
+ }
+
+ public void setSendAsync(boolean sendAsync) {
+ this.sendAsync = sendAsync;
+ }
+
+ public boolean isSendAsync() {
+ return sendAsync;
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsStreamMessage.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsStreamMessage.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsStreamMessage.java
new file mode 100644
index 0000000..bd4f0fe
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsStreamMessage.java
@@ -0,0 +1,485 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.qpid.jms.message;
+
+import javax.jms.JMSException;
+import javax.jms.MessageFormatException;
+import javax.jms.StreamMessage;
+
+import org.apache.qpid.jms.message.facade.JmsStreamMessageFacade;
+
+/**
+ * JMS Stream message implementation.
+ */
+public class JmsStreamMessage extends JmsMessage implements StreamMessage {
+
+ private static final int NO_BYTES_IN_FLIGHT = -1;
+
+ private final JmsStreamMessageFacade facade;
+
+ private byte[] bytes;
+ private int remainingBytes = NO_BYTES_IN_FLIGHT;
+
+ public JmsStreamMessage(JmsStreamMessageFacade facade) {
+ super(facade);
+ this.facade = facade;
+ }
+
+ @Override
+ public JmsStreamMessage copy() throws JMSException {
+ JmsStreamMessage other = new JmsStreamMessage(facade.copy());
+ other.copy(this);
+ return other;
+ }
+
+ @Override
+ public void onSend() throws JMSException {
+ super.onSend();
+ reset();
+ }
+
+ @Override
+ public void clearBody() throws JMSException {
+ super.clearBody();
+ bytes = null;
+ remainingBytes = -1;
+ }
+
+ @Override
+ public boolean readBoolean() throws JMSException {
+ checkWriteOnlyBody();
+ checkBytesInFlight();
+
+ Boolean result = null;
+ Object value;
+ value = facade.peek();
+
+ if (value instanceof Boolean) {
+ result = (Boolean) value;
+ } else if (value instanceof String || value == null) {
+ result = Boolean.valueOf((String) value);
+ } else {
+ throw new MessageFormatException(
+ "stream value: " + value.getClass().getSimpleName() + " cannot be converted to a boolean.");
+ }
+
+ facade.pop();
+ return result;
+ }
+
+ @Override
+ public byte readByte() throws JMSException {
+ checkWriteOnlyBody();
+ checkBytesInFlight();
+
+ Byte result = null;
+ Object value = facade.peek();
+
+ if (value instanceof Byte) {
+ result = (Byte) value;
+ } else if (value instanceof String || value == null) {
+ result = Byte.valueOf((String) value);
+ } else {
+ throw new MessageFormatException(
+ "stream value: " + value.getClass().getSimpleName() + " cannot be converted to a boolean.");
+ }
+
+ facade.pop();
+ return result;
+ }
+
+ @Override
+ public short readShort() throws JMSException {
+ checkWriteOnlyBody();
+ checkBytesInFlight();
+
+ Short result = null;
+ Object value = facade.peek();
+
+ if (value instanceof Short) {
+ result = (Short) value;
+ } else if (value instanceof Byte) {
+ result = ((Byte) value).shortValue();
+ } else if (value instanceof String || value == null) {
+ result = Short.valueOf((String) value);
+ } else {
+ throw new MessageFormatException(
+ "stream value: " + value.getClass().getSimpleName() + " cannot be converted to a boolean.");
+ }
+
+ facade.pop();
+ return result;
+ }
+
+ @Override
+ public char readChar() throws JMSException {
+ checkWriteOnlyBody();
+ checkBytesInFlight();
+
+ Character result = null;
+ Object value = facade.peek();
+
+ if (value instanceof Character) {
+ result = (Character) value;
+ } else if (value == null) {
+ throw new NullPointerException("Cannot convert NULL value to char.");
+ } else {
+ throw new MessageFormatException(
+ "stream value: " + value.getClass().getSimpleName() + " cannot be converted to a boolean.");
+ }
+
+ facade.pop();
+ return result;
+ }
+
+ @Override
+ public int readInt() throws JMSException {
+ checkWriteOnlyBody();
+ checkBytesInFlight();
+
+ Integer result = null;
+ Object value = facade.peek();
+
+ if (value instanceof Integer) {
+ result = (Integer) value;
+ } else if (value instanceof Short) {
+ result = ((Short) value).intValue();
+ } else if (value instanceof Byte) {
+ result = ((Byte) value).intValue();
+ } else if (value instanceof String || value == null) {
+ result = Integer.valueOf((String) value);
+ } else {
+ throw new MessageFormatException(
+ "stream value: " + value.getClass().getSimpleName() + " cannot be converted to a boolean.");
+ }
+
+ facade.pop();
+ return result;
+ }
+
+ @Override
+ public long readLong() throws JMSException {
+ checkWriteOnlyBody();
+ checkBytesInFlight();
+
+ Long result = null;
+ Object value = facade.peek();
+
+ if (value instanceof Long) {
+ result = (Long) value;
+ } else if (value instanceof Integer) {
+ result = ((Integer) value).longValue();
+ } else if (value instanceof Short) {
+ result = ((Short) value).longValue();
+ } else if (value instanceof Byte) {
+ result = ((Byte) value).longValue();
+ } else if (value instanceof String || value == null) {
+ result = Long.valueOf((String) value);
+ } else {
+ throw new MessageFormatException(
+ "stream value: " + value.getClass().getSimpleName() + " cannot be converted to a boolean.");
+ }
+
+ facade.pop();
+ return result;
+ }
+
+ @Override
+ public float readFloat() throws JMSException {
+ checkWriteOnlyBody();
+ checkBytesInFlight();
+
+ Float result = null;
+ Object value = facade.peek();
+
+ if (value instanceof Float) {
+ result = (Float) value;
+ } else if (value instanceof String || value == null) {
+ result = Float.valueOf((String) value);
+ } else {
+ throw new MessageFormatException(
+ "stream value: " + value.getClass().getSimpleName() + " cannot be converted to a boolean.");
+ }
+
+ facade.pop();
+ return result;
+ }
+
+ @Override
+ public double readDouble() throws JMSException {
+ checkWriteOnlyBody();
+ checkBytesInFlight();
+
+ Double result = null;
+ Object value = facade.peek();
+
+ if (value instanceof Double) {
+ result = (Double) value;
+ } else if (value instanceof Float) {
+ result = ((Float) value).doubleValue();
+ } else if (value instanceof String || value == null) {
+ result = Double.valueOf((String) value);
+ } else {
+ throw new MessageFormatException(
+ "stream value: " + value.getClass().getSimpleName() + " cannot be converted to a boolean.");
+ }
+
+ facade.pop();
+ return result;
+ }
+
+ @Override
+ public String readString() throws JMSException {
+ checkWriteOnlyBody();
+ checkBytesInFlight();
+
+ String result = null;
+ Object value = facade.peek();
+
+ if (value == null) {
+ result = null;
+ } else if (value instanceof String) {
+ result = (String) value;
+ } else if (value instanceof Float) {
+ result = value.toString();
+ } else if (value instanceof Double) {
+ result = value.toString();
+ } else if (value instanceof Long) {
+ result = value.toString();
+ } else if (value instanceof Integer) {
+ result = value.toString();
+ } else if (value instanceof Short) {
+ result = value.toString();
+ } else if (value instanceof Byte) {
+ result = value.toString();
+ } else if (value instanceof Boolean) {
+ result = value.toString();
+ } else if (value instanceof Character) {
+ result = value.toString();
+ } else {
+ throw new MessageFormatException("stream cannot convert byte array to String");
+ }
+
+ facade.pop();
+ return result;
+ }
+
+ @Override
+ public int readBytes(byte[] target) throws JMSException {
+ checkWriteOnlyBody();
+
+ if (target == null) {
+ throw new NullPointerException("target byte array was null");
+ }
+
+ if (remainingBytes == NO_BYTES_IN_FLIGHT) {
+ Object data = facade.peek();
+ if (data == null) {
+ facade.pop();
+ return -1;
+ } else if (!(data instanceof byte[])) {
+ throw new MessageFormatException("Next stream value is not a byte array");
+ }
+
+ bytes = (byte[]) data;
+ remainingBytes = bytes.length;
+ } else if (remainingBytes == 0) {
+ // We previously read all the bytes, but must have filled the destination array.
+ remainingBytes = NO_BYTES_IN_FLIGHT;
+ bytes = null;
+ facade.pop();
+ return -1;
+ }
+
+ int previouslyRead = bytes.length - remainingBytes;
+ int lengthToCopy = Math.min(target.length, remainingBytes);
+
+ if (lengthToCopy > 0) {
+ System.arraycopy(bytes, previouslyRead, target, 0, lengthToCopy);
+ }
+
+ remainingBytes -= lengthToCopy;
+
+ if (remainingBytes == 0 && lengthToCopy < target.length) {
+ // All bytes have been read and the destination array was not filled on this
+ // call, so the return will enable the caller to determine completion immediately.
+ remainingBytes = NO_BYTES_IN_FLIGHT;
+ bytes = null;
+ facade.pop();
+ }
+
+ return lengthToCopy;
+ }
+
+ @Override
+ public Object readObject() throws JMSException {
+ checkWriteOnlyBody();
+ checkBytesInFlight();
+
+ Object result = null;
+ Object value = facade.peek();
+
+ if (value == null) {
+ result = null;
+ } else if (value instanceof String) {
+ result = value;
+ } else if (value instanceof Float) {
+ result = value;
+ } else if (value instanceof Double) {
+ result = value;
+ } else if (value instanceof Long) {
+ result = value;
+ } else if (value instanceof Integer) {
+ result = value;
+ } else if (value instanceof Short) {
+ result = value;
+ } else if (value instanceof Byte) {
+ result = value;
+ } else if (value instanceof Boolean) {
+ result = value;
+ } else if (value instanceof Character) {
+ result = value;
+ } else if (value instanceof byte[]) {
+ byte[] original = (byte[]) value;
+ result = new byte[original.length];
+ System.arraycopy(original, 0, result, 0, original.length);
+ } else {
+ throw new MessageFormatException("Unknown type found in stream");
+ }
+
+ facade.pop();
+ return result;
+ }
+
+ @Override
+ public void writeBoolean(boolean value) throws JMSException {
+ checkReadOnlyBody();
+ facade.put(value);
+ }
+
+ @Override
+ public void writeByte(byte value) throws JMSException {
+ checkReadOnlyBody();
+ facade.put(value);
+ }
+
+ @Override
+ public void writeShort(short value) throws JMSException {
+ checkReadOnlyBody();
+ facade.put(value);
+ }
+
+ @Override
+ public void writeChar(char value) throws JMSException {
+ checkReadOnlyBody();
+ facade.put(value);
+ }
+
+ @Override
+ public void writeInt(int value) throws JMSException {
+ checkReadOnlyBody();
+ facade.put(value);
+ }
+
+ @Override
+ public void writeLong(long value) throws JMSException {
+ checkReadOnlyBody();
+ facade.put(value);
+ }
+
+ @Override
+ public void writeFloat(float value) throws JMSException {
+ checkReadOnlyBody();
+ facade.put(value);
+ }
+
+ @Override
+ public void writeDouble(double value) throws JMSException {
+ checkReadOnlyBody();
+ facade.put(value);
+ }
+
+ @Override
+ public void writeString(String value) throws JMSException {
+ checkReadOnlyBody();
+ facade.put(value);
+ }
+
+ @Override
+ public void writeBytes(byte[] value) throws JMSException {
+ writeBytes(value, 0, value.length);
+ }
+
+ @Override
+ public void writeBytes(byte[] value, int offset, int length) throws JMSException {
+ checkReadOnlyBody();
+ byte[] copy = new byte[length];
+ System.arraycopy(value, offset, copy, 0, length);
+ facade.put(copy);
+ }
+
+ @Override
+ public void writeObject(Object value) throws JMSException {
+ checkReadOnlyBody();
+ if (value == null) {
+ facade.put(null);
+ } else if (value instanceof String) {
+ facade.put(value);
+ } else if (value instanceof Character) {
+ facade.put(value);
+ } else if (value instanceof Boolean) {
+ facade.put(value);
+ } else if (value instanceof Byte) {
+ facade.put(value);
+ } else if (value instanceof Short) {
+ facade.put(value);
+ } else if (value instanceof Integer) {
+ facade.put(value);
+ } else if (value instanceof Long) {
+ facade.put(value);
+ } else if (value instanceof Float) {
+ facade.put(value);
+ } else if (value instanceof Double) {
+ facade.put(value);
+ } else if (value instanceof byte[]) {
+ writeBytes((byte[]) value);
+ } else {
+ throw new MessageFormatException("Unsupported Object type: " + value.getClass().getSimpleName());
+ }
+ }
+
+ @Override
+ public void reset() throws JMSException {
+ bytes = null;
+ remainingBytes = NO_BYTES_IN_FLIGHT;
+ setReadOnlyBody(true);
+ facade.reset();
+ }
+
+ @Override
+ public String toString() {
+ // TODO - Better toString()
+ return super.toString() + " JmsStreamMessage{ " + facade + " }";
+ }
+
+ private void checkBytesInFlight() throws MessageFormatException {
+ if (remainingBytes != NO_BYTES_IN_FLIGHT) {
+ throw new MessageFormatException(
+ "Partially read byte[] entry still being retrieved using readBytes(byte[] dest)");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/e4decdc1/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsTextMessage.java
----------------------------------------------------------------------
diff --git a/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsTextMessage.java b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsTextMessage.java
new file mode 100644
index 0000000..a08550e
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/message/JmsTextMessage.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.qpid.jms.message;
+
+import javax.jms.JMSException;
+import javax.jms.MessageNotWriteableException;
+import javax.jms.TextMessage;
+
+import org.apache.qpid.jms.message.facade.JmsTextMessageFacade;
+
+public class JmsTextMessage extends JmsMessage implements TextMessage {
+
+ private final JmsTextMessageFacade facade;
+
+ public JmsTextMessage(JmsTextMessageFacade facade) {
+ super(facade);
+ this.facade = facade;
+ }
+
+ @Override
+ public JmsTextMessage copy() throws JMSException {
+ JmsTextMessage other = new JmsTextMessage(facade.copy());
+ other.copy(this);
+ return other;
+ }
+
+ private void copy(JmsTextMessage other) throws JMSException {
+ super.copy(other);
+ }
+
+ @Override
+ public void setText(String text) throws JMSException, MessageNotWriteableException {
+ checkReadOnlyBody();
+ this.facade.setText(text);
+ }
+
+ @Override
+ public String getText() throws JMSException {
+ return facade.getText();
+ }
+
+ @Override
+ public String toString() {
+
+ String text = "";
+ try {
+ text = facade.getText();
+ } catch (JMSException e) {
+ }
+
+ // TODO - Better toString implementation
+ return super.toString() + ":text=" + text;
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org