blob: dd68f6ad819be02689e79c044370a051416c7e0a [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.proton.codec;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.Decimal128;
import org.apache.qpid.proton.amqp.Decimal32;
import org.apache.qpid.proton.amqp.Decimal64;
import org.apache.qpid.proton.amqp.DescribedType;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.UnsignedByte;
import org.apache.qpid.proton.amqp.UnsignedInteger;
import org.apache.qpid.proton.amqp.UnsignedLong;
import org.apache.qpid.proton.amqp.UnsignedShort;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.util.*;
public class DecoderImpl implements ByteBufferDecoder
{
private ByteBuffer _buffer;
private PrimitiveTypeEncoding[] _constructors = new PrimitiveTypeEncoding[256];
private Map<Object, DescribedTypeConstructor> _dynamicTypeConstructors =
new HashMap<Object, DescribedTypeConstructor>();
public DecoderImpl()
{
}
DecoderImpl(final ByteBuffer buffer)
{
_buffer = buffer;
}
TypeConstructor readConstructor()
{
int code = ((int)readRawByte()) & 0xff;
if(code == EncodingCodes.DESCRIBED_TYPE_INDICATOR)
{
final Object descriptor = readObject();
TypeConstructor nestedEncoding = readConstructor();
DescribedTypeConstructor dtc = _dynamicTypeConstructors.get(descriptor);
if(dtc == null)
{
dtc = new DescribedTypeConstructor()
{
public DescribedType newInstance(final Object described)
{
return new UnknownDescribedType(descriptor, described);
}
public Class getTypeClass()
{
return UnknownDescribedType.class;
}
};
register(descriptor, dtc);
}
return new DynamicTypeConstructor(dtc, nestedEncoding);
}
else
{
return _constructors[code];
}
}
public void register(final Object descriptor, final DescribedTypeConstructor dtc)
{
_dynamicTypeConstructors.put(descriptor, dtc);
}
private ClassCastException unexpectedType(final Object val, Class clazz)
{
return new ClassCastException("Unexpected type "
+ val.getClass().getName()
+ ". Expected "
+ clazz.getName() +".");
}
public Boolean readBoolean()
{
return readBoolean(null);
}
public Boolean readBoolean(final Boolean defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof Boolean)
{
return (Boolean) val;
}
throw unexpectedType(val, Boolean.class);
}
public boolean readBoolean(final boolean defaultVal)
{
TypeConstructor constructor = readConstructor();
if(constructor instanceof BooleanType.BooleanEncoding)
{
return ((BooleanType.BooleanEncoding)constructor).readPrimitiveValue();
}
else
{
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else
{
throw unexpectedType(val, Boolean.class);
}
}
}
public Byte readByte()
{
return readByte(null);
}
public Byte readByte(final Byte defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof Byte)
{
return (Byte) val;
}
throw unexpectedType(val, Byte.class);
}
public byte readByte(final byte defaultVal)
{
TypeConstructor constructor = readConstructor();
if(constructor instanceof ByteType.ByteEncoding)
{
return ((ByteType.ByteEncoding)constructor).readPrimitiveValue();
}
else
{
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else
{
throw unexpectedType(val, Byte.class);
}
}
}
public Short readShort()
{
return readShort(null);
}
public Short readShort(final Short defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof Short)
{
return (Short) val;
}
throw unexpectedType(val, Short.class);
}
public short readShort(final short defaultVal)
{
TypeConstructor constructor = readConstructor();
if(constructor instanceof ShortType.ShortEncoding)
{
return ((ShortType.ShortEncoding)constructor).readPrimitiveValue();
}
else
{
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else
{
throw unexpectedType(val, Short.class);
}
}
}
public Integer readInteger()
{
return readInteger(null);
}
public Integer readInteger(final Integer defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof Integer)
{
return (Integer) val;
}
throw unexpectedType(val, Integer.class);
}
public int readInteger(final int defaultVal)
{
TypeConstructor constructor = readConstructor();
if(constructor instanceof IntegerType.IntegerEncoding)
{
return ((IntegerType.IntegerEncoding)constructor).readPrimitiveValue();
}
else
{
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else
{
throw unexpectedType(val, Integer.class);
}
}
}
public Long readLong()
{
return readLong(null);
}
public Long readLong(final Long defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof Long)
{
return (Long) val;
}
throw unexpectedType(val, Long.class);
}
public long readLong(final long defaultVal)
{
TypeConstructor constructor = readConstructor();
if(constructor instanceof LongType.LongEncoding)
{
return ((LongType.LongEncoding)constructor).readPrimitiveValue();
}
else
{
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else
{
throw unexpectedType(val, Long.class);
}
}
}
public UnsignedByte readUnsignedByte()
{
return readUnsignedByte(null);
}
public UnsignedByte readUnsignedByte(final UnsignedByte defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof UnsignedByte)
{
return (UnsignedByte) val;
}
throw unexpectedType(val, UnsignedByte.class);
}
public UnsignedShort readUnsignedShort()
{
return readUnsignedShort(null);
}
public UnsignedShort readUnsignedShort(final UnsignedShort defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof UnsignedShort)
{
return (UnsignedShort) val;
}
throw unexpectedType(val, UnsignedShort.class);
}
public UnsignedInteger readUnsignedInteger()
{
return readUnsignedInteger(null);
}
public UnsignedInteger readUnsignedInteger(final UnsignedInteger defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof UnsignedInteger)
{
return (UnsignedInteger) val;
}
throw unexpectedType(val, UnsignedInteger.class);
}
public UnsignedLong readUnsignedLong()
{
return readUnsignedLong(null);
}
public UnsignedLong readUnsignedLong(final UnsignedLong defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof UnsignedLong)
{
return (UnsignedLong) val;
}
throw unexpectedType(val, UnsignedLong.class);
}
public Character readCharacter()
{
return readCharacter(null);
}
public Character readCharacter(final Character defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof Character)
{
return (Character) val;
}
throw unexpectedType(val, Character.class);
}
public char readCharacter(final char defaultVal)
{
TypeConstructor constructor = readConstructor();
if(constructor instanceof CharacterType.CharacterEncoding)
{
return ((CharacterType.CharacterEncoding)constructor).readPrimitiveValue();
}
else
{
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else
{
throw unexpectedType(val, Character.class);
}
}
}
public Float readFloat()
{
return readFloat(null);
}
public Float readFloat(final Float defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof Float)
{
return (Float) val;
}
throw unexpectedType(val, Float.class);
}
public float readFloat(final float defaultVal)
{
TypeConstructor constructor = readConstructor();
if(constructor instanceof FloatType.FloatEncoding)
{
return ((FloatType.FloatEncoding)constructor).readPrimitiveValue();
}
else
{
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else
{
throw unexpectedType(val, Float.class);
}
}
}
public Double readDouble()
{
return readDouble(null);
}
public Double readDouble(final Double defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof Double)
{
return (Double) val;
}
throw unexpectedType(val, Double.class);
}
public double readDouble(final double defaultVal)
{
TypeConstructor constructor = readConstructor();
if(constructor instanceof DoubleType.DoubleEncoding)
{
return ((DoubleType.DoubleEncoding)constructor).readPrimitiveValue();
}
else
{
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else
{
throw unexpectedType(val, Double.class);
}
}
}
public UUID readUUID()
{
return readUUID(null);
}
public UUID readUUID(final UUID defaultVal)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultVal;
}
else if(val instanceof UUID)
{
return (UUID) val;
}
throw unexpectedType(val, UUID.class);
}
public Decimal32 readDecimal32()
{
return readDecimal32(null);
}
public Decimal32 readDecimal32(final Decimal32 defaultValue)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultValue;
}
else if(val instanceof Decimal32)
{
return (Decimal32) val;
}
throw unexpectedType(val, Decimal32.class);
}
public Decimal64 readDecimal64()
{
return readDecimal64(null);
}
public Decimal64 readDecimal64(final Decimal64 defaultValue)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultValue;
}
else if(val instanceof Decimal64)
{
return (Decimal64) val;
}
throw unexpectedType(val, Decimal64.class);
}
public Decimal128 readDecimal128()
{
return readDecimal128(null);
}
public Decimal128 readDecimal128(final Decimal128 defaultValue)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultValue;
}
else if(val instanceof Decimal128)
{
return (Decimal128) val;
}
throw unexpectedType(val, Decimal128.class);
}
public Date readTimestamp()
{
return readTimestamp(null);
}
public Date readTimestamp(final Date defaultValue)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultValue;
}
else if(val instanceof Date)
{
return (Date) val;
}
throw unexpectedType(val, Date.class);
}
public Binary readBinary()
{
return readBinary(null);
}
public Binary readBinary(final Binary defaultValue)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultValue;
}
else if(val instanceof Binary)
{
return (Binary) val;
}
throw unexpectedType(val, Binary.class);
}
public Symbol readSymbol()
{
return readSymbol(null);
}
public Symbol readSymbol(final Symbol defaultValue)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultValue;
}
else if(val instanceof Symbol)
{
return (Symbol) val;
}
throw unexpectedType(val, Symbol.class);
}
public String readString()
{
return readString(null);
}
public String readString(final String defaultValue)
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return defaultValue;
}
else if(val instanceof String)
{
return (String) val;
}
throw unexpectedType(val, String.class);
}
public List readList()
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return null;
}
else if(val instanceof List)
{
return (List) val;
}
throw unexpectedType(val, List.class);
}
public <T> void readList(final ListProcessor<T> processor)
{
//TODO.
}
public Map readMap()
{
TypeConstructor constructor = readConstructor();
Object val = constructor.readValue();
if(val == null)
{
return null;
}
else if(val instanceof Map)
{
return (Map) val;
}
throw unexpectedType(val, Map.class);
}
public <T> T[] readArray(final Class<T> clazz)
{
return null; //TODO.
}
public Object[] readArray()
{
return (Object[]) readConstructor().readValue();
}
public boolean[] readBooleanArray()
{
return (boolean[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
}
public byte[] readByteArray()
{
return (byte[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
}
public short[] readShortArray()
{
return (short[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
}
public int[] readIntegerArray()
{
return (int[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
}
public long[] readLongArray()
{
return (long[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
}
public float[] readFloatArray()
{
return (float[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
}
public double[] readDoubleArray()
{
return (double[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
}
public char[] readCharacterArray()
{
return (char[]) ((ArrayType.ArrayEncoding)readConstructor()).readValueArray();
}
public <T> T[] readMultiple(final Class<T> clazz)
{
Object val = readObject();
if(val == null)
{
return null;
}
else if(val.getClass().isArray())
{
if(clazz.isAssignableFrom(val.getClass().getComponentType()))
{
return (T[]) val;
}
else
{
throw unexpectedType(val, Array.newInstance(clazz, 0).getClass());
}
}
else if(clazz.isAssignableFrom(val.getClass()))
{
T[] array = (T[]) Array.newInstance(clazz, 1);
array[0] = (T) val;
return array;
}
else
{
throw unexpectedType(val, Array.newInstance(clazz, 0).getClass());
}
}
public Object[] readMultiple()
{
Object val = readObject();
if(val == null)
{
return null;
}
else if(val.getClass().isArray())
{
return (Object[]) val;
}
else
{
Object[] array = (Object[]) Array.newInstance(val.getClass(), 1);
array[0] = val;
return array;
}
}
public byte[] readByteMultiple()
{
return new byte[0]; //TODO.
}
public short[] readShortMultiple()
{
return new short[0]; //TODO.
}
public int[] readIntegerMultiple()
{
return new int[0]; //TODO.
}
public long[] readLongMultiple()
{
return new long[0]; //TODO.
}
public float[] readFloatMultiple()
{
return new float[0]; //TODO.
}
public double[] readDoubleMultiple()
{
return new double[0]; //TODO.
}
public char[] readCharacterMultiple()
{
return new char[0]; //TODO.
}
public Object readObject()
{
TypeConstructor constructor = readConstructor();
if(constructor== null)
{
throw new DecodeException("Unknown constructor");
}
return constructor instanceof ArrayType.ArrayEncoding
? ((ArrayType.ArrayEncoding)constructor).readValueArray()
: constructor.readValue();
}
public Object readObject(final Object defaultValue)
{
Object val = readObject();
return val == null ? defaultValue : val;
}
<V> void register(PrimitiveType<V> type)
{
Collection<? extends PrimitiveTypeEncoding<V>> encodings = type.getAllEncodings();
for(PrimitiveTypeEncoding<V> encoding : encodings)
{
_constructors[((int) encoding.getEncodingCode()) & 0xFF ] = encoding;
}
}
byte readRawByte()
{
return _buffer.get();
}
int readRawInt()
{
return _buffer.getInt();
}
long readRawLong()
{
return _buffer.getLong();
}
short readRawShort()
{
return _buffer.getShort();
}
float readRawFloat()
{
return _buffer.getFloat();
}
double readRawDouble()
{
return _buffer.getDouble();
}
void readRaw(final byte[] data, final int offset, final int length)
{
_buffer.get(data, offset, length);
}
<V> V readRaw(TypeDecoder<V> decoder, int size)
{
V decode = decoder.decode((ByteBuffer) _buffer.slice().limit(size));
_buffer.position(_buffer.position()+size);
return decode;
}
public void setByteBuffer(final ByteBuffer buffer)
{
_buffer = buffer;
}
interface TypeDecoder<V>
{
V decode(ByteBuffer buf);
}
private static class UnknownDescribedType implements DescribedType
{
private final Object _descriptor;
private final Object _described;
public UnknownDescribedType(final Object descriptor, final Object described)
{
_descriptor = descriptor;
_described = described;
}
public Object getDescriptor()
{
return _descriptor;
}
public Object getDescribed()
{
return _described;
}
@Override
public boolean equals(Object obj)
{
return obj instanceof DescribedType
&& _descriptor == null ? ((DescribedType) obj).getDescriptor() == null
: _descriptor.equals(((DescribedType) obj).getDescriptor())
&& _described == null ? ((DescribedType) obj).getDescribed() == null
: _described.equals(((DescribedType) obj).getDescribed());
}
}
public int getByteBufferRemaining() {
return _buffer.remaining();
}
}