![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.qpid.transport.codec.AbstractEncoder Maven / Gradle / Ivy
/*
*
* 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.transport.codec;
import static org.apache.qpid.transport.util.Functions.lsb;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.qpid.transport.Range;
import org.apache.qpid.transport.RangeSet;
import org.apache.qpid.transport.Struct;
import org.apache.qpid.transport.Type;
import org.apache.qpid.transport.Xid;
/**
* AbstractEncoder
*
* @author Rafael H. Schloming
*/
public abstract class AbstractEncoder implements Encoder
{
private static Map,Type> ENCODINGS = new HashMap,Type>();
static
{
ENCODINGS.put(Boolean.class, Type.BOOLEAN);
ENCODINGS.put(String.class, Type.STR16);
ENCODINGS.put(Long.class, Type.INT64);
ENCODINGS.put(Integer.class, Type.INT32);
ENCODINGS.put(Short.class, Type.INT16);
ENCODINGS.put(Byte.class, Type.INT8);
ENCODINGS.put(Map.class, Type.MAP);
ENCODINGS.put(List.class, Type.LIST);
ENCODINGS.put(Float.class, Type.FLOAT);
ENCODINGS.put(Double.class, Type.DOUBLE);
ENCODINGS.put(Character.class, Type.CHAR);
ENCODINGS.put(byte[].class, Type.VBIN32);
ENCODINGS.put(UUID.class, Type.UUID);
ENCODINGS.put(Xid.class, Type.STRUCT32);
}
private final Map str8cache = new LinkedHashMap()
{
@Override protected boolean removeEldestEntry(Map.Entry me)
{
return size() > 4*1024;
}
};
protected abstract void doPut(byte b);
protected abstract void doPut(ByteBuffer src);
protected void put(byte b)
{
doPut(b);
}
protected void put(ByteBuffer src)
{
doPut(src);
}
protected void put(byte[] bytes)
{
put(ByteBuffer.wrap(bytes));
}
protected abstract int beginSize8();
protected abstract void endSize8(int pos);
protected abstract int beginSize16();
protected abstract void endSize16(int pos);
protected abstract int beginSize32();
protected abstract void endSize32(int pos);
public void writeUint8(short b)
{
assert b < 0x100;
put((byte) b);
}
public void writeUint16(int s)
{
assert s < 0x10000;
put(lsb(s >>> 8));
put(lsb(s));
}
public void writeUint32(long i)
{
assert i < 0x100000000L;
put(lsb(i >>> 24));
put(lsb(i >>> 16));
put(lsb(i >>> 8));
put(lsb(i));
}
public void writeSequenceNo(int i)
{
writeUint32(i);
}
public void writeUint64(long l)
{
for (int i = 0; i < 8; i++)
{
put(lsb(l >> (56 - i*8)));
}
}
public void writeDatetime(long l)
{
writeUint64(l);
}
private static final byte[] encode(String s, String charset)
{
try
{
return s.getBytes(charset);
}
catch (UnsupportedEncodingException e)
{
throw new RuntimeException(e);
}
}
public void writeStr8(String s)
{
if (s == null)
{
s = "";
}
byte[] bytes = str8cache.get(s);
if (bytes == null)
{
bytes = encode(s, "UTF-8");
str8cache.put(s, bytes);
}
writeUint8((short) bytes.length);
put(bytes);
}
public void writeStr16(String s)
{
if (s == null)
{
s = "";
}
byte[] bytes = encode(s, "UTF-8");
writeUint16(bytes.length);
put(bytes);
}
public void writeVbin8(byte[] bytes)
{
if (bytes == null) { bytes = new byte[0]; }
if (bytes.length > 255)
{
throw new IllegalArgumentException("array too long: " + bytes.length);
}
writeUint8((short) bytes.length);
put(ByteBuffer.wrap(bytes));
}
public void writeVbin16(byte[] bytes)
{
if (bytes == null) { bytes = new byte[0]; }
writeUint16(bytes.length);
put(ByteBuffer.wrap(bytes));
}
public void writeVbin32(byte[] bytes)
{
if (bytes == null) { bytes = new byte[0]; }
writeUint32(bytes.length);
put(ByteBuffer.wrap(bytes));
}
public void writeSequenceSet(RangeSet ranges)
{
if (ranges == null)
{
writeUint16((short) 0);
}
else
{
writeUint16(ranges.size() * 8);
for (Range range : ranges)
{
writeSequenceNo(range.getLower());
writeSequenceNo(range.getUpper());
}
}
}
public void writeByteRanges(RangeSet ranges)
{
throw new Error("not implemented");
}
public void writeUuid(UUID uuid)
{
long msb = 0;
long lsb = 0;
if (uuid != null)
{
msb = uuid.getMostSignificantBits();
lsb = uuid.getLeastSignificantBits();
}
writeUint64(msb);
writeUint64(lsb);
}
public void writeStruct(int type, Struct s)
{
boolean empty = false;
if (s == null)
{
s = Struct.create(type);
empty = true;
}
int width = s.getSizeWidth();
int pos = -1;
if (width > 0)
{
pos = beginSize(width);
}
if (type > 0)
{
writeUint16(type);
}
s.write(this);
if (width > 0)
{
endSize(width, pos);
}
}
public void writeStruct32(Struct s)
{
if (s == null)
{
writeUint32(0);
}
else
{
int pos = beginSize32();
writeUint16(s.getEncodedType());
s.write(this);
endSize32(pos);
}
}
private Type encoding(Object value)
{
if (value == null)
{
return Type.VOID;
}
Class klass = value.getClass();
Type type = resolve(klass);
if (type == null)
{
throw new IllegalArgumentException
("unable to resolve type: " + klass + ", " + value);
}
else
{
return type;
}
}
static final Type resolve(Class klass)
{
Type type = ENCODINGS.get(klass);
if (type != null)
{
return type;
}
Class sup = klass.getSuperclass();
if (sup != null)
{
type = resolve(klass.getSuperclass());
if (type != null)
{
return type;
}
}
for (Class iface : klass.getInterfaces())
{
type = resolve(iface);
if (type != null)
{
return type;
}
}
return null;
}
public void writeMap(Map map)
{
int pos = beginSize32();
if (map != null)
{
writeUint32(map.size());
writeMapEntries(map);
}
endSize32(pos);
}
protected void writeMapEntries(Map map)
{
for (Map.Entry entry : map.entrySet())
{
String key = entry.getKey();
Object value = entry.getValue();
Type type = encoding(value);
writeStr8(key);
put(type.getCode());
write(type, value);
}
}
public void writeList(List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy