blob: c608f737e39a35f0f7f1fc6be56fb9253b1df054 [file] [log] [blame]
/*
* 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.client.message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.qpid.QpidException;
import org.apache.qpid.client.util.JMSExceptionHelper;
import org.apache.qpid.transport.codec.BBDecoder;
import org.apache.qpid.transport.codec.BBEncoder;
import javax.jms.JMSException;
import javax.jms.MessageFormatException;
import javax.jms.MessageEOFException;
import java.lang.NumberFormatException;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class AMQPEncodedListMessage extends JMSStreamMessage implements
org.apache.qpid.jms.ListMessage, javax.jms.MapMessage
{
private static final Logger _logger = LoggerFactory
.getLogger(AMQPEncodedListMessage.class);
public static final String MIME_TYPE = "amqp/list";
private List<Object> _list = new ArrayList<Object>();
public AMQPEncodedListMessage(AMQMessageDelegateFactory delegateFactory) throws JMSException
{
super(delegateFactory);
currentIndex = 0;
}
AMQPEncodedListMessage(AMQMessageDelegate delegate, ByteBuffer data)
throws QpidException
{
super(delegate, data);
if (data != null)
{
try
{
populateListFromData(data);
}
catch (JMSException je)
{
throw new QpidException("Error populating ListMessage from ByteBuffer", je);
}
}
currentIndex = 0;
}
public String toBodyString() throws JMSException
{
return _list == null ? "" : _list.toString();
}
protected String getMimeType()
{
return MIME_TYPE;
}
/* ListMessage Implementation. */
public boolean add(Object a) throws JMSException
{
checkWritable();
checkAllowedValue(a);
try
{
return _list.add(a);
}
catch (Exception e)
{
throw JMSExceptionHelper.chainJMSException(new MessageFormatException("Error adding to ListMessage"), e);
}
}
public void add(int index, Object element) throws JMSException
{
checkWritable();
checkAllowedValue(element);
try
{
_list.add(index, element);
}
catch (Exception e)
{
throw JMSExceptionHelper.chainJMSException(new MessageFormatException("Error adding to ListMessage at "
+ index), e);
}
}
public boolean contains(Object o) throws JMSException
{
try
{
return _list.contains(o);
}
catch (Exception e)
{
throw JMSExceptionHelper.chainJMSException(new JMSException("Error when looking up object"), e);
}
}
public Object get(int index) throws JMSException
{
try
{
return _list.get(index);
}
catch (IndexOutOfBoundsException e)
{
throw JMSExceptionHelper.chainJMSException(new MessageFormatException(
"Error getting ListMessage element at " + index), e);
}
}
public int indexOf(Object o)
{
return _list.indexOf(o);
}
public Iterator iterator()
{
return _list.iterator();
}
public Object remove(int index) throws JMSException
{
checkWritable();
try
{
return _list.remove(index);
}
catch (IndexOutOfBoundsException e)
{
throw JMSExceptionHelper.chainJMSException(new MessageFormatException(
"Error removing ListMessage element at " + index), e);
}
}
public boolean remove(Object o) throws JMSException
{
checkWritable();
return _list.remove(o);
}
public Object set(int index, Object element) throws JMSException
{
checkWritable();
checkAllowedValue(element);
try
{
return _list.set(index, element);
}
catch (Exception e)
{
throw JMSExceptionHelper.chainJMSException(new MessageFormatException(
"Error setting ListMessage element at " + index), e);
}
}
public int size()
{
return _list.size();
}
public Object[] toArray()
{
return _list.toArray();
}
/* MapMessage Implementation */
private boolean isValidIndex(int index)
{
if (index >= 0 && index < size())
return true;
return false;
}
private int getValidIndex(String indexStr) throws JMSException
{
if ((indexStr == null) || indexStr.equals(""))
{
throw new IllegalArgumentException(
"Property name cannot be null, or the empty String.");
}
int index = 0;
try
{
index = Integer.parseInt(indexStr);
}
catch (NumberFormatException e)
{
throw JMSExceptionHelper.chainJMSException(new JMSException("Invalid index string"), e);
}
if (isValidIndex(index))
return index;
throw new MessageFormatException("Property " + indexStr
+ " should be a valid index into the list of size " + size());
}
private void setGenericForMap(String propName, Object o)
throws JMSException
{
checkWritable();
int index = 0;
try
{
index = Integer.parseInt(propName);
}
catch (NumberFormatException e)
{
throw JMSExceptionHelper.chainJMSException(new JMSException("The property name should be a valid index"),
e);
}
if (isValidIndex(index))
remove(index);
add(index, o);
}
public boolean getBoolean(String propName) throws JMSException
{
return getBooleanImpl(getValidIndex(propName));
}
public byte getByte(String propName) throws JMSException
{
return getByteImpl(getValidIndex(propName));
}
public short getShort(String propName) throws JMSException
{
return getShortImpl(getValidIndex(propName));
}
public int getInt(String propName) throws JMSException
{
return getIntImpl(getValidIndex(propName));
}
public long getLong(String propName) throws JMSException
{
return getLongImpl(getValidIndex(propName));
}
public char getChar(String propName) throws JMSException
{
return getCharImpl(getValidIndex(propName));
}
public float getFloat(String propName) throws JMSException
{
return getFloatImpl(getValidIndex(propName));
}
public double getDouble(String propName) throws JMSException
{
return getDoubleImpl(getValidIndex(propName));
}
public String getString(String propName) throws JMSException
{
return getStringImpl(getValidIndex(propName));
}
public byte[] getBytes(String propName) throws JMSException
{
return getBytesImpl(getValidIndex(propName));
}
public Object getObject(String propName) throws JMSException
{
return get(getValidIndex(propName));
}
public Enumeration getMapNames() throws JMSException
{
List<String> names = new ArrayList<String>();
int i = 0;
while (i < size())
names.add(Integer.toString(i++));
return Collections.enumeration(names);
}
public void setBoolean(String propName, boolean b) throws JMSException
{
setGenericForMap(propName, b);
}
public void setByte(String propName, byte b) throws JMSException
{
setGenericForMap(propName, b);
}
public void setShort(String propName, short i) throws JMSException
{
setGenericForMap(propName, i);
}
public void setChar(String propName, char c) throws JMSException
{
setGenericForMap(propName, c);
}
public void setInt(String propName, int i) throws JMSException
{
setGenericForMap(propName, i);
}
public void setLong(String propName, long l) throws JMSException
{
setGenericForMap(propName, l);
}
public void setFloat(String propName, float v) throws JMSException
{
setGenericForMap(propName, v);
}
public void setDouble(String propName, double v) throws JMSException
{
setGenericForMap(propName, v);
}
public void setString(String propName, String string1) throws JMSException
{
setGenericForMap(propName, string1);
}
public void setBytes(String propName, byte[] bytes) throws JMSException
{
setGenericForMap(propName, bytes);
}
public void setBytes(String propName, byte[] bytes, int offset, int length)
throws JMSException
{
if ((offset == 0) && (length == bytes.length))
{
setBytes(propName, bytes);
}
else
{
byte[] newBytes = new byte[length];
System.arraycopy(bytes, offset, newBytes, 0, length);
setBytes(propName, newBytes);
}
}
public void setObject(String propName, Object value) throws JMSException
{
checkAllowedValue(value);
setGenericForMap(propName, value);
}
public boolean itemExists(String propName) throws JMSException
{
return isValidIndex(Integer.parseInt(propName));
}
// StreamMessage methods
private int currentIndex;
private static final String MESSAGE_EOF_EXCEPTION = "End of Stream (ListMessage) at index: ";
private void setGenericForStream(Object o) throws JMSException
{
checkWritable();
add(o);
currentIndex++;
}
@Override
public boolean readBoolean() throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
return getBooleanImpl(currentIndex++);
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public byte readByte() throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
return getByteImpl(currentIndex++);
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public int readBytes(byte[] value) throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
{
ByteBuffer res = ByteBuffer.wrap(getBytesImpl(currentIndex++));
res.get(value);
return value.length;
}
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public char readChar() throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
return getCharImpl(currentIndex++);
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public double readDouble() throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
return getDoubleImpl(currentIndex++);
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public float readFloat() throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
return getFloatImpl(currentIndex++);
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public int readInt() throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
return getIntImpl(currentIndex++);
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public long readLong() throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
return getLongImpl(currentIndex++);
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public Object readObject() throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
return get(currentIndex++);
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public short readShort() throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
return getShortImpl(currentIndex++);
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public String readString() throws JMSException
{
checkReadable();
if (isValidIndex(currentIndex))
return getStringImpl(currentIndex++);
throw new MessageEOFException(MESSAGE_EOF_EXCEPTION + currentIndex);
}
@Override
public void writeBoolean(boolean value) throws JMSException
{
setGenericForStream(value);
}
@Override
public void writeByte(byte value) throws JMSException
{
setGenericForStream(value);
}
@Override
public void writeBytes(byte[] value) throws JMSException
{
setGenericForStream(value);
}
@Override
public void writeBytes(byte[] value, int offset, int length)
throws JMSException
{
setGenericForStream(value);
}
@Override
public void writeChar(char value) throws JMSException
{
setGenericForStream(value);
}
@Override
public void writeDouble(double value) throws JMSException
{
setGenericForStream(value);
}
@Override
public void writeFloat(float value) throws JMSException
{
setGenericForStream(value);
}
@Override
public void writeInt(int value) throws JMSException
{
setGenericForStream(value);
}
@Override
public void writeLong(long value) throws JMSException
{
setGenericForStream(value);
}
@Override
public void writeObject(Object value) throws JMSException
{
checkAllowedValue(value);
setGenericForStream(value);
}
@Override
public void writeShort(short value) throws JMSException
{
setGenericForStream(value);
}
@Override
public void writeString(String value) throws JMSException
{
setGenericForStream(value);
}
// Common methods
private void checkAllowedValue(Object value) throws MessageFormatException
{
if (((value instanceof Boolean) || (value instanceof Byte)
|| (value instanceof Short) || (value instanceof Integer)
|| (value instanceof Long) || (value instanceof Character)
|| (value instanceof Float) || (value instanceof Double)
|| (value instanceof String) || (value instanceof byte[])
|| (value instanceof List) || (value instanceof Map)
|| (value instanceof UUID) || (value == null)) == false)
{
throw new MessageFormatException("Invalid value " + value
+ "of type " + value.getClass().getName() + ".");
}
}
@Override
public void reset()
{
currentIndex = 0;
setReadable(true);
}
@Override
public void clearBody() throws JMSException
{
super.clearBody();
_list.clear();
currentIndex = 0;
setReadable(false);
}
private boolean getBooleanImpl(int index) throws JMSException
{
Object value = get(index);
if (value instanceof Boolean)
{
return ((Boolean) value).booleanValue();
}
else if ((value instanceof String) || (value == null))
{
try
{
return Boolean.valueOf((String) value);
}
catch (NumberFormatException e)
{
// FALLTHROUGH to exception
}
}
throw new MessageFormatException("Property at " + index + " of type "
+ value.getClass().getName()
+ " cannot be converted to boolean.");
}
private byte getByteImpl(int index) throws JMSException
{
Object value = get(index);
if (value instanceof Byte)
{
return ((Byte) value).byteValue();
}
else if ((value instanceof String) || (value == null))
{
try
{
return Byte.valueOf((String) value).byteValue();
} catch (NumberFormatException e)
{
// FALLTHROUGH to exception
}
}
throw new MessageFormatException("Property at " + index + " of type "
+ value.getClass().getName() + " cannot be converted to byte.");
}
private short getShortImpl(int index) throws JMSException
{
Object value = get(index);
if (value instanceof Short)
{
return ((Short) value).shortValue();
}
else if (value instanceof Byte)
{
return ((Byte) value).shortValue();
}
else if ((value instanceof String) || (value == null))
{
try
{
return Short.valueOf((String) value).shortValue();
} catch (NumberFormatException e)
{
// FALLTHROUGH to exception
}
}
throw new MessageFormatException("Property at " + index + " of type "
+ value.getClass().getName() + " cannot be converted to short.");
}
private int getIntImpl(int index) throws JMSException
{
Object value = get(index);
if (value instanceof Integer)
{
return ((Integer) value).intValue();
}
if (value instanceof Short)
{
return ((Short) value).intValue();
}
if (value instanceof Byte)
{
return ((Byte) value).intValue();
}
if ((value instanceof String) || (value == null))
{
try
{
return Integer.valueOf((String) value).intValue();
}
catch (NumberFormatException e)
{
// FALLTHROUGH to exception
}
}
throw new MessageFormatException("Property at " + index + " of type "
+ value.getClass().getName() + " cannot be converted to int.");
}
private long getLongImpl(int index) throws JMSException
{
Object value = get(index);
if (value instanceof Long)
{
return ((Long) value).longValue();
} else if (value instanceof Integer)
{
return ((Integer) value).longValue();
}
if (value instanceof Short)
{
return ((Short) value).longValue();
}
if (value instanceof Byte)
{
return ((Byte) value).longValue();
} else if ((value instanceof String) || (value == null))
{
try
{
return Long.valueOf((String) value).longValue();
} catch (NumberFormatException e)
{
// FALLTHROUGH to exception
}
}
throw new MessageFormatException("Property at " + index + " of type "
+ value.getClass().getName() + " cannot be converted to long.");
}
private char getCharImpl(int index) throws JMSException
{
Object value = get(index);
if (value instanceof Character)
{
return ((Character) value).charValue();
} else if (value == null)
{
throw new NullPointerException("Property at " + index
+ " has null value and therefore cannot "
+ "be converted to char.");
} else
{
throw new MessageFormatException("Property at " + index
+ " of type " + value.getClass().getName()
+ " cannot be converted to a char.");
}
}
private float getFloatImpl(int index) throws JMSException
{
Object value = get(index);
if (value instanceof Float)
{
return ((Float) value).floatValue();
}
else if ((value instanceof String) || (value == null))
{
try
{
return Float.valueOf((String) value).floatValue();
}
catch (NumberFormatException e)
{
// FALLTHROUGH to exception
}
}
throw new MessageFormatException("Property at " + index + " of type "
+ value.getClass().getName() + " cannot be converted to float.");
}
private double getDoubleImpl(int index) throws JMSException
{
Object value = get(index);
if (value instanceof Double)
{
return ((Double) value).doubleValue();
}
else if (value instanceof Float)
{
return ((Float) value).doubleValue();
}
else if ((value instanceof String) || (value == null))
{
try
{
return Double.valueOf((String) value).doubleValue();
}
catch (NumberFormatException e)
{
// FALLTHROUGH to exception
}
}
throw new MessageFormatException("Property at " + index + " of type "
+ value.getClass().getName()
+ " cannot be converted to double.");
}
private String getStringImpl(int index) throws JMSException
{
Object value = get(index);
if ((value instanceof String) || (value == null))
{
return (String) value;
} else if (value instanceof byte[])
{
throw new MessageFormatException("Property at " + index
+ " of type byte[] " + "cannot be converted to String.");
} else
{
return value.toString();
}
}
private byte[] getBytesImpl(int index) throws JMSException
{
Object value = get(index);
if ((value instanceof byte[]) || (value == null))
{
return (byte[]) value;
}
else
{
throw new MessageFormatException("Property at " + index
+ " of type " + value.getClass().getName()
+ " cannot be converted to byte[].");
}
}
protected void populateListFromData(ByteBuffer data) throws JMSException
{
if (data != null)
{
data.rewind();
BBDecoder decoder = new BBDecoder();
decoder.init(data);
_list = decoder.readList();
}
else
{
_list.clear();
}
}
public ByteBuffer getData() throws JMSException
{
BBEncoder encoder = new BBEncoder(1024);
encoder.writeList(_list);
return encoder.segment();
}
public void setList(List<Object> l)
{
_list = l;
}
public List<Object> asList()
{
return _list;
}
}