| /* |
| * |
| * 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(); |
| } |
| } |