/*
* Copyright 2005 Joe Walker
*
* Licensed 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.directwebremoting.jms;
import java.io.Serializable;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.TextMessage;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.directwebremoting.Hub;
import org.directwebremoting.event.MessageEvent;
/**
* An implementation of all the {@link Message} types rolled into one.
* This allows DWR to not know what type of Message the user wishes to work with
* and to make the decision at runtime depending on how they choose to cast us.
* @author Joe Walker [joe at getahead dot ltd dot uk]
*/
public class DwrMessage implements Message, MapMessage, TextMessage, ObjectMessage
{
/**
* Default ctor
*/
public DwrMessage()
{
}
/**
* Ctor for setting up a {@link TextMessage}
*/
public DwrMessage(String text)
{
setText(text);
}
/**
* Ctor for setting up an {@link ObjectMessage}
*/
public DwrMessage(Serializable object)
{
setObject(object);
}
/**
* Ctor for propagation from the DWR {@link Hub}.
*/
public DwrMessage(Hub hub, MessageEvent message)
{
setMessageEvent(hub, message);
}
/* (non-Javadoc)
* @see javax.jms.Message#acknowledge()
*/
public void acknowledge()
{
throw Unsupported.noManualAcknowledgment();
}
/* (non-Javadoc)
* @see javax.jms.Message#clearBody()
*/
public void clearBody()
{
throw new IllegalStateException("Can raw JMS messages have bodies?");
}
/* (non-Javadoc)
* @see javax.jms.Message#clearProperties()
*/
public void clearProperties()
{
properties.clear();
}
/* (non-Javadoc)
* @see javax.jms.Message#getPropertyNames()
*/
public Enumeration<String> getPropertyNames()
{
return Collections.enumeration(properties.keySet());
}
/* (non-Javadoc)
* @see javax.jms.Message#propertyExists(java.lang.String)
*/
public boolean propertyExists(String name)
{
return properties.containsKey(name);
}
/* (non-Javadoc)
* @see javax.jms.Message#getBooleanProperty(java.lang.String)
*/
public boolean getBooleanProperty(String name)
{
return Boolean.parseBoolean(getStringProperty(name));
}
/* (non-Javadoc)
* @see javax.jms.Message#getByteProperty(java.lang.String)
*/
public byte getByteProperty(String name)
{
return Byte.parseByte(getStringProperty(name));
}
/* (non-Javadoc)
* @see javax.jms.Message#getDoubleProperty(java.lang.String)
*/
public double getDoubleProperty(String name)
{
return Double.parseDouble(getStringProperty(name));
}
/* (non-Javadoc)
* @see javax.jms.Message#getFloatProperty(java.lang.String)
*/
public float getFloatProperty(String name)
{
return Float.parseFloat(getStringProperty(name));
}
/* (non-Javadoc)
* @see javax.jms.Message#getIntProperty(java.lang.String)
*/
public int getIntProperty(String name)
{
return Integer.parseInt(getStringProperty(name));
}
/* (non-Javadoc)
* @see javax.jms.Message#getLongProperty(java.lang.String)
*/
public long getLongProperty(String name)
{
return Long.parseLong(getStringProperty(name));
}
/* (non-Javadoc)
* @see javax.jms.Message#getObjectProperty(java.lang.String)
*/
public Object getObjectProperty(String name)
{
return properties.get(name);
}
/* (non-Javadoc)
* @see javax.jms.Message#getShortProperty(java.lang.String)
*/
public short getShortProperty(String name)
{
return Short.parseShort(getStringProperty(name));
}
/* (non-Javadoc)
* @see javax.jms.Message#getStringProperty(java.lang.String)
*/
public String getStringProperty(String name)
{
return properties.get(name).toString();
}
/* (non-Javadoc)
* @see javax.jms.Message#setBooleanProperty(java.lang.String, boolean)
*/
public void setBooleanProperty(String name, boolean value)
{
properties.put(name, value);
}
/* (non-Javadoc)
* @see javax.jms.Message#setByteProperty(java.lang.String, byte)
*/
public void setByteProperty(String name, byte value)
{
properties.put(name, value);
}
/* (non-Javadoc)
* @see javax.jms.Message#setDoubleProperty(java.lang.String, double)
*/
public void setDoubleProperty(String name, double value)
{
properties.put(name, value);
}
/* (non-Javadoc)
* @see javax.jms.Message#setFloatProperty(java.lang.String, float)
*/
public void setFloatProperty(String name, float value)
{
properties.put(name, value);
}
/* (non-Javadoc)
* @see javax.jms.Message#setIntProperty(java.lang.String, int)
*/
public void setIntProperty(String name, int value)
{
properties.put(name, value);
}
/* (non-Javadoc)
* @see javax.jms.Message#setLongProperty(java.lang.String, long)
*/
public void setLongProperty(String name, long value)
{
properties.put(name, value);
}
/* (non-Javadoc)
* @see javax.jms.Message#setObjectProperty(java.lang.String, java.lang.Object)
*/
public void setObjectProperty(String name, Object value)
{
properties.put(name, value);
}
/* (non-Javadoc)
* @see javax.jms.Message#setShortProperty(java.lang.String, short)
*/
public void setShortProperty(String name, short value)
{
properties.put(name, value);
}
/* (non-Javadoc)
* @see javax.jms.Message#setStringProperty(java.lang.String, java.lang.String)
*/
public void setStringProperty(String name, String value)
{
properties.put(name, value);
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSCorrelationID()
*/
public String getJMSCorrelationID()
{
return correlationId;
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSCorrelationIDAsBytes()
*/
public byte[] getJMSCorrelationIDAsBytes()
{
return correlationId.getBytes();
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSDeliveryMode()
*/
public int getJMSDeliveryMode()
{
return deliveryMode;
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSDestination()
*/
public Destination getJMSDestination()
{
return destination;
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSExpiration()
*/
public long getJMSExpiration()
{
return expiration;
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSMessageID()
*/
public String getJMSMessageID()
{
return messageId;
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSPriority()
*/
public int getJMSPriority()
{
return priority;
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSRedelivered()
*/
public boolean getJMSRedelivered()
{
return redelivered;
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSReplyTo()
*/
public Destination getJMSReplyTo()
{
return replyTo;
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSTimestamp()
*/
public long getJMSTimestamp()
{
return timestamp;
}
/* (non-Javadoc)
* @see javax.jms.Message#getJMSType()
*/
public String getJMSType()
{
return type;
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSCorrelationID(java.lang.String)
*/
public void setJMSCorrelationID(String correlationID)
{
this.correlationId = correlationID;
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSCorrelationIDAsBytes(byte[])
*/
public void setJMSCorrelationIDAsBytes(byte[] correlationID)
{
this.correlationId = new String(correlationID);
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSDeliveryMode(int)
*/
public void setJMSDeliveryMode(int deliveryMode)
{
this.deliveryMode = deliveryMode;
throw Unsupported.noTransactions();
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSDestination(javax.jms.Destination)
*/
public void setJMSDestination(Destination destination)
{
this.destination = destination;
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSExpiration(long)
*/
public void setJMSExpiration(long expiration)
{
this.expiration = expiration;
throw Unsupported.noMessageExpiry();
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSMessageID(java.lang.String)
*/
public void setJMSMessageID(String messageId)
{
this.messageId = messageId;
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSPriority(int)
*/
public void setJMSPriority(int priority)
{
this.priority = priority;
throw Unsupported.noMessagePriority();
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSRedelivered(boolean)
*/
public void setJMSRedelivered(boolean redelivered)
{
this.redelivered = redelivered;
throw Unsupported.noTransactions();
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSReplyTo(javax.jms.Destination)
*/
public void setJMSReplyTo(Destination replyTo)
{
this.replyTo = replyTo;
throw Unsupported.noPointToPoint();
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSTimestamp(long)
*/
public void setJMSTimestamp(long timestamp)
{
this.timestamp = timestamp;
}
/* (non-Javadoc)
* @see javax.jms.Message#setJMSType(java.lang.String)
*/
public void setJMSType(String type)
{
this.type = type;
}
/**
* Holds a reference to a message that we are replying/referring to
*/
private String correlationId;
/**
* @see DeliveryMode
*/
private int deliveryMode;
/**
* The topic or queue that we are destined for
*/
private Destination destination;
/**
* How long until this message expires
*/
private long expiration;
/**
* All JMS messages need a unique id
*/
private String messageId;
/**
* @see Message#setJMSPriority(int)
*/
private int priority;
/**
* Perhaps we will support this when we support Gears?
*/
private boolean redelivered;
/**
* The topic or queue that message replies should be sent to
*/
private Destination replyTo;
/**
* @see Message#setJMSTimestamp(long)
*/
private long timestamp;
/**
* @see Message#setJMSType(String)
*/
private String type;
/**
* The hash of properties assigned to this message
*/
private Map<String, Object> properties = new HashMap<String, Object>();
// The methods from MapMessage
/* (non-Javadoc)
* @see javax.jms.MapMessage#getMapNames()
*/
public Enumeration<String> getMapNames()
{
return Collections.enumeration(map.keySet());
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#itemExists(java.lang.String)
*/
public boolean itemExists(String name)
{
return map.containsKey(name);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getBoolean(java.lang.String)
*/
public boolean getBoolean(String name)
{
return Boolean.parseBoolean(getString(name));
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getByte(java.lang.String)
*/
public byte getByte(String name)
{
return Byte.parseByte(getString(name));
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getBytes(java.lang.String)
*/
public byte[] getBytes(String name)
{
return getString(name).getBytes();
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getChar(java.lang.String)
*/
public char getChar(String name)
{
return getString(name).charAt(0);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getDouble(java.lang.String)
*/
public double getDouble(String name)
{
return Double.parseDouble(getString(name));
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getFloat(java.lang.String)
*/
public float getFloat(String name)
{
return Float.parseFloat(getString(name));
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getInt(java.lang.String)
*/
public int getInt(String name)
{
return Integer.parseInt(getString(name));
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getLong(java.lang.String)
*/
public long getLong(String name)
{
return Long.parseLong(getString(name));
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getShort(java.lang.String)
*/
public short getShort(String name)
{
return Short.parseShort(getString(name));
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getString(java.lang.String)
*/
public String getString(String name)
{
return getObject(name).toString();
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#getObject(java.lang.String)
*/
@SuppressWarnings("unchecked")
public Object getObject(String name)
{
switch (source)
{
case MAP:
return map.get(name);
case MESSAGE_EVENT:
return message.getData(Map.class);
case NONE:
return "";
case SERIALIZABLE:
return ((Map<String, Object>) object).get(name);
case TEXT:
return "";
default:
return "";
}
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setBoolean(java.lang.String, boolean)
*/
public void setBoolean(String name, boolean value)
{
map.put(name, value);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setByte(java.lang.String, byte)
*/
public void setByte(String name, byte value)
{
map.put(name, value);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setBytes(java.lang.String, byte[])
*/
public void setBytes(String name, byte[] value)
{
map.put(name, value);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setBytes(java.lang.String, byte[], int, int)
*/
public void setBytes(String name, byte[] value, int offset, int length)
{
byte[] data = new byte[length];
System.arraycopy(data, 0, value, offset, length);
map.put(name, data);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setChar(java.lang.String, char)
*/
public void setChar(String name, char value)
{
map.put(name, value);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setDouble(java.lang.String, double)
*/
public void setDouble(String name, double value)
{
map.put(name, value);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setFloat(java.lang.String, float)
*/
public void setFloat(String name, float value)
{
map.put(name, value);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setInt(java.lang.String, int)
*/
public void setInt(String name, int value)
{
map.put(name, value);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setLong(java.lang.String, long)
*/
public void setLong(String name, long value)
{
map.put(name, value);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setObject(java.lang.String, java.lang.Object)
*/
public void setObject(String name, Object value)
{
map.put(name, value);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setShort(java.lang.String, short)
*/
public void setShort(String name, short value)
{
map.put(name, value);
setSource(Source.MAP);
}
/* (non-Javadoc)
* @see javax.jms.MapMessage#setString(java.lang.String, java.lang.String)
*/
public void setString(String name, String value)
{
map.put(name, value);
setSource(Source.MAP);
}
// The methods from TextMessage
/* (non-Javadoc)
* @see javax.jms.TextMessage#getText()
*/
public String getText()
{
switch (source)
{
case MAP:
return null;
case MESSAGE_EVENT:
return message.getData(String.class);
case NONE:
return null;
case SERIALIZABLE:
return object.toString();
case TEXT:
return text;
default:
return null;
}
}
/* (non-Javadoc)
* @see javax.jms.TextMessage#setText(java.lang.String)
*/
public void setText(String text)
{
this.text = text;
setSource(Source.TEXT);
}
// The methods from ObjectMessage
/* (non-Javadoc)
* @see javax.jms.ObjectMessage#getObject()
*/
public Serializable getObject()
{
switch (source)
{
case MAP:
return null;
case MESSAGE_EVENT:
return (Serializable) message.getRawData();
case NONE:
return null;
case SERIALIZABLE:
return object;
case TEXT:
return text;
default:
return null;
}
}
/* (non-Javadoc)
* @see javax.jms.ObjectMessage#setObject(java.io.Serializable)
*/
public void setObject(Serializable object)
{
this.object = object;
setSource(Source.SERIALIZABLE);
}
/**
* @param hub
* @param message
*/
private void setMessageEvent(Hub hub, MessageEvent message)
{
this.hub = hub;
this.message = message;
setSource(Source.MESSAGE_EVENT);
}
/**
* We might want to warn people about gratuitous source type changes
*/
private void setSource(Source source)
{
if (this.source != null && this.source != source)
{
log.warn("Changing source of message from " + this.source + " to " + source);
}
this.source = source;
}
/**
* Where did the data for this message come from?
*/
enum Source
{
/**
* Use by the DWR Hub. Data is stored in hub and message
* @see #hub
* @see #message
*/
MESSAGE_EVENT,
/**
* There is no data, we have to assume headers only
*/
NONE,
/**
* Data is stored in text
* @see #text
*/
TEXT,
/**
* Data is stored in the map
* @see #map
*/
MAP,
/**
* Data is stored in the serializable object
* @see #object
*/
SERIALIZABLE,
/**
* Streamed data is not supported yet
*/
// STREAM,
/**
* Binary data is not supported yet
*/
// BYTES,
}
/**
* What is the current source of our data
*/
protected Source source = null;
/**
* The object that we are wrapping
*/
protected Serializable object;
/**
* The message passed over JMS
*/
protected String text;
/**
* The map of contained objects
*/
protected Map<String, Object> map = new HashMap<String, Object>();
/**
* The Hub for when data is received from the client
*/
protected Hub hub;
/**
* The message straight out of the hub
*/
protected MessageEvent message;
/**
* The log stream
*/
private static final Log log = LogFactory.getLog(DwrMessage.class);
}