This commit is contained in:
地平线
2015-09-22 17:34:27 +08:00
parent 92eba39dd8
commit ac6a2e57c6
73 changed files with 6720 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.reflect.Type;
/**
* 对不明类型的对象进行序列化; BSON序列化时将对象的类名写入WriterJSON则不写入。
*
* @author zhangjx
* @param <T>
*/
public final class AnyEncoder<T> implements Encodeable<Writer, T> {
final Factory factory;
AnyEncoder(Factory factory) {
this.factory = factory;
}
@Override
@SuppressWarnings("unchecked")
public void convertTo(final Writer out, final T value) {
if (value == null) {
out.writeNull();
} else {
out.wirteClassName(factory.getEntity(value.getClass()));
factory.loadEncoder(value.getClass()).convertTo(out, value);
}
}
@Override
public Type getType() {
return Object.class;
}
}

View File

@@ -0,0 +1,79 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.reflect.*;
import java.util.*;
/**
* 对象数组的序列化不包含int[]、long[]这样的primitive class数组.
* 数组长度不能超过 32767。 在BSON中数组长度设定的是short对于大于32767长度的数组传输会影响性能所以没有采用int存储。
* 支持一定程度的泛型。
*
* @author zhangjx
* @param <T>
*/
@SuppressWarnings("unchecked")
public final class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
private final Type type;
private final Type componentType;
private final Class componentClass;
private final Decodeable<Reader, T> decoder;
public ArrayDecoder(final Factory factory, final Type type) {
this.type = type;
if (type instanceof GenericArrayType) {
Type t = ((GenericArrayType) type).getGenericComponentType();
this.componentType = t instanceof TypeVariable ? Object.class : t;
} else if ((type instanceof Class) && ((Class) type).isArray()) {
this.componentType = ((Class) type).getComponentType();
} else {
throw new ConvertException("(" + type + ") is not a array type");
}
if (this.componentType instanceof ParameterizedType) {
this.componentClass = (Class) ((ParameterizedType) this.componentType).getRawType();
} else {
this.componentClass = (Class) this.componentType;
}
factory.register(type, this);
this.decoder = factory.loadDecoder(this.componentType);
}
@Override
public T[] convertFrom(Reader in) {
final int len = in.readArrayB();
if (len == Reader.SIGN_NULL) return null;
final Decodeable<Reader, T> localdecoder = this.decoder;
final List<T> result = new ArrayList();
if (len == Reader.SIGN_NOLENGTH) {
while (in.hasNext()) {
result.add(localdecoder.convertFrom(in));
}
} else {
for (int i = 0; i < len; i++) {
result.add(localdecoder.convertFrom(in));
}
}
in.readArrayE();
T[] rs = (T[]) Array.newInstance((Class) this.componentClass, result.size());
return result.toArray(rs);
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", decoder:" + this.decoder + "}";
}
@Override
public Type getType() {
return type;
}
}

View File

@@ -0,0 +1,75 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.reflect.*;
/**
* 对象数组的反序列化不包含int[]、long[]这样的primitive class数组.
* 数组长度不能超过 32767。 在BSON中数组长度设定的是short对于大于32767长度的数组传输会影响性能所以没有采用int存储。
* 支持一定程度的泛型。
*
* @author zhangjx
* @param <T>
*/
@SuppressWarnings("unchecked")
public final class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
private final Type type;
private final Type componentType;
private final Encodeable anyEncoder;
private final Encodeable<Writer, Object> encoder;
public ArrayEncoder(final Factory factory, final Type type) {
this.type = type;
if (type instanceof GenericArrayType) {
Type t = ((GenericArrayType) type).getGenericComponentType();
this.componentType = t instanceof TypeVariable ? Object.class : t;
} else if ((type instanceof Class) && ((Class) type).isArray()) {
this.componentType = ((Class) type).getComponentType();
} else {
throw new ConvertException("(" + type + ") is not a array type");
}
factory.register(type, this);
this.encoder = factory.loadEncoder(this.componentType);
this.anyEncoder = factory.getAnyEncoder();
}
@Override
public void convertTo(Writer out, T[] value) {
if (value == null) {
out.writeNull();
return;
}
if (value.length == 0) {
out.writeArrayB(0);
out.writeArrayE();
return;
}
out.writeArrayB(value.length);
final Type comp = this.componentType;
boolean first = true;
for (Object v : value) {
if (!first) out.writeArrayMark();
((v != null && v.getClass() == comp) ? encoder : anyEncoder).convertTo(out, v);
if (first) first = false;
}
out.writeArrayE();
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.encoder + "}";
}
@Override
public Type getType() {
return type;
}
}

View File

@@ -0,0 +1,69 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import com.wentch.redkale.util.Creator;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* 对象集合的反序列化.
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short对于大于32767长度的集合传输会影响性能所以没有采用int存储。
* 支持一定程度的泛型。
*
* @author zhangjx
* @param <T>
*/
@SuppressWarnings("unchecked")
public final class CollectionDecoder<T> implements Decodeable<Reader, Collection<T>> {
private final Type type;
private final Type componentType;
protected Creator<Collection<T>> creator;
private final Decodeable<Reader, T> decoder;
public CollectionDecoder(final Factory factory, final Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
this.componentType = pt.getActualTypeArguments()[0];
this.creator = factory.loadCreator((Class) pt.getRawType());
factory.register(type, this);
this.decoder = factory.loadDecoder(this.componentType);
} else {
throw new ConvertException("collectiondecoder not support the type (" + type + ")");
}
}
@Override
public Collection<T> convertFrom(Reader in) {
final int len = in.readArrayB();
if (len == Reader.SIGN_NULL) return null;
final Decodeable<Reader, T> localdecoder = this.decoder;
final Collection<T> result = this.creator.create();
if (len == Reader.SIGN_NOLENGTH) {
while (in.hasNext()) {
result.add(localdecoder.convertFrom(in));
}
} else {
for (int i = 0; i < len; i++) {
result.add(localdecoder.convertFrom(in));
}
}
in.readArrayE();
return result;
}
@Override
public Type getType() {
return type;
}
}

View File

@@ -0,0 +1,65 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.reflect.*;
import java.util.Collection;
/**
* 对象集合的序列化.
* 集合大小不能超过 32767。 在BSON中集合大小设定的是short对于大于32767长度的集合传输会影响性能所以没有采用int存储。
* 支持一定程度的泛型。
*
* @author zhangjx
* @param <T>
*/
@SuppressWarnings("unchecked")
public final class CollectionEncoder<T> implements Encodeable<Writer, Collection<T>> {
private final Type type;
private final Encodeable<Writer, Object> encoder;
public CollectionEncoder(final Factory factory, final Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
Type t = ((ParameterizedType) type).getActualTypeArguments()[0];
if (t instanceof TypeVariable) {
this.encoder = factory.getAnyEncoder();
} else {
this.encoder = factory.loadEncoder(t);
}
} else {
this.encoder = factory.getAnyEncoder();
}
}
@Override
public void convertTo(Writer out, Collection<T> value) {
if (value == null) {
out.writeNull();
return;
}
if (value.isEmpty()) {
out.writeArrayB(0);
out.writeArrayE();
return;
}
out.writeArrayB(value.size());
boolean first = true;
for (Object v : value) {
if (!first) out.writeArrayMark();
encoder.convertTo(out, v);
if (first) first = false;
}
out.writeArrayE();
}
@Override
public Type getType() {
return type;
}
}

View File

@@ -0,0 +1,26 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
/**
* 序列化操作类
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public abstract class Convert<R extends Reader, W extends Writer> {
protected final Factory<R, W> factory;
protected Convert(Factory<R, W> factory) {
this.factory = factory;
}
public Factory<R, W> getFactory() {
return this.factory;
}
}

View File

@@ -0,0 +1,44 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
* 依附在setter、getter方法、字段进行简单的配置
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({METHOD, FIELD})
@Retention(RUNTIME)
@Repeatable(ConvertColumns.class)
public @interface ConvertColumn {
/**
* 给字段取个别名, 只对JSON有效
*
* @return
*/
String name() default "";
/**
* 解析/序列化时是否屏蔽该字段
*
* @return
*/
boolean ignore() default false;
/**
* 解析/序列化定制化的TYPE
*
* @return
*/
ConvertType type() default ConvertType.ALL;
}

View File

@@ -0,0 +1,67 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
/**
* ConvertColumn 对应的实体类
*
* @author zhangjx
*/
public final class ConvertColumnEntry {
private String name = "";
private boolean ignore;
private ConvertType convertType;
public ConvertColumnEntry() {
}
public ConvertColumnEntry(ConvertColumn column) {
if (column == null) return;
this.name = column.name();
this.ignore = column.ignore();
this.convertType = column.type();
}
public ConvertColumnEntry(String name, boolean ignore) {
this.name = name;
this.ignore = ignore;
this.convertType = ConvertType.ALL;
}
public ConvertColumnEntry(String name, boolean ignore, ConvertType convertType) {
this.name = name;
this.ignore = ignore;
this.convertType = convertType;
}
public String name() {
return name == null ? "" : name;
}
public void setName(String name) {
this.name = name;
}
public boolean ignore() {
return ignore;
}
public void setIgnore(boolean ignore) {
this.ignore = ignore;
}
public ConvertType type() {
return convertType == null ? ConvertType.ALL : convertType;
}
public void setConvertType(ConvertType convertType) {
this.convertType = convertType;
}
}

View File

@@ -0,0 +1,24 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
* ConvertColumn 的多用类
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({METHOD, FIELD})
@Retention(RUNTIME)
public @interface ConvertColumns {
ConvertColumn[] value();
}

View File

@@ -0,0 +1,25 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 用于类名的别名, 类似javax.persistence.Table
* 该值必须是全局唯一
*
* @author zhangjx
*/
@Inherited
@Documented
@Target({TYPE})
@Retention(RUNTIME)
public @interface ConvertEntity {
String value();
}

View File

@@ -0,0 +1,28 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
/**
*
* @author zhangjx
*/
public class ConvertException extends RuntimeException {
public ConvertException() {
super();
}
public ConvertException(String s) {
super(s);
}
public ConvertException(String message, Throwable cause) {
super(message, cause);
}
public ConvertException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,28 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
/**
*
* @author zhangjx
*/
public enum ConvertType {
JSON(1),
BSON(2),
ALL(127);
private final int value;
private ConvertType(int v) {
this.value = v;
}
public boolean contains(ConvertType type) {
if (type == null) return false;
return this.value >= type.value && (this.value & type.value) > 0;
}
}

View File

@@ -0,0 +1,64 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import com.wentch.redkale.util.Attribute;
/**
*
* @author zhangjx
* @param <R>
* @param <T>
* @param <F>
*/
@SuppressWarnings("unchecked")
public final class DeMember<R extends Reader, T, F> implements Comparable<DeMember<R, T, F>> {
protected final Attribute<T, F> attribute;
protected Decodeable<R, F> decoder;
public DeMember(final Attribute<T, F> attribute) {
this.attribute = attribute;
}
public DeMember(Attribute<T, F> attribute, Decodeable<R, F> decoder) {
this(attribute);
this.decoder = decoder;
}
public final void read(R in, T obj) {
this.attribute.set(obj, decoder.convertFrom(in));
}
public Attribute<T, F> getAttribute() {
return this.attribute;
}
@Override
public final int compareTo(DeMember<R, T, F> o) {
if (o == null) return 1;
return this.attribute.field().compareTo(o.attribute.field());
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof DeMember)) return false;
DeMember other = (DeMember) obj;
return compareTo(other) == 0;
}
@Override
public int hashCode() {
return this.attribute.field().hashCode();
}
@Override
public String toString() {
return "DeMember{" + "attribute=" + attribute.field() + ", decoder=" + decoder + '}';
}
}

View File

@@ -0,0 +1,27 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.reflect.Type;
/**
*
* @author zhangjx
* @param <R>
* @param <T>
*/
public interface Decodeable<R extends Reader, T> {
public T convertFrom(final R in);
/**
* 泛型映射接口
*
* @return
*/
public Type getType();
}

View File

@@ -0,0 +1,76 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import com.wentch.redkale.util.Attribute;
/**
*
* @author zhangjx
* @param <W>
* @param <T>
* @param <F>
*/
@SuppressWarnings("unchecked")
public final class EnMember<W extends Writer, T, F> implements Comparable<EnMember<W, T, F>> {
private final Attribute<T, F> attribute;
final Encodeable<W, F> encoder;
private final boolean istring;
//private final boolean isnumber;
private final boolean isbool;
public EnMember(Attribute<T, F> attribute, Encodeable<W, F> encoder) {
this.attribute = attribute;
this.encoder = encoder;
Class t = attribute.type();
this.istring = CharSequence.class.isAssignableFrom(t);
this.isbool = t == Boolean.class || t == boolean.class;
//this.isnumber = Number.class.isAssignableFrom(t) || (!this.isbool && t.isPrimitive());
}
public boolean write(final W out, final boolean comma, final T obj) {
F value = attribute.get(obj);
if (value == null) return comma;
if (out.isTiny()) {
if (istring) {
if (((CharSequence) value).length() == 0) return comma;
} else if (isbool) {
if (!((Boolean) value)) return comma;
}
}
out.writeField(comma, attribute);
encoder.convertTo(out, value);
return true;
}
@Override
public final int compareTo(EnMember<W, T, F> o) {
if (o == null) return 1;
return this.attribute.field().compareTo(o.attribute.field());
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof EnMember)) return false;
EnMember other = (EnMember) obj;
return compareTo(other) == 0;
}
@Override
public int hashCode() {
return this.attribute.field().hashCode();
}
@Override
public String toString() {
return "EnMember{" + "attribute=" + attribute.field() + ", encoder=" + encoder + '}';
}
}

View File

@@ -0,0 +1,27 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.reflect.Type;
/**
*
* @author zhangjx
* @param <W>
* @param <T>
*/
public interface Encodeable<W extends Writer, T> {
public void convertTo(final W out, T value);
/**
* 泛型映射接口
*
* @return
*/
public Type getType();
}

View File

@@ -0,0 +1,386 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import com.wentch.redkale.convert.ext.*;
import com.wentch.redkale.util.*;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;
import java.lang.reflect.*;
import java.math.BigInteger;
import java.net.*;
import static com.wentch.redkale.convert.ext.InetAddressSimpledCoder.*;
import com.wentch.redkale.util.Creator.Creators;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.*;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
@SuppressWarnings("unchecked")
public abstract class Factory<R extends Reader, W extends Writer> {
private final Factory parent;
protected Convert<R, W> convert;
protected boolean tiny;
private final Encodeable<W, ?> anyEncoder = new AnyEncoder(this);
//-----------------------------------------------------------------------------------
private final HashedMap<Class, Creator> creators = new HashedMap();
private final Map<String, Class> entitys = new ConcurrentHashMap();
private final HashedMap<Type, Decodeable<R, ?>> decoders = new HashedMap();
private final HashedMap<Type, Encodeable<W, ?>> encoders = new HashedMap();
private final HashMap<AccessibleObject, ConvertColumnEntry> columnEntrys = new HashMap();
private final Set<Class> skipIgnores = new HashSet();
private boolean skipAllIgnore = false;
protected Factory(Factory<R, W> parent, boolean tiny) {
this.tiny = tiny;
this.parent = parent;
if (parent == null) {
//---------------------------------------------------------
this.register(boolean.class, BoolSimpledCoder.instance);
this.register(Boolean.class, BoolSimpledCoder.instance);
this.register(byte.class, ByteSimpledCoder.instance);
this.register(Byte.class, ByteSimpledCoder.instance);
this.register(short.class, ShortSimpledCoder.instance);
this.register(Short.class, ShortSimpledCoder.instance);
this.register(char.class, CharSimpledCoder.instance);
this.register(Character.class, CharSimpledCoder.instance);
this.register(int.class, IntSimpledCoder.instance);
this.register(Integer.class, IntSimpledCoder.instance);
this.register(long.class, LongSimpledCoder.instance);
this.register(Long.class, LongSimpledCoder.instance);
this.register(float.class, FloatSimpledCoder.instance);
this.register(Float.class, FloatSimpledCoder.instance);
this.register(double.class, DoubleSimpledCoder.instance);
this.register(Double.class, DoubleSimpledCoder.instance);
this.register(Number.class, NumberSimpledCoder.instance);
this.register(String.class, StringSimpledCoder.instance);
this.register(java.util.Date.class, DateSimpledCoder.instance);
this.register(BigInteger.class, BigIntegerSimpledCoder.instance);
this.register(InetAddress.class, InetAddressSimpledCoder.instance);
this.register(DLong.class, DLongSimpledCoder.instance);
this.register(Class.class, TypeSimpledCoder.instance);
this.register(InetSocketAddress.class, InetSocketAddressSimpledCoder.instance);
this.register(Pattern.class, PatternSimpledCoder.instance);
//---------------------------------------------------------
this.register(boolean[].class, BoolArraySimpledCoder.instance);
this.register(byte[].class, ByteArraySimpledCoder.instance);
this.register(short[].class, ShortArraySimpledCoder.instance);
this.register(char[].class, CharArraySimpledCoder.instance);
this.register(int[].class, IntArraySimpledCoder.instance);
this.register(long[].class, LongArraySimpledCoder.instance);
this.register(float[].class, FloatArraySimpledCoder.instance);
this.register(double[].class, DoubleArraySimpledCoder.instance);
this.register(String[].class, StringArraySimpledCoder.instance);
//---------------------------------------------------------
}
}
public Factory parent() {
return this.parent;
}
public abstract ConvertType getConvertType();
public abstract boolean isReversible();
public abstract Factory createChild();
public abstract Factory createChild(boolean tiny);
public Convert getConvert() {
return convert;
}
public void setTiny(boolean tiny) {
this.tiny = tiny;
}
public ConvertColumnEntry findRef(AccessibleObject field) {
if (field == null) return null;
ConvertColumnEntry en = this.columnEntrys.get(field);
if (en != null) return en;
final ConvertType ct = this.getConvertType();
for (ConvertColumn ref : field.getAnnotationsByType(ConvertColumn.class)) {
if (ref.type().contains(ct)) {
ConvertColumnEntry entry = new ConvertColumnEntry(ref);
if (skipAllIgnore) {
entry.setIgnore(false);
return entry;
}
if (skipIgnores.isEmpty()) return entry;
if (skipIgnores.contains(((Member) field).getDeclaringClass())) entry.setIgnore(false);
return entry;
}
}
return null;
}
final String getEntity(Class clazz) {
ConvertEntity ce = (ConvertEntity) clazz.getAnnotation(ConvertEntity.class);
if (ce != null && findEntity(ce.value()) == null) entitys.put(ce.value(), clazz);
return ce == null ? clazz.getName() : ce.value();
}
private Class findEntity(String name) {
Class clazz = entitys.get(name);
return parent == null ? clazz : parent.findEntity(name);
}
final Class getEntity(String name) {
Class clazz = findEntity(name);
try {
return clazz == null ? Class.forName(name) : clazz;
} catch (Exception ex) {
throw new ConvertException("convert entity is " + name, ex);
}
}
/**
* 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
* <p>
* @param skipIgnore
*/
public final void registerSkipAllIgnore(final boolean skipIgnore) {
this.skipAllIgnore = skipIgnore;
}
/**
* 使该类所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
* <p>
* @param type
*/
public final void registerSkipIgnore(final Class type) {
skipIgnores.add(type);
}
public final void register(final Class type, boolean ignore, String... columns) {
for (String column : columns) {
register(type, column, new ConvertColumnEntry(column, ignore));
}
}
public final boolean register(final Class type, String column, ConvertColumnEntry entry) {
if (type == null || column == null || entry == null) return false;
try {
final Field field = type.getDeclaredField(column);
String get = "get";
if (field.getType() == boolean.class || field.getType() == Boolean.class) get = "is";
char[] cols = column.toCharArray();
cols[0] = Character.toUpperCase(cols[0]);
String col2 = new String(cols);
try {
register(type.getMethod(get + col2), entry);
} catch (Exception ex) {
}
try {
register(type.getMethod("set" + col2, field.getType()), entry);
} catch (Exception ex) {
}
return register(field, entry);
} catch (Exception e) {
return false;
}
}
public final <E> boolean register(final AccessibleObject field, final ConvertColumnEntry entry) {
if (field == null || entry == null) return false;
this.columnEntrys.put(field, entry);
return true;
}
public final <E> void register(final Class<E> clazz, final Creator<? extends E> creator) {
creators.put(clazz, creator);
}
public final <T> Creator<T> findCreator(Class<T> type) {
Creator<T> creator = creators.get(type);
if (creator != null) return creator;
return this.parent == null ? null : this.parent.findCreator(type);
}
public final <T> Creator<T> loadCreator(Class<T> type) {
Creator result = findCreator(type);
if (result == null) {
result = Creators.create(type);
creators.put(type, result);
}
return result;
}
//----------------------------------------------------------------------
public final <E> Encodeable<W, E> getAnyEncoder() {
return (Encodeable<W, E>) anyEncoder;
}
public final <E> void register(final Type clazz, final SimpledCoder<R, W, E> coder) {
decoders.put(clazz, coder);
encoders.put(clazz, coder);
}
public final <E> void register(final Type clazz, final Decodeable<R, E> decoder) {
decoders.put(clazz, decoder);
}
public final <E> void register(final Type clazz, final Encodeable<W, E> printer) {
encoders.put(clazz, printer);
}
public final <E> Decodeable<R, E> findDecoder(final Type type) {
Decodeable<R, E> rs = (Decodeable<R, E>) decoders.get(type);
if (rs != null) return rs;
return this.parent == null ? null : this.parent.findDecoder(type);
}
public final <E> Encodeable<W, E> findEncoder(final Type type) {
Encodeable<W, E> rs = (Encodeable<W, E>) encoders.get(type);
if (rs != null) return rs;
return this.parent == null ? null : this.parent.findEncoder(type);
}
public final <E> Decodeable<R, E> loadDecoder(final Type type) {
Decodeable<R, E> decoder = findDecoder(type);
if (decoder != null) return decoder;
if (type instanceof GenericArrayType) return new ArrayDecoder(this, type);
Class clazz;
if (type instanceof ParameterizedType) {
final ParameterizedType pts = (ParameterizedType) type;
clazz = (Class) (pts).getRawType();
} else if (type instanceof Class) {
clazz = (Class) type;
} else {
throw new ConvertException("not support the type (" + type + ")");
}
decoder = findDecoder(clazz);
if (decoder != null) return decoder;
return createDecoder(type, clazz);
}
public final <E> Decodeable<R, E> createDecoder(final Type type) {
Class clazz;
if (type instanceof ParameterizedType) {
final ParameterizedType pts = (ParameterizedType) type;
clazz = (Class) (pts).getRawType();
} else if (type instanceof Class) {
clazz = (Class) type;
} else {
throw new ConvertException("not support the type (" + type + ")");
}
return createDecoder(type, clazz);
}
private <E> Decodeable<R, E> createDecoder(final Type type, final Class clazz) {
Decodeable<R, E> decoder = null;
ObjectDecoder od = null;
if (clazz.isEnum()) {
decoder = new EnumSimpledCoder(clazz);
} else if (clazz.isArray()) {
decoder = new ArrayDecoder(this, type);
} else if (Collection.class.isAssignableFrom(clazz)) {
decoder = new CollectionDecoder(this, type);
} else if (Map.class.isAssignableFrom(clazz)) {
decoder = new MapDecoder(this, type);
} else if (clazz == Object.class) {
od = new ObjectDecoder(type);
decoder = od;
} else if (!clazz.getName().startsWith("java.")) {
od = new ObjectDecoder(type);
decoder = od;
}
if (decoder == null) throw new ConvertException("not support the type (" + type + ")");
register(type, decoder);
if (od != null) od.init(this);
return decoder;
}
public final <E> Encodeable<W, E> loadEncoder(final Type type) {
Encodeable<W, E> encoder = findEncoder(type);
if (encoder != null) return encoder;
if (type instanceof GenericArrayType) return new ArrayEncoder(this, type);
Class clazz;
if (type instanceof ParameterizedType) {
final ParameterizedType pts = (ParameterizedType) type;
clazz = (Class) (pts).getRawType();
} else if (type instanceof TypeVariable) {
TypeVariable tv = (TypeVariable) type;
Type t = Object.class;
if (tv.getBounds().length == 1) {
t = tv.getBounds()[0];
}
if (!(t instanceof Class)) t = Object.class;
clazz = (Class) t;
} else if (type instanceof Class) {
clazz = (Class) type;
} else {
throw new ConvertException("not support the type (" + type + ")");
}
encoder = findEncoder(clazz);
if (encoder != null) return encoder;
return createEncoder(type, clazz);
}
public final <E> Encodeable<W, E> createEncoder(final Type type) {
Class clazz;
if (type instanceof ParameterizedType) {
final ParameterizedType pts = (ParameterizedType) type;
clazz = (Class) (pts).getRawType();
} else if (type instanceof Class) {
clazz = (Class) type;
} else {
throw new ConvertException("not support the type (" + type + ")");
}
return createEncoder(type, clazz);
}
private <E> Encodeable<W, E> createEncoder(final Type type, final Class clazz) {
Encodeable<W, E> encoder = null;
ObjectEncoder oe = null;
if (clazz.isEnum()) {
encoder = new EnumSimpledCoder(clazz);
} else if (clazz.isArray()) {
encoder = new ArrayEncoder(this, type);
} else if (Collection.class.isAssignableFrom(clazz)) {
encoder = new CollectionEncoder(this, type);
} else if (Map.class.isAssignableFrom(clazz)) {
encoder = new MapEncoder(this, type);
} else if (clazz == Object.class) {
return (Encodeable<W, E>) this.anyEncoder;
} else if (!clazz.getName().startsWith("java.")) {
oe = new ObjectEncoder(type);
encoder = oe;
}
if (encoder == null) throw new ConvertException("not support the type (" + type + ")");
register(type, encoder);
if (oe != null) oe.init(this);
return encoder;
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
/**
* 只增不减的伪Map类
*
* @author zhangjx
* @param <K>
* @param <V>
*/
@SuppressWarnings("unchecked")
public final class HashedMap<K, V> {
protected final transient Entry<K, V>[] table;
public HashedMap() {
this(128);
}
public HashedMap(int initCapacity) {
this.table = new Entry[Math.max(initCapacity, 16)];
}
public final V get(final K key) {
final K k = key;
final Entry<K, V>[] data = this.table;
Entry<K, V> entry = data[k.hashCode() & (data.length - 1)];
while (entry != null) {
if (k == entry.key) return entry.value;
entry = entry.next;
}
return null;
}
public final V put(K key, V value) {
final K k = key;
final Entry<K, V>[] data = this.table;
final int index = k.hashCode() & (data.length - 1);
Entry<K, V> entry = data[index];
while (entry != null) {
if (k == entry.key) {
entry.value = value;
return entry.value;
}
entry = entry.next;
}
data[index] = new Entry(key, value, data[index]);
return null;
}
protected static final class Entry<K, V> {
protected V value;
protected final K key;
protected final Entry<K, V> next;
protected Entry(K key, V value, Entry<K, V> next) {
this.key = key;
this.value = value;
this.next = next;
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import com.wentch.redkale.util.Creator;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
/**
*
* @author zhangjx
* @param <K>
* @param <V>
*/
@SuppressWarnings("unchecked")
public final class MapDecoder<K, V> implements Decodeable<Reader, Map<K, V>> {
private final Type type;
private final Type keyType;
private final Type valueType;
protected Creator<Map<K, V>> creator;
private final Decodeable<Reader, K> keyDecoder;
private final Decodeable<Reader, V> valueDecoder;
public MapDecoder(final Factory factory, final Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
this.keyType = pt.getActualTypeArguments()[0];
this.valueType = pt.getActualTypeArguments()[1];
this.creator = factory.loadCreator((Class) pt.getRawType());
factory.register(type, this);
this.keyDecoder = factory.loadDecoder(this.keyType);
this.valueDecoder = factory.loadDecoder(this.valueType);
} else {
throw new ConvertException("mapdecoder not support the type (" + type + ")");
}
}
@Override
public Map<K, V> convertFrom(Reader in) {
final int len = in.readMapB();
if (len == Reader.SIGN_NULL) return null;
final Map<K, V> result = this.creator.create();
if (len == Reader.SIGN_NOLENGTH) {
while (in.hasNext()) {
K key = keyDecoder.convertFrom(in);
in.skipBlank();
V value = valueDecoder.convertFrom(in);
result.put(key, value);
}
} else {
for (int i = 0; i < len; i++) {
K key = keyDecoder.convertFrom(in);
in.skipBlank();
V value = valueDecoder.convertFrom(in);
result.put(key, value);
}
}
in.readMapE();
return result;
}
@Override
public Type getType() {
return this.type;
}
}

View File

@@ -0,0 +1,62 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
/**
*
* @author zhangjx
* @param <K>
* @param <V>
*/
@SuppressWarnings("unchecked")
public final class MapEncoder<K, V> implements Encodeable<Writer, Map<K, V>> {
private final Type type;
private final Encodeable<Writer, K> keyencoder;
private final Encodeable<Writer, V> valencoder;
public MapEncoder(final Factory factory, final Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
final Type[] pt = ((ParameterizedType) type).getActualTypeArguments();
this.keyencoder = factory.loadEncoder(pt[0]);
this.valencoder = factory.loadEncoder(pt[1]);
} else {
this.keyencoder = factory.getAnyEncoder();
this.valencoder = factory.getAnyEncoder();
}
}
@Override
public void convertTo(Writer out, Map<K, V> value) {
final Map<K, V> values = value;
if (values == null) {
out.writeNull();
return;
}
out.writeMapB(values.size());
boolean first = true;
for (Map.Entry<K, V> en : values.entrySet()) {
if (!first) out.writeArrayMark();
this.keyencoder.convertTo(out, en.getKey());
out.writeMapMark();
this.valencoder.convertTo(out, en.getValue());
if (first) first = false;
}
out.writeMapE();
}
@Override
public Type getType() {
return type;
}
}

View File

@@ -0,0 +1,137 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import static com.wentch.redkale.convert.ObjectEncoder.TYPEZERO;
import com.wentch.redkale.util.Creator;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* @author zhangjx
* @param <R>
* @param <T>
*/
@SuppressWarnings("unchecked")
public final class ObjectDecoder<R extends Reader, T> implements Decodeable<R, T> {
protected final Type type;
protected final Class typeClass;
protected Creator<T> creator;
protected DeMember<R, T, ?>[] members;
protected Factory factory;
protected ObjectDecoder(Type type) {
this.type = ((type instanceof Class) && ((Class) type).isInterface()) ? Object.class : type;
if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
this.typeClass = (Class) pt.getRawType();
} else {
this.typeClass = (Class) type;
}
this.members = new DeMember[0];
}
public void init(final Factory factory) {
this.factory = factory;
if (type == Object.class) return;
Class clazz = null;
if (type instanceof ParameterizedType) {
final ParameterizedType pts = (ParameterizedType) type;
clazz = (Class) (pts).getRawType();
} else if (!(type instanceof Class)) {
throw new ConvertException("[" + type + "] is no a class");
} else {
clazz = (Class) type;
}
final Type[] virGenericTypes = this.typeClass.getTypeParameters();
final Type[] realGenericTypes = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments() : TYPEZERO;
this.creator = factory.loadCreator(clazz);
final Set<DeMember> list = new HashSet();
try {
ConvertColumnEntry ref;
for (final Field field : clazz.getFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
ref = factory.findRef(field);
if (ref != null && ref.ignore()) continue;
Type t = ObjectEncoder.makeGenericType(field.getGenericType(), virGenericTypes, realGenericTypes);
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, field, null, null), factory.loadDecoder(t)));
}
final boolean reversible = factory.isReversible();
for (final Method method : clazz.getMethods()) {
if (Modifier.isStatic(method.getModifiers())) continue;
if (Modifier.isAbstract(method.getModifiers())) continue;
if (method.isSynthetic()) continue;
if (method.getName().length() < 4) continue;
if (!method.getName().startsWith("set")) continue;
if (method.getParameterTypes().length != 1) continue;
if (method.getReturnType() != void.class) continue;
if (reversible) {
boolean is = method.getParameterTypes()[0] == boolean.class || method.getParameterTypes()[0] == Boolean.class;
try {
clazz.getMethod(method.getName().replaceFirst("set", is ? "is" : "get"));
} catch (Exception e) {
continue;
}
}
ref = factory.findRef(method);
if (ref != null && ref.ignore()) continue;
Type t = ObjectEncoder.makeGenericType(method.getGenericParameterTypes()[0], virGenericTypes, realGenericTypes);
list.add(new DeMember(ObjectEncoder.createAttribute(factory, clazz, null, null, method), factory.loadDecoder(t)));
}
this.members = list.toArray(new DeMember[list.size()]);
Arrays.sort(this.members);
} catch (Exception ex) {
throw new ConvertException(ex);
}
}
/**
* 对象格式: [0x1][short字段个数][字段名][字段值]...[0x2]
*
* @param in
* @return
*/
@Override
public final T convertFrom(final R in) {
final String clazz = in.readClassName();
if (clazz != null && !clazz.isEmpty()) return (T) factory.loadDecoder(factory.getEntity(clazz)).convertFrom(in);
if (in.readObjectB() == Reader.SIGN_NULL) return null;
final T result = this.creator.create();
final AtomicInteger index = new AtomicInteger();
while (in.hasNext()) {
DeMember member = in.readField(index, members);
in.skipBlank();
if (member == null) {
in.skipValue(); //跳过该属性的值
} else {
member.read(in, result);
}
index.incrementAndGet();
}
in.readObjectE();
return result;
}
@Override
public final Type getType() {
return this.type;
}
@Override
public String toString() {
return "ObjectDecoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
}
}

View File

@@ -0,0 +1,214 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import com.wentch.redkale.util.Attribute;
import com.wentch.redkale.util.Attribute.Attributes;
import java.lang.reflect.*;
import java.util.*;
/**
*
* @author zhangjx
* @param <W>
* @param <T>
*/
@SuppressWarnings("unchecked")
public final class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
static final Type[] TYPEZERO = new Type[0];
protected final Type type;
protected final Class typeClass;
protected EnMember[] members;
protected Factory factory;
protected ObjectEncoder(Type type) {
this.type = type;
if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
this.typeClass = (Class) pt.getRawType();
} else {
this.typeClass = (Class) type;
}
this.members = new EnMember[0];
}
static Type makeGenericType(final Type type, final Type[] virGenericTypes, final Type[] realGenericTypes) {
if (type instanceof Class) {
return type;
} else if (type instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) type;
Type[] paramTypes = pt.getActualTypeArguments();
final Type[] newTypes = new Type[paramTypes.length];
int count = 0;
for (int i = 0; i < newTypes.length; i++) {
newTypes[i] = makeGenericType(paramTypes[i], virGenericTypes, realGenericTypes);
if (paramTypes[i] == newTypes[i]) count++;
}
if (count == paramTypes.length) return pt;
return new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return newTypes;
}
@Override
public Type getRawType() {
return pt.getRawType();
}
@Override
public Type getOwnerType() {
return pt.getOwnerType();
}
};
}
if (realGenericTypes == null) return type;
if (type instanceof WildcardType) {
final WildcardType wt = (WildcardType) type;
for (Type f : wt.getUpperBounds()) {
for (int i = 0; i < virGenericTypes.length; i++) {
if (virGenericTypes[i] == f) return realGenericTypes.length == 0 ? Object.class : realGenericTypes[i];
}
}
} else if (type instanceof TypeVariable) {
for (int i = 0; i < virGenericTypes.length; i++) {
if (virGenericTypes[i] == type) return i >= realGenericTypes.length ? Object.class : realGenericTypes[i];
}
}
return type;
}
private static String readGetSetFieldName(Method method) {
if (method == null) return null;
String fname = method.getName();
if (!fname.startsWith("is") && !fname.startsWith("get") && !fname.startsWith("set")) return fname;
fname = fname.substring(fname.startsWith("is") ? 2 : 3);
if (fname.length() > 1 && !(fname.charAt(1) >= 'A' && fname.charAt(1) <= 'Z')) {
fname = Character.toLowerCase(fname.charAt(0)) + fname.substring(1);
} else if (fname.length() == 1) {
fname = "" + Character.toLowerCase(fname.charAt(0));
}
return fname;
}
static Attribute createAttribute(final Factory factory, Class clazz, final Field field, final Method getter, final Method setter) {
String fieldalias = null;
if (field != null) { // public field
ConvertColumnEntry ref = factory.findRef(field);
fieldalias = ref == null || ref.name().isEmpty() ? field.getName() : ref.name();
} else if (getter != null) {
ConvertColumnEntry ref = factory.findRef(getter);
String mfieldname = readGetSetFieldName(getter);
if (ref == null) {
try {
ref = factory.findRef(clazz.getDeclaredField(mfieldname));
} catch (Exception e) {
}
}
fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name();
} else { // setter != null
ConvertColumnEntry ref = factory.findRef(setter);
String mfieldname = readGetSetFieldName(setter);
if (ref == null) {
try {
ref = factory.findRef(clazz.getDeclaredField(mfieldname));
} catch (Exception e) {
}
}
fieldalias = ref == null || ref.name().isEmpty() ? mfieldname : ref.name();
}
return Attributes.create(clazz, fieldalias, field, getter, setter);
}
public void init(final Factory factory) {
this.factory = factory;
if (type == Object.class) return;
//if (!(type instanceof Class)) throw new ConvertException("[" + type + "] is no a class");
final Class clazz = this.typeClass;
final Set<EnMember> list = new HashSet();
final Type[] virGenericTypes = this.typeClass.getTypeParameters();
final Type[] realGenericTypes = (type instanceof ParameterizedType) ? ((ParameterizedType) type).getActualTypeArguments() : null;
if (realGenericTypes != null) {
// println(type + "," + Arrays.toString(virGenericTypes) + ", " + Arrays.toString(realGenericTypes));
}
try {
ConvertColumnEntry ref;
for (final Field field : clazz.getFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
ref = factory.findRef(field);
if (ref != null && ref.ignore()) continue;
Type t = makeGenericType(field.getGenericType(), virGenericTypes, realGenericTypes);
list.add(new EnMember(createAttribute(factory, clazz, field, null, null), factory.loadEncoder(t)));
}
final boolean reversible = factory.isReversible();
for (final Method method : clazz.getMethods()) {
if (Modifier.isStatic(method.getModifiers())) continue;
if (Modifier.isAbstract(method.getModifiers())) continue;
if (method.isSynthetic()) continue;
if (method.getName().length() < 3) continue;
if (method.getName().equals("getClass")) continue;
if (!method.getName().startsWith("is") && !method.getName().startsWith("get")) continue;
if (method.getParameterTypes().length != 0) continue;
if (method.getReturnType() == void.class) continue;
if (reversible) {
boolean is = method.getName().startsWith("is");
try {
clazz.getMethod(method.getName().replaceFirst(is ? "is" : "get", "set"), method.getReturnType());
} catch (Exception e) {
continue;
}
}
ref = factory.findRef(method);
if (ref != null && ref.ignore()) continue;
Type t = makeGenericType(method.getGenericReturnType(), virGenericTypes, realGenericTypes);
list.add(new EnMember(createAttribute(factory, clazz, null, method, null), factory.loadEncoder(t)));
}
this.members = list.toArray(new EnMember[list.size()]);
Arrays.sort(this.members);
} catch (Exception ex) {
throw new ConvertException(ex);
}
}
@Override
public final void convertTo(W out, T value) {
if (value == null) {
out.wirteClassName(null);
out.writeNull();
return;
}
if (value != null && value.getClass() != this.typeClass) {
final Class clz = value.getClass();
out.wirteClassName(factory.getEntity(clz));
factory.loadEncoder(clz).convertTo(out, value);
return;
}
out.writeObjectB(members.length, value);
boolean comma = false;
for (EnMember member : members) {
comma = member.write(out, comma, value);
}
out.writeObjectE(value);
}
@Override
public final Type getType() {
return this.type;
}
@Override
public String toString() {
return "ObjectEncoder{" + "type=" + type + ", members=" + Arrays.toString(members) + '}';
}
}

View File

@@ -0,0 +1,112 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.util.concurrent.atomic.AtomicInteger;
/**
*
* @author zhangjx
*/
public interface Reader {
public static final short SIGN_NULL = -1;
public static final short SIGN_NOLENGTH = -2;
/**
* 是否还存在下个元素或字段
*
* @return
*/
public boolean hasNext();
/**
* 跳过值(不包含值前面的字段)
*/
public void skipValue();
/**
* /跳过字段与值之间的多余内容, json就是跳过:符, map跳过:
*/
public void skipBlank();
/**
* 读取对象的开头 返回字段数
*
* @return
*/
public int readObjectB();
/**
* 读取对象的尾端
*
*/
public void readObjectE();
/**
* 读取数组的开头并返回数组的长度
*
* @return
*/
public int readArrayB();
/**
* 读取数组的尾端
*
*/
public void readArrayE();
/**
* 读取map的开头并返回map的size
*
* @return
*/
public int readMapB();
/**
* 读取数组的尾端
*
*/
public void readMapE();
/**
* 根据字段读取字段对应的DeMember
*
* @param index
* @param members
* @return
*/
public DeMember readField(final AtomicInteger index, final DeMember[] members);
public boolean readBoolean();
public byte readByte();
public char readChar();
public short readShort();
public int readInt();
public long readLong();
public float readFloat();
public double readDouble();
/**
* 读取无转义字符长度不超过255的字符串 例如枚举值、字段名、类名字符串等
*
* @return
*/
public String readSmallString();
public String readClassName();
public String readString();
}

View File

@@ -0,0 +1,42 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
* @param <T>
*/
public abstract class SimpledCoder<R extends Reader, W extends Writer, T> implements Decodeable<R, T>, Encodeable<W, T> {
private Type type;
@Override
public abstract void convertTo(final W out, final T value);
@Override
public abstract T convertFrom(final R in);
@Override
@SuppressWarnings("unchecked")
public Class<T> getType() {
if (type == null) {
Type[] ts = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
type = ts[ts.length - 1];
}
return (Class<T>) type;
}
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}

View File

@@ -0,0 +1,120 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert;
import com.wentch.redkale.util.Attribute;
/**
*
* @author zhangjx
*/
public interface Writer {
/**
* 当tiny=true时 字符串为空、boolean为false的字段值都会被跳过 不会输出。
* <p>
* @return
*/
public boolean isTiny();
/**
* 输出null值
*/
public void writeNull();
/**
*
* @param clazz
*/
public void wirteClassName(String clazz);
/**
* 输出一个对象前的操作
*
* @param fieldCount 字段个数
*
* @param obj
*/
public void writeObjectB(int fieldCount, Object obj);
/**
* 输出一个对象后的操作
*
* @param obj
*/
public void writeObjectE(Object obj);
/**
* 输出一个数组前的操作
*
* @param size 数组长度
*/
public void writeArrayB(int size);
/**
* 输出数组元素间的间隔符
*
*/
public void writeArrayMark();
/**
* 输出一个数组后的操作
*
*/
public void writeArrayE();
/**
* 输出一个Map前的操作
*
* @param size map大小
*/
public void writeMapB(int size);
/**
* 输出一个Map中key与value间的间隔符
*
*/
public void writeMapMark();
/**
* 输出一个Map后的操作
*
*/
public void writeMapE();
/**
* 输出一个字段
*
* @param comma 是否非第一个字段
* @param attribute
*/
public void writeField(boolean comma, Attribute attribute);
public void writeBoolean(boolean value);
public void writeByte(byte value);
public void writeChar(char value);
public void writeShort(short value);
public void writeInt(int value);
public void writeLong(long value);
public void writeFloat(float value);
public void writeDouble(double value);
/**
* 写入无转义字符长度不超过255的字符串 例如枚举值、字段名、类名字符串等 *
*
* @param value
*/
public void writeSmallString(String value);
public void writeString(String value);
}

View File

@@ -0,0 +1,104 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.bson;
import com.wentch.redkale.convert.*;
import com.wentch.redkale.util.*;
import java.lang.reflect.*;
import java.nio.*;
/**
* BSON协议格式:
* 1). 基本数据类型: 直接转换成byte[]
* 2). SmallString(无特殊字符且长度小于256的字符串): length(1 byte) + byte[](utf8); 通常用于类名、字段名、枚举。
* 3). String: length(4 bytes) + byte[](utf8);
* 4). 数组: length(4 bytes) + byte[]...
* 5). Object:
* 1. realclass (SmallString) (如果指定格式化的class与实体对象的class不一致才会有该值)
* 2. 空字符串(SmallString)
* 3. SIGN_OBJECTB 标记位值固定为0xBB (short)
* 4. 循环字段值:
* 4.1 SIGN_HASNEXT 标记位值固定为1 (byte)
* 4.2 字段类型; 1-9为基本类型&字符串; 101-109为基本类型&字符串的数组; 127为Object
* 4.3 字段名 (SmallString)
* 4.4 字段的值Object
* 5. SIGN_NONEXT 标记位值固定为0 (byte)
* 6. SIGN_OBJECTE 标记位值固定为0xEE (short)
*
* @author zhangjx
*/
public final class BsonConvert extends Convert<BsonReader, BsonWriter> {
private static final ObjectPool<BsonReader> readerPool = BsonReader.createPool(Integer.getInteger("convert.bson.pool.size", 16));
private static final ObjectPool<BsonWriter> writerPool = BsonWriter.createPool(Integer.getInteger("convert.bson.pool.size", 16));
private final boolean tiny;
protected BsonConvert(Factory<BsonReader, BsonWriter> factory, boolean tiny) {
super(factory);
this.tiny = tiny;
}
public <T> T convertFrom(final Type type, final byte[] bytes) {
if (bytes == null) return null;
return convertFrom(type, bytes, 0, bytes.length);
}
public <T> T convertFrom(final Type type, final byte[] bytes, int start, int len) {
if (type == null) return null;
final BsonReader in = readerPool.poll();
in.setBytes(bytes, start, len);
@SuppressWarnings("unchecked")
T rs = (T) factory.loadDecoder(type).convertFrom(in);
readerPool.offer(in);
return rs;
}
public byte[] convertTo(final Type type, Object value) {
if (type == null) return null;
final BsonWriter out = writerPool.poll();
out.setTiny(tiny);
factory.loadEncoder(type).convertTo(out, value);
byte[] result = out.toArray();
writerPool.offer(out);
return result;
}
public byte[] convertTo(Object value) {
if (value == null) {
final BsonWriter out = writerPool.poll();
out.setTiny(tiny);
out.writeNull();
byte[] result = out.toArray();
writerPool.offer(out);
return result;
}
return convertTo(value.getClass(), value);
}
public ByteBuffer convertToBuffer(final Type type, Object value) {
if (type == null) return null;
final BsonWriter out = writerPool.poll();
out.setTiny(tiny);
factory.loadEncoder(type).convertTo(out, value);
ByteBuffer result = out.toBuffer();
writerPool.offer(out);
return result;
}
public ByteBuffer convertToBuffer(Object value) {
if (value == null) {
final BsonWriter out = writerPool.poll();
out.setTiny(tiny);
out.writeNull();
ByteBuffer result = out.toBuffer();
writerPool.offer(out);
return result;
}
return convertToBuffer(value.getClass(), value);
}
}

View File

@@ -0,0 +1,62 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.bson;
import com.wentch.redkale.convert.*;
import java.io.Serializable;
/**
*
* @author zhangjx
*/
public final class BsonFactory extends Factory<BsonReader, BsonWriter> {
private static final BsonFactory instance = new BsonFactory(null, Boolean.getBoolean("convert.bson.tiny"));
static final Decodeable objectDecoder = instance.loadDecoder(Object.class);
static final Encodeable objectEncoder = instance.loadEncoder(Object.class);
static {
instance.register(Serializable.class, objectDecoder);
instance.register(Serializable.class, objectEncoder);
}
private BsonFactory(BsonFactory parent, boolean tiny) {
super(parent, tiny);
}
public static BsonFactory root() {
return instance;
}
@Override
public final BsonConvert getConvert() {
if (convert == null) convert = new BsonConvert(this, tiny);
return (BsonConvert) convert;
}
@Override
public BsonFactory createChild() {
return new BsonFactory(this, this.tiny);
}
@Override
public BsonFactory createChild(boolean tiny) {
return new BsonFactory(this, tiny);
}
@Override
public ConvertType getConvertType() {
return ConvertType.BSON;
}
@Override
public boolean isReversible() {
return true;
}
}

View File

@@ -0,0 +1,311 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.bson;
import com.wentch.redkale.convert.*;
import com.wentch.redkale.convert.ext.*;
import com.wentch.redkale.util.*;
import java.util.concurrent.atomic.*;
/**
*
* @author zhangjx
*/
public final class BsonReader implements Reader {
public static final short SIGN_OBJECTB = (short) 0xBB;
public static final short SIGN_OBJECTE = (short) 0xEE;
public static final byte SIGN_HASNEXT = 1;
public static final byte SIGN_NONEXT = 0;
public static final byte VERBOSE_NO = 1;
public static final byte VERBOSE_YES = 2;
private int position = -1;
private byte typeval; //字段的类型值 对应 BsonWriter.writeField
private byte[] content;
public BsonReader() {
}
public static ObjectPool<BsonReader> createPool(int max) {
return new ObjectPool<BsonReader>(max, new Creator<BsonReader>() {
@Override
public BsonReader create(Object... params) {
return new BsonReader();
}
}, null, new Predicate<BsonReader>() {
@Override
public boolean test(BsonReader t) {
return t.recycle();
}
});
}
public BsonReader(byte[] bytes) {
setBytes(bytes, 0, bytes.length);
}
public BsonReader(byte[] bytes, int start, int len) {
setBytes(bytes, start, len);
}
public final void setBytes(byte[] bytes) {
setBytes(bytes, 0, bytes.length);
}
public final void setBytes(byte[] bytes, int start, int len) {
this.content = bytes;
this.position = start - 1;
//this.limit = start + len - 1;
}
protected boolean recycle() {
this.position = -1;
this.typeval = 0;
//this.limit = -1;
this.content = null;
return true;
}
public void close() {
this.recycle();
}
/**
* 跳过属性的值
*/
@Override
public final void skipValue() {
if (typeval == 0) return;
final byte val = this.typeval;
this.typeval = 0;
switch (val) {
case 1: readBoolean();
break;
case 2: readByte();
break;
case 3: readShort();
break;
case 4: readChar();
break;
case 5: readInt();
break;
case 6: readLong();
break;
case 7: readFloat();
break;
case 8: readDouble();
break;
case 9: readString();
break;
case 101:
BoolArraySimpledCoder.instance.convertFrom(this);
break;
case 102:
ByteArraySimpledCoder.instance.convertFrom(this);
break;
case 103:
ShortArraySimpledCoder.instance.convertFrom(this);
break;
case 104:
CharArraySimpledCoder.instance.convertFrom(this);
break;
case 105:
IntArraySimpledCoder.instance.convertFrom(this);
break;
case 106:
LongArraySimpledCoder.instance.convertFrom(this);
break;
case 107:
FloatArraySimpledCoder.instance.convertFrom(this);
break;
case 108:
DoubleArraySimpledCoder.instance.convertFrom(this);
break;
case 109:
StringArraySimpledCoder.instance.convertFrom(this);
break;
case 127:
BsonFactory.objectDecoder.convertFrom(this);
break;
}
}
/**
* 判断下一个非空白字节是否为{
*
*/
@Override
public int readObjectB() {
short bt = readShort();
if (bt == Reader.SIGN_NULL) return bt;
if (bt != SIGN_OBJECTB) {
throw new ConvertException("a bson object must begin with " + (SIGN_OBJECTB)
+ " (position = " + position + ") but '" + this.content[this.position] + "'");
}
return bt;
}
@Override
public void readObjectE() {
if (readShort() != SIGN_OBJECTE) {
throw new ConvertException("a bson object must end with " + (SIGN_OBJECTE)
+ " (position = " + position + ") but '" + this.content[this.position] + "'");
}
}
@Override
public int readMapB() {
return readArrayB();
}
@Override
public void readMapE() {
}
/**
* 判断下一个非空白字节是否为[
*
* @return
*/
@Override
public int readArrayB() {
return readInt();
}
@Override
public void readArrayE() {
}
/**
* 判断下一个非空白字节是否:
*/
@Override
public void skipBlank() {
}
/**
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
*
* @return
*/
@Override
public boolean hasNext() {
byte b = readByte();
if (b == SIGN_HASNEXT) return true;
if (b != SIGN_NONEXT) throw new ConvertException("hasNext option must be (" + (SIGN_HASNEXT)
+ " or " + (SIGN_NONEXT) + ") but '" + b + "' at position(" + this.position + ")");
return false;
}
@Override
public DeMember readField(final AtomicInteger index, final DeMember[] members) {
final String exceptedfield = readSmallString();
this.typeval = readByte();
final int len = members.length;
int v = index.get();
if (v >= len) {
v = 0;
index.set(0);
}
for (int k = v; k < len; k++) {
if (exceptedfield.equals(members[k].getAttribute().field())) {
index.set(k);
return members[k];
}
}
for (int k = 0; k < v; k++) {
if (exceptedfield.equals(members[k].getAttribute().field())) {
index.set(k);
return members[k];
}
}
return null;
}
//------------------------------------------------------------
@Override
public boolean readBoolean() {
return content[++this.position] == 1;
}
@Override
public byte readByte() {
return content[++this.position];
}
@Override
public char readChar() {
return (char) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
}
@Override
public short readShort() {
return (short) ((0xff00 & (content[++this.position] << 8)) | (0xff & content[++this.position]));
}
@Override
public int readInt() {
return ((content[++this.position] & 0xff) << 24) | ((content[++this.position] & 0xff) << 16)
| ((content[++this.position] & 0xff) << 8) | (content[++this.position] & 0xff);
}
@Override
public long readLong() {
return ((((long) content[++this.position] & 0xff) << 56)
| (((long) content[++this.position] & 0xff) << 48)
| (((long) content[++this.position] & 0xff) << 40)
| (((long) content[++this.position] & 0xff) << 32)
| (((long) content[++this.position] & 0xff) << 24)
| (((long) content[++this.position] & 0xff) << 16)
| (((long) content[++this.position] & 0xff) << 8)
| (((long) content[++this.position] & 0xff)));
}
@Override
public float readFloat() {
return Float.intBitsToFloat(readInt());
}
@Override
public double readDouble() {
return Double.longBitsToDouble(readLong());
}
@Override
public String readClassName() {
return readSmallString();
}
@Override
public String readSmallString() {
int len = 0xff & readByte();
if (len == 0) return "";
String value = new String(content, ++this.position, len);
this.position += len - 1;
return value;
}
@Override
public String readString() {
int len = readInt();
if (len == SIGN_NULL) return null;
if (len == 0) return "";
String value = new String(Utility.decodeUTF8(content, ++this.position, len));
this.position += len - 1;
return value;
}
}

View File

@@ -0,0 +1,17 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.bson;
import com.wentch.redkale.convert.SimpledCoder;
/**
*
* @author zhangjx
* @param <T>
*/
public abstract class BsonSimpledCoder<T> extends SimpledCoder<BsonReader, BsonWriter, T> {
}

View File

@@ -0,0 +1,300 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.bson;
import com.wentch.redkale.convert.*;
import com.wentch.redkale.util.*;
import java.nio.*;
/**
*
* @author zhangjx
*/
public final class BsonWriter implements Writer {
private static final int defaultSize = Integer.getInteger("convert.bson.writer.buffer.defsize", 1024);
protected int count;
private byte[] content;
protected boolean tiny;
public static ObjectPool<BsonWriter> createPool(int max) {
return new ObjectPool<BsonWriter>(max, new Creator<BsonWriter>() {
@Override
public BsonWriter create(Object... params) {
return new BsonWriter();
}
}, null, new Predicate<BsonWriter>() {
@Override
public boolean test(BsonWriter t) {
return t.recycle();
}
});
}
public byte[] toArray() {
if (count == content.length) return content;
byte[] newdata = new byte[count];
System.arraycopy(content, 0, newdata, 0, count);
return newdata;
}
public ByteBuffer toBuffer() {
return ByteBuffer.wrap(content, 0, count);
}
public BsonWriter() {
this(defaultSize);
}
public BsonWriter(int size) {
this.content = new byte[size > 32 ? size : 32];
}
@Override
public boolean isTiny() {
return tiny;
}
public void setTiny(boolean tiny) {
this.tiny = tiny;
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
/**
* 返回指定至少指定长度的缓冲区
*
* @param len
* @return
*/
public byte[] expand(int len) {
int newcount = count + len;
if (newcount <= content.length) return content;
byte[] newdata = new byte[Math.max(content.length * 3 / 2, newcount)];
System.arraycopy(content, 0, newdata, 0, count);
this.content = newdata;
return newdata;
}
public void writeTo(final byte ch) {
expand(1);
content[count++] = ch;
}
public void writeTo(final byte... chs) {
int len = chs.length;
expand(len);
System.arraycopy(chs, 0, content, count, len);
count += len;
}
public void writeTo(final byte[] chs, final int start, final int end) {
int len = end - start;
expand(len);
System.arraycopy(chs, start, content, count, len);
count += len;
}
protected boolean recycle() {
this.count = 0;
if (this.content.length > defaultSize) {
this.content = new byte[defaultSize];
}
return true;
}
//------------------------------------------------------------------------
public final int count() {
return this.count;
}
public final void count(int count) {
if (count >= 0) this.count = count;
}
//-----------------------------------------------------------------------
@Override
public String toString() {
return new String(content, 0, count);
}
@Override
public void writeBoolean(boolean value) {
writeTo(value ? (byte) 1 : (byte) 0);
}
@Override
public void writeByte(byte value) {
writeTo(value);
}
@Override
public void writeChar(final char value) {
writeTo((byte) ((value & 0xFF00) >> 8), (byte) (value & 0xFF));
}
@Override
public void writeShort(short value) {
writeTo((byte) (value >> 8), (byte) value);
}
@Override
public void writeInt(int value) {
writeTo((byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
}
@Override
public void writeLong(long value) {
writeTo((byte) (value >> 56), (byte) (value >> 48), (byte) (value >> 40), (byte) (value >> 32),
(byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value);
}
@Override
public void writeFloat(float value) {
writeInt(Float.floatToIntBits(value));
}
@Override
public void writeDouble(double value) {
writeLong(Double.doubleToLongBits(value));
}
@Override
public void wirteClassName(String clazz) {
writeSmallString(clazz == null ? "" : clazz);
}
@Override
public final void writeObjectB(int fieldCount, Object obj) {
writeSmallString("");
writeShort(BsonReader.SIGN_OBJECTB);
}
@Override
public final void writeObjectE(Object obj) {
writeByte(BsonReader.SIGN_NONEXT);
writeShort(BsonReader.SIGN_OBJECTE);
}
@Override
public final void writeField(boolean comma, Attribute attribute) {
writeByte(BsonReader.SIGN_HASNEXT);
writeSmallString(attribute.field());
byte typeval = 127; //字段的类型值
final Class type = attribute.type();
if (type == boolean.class || type == Boolean.class) {
typeval = 1;
} else if (type == byte.class || type == Byte.class) {
typeval = 2;
} else if (type == short.class || type == Short.class) {
typeval = 3;
} else if (type == char.class || type == Character.class) {
typeval = 4;
} else if (type == int.class || type == Integer.class) {
typeval = 5;
} else if (type == long.class || type == Long.class) {
typeval = 6;
} else if (type == float.class || type == Float.class) {
typeval = 7;
} else if (type == double.class || type == Double.class) {
typeval = 8;
} else if (type == String.class) {
typeval = 9;
} else if (type == boolean[].class || type == Boolean[].class) {
typeval = 101;
} else if (type == byte[].class || type == Byte[].class) {
typeval = 102;
} else if (type == short[].class || type == Short[].class) {
typeval = 103;
} else if (type == char[].class || type == Character[].class) {
typeval = 104;
} else if (type == int[].class || type == Integer[].class) {
typeval = 105;
} else if (type == long[].class || type == Long[].class) {
typeval = 106;
} else if (type == float[].class || type == Float[].class) {
typeval = 107;
} else if (type == double[].class || type == Double[].class) {
typeval = 108;
} else if (type == String[].class) {
typeval = 109;
}
writeByte(typeval);
}
/**
* 对于类的字段名、枚举值这些长度一般不超过255且不会出现双字节字符的字符串采用writeSmallString处理, readSmallString用于读取
*
* @param value
*/
@Override
public void writeSmallString(String value) {
if (value.isEmpty()) {
writeTo((byte) 0);
return;
}
char[] chars = Utility.charArray(value);
if (chars.length > 255) throw new ConvertException("'" + value + "' has very long length");
byte[] bytes = new byte[chars.length + 1];
bytes[0] = (byte) chars.length;
for (int i = 0; i < chars.length; i++) {
if (chars[i] > Byte.MAX_VALUE) throw new ConvertException("'" + value + "' has double-word");
bytes[i + 1] = (byte) chars[i];
}
writeTo(bytes);
}
@Override
public void writeString(String value) {
if (value == null) {
writeInt(Reader.SIGN_NULL);
return;
} else if (value.isEmpty()) {
writeInt(0);
return;
}
byte[] bytes = Utility.encodeUTF8(value);
writeInt(bytes.length);
writeTo(bytes);
}
@Override
public final void writeNull() {
writeShort(Reader.SIGN_NULL);
}
@Override
public void writeArrayB(int size) {
writeInt(size);
}
@Override
public void writeArrayMark() {
}
@Override
public void writeArrayE() {
}
@Override
public void writeMapB(int size) {
writeArrayB(size);
}
@Override
public void writeMapMark() {
}
@Override
public void writeMapE() {
}
}

View File

@@ -0,0 +1,38 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
import com.wentch.redkale.convert.Reader;
import java.math.BigInteger;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class BigIntegerSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, BigInteger> {
public static final BigIntegerSimpledCoder instance = new BigIntegerSimpledCoder();
@Override
public void convertTo(W out, BigInteger value) {
if (value == null) {
out.writeNull();
return;
}
ByteArraySimpledCoder.instance.convertTo(out, value.toByteArray());
}
@Override
public BigInteger convertFrom(R in) {
byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in);
return bytes == null ? null : new BigInteger(bytes);
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class BoolArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, boolean[]> {
public static final BoolArraySimpledCoder instance = new BoolArraySimpledCoder();
@Override
public void convertTo(W out, boolean[] values) {
if (values == null) {
out.writeNull();
return;
}
out.writeArrayB(values.length);
boolean flag = false;
for (boolean v : values) {
if (flag) out.writeArrayMark();
out.writeBoolean(v);
flag = true;
}
out.writeArrayE();
}
@Override
public boolean[] convertFrom(R in) {
int len = in.readArrayB();
if (len == Reader.SIGN_NULL) {
return null;
} else if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
boolean[] data = new boolean[8];
while (in.hasNext()) {
if (size >= data.length) {
boolean[] newdata = new boolean[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = in.readBoolean();
}
in.readArrayE();
boolean[] newdata = new boolean[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
boolean[] values = new boolean[len];
for (int i = 0; i < values.length; i++) {
values[i] = in.readBoolean();
}
in.readArrayE();
return values;
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class BoolSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Boolean> {
public static final BoolSimpledCoder instance = new BoolSimpledCoder();
@Override
public void convertTo(W out, Boolean value) {
out.writeBoolean(value);
}
@Override
public Boolean convertFrom(R in) {
return in.readBoolean();
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class ByteArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, byte[]> {
public static final ByteArraySimpledCoder instance = new ByteArraySimpledCoder();
@Override
public void convertTo(W out, byte[] values) {
if (values == null) {
out.writeNull();
return;
}
out.writeArrayB(values.length);
boolean flag = false;
for (byte v : values) {
if (flag) out.writeArrayMark();
out.writeByte(v);
flag = true;
}
out.writeArrayE();
}
@Override
public byte[] convertFrom(R in) {
int len = in.readArrayB();
if (len == Reader.SIGN_NULL) {
return null;
} else if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
byte[] data = new byte[8];
while (in.hasNext()) {
if (size >= data.length) {
byte[] newdata = new byte[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = in.readByte();
}
in.readArrayE();
byte[] newdata = new byte[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
byte[] values = new byte[len];
for (int i = 0; i < values.length; i++) {
values[i] = in.readByte();
}
in.readArrayE();
return values;
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class ByteSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Byte> {
public static final ByteSimpledCoder instance = new ByteSimpledCoder();
@Override
public void convertTo(W out, Byte value) {
out.writeByte(value);
}
@Override
public Byte convertFrom(R in) {
return in.readByte();
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class CharArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, char[]> {
public static final CharArraySimpledCoder instance = new CharArraySimpledCoder();
@Override
public void convertTo(W out, char[] values) {
if (values == null) {
out.writeNull();
return;
}
out.writeArrayB(values.length);
boolean flag = false;
for (char v : values) {
if (flag) out.writeArrayMark();
out.writeChar(v);
flag = true;
}
out.writeArrayE();
}
@Override
public char[] convertFrom(R in) {
int len = in.readArrayB();
if (len == Reader.SIGN_NULL) {
return null;
} else if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
char[] data = new char[8];
while (in.hasNext()) {
if (size >= data.length) {
char[] newdata = new char[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = in.readChar();
}
in.readArrayE();
char[] newdata = new char[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
char[] values = new char[len];
for (int i = 0; i < values.length; i++) {
values[i] = in.readChar();
}
in.readArrayE();
return values;
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class CharSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Character> {
public static final CharSimpledCoder instance = new CharSimpledCoder();
@Override
public void convertTo(W out, Character value) {
out.writeChar(value);
}
@Override
public Character convertFrom(R in) {
return in.readChar();
}
}

View File

@@ -0,0 +1,40 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.Writer;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.util.DLong;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class DLongSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, DLong> {
public static final DLongSimpledCoder instance = new DLongSimpledCoder();
@Override
public void convertTo(final W out, final DLong value) {
if (value == null) {
out.writeNull();
} else {
out.writeSmallString(value.getFirst() + "_" + value.getSecond());
}
}
@Override
public DLong convertFrom(R in) {
String str = in.readString();
if (str == null) return null;
int pos = str.indexOf('_');
return new DLong(Long.parseLong(str.substring(0, pos)), Long.parseLong(str.substring(pos + 1)));
}
}

View File

@@ -0,0 +1,33 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
import java.util.Date;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class DateSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Date> {
public static final DateSimpledCoder instance = new DateSimpledCoder();
@Override
public void convertTo(W out, Date value) {
out.writeLong(value.getTime());
}
@Override
public Date convertFrom(R in) {
return new Date(in.readLong());
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class DoubleArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, double[]> {
public static final DoubleArraySimpledCoder instance = new DoubleArraySimpledCoder();
@Override
public void convertTo(W out, double[] values) {
if (values == null) {
out.writeNull();
return;
}
out.writeArrayB(values.length);
boolean flag = false;
for (double v : values) {
if (flag) out.writeArrayMark();
out.writeDouble(v);
flag = true;
}
out.writeArrayE();
}
@Override
public double[] convertFrom(R in) {
int len = in.readArrayB();
if (len == Reader.SIGN_NULL) {
return null;
} else if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
double[] data = new double[8];
while (in.hasNext()) {
if (size >= data.length) {
double[] newdata = new double[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = in.readDouble();
}
in.readArrayE();
double[] newdata = new double[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
double[] values = new double[len];
for (int i = 0; i < values.length; i++) {
values[i] = in.readDouble();
}
in.readArrayE();
return values;
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class DoubleSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Double> {
public static final DoubleSimpledCoder instance = new DoubleSimpledCoder();
@Override
public void convertTo(W out, Double value) {
out.writeDouble(value);
}
@Override
public Double convertFrom(R in) {
return in.readDouble();
}
}

View File

@@ -0,0 +1,44 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
* @param <E>
*/
public final class EnumSimpledCoder<R extends Reader, W extends Writer, E extends Enum> extends SimpledCoder<R, W, E> {
private final Class<E> type;
public EnumSimpledCoder(Class<E> type) {
this.type = type;
}
@Override
public void convertTo(final W out, final E value) {
if (value == null) {
out.writeNull();
} else {
out.writeSmallString(value.toString());
}
}
@Override
@SuppressWarnings("unchecked")
public E convertFrom(final R in) {
String value = in.readSmallString();
if (value == null) return null;
return (E) Enum.valueOf(type, value);
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class FloatArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, float[]> {
public static final FloatArraySimpledCoder instance = new FloatArraySimpledCoder();
@Override
public void convertTo(W out, float[] values) {
if (values == null) {
out.writeNull();
return;
}
out.writeArrayB(values.length);
boolean flag = false;
for (float v : values) {
if (flag) out.writeArrayMark();
out.writeFloat(v);
flag = true;
}
out.writeArrayE();
}
@Override
public float[] convertFrom(R in) {
int len = in.readArrayB();
if (len == Reader.SIGN_NULL) {
return null;
} else if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
float[] data = new float[8];
while (in.hasNext()) {
if (size >= data.length) {
float[] newdata = new float[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = in.readFloat();
}
in.readArrayE();
float[] newdata = new float[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
float[] values = new float[len];
for (int i = 0; i < values.length; i++) {
values[i] = in.readFloat();
}
in.readArrayE();
return values;
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class FloatSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Float> {
public static final FloatSimpledCoder instance = new FloatSimpledCoder();
@Override
public void convertTo(W out, Float value) {
out.writeFloat(value);
}
@Override
public Float convertFrom(R in) {
return in.readFloat();
}
}

View File

@@ -0,0 +1,70 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
import com.wentch.redkale.convert.Reader;
import java.net.*;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class InetAddressSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, InetAddress> {
public static final InetAddressSimpledCoder instance = new InetAddressSimpledCoder();
@Override
public void convertTo(W out, InetAddress value) {
if (value == null) {
out.writeNull();
return;
}
ByteArraySimpledCoder.instance.convertTo(out, value.getAddress());
}
@Override
public InetAddress convertFrom(R in) {
byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in);
if (bytes == null) return null;
try {
return InetAddress.getByAddress(bytes);
} catch (Exception ex) {
return null;
}
}
public final static class InetSocketAddressSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, InetSocketAddress> {
public static final InetSocketAddressSimpledCoder instance = new InetSocketAddressSimpledCoder();
@Override
public void convertTo(W out, InetSocketAddress value) {
if (value == null) {
out.writeNull();
return;
}
ByteArraySimpledCoder.instance.convertTo(out, value.getAddress().getAddress());
out.writeInt(value.getPort());
}
@Override
public InetSocketAddress convertFrom(R in) {
byte[] bytes = ByteArraySimpledCoder.instance.convertFrom(in);
if (bytes == null) return null;
int port = in.readInt();
try {
return new InetSocketAddress(InetAddress.getByAddress(bytes), port);
} catch (Exception ex) {
return null;
}
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class IntArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, int[]> {
public static final IntArraySimpledCoder instance = new IntArraySimpledCoder();
@Override
public void convertTo(W out, int[] values) {
if (values == null) {
out.writeNull();
return;
}
out.writeArrayB(values.length);
boolean flag = false;
for (int v : values) {
if (flag) out.writeArrayMark();
out.writeInt(v);
flag = true;
}
out.writeArrayE();
}
@Override
public int[] convertFrom(R in) {
int len = in.readArrayB();
if (len == Reader.SIGN_NULL) {
return null;
} else if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
int[] data = new int[8];
while (in.hasNext()) {
if (size >= data.length) {
int[] newdata = new int[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = in.readInt();
}
in.readArrayE();
int[] newdata = new int[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
int[] values = new int[len];
for (int i = 0; i < values.length; i++) {
values[i] = in.readInt();
}
in.readArrayE();
return values;
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class IntSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Integer> {
public static final IntSimpledCoder instance = new IntSimpledCoder();
@Override
public void convertTo(W out, Integer value) {
out.writeInt(value);
}
@Override
public Integer convertFrom(R in) {
return in.readInt();
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class LongArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, long[]> {
public static final LongArraySimpledCoder instance = new LongArraySimpledCoder();
@Override
public void convertTo(W out, long[] values) {
if (values == null) {
out.writeNull();
return;
}
out.writeArrayB(values.length);
boolean flag = false;
for (long v : values) {
if (flag) out.writeArrayMark();
out.writeLong(v);
flag = true;
}
out.writeArrayE();
}
@Override
public long[] convertFrom(R in) {
int len = in.readArrayB();
if (len == Reader.SIGN_NULL) {
return null;
} else if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
long[] data = new long[8];
while (in.hasNext()) {
if (size >= data.length) {
long[] newdata = new long[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = in.readInt();
}
in.readArrayE();
long[] newdata = new long[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
long[] values = new long[len];
for (int i = 0; i < values.length; i++) {
values[i] = in.readInt();
}
in.readArrayE();
return values;
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class LongSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Long> {
public static final LongSimpledCoder instance = new LongSimpledCoder();
@Override
public void convertTo(W out, Long value) {
out.writeLong(value);
}
@Override
public Long convertFrom(R in) {
return in.readLong();
}
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class NumberSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Number> {
public static final NumberSimpledCoder instance = new NumberSimpledCoder();
@Override
public void convertTo(W out, Number value) {
out.writeLong(value == null ? 0L : value.longValue());
}
@Override
public Number convertFrom(R in) {
return in.readLong();
}
}

View File

@@ -0,0 +1,38 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.*;
import java.util.regex.*;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public class PatternSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Pattern> {
public static final PatternSimpledCoder instance = new PatternSimpledCoder();
@Override
public void convertTo(W out, Pattern value) {
if (value == null) {
out.writeNull();
} else {
out.writeString(value.flags() + "," + value.pattern());
}
}
@Override
public Pattern convertFrom(R in) {
String value = in.readString();
if (value == null) return null;
int pos = value.indexOf(',');
return Pattern.compile(value.substring(pos + 1), Integer.parseInt(value.substring(0, pos)));
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class ShortArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, short[]> {
public static final ShortArraySimpledCoder instance = new ShortArraySimpledCoder();
@Override
public void convertTo(W out, short[] values) {
if (values == null) {
out.writeNull();
return;
}
out.writeArrayB(values.length);
boolean flag = false;
for (short v : values) {
if (flag) out.writeArrayMark();
out.writeShort(v);
flag = true;
}
out.writeArrayE();
}
@Override
public short[] convertFrom(R in) {
int len = in.readArrayB();
if (len == Reader.SIGN_NULL) {
return null;
} else if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
short[] data = new short[8];
while (in.hasNext()) {
if (size >= data.length) {
short[] newdata = new short[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = in.readShort();
}
in.readArrayE();
short[] newdata = new short[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
short[] values = new short[len];
for (int i = 0; i < values.length; i++) {
values[i] = in.readShort();
}
in.readArrayE();
return values;
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class ShortSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Short> {
public static final ShortSimpledCoder instance = new ShortSimpledCoder();
@Override
public void convertTo(W out, Short value) {
out.writeShort(value);
}
@Override
public Short convertFrom(R in) {
return in.readShort();
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class StringArraySimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, String[]> {
public static final StringArraySimpledCoder instance = new StringArraySimpledCoder();
@Override
public void convertTo(W out, String[] values) {
if (values == null) {
out.writeNull();
return;
}
out.writeArrayB(values.length);
boolean flag = false;
for (String v : values) {
if (flag) out.writeArrayMark();
out.writeString(v);
flag = true;
}
out.writeArrayE();
}
@Override
public String[] convertFrom(R in) {
int len = in.readArrayB();
if (len == Reader.SIGN_NULL) {
return null;
} else if (len == Reader.SIGN_NOLENGTH) {
int size = 0;
String[] data = new String[8];
while (in.hasNext()) {
if (size >= data.length) {
String[] newdata = new String[data.length + 4];
System.arraycopy(data, 0, newdata, 0, size);
data = newdata;
}
data[size++] = in.readString();
}
in.readArrayE();
String[] newdata = new String[size];
System.arraycopy(data, 0, newdata, 0, size);
return newdata;
} else {
String[] values = new String[len];
for (int i = 0; i < values.length; i++) {
values[i] = in.readString();
}
in.readArrayE();
return values;
}
}
}

View File

@@ -0,0 +1,32 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.SimpledCoder;
import com.wentch.redkale.convert.Writer;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class StringSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, String> {
public static final StringSimpledCoder instance = new StringSimpledCoder();
@Override
public void convertTo(W out, String value) {
out.writeString(value);
}
@Override
public String convertFrom(R in) {
return in.readString();
}
}

View File

@@ -0,0 +1,42 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.ext;
import com.wentch.redkale.convert.Reader;
import com.wentch.redkale.convert.Writer;
import com.wentch.redkale.convert.SimpledCoder;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public class TypeSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<R, W, Class> {
public static final TypeSimpledCoder instance = new TypeSimpledCoder();
@Override
public void convertTo(final W out, final Class value) {
if (value == null) {
out.writeNull();
} else {
out.writeSmallString(value.getName());
}
}
@Override
public Class convertFrom(R in) {
String str = in.readSmallString();
if (str == null) return null;
try {
return Class.forName(str);
} catch (Exception e) {
return null;
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.json;
import com.wentch.redkale.convert.*;
import com.wentch.redkale.convert.ext.*;
import java.net.*;
/**
*
* @author zhangjx
* @param <R>
* @param <W>
*/
public final class InetAddressJsonSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<JsonReader, JsonWriter, InetAddress> {
public static final InetAddressJsonSimpledCoder instance = new InetAddressJsonSimpledCoder();
@Override
public void convertTo(JsonWriter out, InetAddress value) {
if (value == null) {
out.writeNull();
return;
}
StringSimpledCoder.instance.convertTo(out, value.getHostAddress());
}
@Override
public InetAddress convertFrom(JsonReader in) {
String str = StringSimpledCoder.instance.convertFrom(in);
if (str == null) return null;
try {
return InetAddress.getByName(str);
} catch (Exception ex) {
return null;
}
}
public final static class InetSocketAddressJsonSimpledCoder<R extends Reader, W extends Writer> extends SimpledCoder<JsonReader, JsonWriter, InetSocketAddress> {
public static final InetSocketAddressJsonSimpledCoder instance = new InetSocketAddressJsonSimpledCoder();
@Override
public void convertTo(JsonWriter out, InetSocketAddress value) {
if (value == null) {
out.writeNull();
return;
}
StringSimpledCoder.instance.convertTo(out, value.getHostString() + ":" + value.getPort());
}
@Override
public InetSocketAddress convertFrom(JsonReader in) {
String str = StringSimpledCoder.instance.convertFrom(in);
if (str == null) return null;
try {
int pos = str.indexOf(':');
return new InetSocketAddress(str.substring(0, pos), Integer.parseInt(str.substring(pos + 1)));
} catch (Exception ex) {
return null;
}
}
}
}

View File

@@ -0,0 +1,88 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.json;
import com.wentch.redkale.convert.*;
import com.wentch.redkale.util.*;
import java.lang.reflect.*;
/**
*
* @author zhangjx
*/
@SuppressWarnings("unchecked")
public final class JsonConvert extends Convert<JsonReader, JsonWriter> {
public static final Type TYPE_MAP_STRING_STRING = new TypeToken<java.util.LinkedHashMap<String, String>>() {
}.getType();
private static final ObjectPool<JsonReader> readerPool = JsonReader.createPool(Integer.getInteger("convert.json.pool.size", 16));
private static final ObjectPool<JsonWriter> writerPool = JsonWriter.createPool(Integer.getInteger("convert.json.pool.size", 16));
private final boolean tiny;
protected JsonConvert(JsonFactory factory, boolean tiny) {
super(factory);
this.tiny = tiny;
}
@Override
public JsonFactory getFactory() {
return (JsonFactory) factory;
}
public <T> T convertFrom(final Type type, final String text) {
if (text == null) return null;
return convertFrom(type, Utility.charArray(text));
}
public <T> T convertFrom(final Type type, final char[] text) {
if (text == null) return null;
return convertFrom(type, text, 0, text.length);
}
public <T> T convertFrom(final Type type, final char[] text, int start, int len) {
if (text == null || type == null) return null;
final JsonReader in = readerPool.poll();
in.setText(text, start, len);
T rs = (T) factory.loadDecoder(type).convertFrom(in);
readerPool.offer(in);
return rs;
}
public String convertTo(final Type type, Object value) {
if (type == null) return null;
if (value == null) return "null";
final JsonWriter out = writerPool.poll();
out.setTiny(tiny);
factory.loadEncoder(type).convertTo(out, value);
String result = out.toString();
writerPool.offer(out);
return result;
}
public String convertTo(Object value) {
if (value == null) return "null";
return convertTo(value.getClass(), value);
}
public byte[] convertToUTF8Bytes(Object value) {
if (value == null) return new byte[]{110, 117, 108, 108};
return convertToUTF8Bytes(value.getClass(), value);
}
public byte[] convertToUTF8Bytes(final Type type, Object value) {
if (type == null) return null;
if (value == null) return new byte[]{110, 117, 108, 108};
final JsonWriter out = writerPool.poll();
out.setTiny(tiny);
factory.loadEncoder(type).convertTo(out, value);
byte[] result = out.toUTF8Bytes();
writerPool.offer(out);
return result;
}
}

View File

@@ -0,0 +1,60 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.json;
import com.wentch.redkale.convert.ConvertType;
import com.wentch.redkale.convert.Factory;
import java.io.Serializable;
import java.net.*;
/**
*
* @author zhangjx
*/
public final class JsonFactory extends Factory<JsonReader, JsonWriter> {
private static final JsonFactory instance = new JsonFactory(null, Boolean.getBoolean("convert.json.tiny"));
static {
instance.register(InetAddress.class, InetAddressJsonSimpledCoder.instance);
instance.register(InetSocketAddress.class, InetAddressJsonSimpledCoder.InetSocketAddressJsonSimpledCoder.instance);
instance.register(Serializable.class, instance.loadEncoder(Object.class));
}
private JsonFactory(JsonFactory parent, boolean tiny) {
super(parent, tiny);
}
public static JsonFactory root() {
return instance;
}
@Override
public final JsonConvert getConvert() {
if (convert == null) convert = new JsonConvert(this, tiny);
return (JsonConvert) convert;
}
@Override
public JsonFactory createChild() {
return new JsonFactory(this, this.tiny);
}
@Override
public JsonFactory createChild(boolean tiny) {
return new JsonFactory(this, tiny);
}
@Override
public ConvertType getConvertType() {
return ConvertType.JSON;
}
@Override
public boolean isReversible() {
return false;
}
}

View File

@@ -0,0 +1,575 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.json;
import com.wentch.redkale.convert.*;
import com.wentch.redkale.util.*;
import java.util.concurrent.atomic.*;
/**
*
* @author zhangjx
*/
public final class JsonReader implements Reader {
private int position = -1;
private char[] text;
private int limit;
public static ObjectPool<JsonReader> createPool(int max) {
return new ObjectPool<JsonReader>(max, new Creator<JsonReader>() {
@Override
public JsonReader create(Object... params) {
return new JsonReader();
}
}, null, new Predicate<JsonReader>() {
@Override
public boolean test(JsonReader t) {
return t.recycle();
}
});
}
public JsonReader() {
}
public JsonReader(String json) {
setText(Utility.charArray(json));
}
public JsonReader(char[] text) {
setText(text, 0, text.length);
}
public JsonReader(char[] text, int start, int len) {
setText(text, start, len);
}
public final void setText(String text) {
JsonReader.this.setText(Utility.charArray(text));
}
public final void setText(char[] text) {
setText(text, 0, text.length);
}
public final void setText(char[] text, int start, int len) {
this.text = text;
this.position = start - 1;
this.limit = start + len - 1;
}
protected boolean recycle() {
this.position = -1;
this.limit = -1;
this.text = null;
return true;
}
public void close() {
this.recycle();
}
/**
* 找到指定的属性值 例如: {id : 1, data : { name : 'a', items : [1,2,3]}} seek('data.items') 直接跳转到 [1,2,3];
*
* @param key
*/
public final void seek(String key) {
if (key == null || key.length() < 1) return;
final String[] keys = key.split("\\.");
nextGoodChar(); //读掉 { [
for (String key1 : keys) {
while (this.hasNext()) {
String field = this.readSmallString();
skipBlank();
if (key1.equals(field)) break;
skipValue();
}
}
}
/**
* 跳过属性的值
*/
@Override
public final void skipValue() {
final char ch = nextGoodChar();
if (ch == '"' || ch == '\'') {
backChar(ch);
readString();
} else if (ch == '{') {
while (hasNext()) {
this.readSmallString(); //读掉field
this.skipBlank();
this.skipValue();
}
} else if (ch == '[') {
while (hasNext()) {
this.skipValue();
}
} else {
char c;
for (;;) {
c = nextChar();
if (c <= ' ') return;
if (c == '}' || c == ']' || c == ',' || c == ':') {
backChar(c);
return;
}
}
}
}
/**
* 读取下一个字符, 不跳过空白字符
*
* @return
*/
protected char nextChar() {
return this.text[++this.position];
}
/**
* 跳过空白字符, 返回一个非空白字符
*
* @return
*/
protected char nextGoodChar() {
char c = nextChar();
if (c > ' ') return c;
for (;;) {
c = nextChar();
if (c > ' ') return c;
}
}
/**
* 回退最后读取的字符
*
* @param ch
*/
protected void backChar(char ch) {
this.position--;
}
/**
* 判断下一个非空白字符是否为{
*
*/
@Override
public int readObjectB() {
char ch = this.text[++this.position];
if (ch == '{') return SIGN_NOLENGTH;
if (ch <= ' ') {
for (;;) {
ch = this.text[++this.position];
if (ch > ' ') break;
}
if (ch == '{') return SIGN_NOLENGTH;
}
if (ch == 'n' && text[++position] == 'u' && text[++position] == 'l' && text[++position] == 'l') return SIGN_NULL;
if (ch == 'N' && text[++position] == 'U' && text[++position] == 'L' && text[++position] == 'L') return SIGN_NULL;
throw new ConvertException("a json object text must begin with '{' (position = " + position + ") but '" + ch + "' in (" + new String(this.text) + ")");
}
@Override
public void readObjectE() {
}
/**
* 判断下一个非空白字符是否为{
*
*/
@Override
public int readMapB() {
return readArrayB();
}
@Override
public void readMapE() {
}
/**
* 判断下一个非空白字符是否为[
*
* @return
*/
@Override
public int readArrayB() {
char ch = this.text[++this.position];
if (ch == '[') return SIGN_NOLENGTH;
if (ch == '{') return SIGN_NOLENGTH;
if (ch <= ' ') {
for (;;) {
ch = this.text[++this.position];
if (ch > ' ') break;
}
if (ch == '[') return SIGN_NOLENGTH;
if (ch == '{') return SIGN_NOLENGTH;
}
if (ch == 'n' && text[++position] == 'u' && text[++position] == 'l' && text[++position] == 'l') return SIGN_NULL;
if (ch == 'N' && text[++position] == 'U' && text[++position] == 'L' && text[++position] == 'L') return SIGN_NULL;
throw new ConvertException("a json array text must begin with '[' (position = " + position + ") but '" + ch + "' in (" + new String(this.text) + ")");
}
@Override
public void readArrayE() {
}
/**
* 判断下一个非空白字符是否:
*/
@Override
public void skipBlank() {
char ch = this.text[++this.position];
if (ch == ':') return;
if (ch <= ' ') {
for (;;) {
ch = this.text[++this.position];
if (ch > ' ') break;
}
if (ch == ':') return;
}
throw new ConvertException("'" + new String(text) + "'expected a ':' but '" + ch + "'(position = " + position + ") in (" + new String(this.text) + ")");
}
/**
* 判断对象是否存在下一个属性或者数组是否存在下一个元素
*
* @return
*/
@Override
public boolean hasNext() {
char ch = this.text[++this.position];
if (ch == ',') return true;
if (ch == '}' || ch == ']') return false;
if (ch <= ' ') {
for (;;) {
ch = this.text[++this.position];
if (ch > ' ') break;
}
if (ch == ',') return true;
if (ch == '}' || ch == ']') return false;
}
this.position--;
return true;
}
@Override
public String readClassName() {
return null;
}
@Override
public String readSmallString() {
final int eof = this.limit;
if (this.position == eof) return null;
final char[] text0 = this.text;
int currpos = this.position;
char ch = text0[++currpos];
if (ch <= ' ') {
for (;;) {
ch = text0[++currpos];
if (ch > ' ') break;
}
}
if (ch == '"' || ch == '\'') {
final char quote = ch;
final int start = currpos + 1;
for (;;) {
ch = text0[++currpos];
if (ch == '\\') {
this.position = currpos - 1;
return readEscapeValue(quote, start);
} else if (ch == quote) {
break;
}
}
this.position = currpos;
char[] chs = new char[currpos - start];
System.arraycopy(text0, start, chs, 0, chs.length);
return new String(chs);
} else {
int start = currpos;
for (;;) {
if (currpos == eof) break;
ch = text0[++currpos];
if (ch == ',' || ch == ']' || ch == '}' || ch <= ' ' || ch == ':') break;
}
int len = currpos - start;
if (len < 1) {
this.position = currpos;
return String.valueOf(ch);
}
this.position = currpos - 1;
if (len == 4 && text0[start] == 'n' && text0[start + 1] == 'u' && text0[start + 2] == 'l' && text0[start + 3] == 'l') return null;
return new String(text0, start, len);
}
}
/**
* 读取一个int
*
* @return
*/
@Override
public final int readInt() {
final char[] text0 = this.text;
final int eof = this.limit;
int currpos = this.position;
char firstchar = text0[++currpos];
if (firstchar <= ' ') {
for (;;) {
firstchar = text0[++currpos];
if (firstchar > ' ') break;
}
}
if (firstchar == '"' || firstchar == '\'') {
firstchar = text0[++currpos];
if (firstchar == '"' || firstchar == '\'') {
this.position = currpos;
return 0;
}
}
int value = 0;
final boolean negative = firstchar == '-';
if (!negative) {
if (firstchar < '0' || firstchar > '9') throw new NumberFormatException("illegal escape(" + firstchar + ") (position = " + currpos + ") in (" + new String(this.text) + ")");
value = firstchar - '0';
}
for (;;) {
if (currpos == eof) break;
char ch = text0[++currpos];
if (ch >= '0' && ch <= '9') {
value = (value << 3) + (value << 1) + (ch - '0');
} else if (ch == '"' || ch == '\'') {
} else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') {
break;
} else {
throw new NumberFormatException("illegal escape(" + ch + ") (position = " + currpos + ") in (" + new String(this.text) + ")");
}
}
this.position = currpos - 1;
return negative ? -value : value;
}
/**
* 读取一个long
*
* @return
*/
@Override
public final long readLong() {
final char[] text0 = this.text;
final int eof = this.limit;
int currpos = this.position;
char firstchar = text0[++currpos];
if (firstchar <= ' ') {
for (;;) {
firstchar = text0[++currpos];
if (firstchar > ' ') break;
}
}
if (firstchar == '"' || firstchar == '\'') {
firstchar = text0[++currpos];
if (firstchar == '"' || firstchar == '\'') {
this.position = currpos;
return 0L;
}
}
long value = 0;
final boolean negative = firstchar == '-';
if (!negative) {
if (firstchar < '0' || firstchar > '9') throw new NumberFormatException("illegal escape(" + firstchar + ") (position = " + currpos + ") in (" + new String(this.text) + ")");
value = firstchar - '0';
}
for (;;) {
if (currpos == eof) break;
char ch = text0[++currpos];
if (ch >= '0' && ch <= '9') {
value = (value << 3) + (value << 1) + (ch - '0');
} else if (ch == '"' || ch == '\'') {
} else if (ch == ',' || ch == '}' || ch == ']' || ch <= ' ' || ch == ':') {
break;
} else {
throw new NumberFormatException("illegal escape(" + ch + ") (position = " + currpos + ") but '" + ch + "' in (" + new String(this.text) + ")");
}
}
this.position = currpos - 1;
return negative ? -value : value;
}
@Override
public DeMember readField(final AtomicInteger index, final DeMember[] members) {
final String exceptedfield = this.readSmallString();
final int len = members.length;
int v = index.get();
if (v >= len) {
v = 0;
index.set(0);
}
for (int k = v; k < len; k++) {
if (exceptedfield.equals(members[k].getAttribute().field())) {
index.set(k);
return members[k];
}
}
for (int k = 0; k < v; k++) {
if (exceptedfield.equals(members[k].getAttribute().field())) {
index.set(k);
return members[k];
}
}
return null;
//if (result == null && len == 1 && text0[start] == '@') return REFER;
}
//------------------------------------------------------------
@Override
public boolean readBoolean() {
return "true".equalsIgnoreCase(this.readSmallString());
}
@Override
public byte readByte() {
return (byte) readInt();
}
@Override
public char readChar() {
return (char) readInt();
}
@Override
public short readShort() {
return (short) readInt();
}
@Override
public float readFloat() {
String chars = readSmallString();
if (chars == null || chars.isEmpty()) return 0.f;
return Float.parseFloat(chars);
}
@Override
public double readDouble() {
String chars = readSmallString();
if (chars == null || chars.isEmpty()) return 0.0;
return Double.parseDouble(chars);
}
/**
* 读取字符串, 必须是"或者'包围的字符串值
*
* @return
*/
@Override
public String readString() {
final char[] text0 = this.text;
int currpos = this.position;
char expected = text0[++currpos];
if (expected <= ' ') {
for (;;) {
expected = text0[++currpos];
if (expected > ' ') break;
}
}
if (expected != '"' && expected != '\'') {
if (expected == 'n' && text0.length > currpos + 3) {
if (text0[++currpos] == 'u' && text0[++currpos] == 'l' && text0[++currpos] == 'l') {
this.position = currpos;
if (text0.length > currpos + 4) {
char ch = text0[currpos + 1];
if (ch == ',' || ch <= ' ' || ch == '}' || ch == ']' || ch == ':') return null;
} else {
return null;
}
}
} else {
final int start = currpos;
for (;;) {
char ch = text0[currpos];
if (ch == ',' || ch <= ' ' || ch == '}' || ch == ']' || ch == ':') break;
currpos++;
}
if (currpos == start) throw new ConvertException("expected a string after a key but '" + text0[position] + "' (position = " + position + ") in (" + new String(this.text) + ")");
this.position = currpos - 1;
return new String(text0, start, currpos - start);
}
this.position = currpos;
throw new ConvertException("expected a ':' after a key but '" + text0[position] + "' (position = " + position + ") in (" + new String(this.text) + ")");
}
final int start = ++currpos;
for (;;) {
char ch = text0[currpos];
if (ch == expected) {
break;
} else if (ch == '\\') {
this.position = currpos - 1;
return readEscapeValue(expected, start);
}
currpos++;
}
this.position = currpos;
return new String(text0, start, currpos - start);
}
private String readEscapeValue(final char expected, int start) {
StringBuilder array = new StringBuilder();
final char[] text0 = this.text;
int pos = this.position;
array.append(text0, start, pos + 1 - start);
char c;
for (;;) {
c = text0[++pos];
if (c == expected) {
this.position = pos;
return array.toString();
} else if (c == '\\') {
c = text0[++pos];
switch (c) {
case '"':
case '\'':
case '\\':
case '/':
array.append(c);
break;
case 'n':
array.append('\n');
break;
case 'r':
array.append('\r');
break;
case 'u':
array.append((char) Integer.parseInt(new String(new char[]{text0[++pos], text0[++pos], text0[++pos], text0[++pos]}), 16));
break;
case 't':
array.append('\t');
break;
case 'b':
array.append('\b');
break;
case 'f':
array.append('\f');
break;
default:
this.position = pos;
throw new ConvertException("illegal escape(" + c + ") (position = " + this.position + ") in (" + new String(this.text) + ")");
}
} else {
array.append(c);
}
}
}
}

View File

@@ -0,0 +1,17 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.json;
import com.wentch.redkale.convert.SimpledCoder;
/**
*
* @author zhangjx
* @param <T>
*/
public abstract class JsonSimpledCoder<T> extends SimpledCoder<JsonReader, JsonWriter, T> {
}

View File

@@ -0,0 +1,299 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.convert.json;
import com.wentch.redkale.convert.*;
import com.wentch.redkale.util.*;
/**
*
* writeTo系列的方法输出的字符不能含特殊字符
*
* @author zhangjx
*/
public final class JsonWriter implements Writer {
private static final char[] CHARS_TUREVALUE = "true".toCharArray();
private static final char[] CHARS_FALSEVALUE = "false".toCharArray();
private static final int defaultSize = Integer.getInteger("convert.json.writer.buffer.defsize", 1024);
protected int count;
private char[] content;
protected boolean tiny;
public static ObjectPool<JsonWriter> createPool(int max) {
return new ObjectPool<JsonWriter>(max, new Creator<JsonWriter>() {
@Override
public JsonWriter create(Object... params) {
return new JsonWriter();
}
}, null, new Predicate<JsonWriter>() {
@Override
public boolean test(JsonWriter t) {
return t.recycle();
}
});
}
public JsonWriter() {
this(defaultSize);
}
public JsonWriter(int size) {
this.content = new char[size > 128 ? size : 128];
}
@Override
public boolean isTiny() {
return tiny;
}
public void setTiny(boolean tiny) {
this.tiny = tiny;
}
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
/**
* 返回指定至少指定长度的缓冲区
*
* @param len
* @return
*/
public char[] expand(int len) {
int newcount = count + len;
if (newcount <= content.length) return content;
char[] newdata = new char[Math.max(content.length * 3 / 2, newcount)];
System.arraycopy(content, 0, newdata, 0, count);
this.content = newdata;
return newdata;
}
public void writeTo(final char ch) {
expand(1);
content[count++] = ch;
}
public void writeTo(final char... chs) {
int len = chs.length;
expand(len);
System.arraycopy(chs, 0, content, count, len);
count += len;
}
public void writeTo(final char[] chs, final int start, final int end) {
int len = end - start;
expand(len);
System.arraycopy(chs, start, content, count, len);
count += len;
}
/**
* <b>注意:</b> 该String值不能为null且不会进行转义 只用于不含需要转义字符的字符串例如enum、double、BigInteger转换的String
*
* @param quote
* @param value
*/
public void writeTo(final boolean quote, final String value) {
int len = value.length();
expand(len + (quote ? 2 : 0));
if (quote) content[count++] = '"';
value.getChars(0, len, content, count);
count += len;
if (quote) content[count++] = '"';
}
protected boolean recycle() {
this.count = 0;
if (this.content.length > defaultSize) {
this.content = new char[defaultSize];
}
return true;
}
public char[] toArray() {
if (count == content.length) return content;
char[] newdata = new char[count];
System.arraycopy(content, 0, newdata, 0, count);
return newdata;
}
public byte[] toUTF8Bytes() {
return Utility.encodeUTF8(content, 0, count);
}
//------------------------------------------------------------------------
public final int count() {
return this.count;
}
public final void count(int count) {
if (count >= 0) this.count = count;
}
// @SuppressWarnings("unchecked")
// public final boolean writeRefer(final Object value) {
// if (stack == null) return false;
// int index = stack.indexOf(value);
// if (index > -1) {
// int deep = stack.size() - index;
// if (deep < 0) throw new ConvertException("the refer deep value(" + deep + ") is illegal");
// writeTo('{', '"', '@', '"', ':', '"');
// for (int i = 0; i < deep; i++) {
// writeTo('@');
// }
// writeTo('"', '}');
// return true;
// }
// return false;
// }
//-----------------------------------------------------------------------
@Override
public String toString() {
return new String(content, 0, count);
}
@Override
public void writeBoolean(boolean value) {
writeTo(value ? CHARS_TUREVALUE : CHARS_FALSEVALUE);
}
@Override
public void writeByte(byte value) {
writeInt(value);
}
@Override
public void writeChar(char value) {
writeInt(value);
}
@Override
public void writeShort(short value) {
writeInt(value);
}
@Override
public void writeInt(int value) {
writeSmallString(String.valueOf(value));
}
@Override
public void writeLong(long value) {
writeSmallString(String.valueOf(value));
}
@Override
public void writeFloat(float value) {
writeSmallString(String.valueOf(value));
}
@Override
public void writeDouble(double value) {
writeSmallString(String.valueOf(value));
}
@Override
public void writeString(String value) {
if (value == null) {
writeNull();
return;
}
expand(value.length() * 2 + 2);
content[count++] = '"';
for (char ch : Utility.charArray(value)) {
switch (ch) {
case '\n': content[count++] = '\\';
content[count++] = 'n';
break;
case '\r': content[count++] = '\\';
content[count++] = 'r';
break;
case '\t': content[count++] = '\\';
content[count++] = 't';
break;
case '\\': content[count++] = '\\';
content[count++] = ch;
break;
case '"': content[count++] = '\\';
content[count++] = ch;
break;
default: content[count++] = ch;
break;
}
}
content[count++] = '"';
}
@Override
public void wirteClassName(String clazz) {
}
@Override
public final void writeObjectB(int fieldCount, Object obj) {
writeTo('{');
}
@Override
public final void writeObjectE(Object obj) {
writeTo('}');
}
@Override
public final void writeField(boolean comma, Attribute attribute) {
if (comma) writeTo(',');
writeTo('"');
writeSmallString(attribute.field());
writeTo('"');
writeTo(':');
}
@Override
public final void writeNull() {
writeTo('n', 'u', 'l', 'l');
}
@Override
public void writeArrayB(int size) {
writeTo('[');
}
@Override
public void writeArrayMark() {
writeTo(',');
}
@Override
public void writeArrayE() {
writeTo(']');
}
@Override
public void writeMapB(int size) {
writeTo('{');
}
@Override
public void writeMapMark() {
writeTo(':');
}
@Override
public void writeMapE() {
writeTo('}');
}
@Override
public void writeSmallString(String value) {
writeTo(false, value);
}
}

View File

@@ -0,0 +1,300 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
import java.lang.reflect.*;
import static org.objectweb.asm.Opcodes.*;
import org.objectweb.asm.Type;
/**
* 该类功能是动态映射一个Data类中成员对应的getter、setter方法 代替低效的反射实现方式。
* 映射Field时field要么是public非final要么存在对应的getter、setter方法。
*
* @author zhangjx
* @param <T>
* @param <F>
*/
public interface Attribute<T, F> {
public Class type();
public Class declaringClass();
public String field();
public F get(T obj);
public void set(T obj, F value);
public static final class Attributes {
public static <T, F> Attribute<T, F> create(final Field field) {
return create((Class<T>) field.getDeclaringClass(), field.getName(), field, null, null);
}
public static <T, F> Attribute<T, F> create(String fieldname, final Field field) {
return create((Class<T>) field.getDeclaringClass(), fieldname, field, null, null);
}
public static <T, F> Attribute<T, F> create(Class<T> clazz, final String fieldname) {
try {
return create(clazz, fieldname, clazz.getDeclaredField(fieldname), null, null);
} catch (NoSuchFieldException ex) {
throw new RuntimeException(ex);
} catch (SecurityException ex2) {
throw new RuntimeException(ex2);
}
}
public static <T, F> Attribute<T, F> create(Class<T> clazz, final java.lang.reflect.Field field) {
return create(clazz, field.getName(), field);
}
public static <T, F> Attribute<T, F> create(Class<T> clazz, final String fieldname, final java.lang.reflect.Field field) {
return create(clazz, fieldname, field, null, null);
}
public static <T, F> Attribute<T, F> create(final Method getter, final Method setter) {
return create((Class) (getter == null ? setter.getDeclaringClass() : getter.getDeclaringClass()), null, null, getter, setter);
}
public static <T, F> Attribute<T, F> create(Class<T> clazz, final Method getter, final Method setter) {
return create(clazz, null, null, getter, setter);
}
public static <T, F> Attribute<T, F> create(Class<T> clazz, final String fieldalias, final Method getter, final Method setter) {
return create(clazz, fieldalias, null, getter, setter);
}
@SuppressWarnings("unchecked")
public static <T, F> Attribute<T, F> create(final Class<T> clazz, String fieldalias0, final Field field0, Method getter0, Method setter0) {
if (fieldalias0 != null && fieldalias0.isEmpty()) fieldalias0 = null;
int mod = field0 == null ? Modifier.STATIC : field0.getModifiers();
if (field0 != null && !Modifier.isStatic(mod) && !Modifier.isPublic(mod)) {
Class t = field0.getType();
char[] fs = field0.getName().toCharArray();
fs[0] = Character.toUpperCase(fs[0]);
String mn = new String(fs);
if (getter0 == null) {
String prefix = t == boolean.class || t == Boolean.class ? "is" : "get";
try {
getter0 = clazz.getMethod(prefix + mn);
} catch (Exception ex) {
}
}
if (setter0 == null) {
try {
setter0 = clazz.getMethod("set" + mn, field0.getType());
} catch (Exception ex) {
}
}
}
final Field field = field0 == null ? null : (!Modifier.isPublic(mod) || Modifier.isStatic(mod) ? null : field0);
final java.lang.reflect.Method getter = getter0;
final java.lang.reflect.Method setter = setter0;
if (fieldalias0 == null) {
if (field0 != null) {
fieldalias0 = field0.getName();
} else {
String s;
if (getter0 != null) {
s = getter0.getName().substring(getter0.getName().startsWith("is") ? 2 : 3);
} else {
s = setter0.getName().substring(3);
}
char[] d = s.toCharArray();
if (d.length < 2 || Character.isLowerCase(d[1])) {
d[0] = Character.toLowerCase(d[0]);
}
fieldalias0 = new String(d);
}
}
if (getter == null && setter == null && field == null) {
throw new RuntimeException("[" + clazz + "]have no public field or setter or getter");
}
final String fieldname = fieldalias0;
Class column;
if (field != null) { // public field
column = field.getType();
} else if (getter != null) {
column = getter.getReturnType();
} else { // setter != null
column = setter.getParameterTypes()[0];
}
final Class pcolumn = column;
if (column.isPrimitive()) column = Array.get(Array.newInstance(column, 1), 0).getClass();
final String supDynName = Attribute.class.getName().replace('.', '/');
final String interName = clazz.getName().replace('.', '/');
final String columnName = column.getName().replace('.', '/');
final String interDesc = Type.getDescriptor(clazz);
final String columnDesc = Type.getDescriptor(column);
ClassLoader loader = Attribute.class.getClassLoader();
String newDynName = supDynName + "_Dyn_" + clazz.getSimpleName() + "_"
+ fieldname.substring(fieldname.indexOf('.') + 1) + "_" + pcolumn.getSimpleName().replace("[]", "Array");
if (String.class.getClassLoader() != clazz.getClassLoader()) {
loader = clazz.getClassLoader();
newDynName = interName + "_Dyn" + Attribute.class.getSimpleName() + "_"
+ fieldname.substring(fieldname.indexOf('.') + 1) + "_" + pcolumn.getSimpleName().replace("[]", "Array");
}
try {
return (Attribute) Class.forName(newDynName.replace('/', '.')).newInstance();
} catch (Exception ex) {
}
//---------------------------------------------------
final org.objectweb.asm.ClassWriter cw = new org.objectweb.asm.ClassWriter(0);
org.objectweb.asm.MethodVisitor mv;
cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + interDesc + columnDesc + ">;", "java/lang/Object", new String[]{supDynName});
{ //构造方法
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{ //field 方法
mv = cw.visitMethod(ACC_PUBLIC, "field", "()Ljava/lang/String;", null, null);
mv.visitLdcInsn(fieldname);
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{ //type 方法
mv = cw.visitMethod(ACC_PUBLIC, "type", "()Ljava/lang/Class;", null, null);
if (pcolumn == boolean.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
} else if (pcolumn == byte.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
} else if (pcolumn == char.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
} else if (pcolumn == short.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
} else if (pcolumn == int.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
} else if (pcolumn == float.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
} else if (pcolumn == long.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
} else if (pcolumn == double.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
} else {
mv.visitLdcInsn(Type.getType(pcolumn));
}
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{ //declaringClass 方法
mv = cw.visitMethod(ACC_PUBLIC, "declaringClass", "()Ljava/lang/Class;", null, null);
mv.visitLdcInsn(Type.getType(clazz));
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{ //get 方法
mv = cw.visitMethod(ACC_PUBLIC, "get", "(" + interDesc + ")" + columnDesc, null, null);
int m = 1;
if (getter == null) {
if (field == null) {
mv.visitInsn(ACONST_NULL);
} else { //public field
mv.visitVarInsn(ALOAD, 1);
mv.visitFieldInsn(GETFIELD, interName, field.getName(), Type.getDescriptor(pcolumn));
if (pcolumn != column) {
mv.visitMethodInsn(INVOKESTATIC, columnName, "valueOf", "(" + Type.getDescriptor(pcolumn) + ")" + columnDesc, false);
}
}
} else {
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, interName, getter.getName(), Type.getMethodDescriptor(getter), false);
if (pcolumn != column) {
mv.visitMethodInsn(INVOKESTATIC, columnName, "valueOf", "(" + Type.getDescriptor(pcolumn) + ")" + columnDesc, false);
m = 2;
}
}
mv.visitInsn(ARETURN);
mv.visitMaxs(m, 2);
mv.visitEnd();
}
{ //set 方法
mv = cw.visitMethod(ACC_PUBLIC, "set", "(" + interDesc + columnDesc + ")V", null, null);
int m = 2;
if (setter == null) {
if (field == null || Modifier.isFinal(field.getModifiers())) {
m = 0;
} else { //public field
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
if (pcolumn != column) {
try {
java.lang.reflect.Method pm = column.getMethod(pcolumn.getSimpleName() + "Value");
mv.visitMethodInsn(INVOKEVIRTUAL, columnName, pm.getName(), Type.getMethodDescriptor(pm), false);
} catch (Exception ex) {
throw new RuntimeException(ex); //不可能会发生
}
}
mv.visitFieldInsn(PUTFIELD, interName, field.getName(), Type.getDescriptor(pcolumn));
}
} else {
mv.visitVarInsn(ALOAD, 1);
mv.visitVarInsn(ALOAD, 2);
if (pcolumn != column) {
try {
java.lang.reflect.Method pm = column.getMethod(pcolumn.getSimpleName() + "Value");
mv.visitMethodInsn(INVOKEVIRTUAL, columnName, pm.getName(), Type.getMethodDescriptor(pm), false);
m = 3;
} catch (Exception ex) {
throw new RuntimeException(ex); //不可能会发生
}
}
mv.visitMethodInsn(INVOKEVIRTUAL, interName, setter.getName(), Type.getMethodDescriptor(setter), false);
}
mv.visitInsn(RETURN);
mv.visitMaxs(m, 3);
mv.visitEnd();
}
{ //虚拟get
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, interName);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "get", "(" + interDesc + ")" + columnDesc, false);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
{//虚拟set
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, interName);
mv.visitVarInsn(ALOAD, 2);
mv.visitTypeInsn(CHECKCAST, columnName);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "set", "(" + interDesc + columnDesc + ")V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(3, 3);
mv.visitEnd();
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
Class<Attribute> creatorClazz = (Class<Attribute>) new ClassLoader(loader) {
public final Class<?> loadClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length);
}
}.loadClass(newDynName.replace('/', '.'), bytes);
try {
return creatorClazz.newInstance();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
}

View File

@@ -0,0 +1,27 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
/**
* JDK 8 java.util.function.BiPredicate
*
* @author zhangjx
* @param <T>
* @param <U>
*/
public interface BiPredicate<T, U> {
/**
* Evaluates this predicate on the given arguments.
*
* @param t the first input argument
* @param u the second input argument
* @return {@code true} if the input arguments match the predicate,
* otherwise {@code false}
*/
boolean test(T t, U u);
}

View File

@@ -0,0 +1,161 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
import java.nio.*;
import java.nio.charset.*;
/**
*
* @author zhangjx
*/
public final class ByteArray {
private byte[] content;
private int count;
public ByteArray() {
this(1024);
}
public ByteArray(int size) {
content = new byte[Math.max(128, size)];
}
public void clear() {
this.count = 0;
}
public int find(byte value) {
return find(0, value);
}
public boolean equal(final byte[] bytes) {
if (bytes == null || count != bytes.length) return false;
for (int i = 0; i < count; i++) {
if (content[i] != bytes[i]) return false;
}
return true;
}
public boolean isEmpty() {
return count == 0;
}
public int count() {
return count;
}
public void write(byte[] buf) {
System.arraycopy(this.content, 0, buf, 0, count);
}
public byte[] directBytes() {
return content;
}
public int find(int offset, char value) {
return find(offset, (byte) value);
}
public int find(int offset, byte value) {
return find(offset, -1, value);
}
public int find(int offset, int limit, char value) {
return find(offset, limit, (byte) value);
}
public int find(int offset, int limit, byte value) {
byte[] bytes = this.content;
int end = limit > 0 ? limit : count;
for (int i = offset; i < end; i++) {
if (bytes[i] == value) return i;
}
return -1;
}
public void removeLastByte() {
if (count > 0) count--;
}
public void addInt(int value) {
add((byte) (value >> 24 & 0xFF), (byte) (value >> 16 & 0xFF), (byte) (value >> 8 & 0xFF), (byte) (value & 0xFF));
}
public void add(byte value) {
if (count >= content.length - 1) {
byte[] ns = new byte[content.length + 8];
System.arraycopy(content, 0, ns, 0, count);
this.content = ns;
}
content[count++] = value;
}
public void add(byte... values) {
if (count >= content.length - values.length) {
byte[] ns = new byte[content.length + values.length];
System.arraycopy(content, 0, ns, 0, count);
this.content = ns;
}
System.arraycopy(content, count, values, 0, values.length);
count += values.length;
}
public void add(ByteBuffer buffer, int len) {
if (len < 1) return;
if (count >= content.length - len) {
byte[] ns = new byte[content.length + len];
System.arraycopy(content, 0, ns, 0, count);
this.content = ns;
}
buffer.get(content, count, len);
count += len;
}
@Override
public String toString() {
return new String(content, 0, count);
}
public String toString(final Charset charset) {
return toString(0, count, charset);
}
public String toString(final int offset, int len, final Charset charset) {
if (charset == null) return new String(Utility.decodeUTF8(content, offset, len));
return new String(content, offset, len, charset);
}
public String toDecodeString(final int offset, int len, final Charset charset) {
int index = offset;
for (int i = offset; i < (offset + len); i++) {
if (content[i] == '+') {
content[index] = ' ';
} else if (content[i] == '%') {
content[index] = (byte) ((hexBit(content[++i]) * 16 + hexBit(content[++i])));
} else {
content[index] = content[i];
}
index++;
}
for (int i = index + 1; i < (offset + len); i++) {
content[i] = ' ';
}
len = index - offset;
if (charset == null) return new String(Utility.decodeUTF8(content, offset, len));
return new String(content, offset, len, charset);
}
private static int hexBit(byte b) {
if ('0' <= b && '9' >= b) return b - '0';
if ('a' <= b && 'z' >= b) return b - 'a' + 10;
if ('A' <= b && 'Z' >= b) return b - 'A' + 10;
return b;
}
}

View File

@@ -0,0 +1,22 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
/**
* JDK 8 java.util.function.Consumer
*
* @author zhangjx
* @param <T>
*/
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
}

View File

@@ -0,0 +1,210 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
import java.beans.ConstructorProperties;
import java.lang.reflect.*;
import java.util.*;
import org.objectweb.asm.*;
import static org.objectweb.asm.Opcodes.*;
import org.objectweb.asm.Type;
/**
* 实现一个类的构造方法。 代替低效的反射实现方式。
*
* @author zhangjx
* @param <T>
*/
public interface Creator<T> {
//
// static class PooledCreator<T> implements Creator<T> {
//
// private final T defValue;
//
// private final Reproduce<T, T> reproduce;
//
// private final ReferenceQueue<T> refQueue = new ReferenceQueue();
//
// private final Queue<T> queue;
//
// private final Creator<T> creator;
//
// public PooledCreator(int max, Class<T> clazz, Creator<T> creator) {
// this.creator = creator;
// this.defValue = creator.create();
// this.reproduce = Reproduce.create(clazz, clazz);
// this.queue = new ArrayBlockingQueue<>(Math.max(Runtime.getRuntime().availableProcessors() * 2, max));
// new Thread() {
// {
// setDaemon(true);
// setName(PooledCreator.class.getSimpleName() + " " + clazz.getSimpleName() + " Reference Handler");
// }
//
// @Override
// public void run() {
// try {
// for (;;) {
// T r = refQueue.remove().get();
// if (r == null) continue;
// reproduce.copy(r, defValue);
// queue.offer(r);
// }
// } catch (Exception e) {
// //do nothind
// }
// }
// }.start();
// }
//
// @Override
// public T create(Object... params) {
// T rs = queue.poll();
// if (rs == null) {
// rs = creator.create(params);
// }
// return new WeakReference<>(rs, refQueue).get();
// }
//
// }
//
// @SuppressWarnings("unchecked")
// public static <T> Creator<T> create(int max, Class<T> clazz) {
// return new PooledCreator<>(max, clazz, create(clazz));
// }
//
// @SuppressWarnings("unchecked")
// public static <T> Creator<T> create(int max, Class<T> clazz, Creator<T> creator) {
// return new PooledCreator<>(max, clazz, creator);
// }
public T create(Object... params);
public static final class Creators {
@SuppressWarnings("unchecked")
public static <T> Creator<T> create(Class<T> clazz) {
if (clazz.isAssignableFrom(ArrayList.class)) {
clazz = (Class<T>) ArrayList.class;
} else if (clazz.isAssignableFrom(HashMap.class)) {
clazz = (Class<T>) HashMap.class;
} else if (clazz.isAssignableFrom(HashSet.class)) {
clazz = (Class<T>) HashSet.class;
}
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) {
throw new RuntimeException("[" + clazz + "] is a interface or abstract class, cannot create it's Creator.");
}
final String supDynName = Creator.class.getName().replace('.', '/');
final String interName = clazz.getName().replace('.', '/');
final String interDesc = Type.getDescriptor(clazz);
ClassLoader loader = Creator.class.getClassLoader();
String newDynName = supDynName + "_" + clazz.getSimpleName() + "_" + (System.currentTimeMillis() % 10000);
if (String.class.getClassLoader() != clazz.getClassLoader()) {
loader = clazz.getClassLoader();
newDynName = interName + "_Dyn" + Creator.class.getSimpleName();
}
try {
return (Creator) Class.forName(newDynName.replace('/', '.')).newInstance();
} catch (Exception ex) {
}
Constructor<T> constructor = null;
for (Constructor c : clazz.getConstructors()) {
if (c.getParameterCount() == 0) {
constructor = c;
break;
}
}
if (constructor == null) {
for (Constructor c : clazz.getConstructors()) {
if (c.getAnnotation(ConstructorProperties.class) != null) {
constructor = c;
break;
}
}
}
if (constructor == null) throw new RuntimeException("[" + clazz + "] have no public or java.beans.ConstructorProperties-Annotation constructor.");
//-------------------------------------------------------------
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_6, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + interDesc + ">;", "java/lang/Object", new String[]{supDynName});
{//构造方法
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
ConstructorProperties cps = constructor.getAnnotation(ConstructorProperties.class);
if (cps != null) {
av0 = mv.visitAnnotation("Ljava/beans/ConstructorProperties;", true);
AnnotationVisitor av1 = av0.visitArray("value");
for (String n : cps.value()) {
av1.visit(null, n);
}
av1.visitEnd();
av0.visitEnd();
}
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
}
{//create 方法
mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)L" + interName + ";", null, null);
mv.visitTypeInsn(NEW, interName);
mv.visitInsn(DUP);
//---------------------------------------
{
Parameter[] params = constructor.getParameters();
final int[] iconsts = {ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5};
for (int i = 0; i < params.length; i++) {
mv.visitVarInsn(ALOAD, 1);
if (i < 6) {
mv.visitInsn(iconsts[i]);
} else {
mv.visitIntInsn(BIPUSH, i);
}
mv.visitInsn(AALOAD);
Class ct = params[i].getType();
mv.visitTypeInsn(CHECKCAST, Type.getInternalName(ct));
if (ct.isPrimitive()) {
Class fct = Array.get(Array.newInstance(ct, 1), 0).getClass();
try {
Method pm = ct.getMethod(ct.getSimpleName() + "Value");
mv.visitMethodInsn(INVOKEVIRTUAL, fct.getName().replace('.', '/'), pm.getName(), Type.getMethodDescriptor(pm), false);
} catch (Exception ex) {
throw new RuntimeException(ex); //不可能会发生
}
}
}
}
//---------------------------------------
mv.visitMethodInsn(INVOKESPECIAL, interName, "<init>", Type.getConstructorDescriptor(constructor), false);
mv.visitInsn(ARETURN);
mv.visitMaxs((constructor.getParameterCount() > 0 ? (constructor.getParameterCount() + 3) : 2), 2);
mv.visitEnd();
}
{ //虚拟 create 方法
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_VARARGS + ACC_SYNTHETIC, "create", "([Ljava/lang/Object;)Ljava/lang/Object;", null, null);
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "create", "([Ljava/lang/Object;)" + interDesc, false);
mv.visitInsn(ARETURN);
mv.visitMaxs(2, 2);
mv.visitEnd();
}
cw.visitEnd();
byte[] bytes = cw.toByteArray();
Class<?> creatorClazz = new ClassLoader(loader) {
public final Class<?> loadClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length);
}
}.loadClass(newDynName.replace('/', '.'), bytes);
try {
return (Creator) creatorClazz.newInstance();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
/**
*
* @author zhangjx
*/
public final class DLong extends Number implements Comparable<DLong> {
private final long first;
private final long second;
public DLong(long one, long two) {
this.first = one;
this.second = two;
}
public long getFirst() {
return first;
}
public long getSecond() {
return second;
}
public boolean compare(long one, long two) {
return this.first == one && this.second == two;
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final DLong other = (DLong) obj;
return (this.first == other.first && this.second == other.second);
}
@Override
public int hashCode() {
int hash = 7;
hash = 89 * hash + (int) (this.first ^ (this.first >>> 32));
hash = 89 * hash + (int) (this.second ^ (this.second >>> 32));
return hash;
}
@Override
public String toString() {
return this.first + "_" + this.second;
}
@Override
public int intValue() {
return (int) longValue();
}
@Override
public long longValue() {
return first ^ second;
}
@Override
public float floatValue() {
return (float) longValue();
}
@Override
public double doubleValue() {
return (double) longValue();
}
@Override
public int compareTo(DLong o) {
return (int) (first == o.first ? (second - o.second) : (first - o.first));
}
}

View File

@@ -0,0 +1,143 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
import java.util.*;
import org.objectweb.asm.*;
/**
*
* @author zhangjx
*/
public class DebugMethodVisitor {
private final MethodVisitor visitor;
private boolean debug = false;
public void setDebug(boolean d) {
debug = d;
}
private final Map<Label, Integer> labels = new LinkedHashMap();
private static final String[] opcodes = new String[200]; //0 -18
static {
try {
for (java.lang.reflect.Field field : Opcodes.class.getFields()) {
String name = field.getName();
if (name.startsWith("ASM")) continue;
if (name.startsWith("V1_")) continue;
if (name.startsWith("ACC_")) continue;
if (name.startsWith("T_")) continue;
if (name.startsWith("H_")) continue;
if (name.startsWith("F_")) continue;
if (field.getType() != int.class) continue;
opcodes[(int) (Integer) field.get(null)] = name;
}
} catch (Exception ex) {
throw new RuntimeException(ex); //不可能会发生
}
}
public DebugMethodVisitor(MethodVisitor visitor) {
//super(Opcodes.ASM5, visitor);
this.visitor = visitor;
}
public AnnotationVisitor visitAnnotation(String desc, boolean flag) {
AnnotationVisitor av = visitor.visitAnnotation(desc, flag);
if (debug) System.out.println("mv.visitAnnotation(\"" + desc + "\", " + flag + ");");
return av;
}
public void visitParameter(String name, int access) {
visitor.visitParameter(name, access);
if (debug) System.out.println("mv.visitParameter(" + name + ", " + access + ");");
}
public void visitVarInsn(int opcode, int var) {
visitor.visitVarInsn(opcode, var);
if (debug) System.out.println("mv.visitVarInsn(" + opcodes[opcode] + ", " + var + ");");
}
public void visitJumpInsn(int opcode, Label var) { //调用次方法的 ClassWriter 必须由 COMPUTE_FRAMES 构建
visitor.visitJumpInsn(opcode, var);
if (debug) {
Integer index = labels.get(var);
if (index == null) {
index = labels.size();
labels.put(var, index);
System.out.println("Label l" + index + " = new Label();");
}
System.out.println("mv.visitJumpInsn(" + opcodes[opcode] + ", l" + index + ");");
}
}
public void visitCode() {
visitor.visitCode();
if (debug) System.out.println("mv.visitCode();");
}
public void visitLabel(Label var) {
visitor.visitLabel(var);
if (debug) {
Integer index = labels.get(var);
if (index == null) {
index = labels.size();
labels.put(var, index);
System.out.println("Label l" + index + " = new Label();");
}
System.out.println("mv.visitLabel(l" + index + ");");
}
}
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
if (debug) System.out.println("mv.visitMethodInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\", " + itf + ");");
}
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
visitor.visitFieldInsn(opcode, owner, name, desc);
if (debug) System.out.println("mv.visitFieldInsn(" + opcodes[opcode] + ", \"" + owner + "\", \"" + name + "\", \"" + desc + "\");");
}
public void visitTypeInsn(int opcode, String type) {
visitor.visitTypeInsn(opcode, type);
if (debug) System.out.println("mv.visitTypeInsn(" + opcodes[opcode] + ", \"" + type + "\");");
}
public void visitInsn(int opcode) {
visitor.visitInsn(opcode);
if (debug) System.out.println("mv.visitInsn(" + opcodes[opcode] + ");");
}
public void visitIntInsn(int opcode, int value) {
visitor.visitIntInsn(opcode, value);
if (debug) System.out.println("mv.visitIntInsn(" + opcodes[opcode] + ", " + value + ");");
}
public void visitIincInsn(int opcode, int value) {
visitor.visitIincInsn(opcode, value);
if (debug) System.out.println("mv.visitIincInsn(" + opcode + ", " + value + ");");
}
public void visitLdcInsn(Object o) {
visitor.visitLdcInsn(o);
if (debug) System.out.println("mv.visitLdcInsn(" + o + ");");
}
public void visitMaxs(int maxStack, int maxLocals) {
visitor.visitMaxs(maxStack, maxLocals);
if (debug) System.out.println("mv.visitMaxs(" + maxStack + ", " + maxLocals + ");");
}
public void visitEnd() {
visitor.visitEnd();
if (debug) System.out.println("mv.visitEnd();\r\n\r\n\r\n");
}
}

View File

@@ -0,0 +1,95 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
import com.wentch.redkale.util.Creator.Creators;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.logging.*;
/**
*
* @author zhangjx
* @param <T>
*/
public final class ObjectPool<T> {
private static final Logger logger = Logger.getLogger(ObjectPool.class.getSimpleName());
private final boolean debug;
private final Queue<T> queue;
private Creator<T> creator;
private final Consumer<T> prepare;
private final Predicate<T> recycler;
private final AtomicLong creatCounter;
private final AtomicLong cycleCounter;
public ObjectPool(Class<T> clazz, Consumer<T> prepare, Predicate<T> recycler) {
this(2, clazz, prepare, recycler);
}
public ObjectPool(int max, Class<T> clazz, Consumer<T> prepare, Predicate<T> recycler) {
this(max, Creators.create(clazz), prepare, recycler);
}
public ObjectPool(Creator<T> creator, Consumer<T> prepare, Predicate<T> recycler) {
this(2, creator, prepare, recycler);
}
public ObjectPool(int max, Creator<T> creator, Consumer<T> prepare, Predicate<T> recycler) {
this(null, null, max, creator, prepare, recycler);
}
public ObjectPool(AtomicLong creatCounter, AtomicLong cycleCounter, int max, Creator<T> creator, Consumer<T> prepare, Predicate<T> recycler) {
this.creatCounter = creatCounter;
this.cycleCounter = cycleCounter;
this.creator = creator;
this.prepare = prepare;
this.recycler = recycler;
this.queue = new ArrayBlockingQueue(Math.max(Runtime.getRuntime().availableProcessors() * 2, max));
this.debug = logger.isLoggable(Level.FINER);
}
public void setCreator(Creator<T> creator) {
this.creator = creator;
}
public T poll() {
T result = queue.poll();
if (result == null) {
if (creatCounter != null) creatCounter.incrementAndGet();
result = this.creator.create();
}
if (prepare != null) prepare.accept(result);
return result;
}
public void offer(final T e) {
if (e != null && recycler.test(e)) {
if (cycleCounter != null) cycleCounter.incrementAndGet();
if (debug) {
for (T t : queue) {
if (t == e) logger.log(Level.WARNING, "[" + Thread.currentThread().getName() + "] repeat offer the same object(" + e + ")", new Exception());
}
}
queue.offer(e);
}
}
public long getCreatCount() {
return creatCounter.longValue();
}
public long getCycleCount() {
return cycleCounter.longValue();
}
}

View File

@@ -0,0 +1,24 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
/**
* JDK 8 java.util.function.Predicate
*
* @author zhangjx
* @param <T>
*/
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
}

View File

@@ -0,0 +1,26 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
*
* @author zhangjx
* @param <T>
*/
public abstract class TypeToken<T> {
private final Type type;
public TypeToken() {
type = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
public final Type getType() {
return type;
}
}

View File

@@ -0,0 +1,508 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.util;
import java.io.*;
import java.lang.reflect.Field;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.charset.*;
import java.time.*;
import java.util.*;
import javax.net.ssl.*;
/**
*
* @author zhangjx
*/
public final class Utility {
private static final String format = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%tL";
private static final Charset UTF_8 = Charset.forName("UTF-8");
private static final char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
private static final sun.misc.Unsafe UNSAFE;
private static final long strvaloffset;
private static final javax.net.ssl.SSLContext DEFAULTSSL_CONTEXT;
static {
sun.misc.Unsafe usafe = null;
long fd = 0L;
try {
Field safeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
safeField.setAccessible(true);
usafe = (sun.misc.Unsafe) safeField.get(null);
fd = usafe.objectFieldOffset(String.class.getDeclaredField("value"));
} catch (Exception e) {
throw new RuntimeException(e); //不可能会发生
}
UNSAFE = usafe;
strvaloffset = fd;
try {
DEFAULTSSL_CONTEXT = javax.net.ssl.SSLContext.getInstance("SSL");
DEFAULTSSL_CONTEXT.init(null, new javax.net.ssl.TrustManager[]{new javax.net.ssl.X509TrustManager() {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException {
}
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) throws java.security.cert.CertificateException {
}
}}, null);
} catch (Exception e) {
throw new RuntimeException(e); //不可能会发生
}
}
private Utility() {
}
public static String now() {
return String.format(format, System.currentTimeMillis());
}
public static void println(String string, ByteBuffer buffer) {
if (buffer == null || !buffer.hasRemaining()) return;
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
buffer.flip();
println(string, bytes);
}
public static void println(String string, byte... bytes) {
if (bytes == null) return;
StringBuilder sb = new StringBuilder();
if (string != null) sb.append(string);
sb.append(bytes.length).append(".[");
boolean last = false;
for (byte b : bytes) {
if (last) sb.append(',');
int v = b & 0xff;
if (v < 16) sb.append('0');
sb.append(Integer.toHexString(v));
last = true;
}
sb.append(']');
(System.out).println(sb);
}
/**
* 返回本机的第一个内网IPv4地址 没有则返回null
* <p>
* @return
*/
public static InetAddress localInetAddress() {
InetAddress back = null;
try {
Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
while (nifs.hasMoreElements()) {
NetworkInterface nif = nifs.nextElement();
if (!nif.isUp()) continue;
Enumeration<InetAddress> eis = nif.getInetAddresses();
while (eis.hasMoreElements()) {
InetAddress ia = eis.nextElement();
if (ia.isLoopbackAddress()) back = ia;
if (ia.isSiteLocalAddress()) return ia;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return back;
}
public static int today() {
java.time.LocalDate today = java.time.LocalDate.now();
return today.getYear() * 10000 + today.getMonthValue() * 100 + today.getDayOfMonth();
}
//时间点所在星期的周一
public static long monday(long time) {
ZoneId zid = ZoneId.systemDefault();
Instant instant = Instant.ofEpochMilli(time);
LocalDate ld = instant.atZone(zid).toLocalDate();
ld = ld.minusDays(ld.getDayOfWeek().getValue() - 1);
return ld.atStartOfDay(zid).toInstant().toEpochMilli();
}
//时间点所在星期的周日
public static long sunday(long time) {
ZoneId zid = ZoneId.systemDefault();
Instant instant = Instant.ofEpochMilli(time);
LocalDate ld = instant.atZone(zid).toLocalDate();
ld = ld.plusDays(7 - ld.getDayOfWeek().getValue());
return ld.atStartOfDay(zid).toInstant().toEpochMilli();
}
//时间点所在月份的1号
public static long monthFirstDay(long time) {
ZoneId zid = ZoneId.systemDefault();
Instant instant = Instant.ofEpochMilli(time);
LocalDate ld = instant.atZone(zid).toLocalDate().withDayOfMonth(1);
return ld.atStartOfDay(zid).toInstant().toEpochMilli();
}
public static String binToHexString(byte[] bytes) {
return new String(binToHex(bytes));
}
public static char[] binToHex(byte[] bytes) {
return binToHex(bytes, 0, bytes.length);
}
public static String binToHexString(byte[] bytes, int offset, int len) {
return new String(binToHex(bytes, offset, len));
}
public static char[] binToHex(byte[] bytes, int offset, int len) {
final char[] sb = new char[len * 2];
final int end = offset + len;
int index = 0;
final char[] hexs = hex;
for (int i = offset; i < end; i++) {
byte b = bytes[i];
sb[index++] = (hexs[((b >> 4) & 0xF)]);
sb[index++] = hexs[((b) & 0xF)];
}
return sb;
}
public static byte[] hexToBin(CharSequence src) {
return hexToBin(src, 0, src.length());
}
public static byte[] hexToBin(CharSequence src, int offset, int len) {
final int size = (len + 1) / 2;
final byte[] bytes = new byte[size];
final int end = offset + len;
String digits = "0123456789abcdef";
for (int i = 0; i < size; i++) {
int ch1 = src.charAt(offset + i * 2);
if ('A' <= ch1 && 'F' >= ch1) ch1 = ch1 - 'A' + 'a';
int ch2 = src.charAt(offset + i * 2 + 1);
if ('A' <= ch2 && 'F' >= ch2) ch2 = ch2 - 'A' + 'a';
int pos1 = digits.indexOf(ch1);
if (pos1 < 0) throw new NumberFormatException();
int pos2 = digits.indexOf(ch2);
if (pos2 < 0) throw new NumberFormatException();
bytes[i] = (byte) (pos1 * 0x10 + pos2);
}
return bytes;
}
public static byte[] hexToBin(char[] src) {
return hexToBin(src, 0, src.length);
}
public static byte[] hexToBin(char[] src, int offset, int len) {
final int size = (len + 1) / 2;
final byte[] bytes = new byte[size];
final int end = offset + len;
String digits = "0123456789abcdef";
for (int i = 0; i < size; i++) {
int ch1 = src[offset + i * 2];
if ('A' <= ch1 && 'F' >= ch1) ch1 = ch1 - 'A' + 'a';
int ch2 = src[offset + i * 2 + 1];
if ('A' <= ch2 && 'F' >= ch2) ch2 = ch2 - 'A' + 'a';
int pos1 = digits.indexOf(ch1);
if (pos1 < 0) throw new NumberFormatException();
int pos2 = digits.indexOf(ch2);
if (pos2 < 0) throw new NumberFormatException();
bytes[i] = (byte) (pos1 * 0x10 + pos2);
}
return bytes;
}
//-----------------------------------------------------------------------------
public static char[] decodeUTF8(final byte[] array) {
return decodeUTF8(array, 0, array.length);
}
public static char[] decodeUTF8(final byte[] array, final int start, final int len) {
byte b;
int size = len;
final byte[] bytes = array;
final int limit = start + len;
for (int i = start; i < limit; i++) {
b = bytes[i];
if ((b >> 5) == -2) {
size--;
} else if ((b >> 4) == -2) {
size -= 2;
}
}
final char[] text = new char[size];
size = 0;
for (int i = start; i < limit;) {
b = bytes[i++];
if (b >= 0) {
text[size++] = (char) b;
} else if ((b >> 5) == -2) {
text[size++] = (char) (((b << 6) ^ bytes[i++]) ^ (((byte) 0xC0 << 6) ^ ((byte) 0x80)));
} else if ((b >> 4) == -2) {
text[size++] = (char) ((b << 12) ^ (bytes[i++] << 6) ^ (bytes[i++] ^ (((byte) 0xE0 << 12) ^ ((byte) 0x80 << 6) ^ ((byte) 0x80))));
}
}
return text;
}
public static byte[] encodeUTF8(final String value) {
if (value == null) return new byte[0];
return encodeUTF8((char[]) UNSAFE.getObject(value, strvaloffset));
}
public static byte[] encodeUTF8(final char[] array) {
return encodeUTF8(array, 0, array.length);
}
public static byte[] encodeUTF8(final char[] text, final int start, final int len) {
char c;
int size = 0;
final char[] chars = text;
final int limit = start + len;
for (int i = start; i < limit; i++) {
c = chars[i];
if (c < 0x80) {
size++;
} else if (c < 0x800) {
size += 2;
} else {
size += 3;
}
}
final byte[] bytes = new byte[size];
size = 0;
for (int i = start; i < limit; i++) {
c = chars[i];
if (c < 0x80) {
bytes[size++] = (byte) c;
} else if (c < 0x800) {
bytes[size++] = (byte) (0xc0 | (c >> 6));
bytes[size++] = (byte) (0x80 | (c & 0x3f));
} else {
bytes[size++] = (byte) (0xe0 | ((c >> 12)));
bytes[size++] = (byte) (0x80 | ((c >> 6) & 0x3f));
bytes[size++] = (byte) (0x80 | (c & 0x3f));
}
}
return bytes;
}
public static char[] charArray(String value) {
return value == null ? null : (char[]) UNSAFE.getObject(value, strvaloffset);
}
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, final char[] array) {
return encodeUTF8(buffer, array, 0, array.length);
}
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, int bytesLength, final char[] array) {
return encodeUTF8(buffer, bytesLength, array, 0, array.length);
}
public static int encodeUTF8Length(String value) {
if (value == null) return -1;
return encodeUTF8Length((char[]) UNSAFE.getObject(value, strvaloffset));
}
public static int encodeUTF8Length(final char[] text) {
return encodeUTF8Length(text, 0, text.length);
}
public static int encodeUTF8Length(final char[] text, final int start, final int len) {
char c;
int size = 0;
final char[] chars = text;
final int limit = start + len;
for (int i = start; i < limit; i++) {
c = chars[i];
size += (c < 0x80 ? 1 : (c < 0x800 ? 2 : 3));
}
return size;
}
/**
* 将两个数字组装成一个long
* <p>
* @param high
* @param low
* @return
*/
public static long merge(long high, long low) {
return high << 32 | low;
}
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, final char[] text, final int start, final int len) {
return encodeUTF8(buffer, encodeUTF8Length(text, start, len), text, start, len);
}
public static ByteBuffer encodeUTF8(final ByteBuffer buffer, int bytesLength, final char[] text, final int start, final int len) {
char c;
char[] chars = text;
final int limit = start + len;
int remain = buffer.remaining();
final ByteBuffer buffer2 = remain >= bytesLength ? null : ByteBuffer.allocate(bytesLength - remain + 3); //最差情况buffer最后两byte没有填充
ByteBuffer buf = buffer;
for (int i = start; i < limit; i++) {
c = chars[i];
if (c < 0x80) {
if (buf.remaining() < 1) buf = buffer2;
buf.put((byte) c);
} else if (c < 0x800) {
if (buf.remaining() < 2) buf = buffer2;
buf.put((byte) (0xc0 | (c >> 6)));
buf.put((byte) (0x80 | (c & 0x3f)));
} else {
if (buf.remaining() < 3) buf = buffer2;
buf.put((byte) (0xe0 | ((c >> 12))));
buf.put((byte) (0x80 | ((c >> 6) & 0x3f)));
buf.put((byte) (0x80 | (c & 0x3f)));
}
}
if (buffer2 != null) buffer2.flip();
return buffer2;
}
//-----------------------------------------------------------------------------
public static Socket createDefaultSSLSocket(InetSocketAddress address) throws IOException {
return createDefaultSSLSocket(address.getAddress(), address.getPort());
}
public static Socket createDefaultSSLSocket(InetAddress host, int port) throws IOException {
Socket socket = DEFAULTSSL_CONTEXT.getSocketFactory().createSocket(host, port);
return socket;
}
public static String postHttpContent(String url) throws IOException {
return remoteHttpContent(null, "POST", url, null, null).toString("UTF-8");
}
public static String postHttpContent(String url, String body) throws IOException {
return remoteHttpContent(null, "POST", url, null, body).toString("UTF-8");
}
public static String postHttpContent(String url, Map<String, String> headers, String body) throws IOException {
return remoteHttpContent(null, "POST", url, headers, body).toString("UTF-8");
}
public static String postHttpContent(SSLContext ctx, String url) throws IOException {
return remoteHttpContent(ctx, "POST", url, null, null).toString("UTF-8");
}
public static String postHttpContent(SSLContext ctx, String url, String body) throws IOException {
return remoteHttpContent(ctx, "POST", url, null, body).toString("UTF-8");
}
public static String postHttpContent(SSLContext ctx, String url, Map<String, String> headers, String body) throws IOException {
return remoteHttpContent(ctx, "POST", url, headers, body).toString("UTF-8");
}
public static byte[] postHttpBytesContent(String url) throws IOException {
return remoteHttpContent(null, "POST", url, null, null).toByteArray();
}
public static byte[] postHttpBytesContent(SSLContext ctx, String url) throws IOException {
return remoteHttpContent(ctx, "POST", url, null, null).toByteArray();
}
public static byte[] postHttpBytesContent(String url, Map<String, String> headers, String body) throws IOException {
return remoteHttpContent(null, "POST", url, headers, body).toByteArray();
}
public static byte[] postHttpBytesContent(SSLContext ctx, String url, Map<String, String> headers, String body) throws IOException {
return remoteHttpContent(ctx, "POST", url, headers, body).toByteArray();
}
public static String getHttpContent(String url) throws IOException {
return remoteHttpContent(null, "GET", url, null, null).toString("UTF-8");
}
public static String getHttpContent(SSLContext ctx, String url) throws IOException {
return remoteHttpContent(ctx, "GET", url, null, null).toString("UTF-8");
}
public static String getHttpContent(SSLContext ctx, String url, Map<String, String> headers, String body) throws IOException {
return remoteHttpContent(ctx, "GET", url, headers, body).toString("UTF-8");
}
public static String getHttpContent(String url, Map<String, String> headers, String body) throws IOException {
return remoteHttpContent(null, "GET", url, headers, body).toString("UTF-8");
}
public static byte[] getHttpBytesContent(String url) throws IOException {
return remoteHttpContent(null, "GET", url, null, null).toByteArray();
}
public static byte[] getHttpBytesContent(SSLContext ctx, String url) throws IOException {
return remoteHttpContent(ctx, "GET", url, null, null).toByteArray();
}
public static byte[] getHttpBytesContent(String url, Map<String, String> headers, String body) throws IOException {
return remoteHttpContent(null, "GET", url, headers, body).toByteArray();
}
public static byte[] getHttpBytesContent(SSLContext ctx, String url, Map<String, String> headers, String body) throws IOException {
return remoteHttpContent(ctx, "GET", url, headers, body).toByteArray();
}
protected static ByteArrayOutputStream remoteHttpContent(SSLContext ctx, String method, String url, Map<String, String> headers, String body) throws IOException {
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setConnectTimeout(3000);
conn.setReadTimeout(3000);
if (conn instanceof HttpsURLConnection) ((HttpsURLConnection) conn).setSSLSocketFactory((ctx == null ? DEFAULTSSL_CONTEXT : ctx).getSocketFactory());
conn.setRequestMethod(method);
if (headers != null) {
for (Map.Entry<String, String> en : headers.entrySet()) {
conn.setRequestProperty(en.getKey(), en.getValue());
}
}
if (body != null) {
conn.setDoInput(true);
conn.setDoOutput(true);
conn.getOutputStream().write(body.getBytes(UTF_8));
}
conn.connect();
int rs = conn.getResponseCode();
if (rs == 301 || rs == 302) {
String newurl = conn.getHeaderField("Location");
conn.disconnect();
return remoteHttpContent(ctx, method, newurl, headers, body);
}
InputStream in = conn.getInputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
byte[] bytes = new byte[1024];
int pos;
while ((pos = in.read(bytes)) != -1) {
out.write(bytes, 0, pos);
}
conn.disconnect();
return out;
}
public static String read(InputStream in) throws IOException {
return read(in, "UTF-8");
}
public static String read(InputStream in, String charsetName) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
byte[] bytes = new byte[1024];
int pos;
while ((pos = in.read(bytes)) != -1) {
out.write(bytes, 0, pos);
}
return charsetName == null ? out.toString() : out.toString(charsetName);
}
}