blob: 0cb7f85bd98597a2bf656607ee670044e6012f90 [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.server.protocol.v1_0.codec;
import org.apache.qpid.server.protocol.v1_0.type.AmqpErrorException;
import org.apache.qpid.server.protocol.v1_0.type.transport.AmqpError;
import org.apache.qpid.server.protocol.v1_0.type.transport.ConnectionError;
import org.apache.qpid.bytebuffer.QpidByteBuffer;
import java.nio.charset.Charset;
public class ValueHandler implements DescribedTypeConstructorRegistry.Source
{
private static final byte DESCRIBED_TYPE = (byte)0;
private final DescribedTypeConstructorRegistry _describedTypeConstructorRegistry;
private static final TypeConstructor[][] TYPE_CONSTRUCTORS =
{
{},
{},
{},
{},
{ NullTypeConstructor.getInstance(), BooleanConstructor.getTrueInstance(),
BooleanConstructor.getFalseInstance(), ZeroUIntConstructor.getInstance(),
ZeroULongConstructor.getInstance(), ZeroListConstructor.getInstance() },
{ UByteTypeConstructor.getInstance(), ByteTypeConstructor.getInstance(),
SmallUIntConstructor.getInstance(), SmallULongConstructor.getInstance(),
SmallIntConstructor.getInstance(), SmallLongConstructor.getInstance(),
BooleanConstructor.getByteInstance()},
{ UShortTypeConstructor.getInstance(), ShortTypeConstructor.getInstance() },
{ UIntTypeConstructor.getInstance(), IntTypeConstructor.getInstance(),
FloatTypeConstructor.getInstance(), CharTypeConstructor.getInstance(),
DecimalConstructor.getDecimal32Instance()},
{ ULongTypeConstructor.getInstance(), LongTypeConstructor.getInstance(),
DoubleTypeConstructor.getInstance(), TimestampTypeConstructor.getInstance(),
DecimalConstructor.getDecimal64Instance()},
{ null, null,
null, null,
DecimalConstructor.getDecimal128Instance(), null,
null, null,
UUIDTypeConstructor.getInstance() },
{ BinaryTypeConstructor.getInstance(1),
StringTypeConstructor.getInstance(1, Charset.forName("UTF8")),
StringTypeConstructor.getInstance(1, Charset.forName("UTF16")),
SymbolTypeConstructor.getInstance(1) },
{ BinaryTypeConstructor.getInstance(4),
StringTypeConstructor.getInstance(4, Charset.forName("UTF8")),
StringTypeConstructor.getInstance(4, Charset.forName("UTF16")),
SymbolTypeConstructor.getInstance(4) },
{ CompoundTypeConstructor.getInstance(1, CompoundTypeConstructor.LIST_ASSEMBLER_FACTORY),
CompoundTypeConstructor.getInstance(1, CompoundTypeConstructor.MAP_ASSEMBLER_FACTORY) },
{ CompoundTypeConstructor.getInstance(4, CompoundTypeConstructor.LIST_ASSEMBLER_FACTORY),
CompoundTypeConstructor.getInstance(4, CompoundTypeConstructor.MAP_ASSEMBLER_FACTORY) },
{
ArrayTypeConstructor.getOneByteSizeTypeConstructor()
},
{
ArrayTypeConstructor.getFourByteSizeTypeConstructor()
}
};
public ValueHandler(DescribedTypeConstructorRegistry registry)
{
_describedTypeConstructorRegistry = registry;
}
public Object parse(final QpidByteBuffer in) throws AmqpErrorException
{
TypeConstructor constructor = readConstructor(in);
return constructor.construct(in, this);
}
public TypeConstructor readConstructor(QpidByteBuffer in) throws AmqpErrorException
{
if(!in.hasRemaining())
{
throw new AmqpErrorException(AmqpError.DECODE_ERROR, "Insufficient data - expected type, no data remaining");
}
byte formatCode = in.get();
if(formatCode == DESCRIBED_TYPE)
{
Object descriptor = parse(in);
DescribedTypeConstructor describedTypeConstructor = _describedTypeConstructorRegistry.getConstructor(descriptor);
if(describedTypeConstructor==null)
{
describedTypeConstructor=new DefaultDescribedTypeConstructor(descriptor);
}
TypeConstructor typeConstructor = readConstructor(in);
return describedTypeConstructor.construct(typeConstructor);
}
else
{
int subCategory = (formatCode >> 4) & 0x0F;
int subtype = formatCode & 0x0F;
TypeConstructor tc;
try
{
tc = TYPE_CONSTRUCTORS[subCategory][subtype];
}
catch(IndexOutOfBoundsException e)
{
tc = null;
}
if(tc == null)
{
throw new AmqpErrorException(ConnectionError.FRAMING_ERROR,"Unknown type format-code 0x%02x", formatCode);
}
return tc;
}
}
@Override
public String toString()
{
return "ValueHandler{" +
", _describedTypeConstructorRegistry=" + _describedTypeConstructorRegistry +
'}';
}
public DescribedTypeConstructorRegistry getDescribedTypeRegistry()
{
return _describedTypeConstructorRegistry;
}
}