From 34afb829162ab43b1330992d9136c7f535be0467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=9C=B0=E5=B9=B3=E7=BA=BF?= <22250530@qq.com> Date: Tue, 22 Sep 2015 17:39:01 +0800 Subject: [PATCH] --- convert-jdk6/lib/asm-5.0.4.jar | Bin 0 -> 53297 bytes .../wentch/redkale/convert/AnyEncoder.java | 40 ++ .../wentch/redkale/convert/ArrayDecoder.java | 79 +++ .../wentch/redkale/convert/ArrayEncoder.java | 75 +++ .../redkale/convert/CollectionDecoder.java | 69 +++ .../redkale/convert/CollectionEncoder.java | 65 ++ .../com/wentch/redkale/convert/Convert.java | 26 + .../wentch/redkale/convert/ConvertColumn.java | 44 ++ .../redkale/convert/ConvertColumnEntry.java | 67 ++ .../redkale/convert/ConvertColumns.java | 24 + .../wentch/redkale/convert/ConvertEntity.java | 25 + .../redkale/convert/ConvertException.java | 28 + .../wentch/redkale/convert/ConvertType.java | 28 + .../com/wentch/redkale/convert/DeMember.java | 64 ++ .../wentch/redkale/convert/Decodeable.java | 27 + .../com/wentch/redkale/convert/EnMember.java | 76 +++ .../wentch/redkale/convert/Encodeable.java | 27 + .../com/wentch/redkale/convert/Factory.java | 386 ++++++++++++ .../com/wentch/redkale/convert/HashedMap.java | 68 +++ .../wentch/redkale/convert/MapDecoder.java | 78 +++ .../wentch/redkale/convert/MapEncoder.java | 62 ++ .../wentch/redkale/convert/ObjectDecoder.java | 137 +++++ .../wentch/redkale/convert/ObjectEncoder.java | 214 +++++++ .../com/wentch/redkale/convert/Reader.java | 112 ++++ .../wentch/redkale/convert/SimpledCoder.java | 42 ++ .../com/wentch/redkale/convert/Writer.java | 120 ++++ .../redkale/convert/bson/BsonConvert.java | 104 ++++ .../redkale/convert/bson/BsonFactory.java | 62 ++ .../redkale/convert/bson/BsonReader.java | 311 ++++++++++ .../convert/bson/BsonSimpledCoder.java | 17 + .../redkale/convert/bson/BsonWriter.java | 300 +++++++++ .../convert/ext/BigIntegerSimpledCoder.java | 38 ++ .../convert/ext/BoolArraySimpledCoder.java | 68 +++ .../redkale/convert/ext/BoolSimpledCoder.java | 32 + .../convert/ext/ByteArraySimpledCoder.java | 68 +++ .../redkale/convert/ext/ByteSimpledCoder.java | 32 + .../convert/ext/CharArraySimpledCoder.java | 68 +++ .../redkale/convert/ext/CharSimpledCoder.java | 33 + .../convert/ext/DLongSimpledCoder.java | 40 ++ .../redkale/convert/ext/DateSimpledCoder.java | 33 + .../convert/ext/DoubleArraySimpledCoder.java | 68 +++ .../convert/ext/DoubleSimpledCoder.java | 32 + .../redkale/convert/ext/EnumSimpledCoder.java | 44 ++ .../convert/ext/FloatArraySimpledCoder.java | 68 +++ .../convert/ext/FloatSimpledCoder.java | 32 + .../convert/ext/InetAddressSimpledCoder.java | 70 +++ .../convert/ext/IntArraySimpledCoder.java | 68 +++ .../redkale/convert/ext/IntSimpledCoder.java | 32 + .../convert/ext/LongArraySimpledCoder.java | 68 +++ .../redkale/convert/ext/LongSimpledCoder.java | 33 + .../convert/ext/NumberSimpledCoder.java | 32 + .../convert/ext/PatternSimpledCoder.java | 38 ++ .../convert/ext/ShortArraySimpledCoder.java | 68 +++ .../convert/ext/ShortSimpledCoder.java | 32 + .../convert/ext/StringArraySimpledCoder.java | 68 +++ .../convert/ext/StringSimpledCoder.java | 32 + .../redkale/convert/ext/TypeSimpledCoder.java | 42 ++ .../json/InetAddressJsonSimpledCoder.java | 68 +++ .../redkale/convert/json/JsonConvert.java | 88 +++ .../redkale/convert/json/JsonFactory.java | 60 ++ .../redkale/convert/json/JsonReader.java | 575 ++++++++++++++++++ .../convert/json/JsonSimpledCoder.java | 17 + .../redkale/convert/json/JsonWriter.java | 299 +++++++++ .../com/wentch/redkale/util/Attribute.java | 300 +++++++++ .../com/wentch/redkale/util/BiPredicate.java | 27 + .../com/wentch/redkale/util/ByteArray.java | 161 +++++ .../src/com/wentch/redkale/util/Consumer.java | 22 + .../src/com/wentch/redkale/util/Creator.java | 210 +++++++ .../src/com/wentch/redkale/util/DLong.java | 81 +++ .../redkale/util/DebugMethodVisitor.java | 143 +++++ .../com/wentch/redkale/util/ObjectPool.java | 95 +++ .../com/wentch/redkale/util/Predicate.java | 24 + .../com/wentch/redkale/util/TypeToken.java | 26 + .../src/com/wentch/redkale/util/Utility.java | 508 ++++++++++++++++ 74 files changed, 6720 insertions(+) create mode 100644 convert-jdk6/lib/asm-5.0.4.jar create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/AnyEncoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ArrayDecoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ArrayEncoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/CollectionDecoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/CollectionEncoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/Convert.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ConvertColumn.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ConvertColumnEntry.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ConvertColumns.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ConvertEntity.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ConvertException.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ConvertType.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/DeMember.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/Decodeable.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/EnMember.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/Encodeable.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/Factory.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/HashedMap.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/MapDecoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/MapEncoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ObjectDecoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ObjectEncoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/Reader.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/SimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/Writer.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/bson/BsonConvert.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/bson/BsonFactory.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/bson/BsonReader.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/bson/BsonSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/bson/BsonWriter.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/BigIntegerSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/BoolArraySimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/BoolSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/ByteArraySimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/ByteSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/CharArraySimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/CharSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/DLongSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/DateSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/DoubleArraySimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/DoubleSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/EnumSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/FloatArraySimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/FloatSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/InetAddressSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/IntArraySimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/IntSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/LongArraySimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/LongSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/NumberSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/PatternSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/ShortArraySimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/ShortSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/StringArraySimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/StringSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/ext/TypeSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/json/InetAddressJsonSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/json/JsonConvert.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/json/JsonFactory.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/json/JsonReader.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/json/JsonSimpledCoder.java create mode 100644 convert-jdk6/src/com/wentch/redkale/convert/json/JsonWriter.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/Attribute.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/BiPredicate.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/ByteArray.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/Consumer.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/Creator.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/DLong.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/DebugMethodVisitor.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/ObjectPool.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/Predicate.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/TypeToken.java create mode 100644 convert-jdk6/src/com/wentch/redkale/util/Utility.java diff --git a/convert-jdk6/lib/asm-5.0.4.jar b/convert-jdk6/lib/asm-5.0.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..cdb283dd7f6d7d420ba0fca8ec23e1f38fc3b7c1 GIT binary patch literal 53297 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 literal 0 HcmV?d00001 diff --git a/convert-jdk6/src/com/wentch/redkale/convert/AnyEncoder.java b/convert-jdk6/src/com/wentch/redkale/convert/AnyEncoder.java new file mode 100644 index 000000000..0a8f253aa --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/AnyEncoder.java @@ -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序列化时将对象的类名写入Writer,JSON则不写入。 + * + * @author zhangjx + * @param + */ +public final class AnyEncoder implements Encodeable { + + 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; + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ArrayDecoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ArrayDecoder.java new file mode 100644 index 000000000..fa41b8b3a --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ArrayDecoder.java @@ -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 + */ +@SuppressWarnings("unchecked") +public final class ArrayDecoder implements Decodeable { + + private final Type type; + + private final Type componentType; + + private final Class componentClass; + + private final Decodeable 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 localdecoder = this.decoder; + final List 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; + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ArrayEncoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ArrayEncoder.java new file mode 100644 index 000000000..b75fe4be9 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ArrayEncoder.java @@ -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 + */ +@SuppressWarnings("unchecked") +public final class ArrayEncoder implements Encodeable { + + private final Type type; + + private final Type componentType; + + private final Encodeable anyEncoder; + + private final Encodeable 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; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/CollectionDecoder.java b/convert-jdk6/src/com/wentch/redkale/convert/CollectionDecoder.java new file mode 100644 index 000000000..df87cfd99 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/CollectionDecoder.java @@ -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 + */ +@SuppressWarnings("unchecked") +public final class CollectionDecoder implements Decodeable> { + + private final Type type; + + private final Type componentType; + + protected Creator> creator; + + private final Decodeable 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 convertFrom(Reader in) { + final int len = in.readArrayB(); + if (len == Reader.SIGN_NULL) return null; + final Decodeable localdecoder = this.decoder; + final Collection 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; + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/CollectionEncoder.java b/convert-jdk6/src/com/wentch/redkale/convert/CollectionEncoder.java new file mode 100644 index 000000000..e823a5775 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/CollectionEncoder.java @@ -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 + */ +@SuppressWarnings("unchecked") +public final class CollectionEncoder implements Encodeable> { + + private final Type type; + + private final Encodeable 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 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; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/Convert.java b/convert-jdk6/src/com/wentch/redkale/convert/Convert.java new file mode 100644 index 000000000..61b42ff63 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/Convert.java @@ -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 + * @param + */ +public abstract class Convert { + + protected final Factory factory; + + protected Convert(Factory factory) { + this.factory = factory; + } + + public Factory getFactory() { + return this.factory; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ConvertColumn.java b/convert-jdk6/src/com/wentch/redkale/convert/ConvertColumn.java new file mode 100644 index 000000000..1a868f0c4 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ConvertColumn.java @@ -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; +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ConvertColumnEntry.java b/convert-jdk6/src/com/wentch/redkale/convert/ConvertColumnEntry.java new file mode 100644 index 000000000..c5339b17a --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ConvertColumnEntry.java @@ -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; + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ConvertColumns.java b/convert-jdk6/src/com/wentch/redkale/convert/ConvertColumns.java new file mode 100644 index 000000000..a5e613ad0 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ConvertColumns.java @@ -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(); +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ConvertEntity.java b/convert-jdk6/src/com/wentch/redkale/convert/ConvertEntity.java new file mode 100644 index 000000000..99bd4330c --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ConvertEntity.java @@ -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(); +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ConvertException.java b/convert-jdk6/src/com/wentch/redkale/convert/ConvertException.java new file mode 100644 index 000000000..338e1f44e --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ConvertException.java @@ -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); + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ConvertType.java b/convert-jdk6/src/com/wentch/redkale/convert/ConvertType.java new file mode 100644 index 000000000..7871a01d8 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ConvertType.java @@ -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; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/DeMember.java b/convert-jdk6/src/com/wentch/redkale/convert/DeMember.java new file mode 100644 index 000000000..2897e7d23 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/DeMember.java @@ -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 + * @param + * @param + */ +@SuppressWarnings("unchecked") +public final class DeMember implements Comparable> { + + protected final Attribute attribute; + + protected Decodeable decoder; + + public DeMember(final Attribute attribute) { + this.attribute = attribute; + } + + public DeMember(Attribute attribute, Decodeable decoder) { + this(attribute); + this.decoder = decoder; + } + + public final void read(R in, T obj) { + this.attribute.set(obj, decoder.convertFrom(in)); + } + + public Attribute getAttribute() { + return this.attribute; + } + + @Override + public final int compareTo(DeMember 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 + '}'; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/Decodeable.java b/convert-jdk6/src/com/wentch/redkale/convert/Decodeable.java new file mode 100644 index 000000000..c6b58899a --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/Decodeable.java @@ -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 + * @param + */ +public interface Decodeable { + + public T convertFrom(final R in); + + /** + * 泛型映射接口 + * + * @return + */ + public Type getType(); + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/EnMember.java b/convert-jdk6/src/com/wentch/redkale/convert/EnMember.java new file mode 100644 index 000000000..beb71576e --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/EnMember.java @@ -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 + * @param + * @param + */ +@SuppressWarnings("unchecked") +public final class EnMember implements Comparable> { + + private final Attribute attribute; + + final Encodeable encoder; + + private final boolean istring; + + //private final boolean isnumber; + private final boolean isbool; + + public EnMember(Attribute attribute, Encodeable 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 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 + '}'; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/Encodeable.java b/convert-jdk6/src/com/wentch/redkale/convert/Encodeable.java new file mode 100644 index 000000000..595383445 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/Encodeable.java @@ -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 + * @param + */ +public interface Encodeable { + + public void convertTo(final W out, T value); + + /** + * 泛型映射接口 + * + * @return + */ + public Type getType(); + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/Factory.java b/convert-jdk6/src/com/wentch/redkale/convert/Factory.java new file mode 100644 index 000000000..c27cdfc75 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/Factory.java @@ -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 + * @param + */ +@SuppressWarnings("unchecked") +public abstract class Factory { + + private final Factory parent; + + protected Convert convert; + + protected boolean tiny; + + private final Encodeable anyEncoder = new AnyEncoder(this); + + //----------------------------------------------------------------------------------- + private final HashedMap creators = new HashedMap(); + + private final Map entitys = new ConcurrentHashMap(); + + private final HashedMap> decoders = new HashedMap(); + + private final HashedMap> encoders = new HashedMap(); + + private final HashMap columnEntrys = new HashMap(); + + private final Set skipIgnores = new HashSet(); + + private boolean skipAllIgnore = false; + + protected Factory(Factory 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 + *

+ * @param skipIgnore + */ + public final void registerSkipAllIgnore(final boolean skipIgnore) { + this.skipAllIgnore = skipIgnore; + } + + /** + * 使该类所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false + *

+ * @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 boolean register(final AccessibleObject field, final ConvertColumnEntry entry) { + if (field == null || entry == null) return false; + this.columnEntrys.put(field, entry); + return true; + } + + public final void register(final Class clazz, final Creator creator) { + creators.put(clazz, creator); + } + + public final Creator findCreator(Class type) { + Creator creator = creators.get(type); + if (creator != null) return creator; + return this.parent == null ? null : this.parent.findCreator(type); + } + + public final Creator loadCreator(Class type) { + Creator result = findCreator(type); + if (result == null) { + result = Creators.create(type); + creators.put(type, result); + } + return result; + } + + //---------------------------------------------------------------------- + public final Encodeable getAnyEncoder() { + return (Encodeable) anyEncoder; + } + + public final void register(final Type clazz, final SimpledCoder coder) { + decoders.put(clazz, coder); + encoders.put(clazz, coder); + } + + public final void register(final Type clazz, final Decodeable decoder) { + decoders.put(clazz, decoder); + } + + public final void register(final Type clazz, final Encodeable printer) { + encoders.put(clazz, printer); + } + + public final Decodeable findDecoder(final Type type) { + Decodeable rs = (Decodeable) decoders.get(type); + if (rs != null) return rs; + return this.parent == null ? null : this.parent.findDecoder(type); + } + + public final Encodeable findEncoder(final Type type) { + Encodeable rs = (Encodeable) encoders.get(type); + if (rs != null) return rs; + return this.parent == null ? null : this.parent.findEncoder(type); + } + + public final Decodeable loadDecoder(final Type type) { + Decodeable 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 Decodeable 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 Decodeable createDecoder(final Type type, final Class clazz) { + Decodeable 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 Encodeable loadEncoder(final Type type) { + Encodeable 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 Encodeable 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 Encodeable createEncoder(final Type type, final Class clazz) { + Encodeable 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) 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; + + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/HashedMap.java b/convert-jdk6/src/com/wentch/redkale/convert/HashedMap.java new file mode 100644 index 000000000..2236f85f8 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/HashedMap.java @@ -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 + * @param + */ +@SuppressWarnings("unchecked") +public final class HashedMap { + + protected final transient Entry[] 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[] data = this.table; + Entry 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[] data = this.table; + final int index = k.hashCode() & (data.length - 1); + Entry 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 { + + protected V value; + + protected final K key; + + protected final Entry next; + + protected Entry(K key, V value, Entry next) { + this.key = key; + this.value = value; + this.next = next; + } + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/MapDecoder.java b/convert-jdk6/src/com/wentch/redkale/convert/MapDecoder.java new file mode 100644 index 000000000..dfd7c2c1e --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/MapDecoder.java @@ -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 + * @param + */ +@SuppressWarnings("unchecked") +public final class MapDecoder implements Decodeable> { + + private final Type type; + + private final Type keyType; + + private final Type valueType; + + protected Creator> creator; + + private final Decodeable keyDecoder; + + private final Decodeable 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 convertFrom(Reader in) { + final int len = in.readMapB(); + if (len == Reader.SIGN_NULL) return null; + final Map 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; + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/MapEncoder.java b/convert-jdk6/src/com/wentch/redkale/convert/MapEncoder.java new file mode 100644 index 000000000..b4c12ff39 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/MapEncoder.java @@ -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 + * @param + */ +@SuppressWarnings("unchecked") +public final class MapEncoder implements Encodeable> { + + private final Type type; + + private final Encodeable keyencoder; + + private final Encodeable 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 value) { + final Map values = value; + if (values == null) { + out.writeNull(); + return; + } + out.writeMapB(values.size()); + boolean first = true; + for (Map.Entry 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; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ObjectDecoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ObjectDecoder.java new file mode 100644 index 000000000..d62e7572f --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ObjectDecoder.java @@ -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 + * @param + */ +@SuppressWarnings("unchecked") +public final class ObjectDecoder implements Decodeable { + + protected final Type type; + + protected final Class typeClass; + + protected Creator creator; + + protected DeMember[] 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 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) + '}'; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ObjectEncoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ObjectEncoder.java new file mode 100644 index 000000000..f5560d6ce --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ObjectEncoder.java @@ -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 + * @param + */ +@SuppressWarnings("unchecked") +public final class ObjectEncoder implements Encodeable { + + 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 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) + '}'; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/Reader.java b/convert-jdk6/src/com/wentch/redkale/convert/Reader.java new file mode 100644 index 000000000..ba40ed756 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/Reader.java @@ -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(); + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/SimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/SimpledCoder.java new file mode 100644 index 000000000..db0e42657 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/SimpledCoder.java @@ -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 + * @param + * @param + */ +public abstract class SimpledCoder implements Decodeable, Encodeable { + + 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 getType() { + if (type == null) { + Type[] ts = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments(); + type = ts[ts.length - 1]; + } + return (Class) type; + } + + @Override + public String toString() { + return this.getClass().getSimpleName(); + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/Writer.java b/convert-jdk6/src/com/wentch/redkale/convert/Writer.java new file mode 100644 index 000000000..adcba5e91 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/Writer.java @@ -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的字段值都会被跳过, 不会输出。 + *

+ * @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); +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonConvert.java b/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonConvert.java new file mode 100644 index 000000000..7f2961461 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonConvert.java @@ -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 { + + private static final ObjectPool readerPool = BsonReader.createPool(Integer.getInteger("convert.bson.pool.size", 16)); + + private static final ObjectPool writerPool = BsonWriter.createPool(Integer.getInteger("convert.bson.pool.size", 16)); + + private final boolean tiny; + + protected BsonConvert(Factory factory, boolean tiny) { + super(factory); + this.tiny = tiny; + } + + public T convertFrom(final Type type, final byte[] bytes) { + if (bytes == null) return null; + return convertFrom(type, bytes, 0, bytes.length); + } + + public 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); + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonFactory.java b/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonFactory.java new file mode 100644 index 000000000..8097f6cab --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonFactory.java @@ -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 { + + 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; + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonReader.java b/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonReader.java new file mode 100644 index 000000000..f2d23d815 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonReader.java @@ -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 createPool(int max) { + return new ObjectPool(max, new Creator() { + + @Override + public BsonReader create(Object... params) { + return new BsonReader(); + } + }, null, new Predicate() { + + @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; + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonSimpledCoder.java new file mode 100644 index 000000000..840e1fca3 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonSimpledCoder.java @@ -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 + */ +public abstract class BsonSimpledCoder extends SimpledCoder { + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonWriter.java b/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonWriter.java new file mode 100644 index 000000000..62dc08927 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/bson/BsonWriter.java @@ -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 createPool(int max) { + return new ObjectPool(max, new Creator() { + + @Override + public BsonWriter create(Object... params) { + return new BsonWriter(); + } + }, null, new Predicate() { + + @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() { + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/BigIntegerSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/BigIntegerSimpledCoder.java new file mode 100644 index 000000000..735e85c3e --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/BigIntegerSimpledCoder.java @@ -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 + * @param + */ +public final class BigIntegerSimpledCoder extends SimpledCoder { + + 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); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/BoolArraySimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/BoolArraySimpledCoder.java new file mode 100644 index 000000000..696386202 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/BoolArraySimpledCoder.java @@ -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 + * @param + */ +public final class BoolArraySimpledCoder extends SimpledCoder { + + 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; + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/BoolSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/BoolSimpledCoder.java new file mode 100644 index 000000000..4b13eb923 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/BoolSimpledCoder.java @@ -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 + * @param + */ +public final class BoolSimpledCoder extends SimpledCoder { + + 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(); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/ByteArraySimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/ByteArraySimpledCoder.java new file mode 100644 index 000000000..ffd09ccce --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/ByteArraySimpledCoder.java @@ -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 + * @param + */ +public final class ByteArraySimpledCoder extends SimpledCoder { + + 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; + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/ByteSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/ByteSimpledCoder.java new file mode 100644 index 000000000..e76a6e84c --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/ByteSimpledCoder.java @@ -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 + * @param + */ +public final class ByteSimpledCoder extends SimpledCoder { + + 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(); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/CharArraySimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/CharArraySimpledCoder.java new file mode 100644 index 000000000..9b5be5edb --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/CharArraySimpledCoder.java @@ -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 + * @param + */ +public final class CharArraySimpledCoder extends SimpledCoder { + + 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; + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/CharSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/CharSimpledCoder.java new file mode 100644 index 000000000..26b501043 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/CharSimpledCoder.java @@ -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 + * @param + */ +public final class CharSimpledCoder extends SimpledCoder { + + 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(); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/DLongSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/DLongSimpledCoder.java new file mode 100644 index 000000000..b6fce842a --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/DLongSimpledCoder.java @@ -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 + * @param + */ +public final class DLongSimpledCoder extends SimpledCoder { + + 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))); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/DateSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/DateSimpledCoder.java new file mode 100644 index 000000000..4df76df2f --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/DateSimpledCoder.java @@ -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 + * @param + */ +public final class DateSimpledCoder extends SimpledCoder { + + 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()); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/DoubleArraySimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/DoubleArraySimpledCoder.java new file mode 100644 index 000000000..04aa3a543 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/DoubleArraySimpledCoder.java @@ -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 + * @param + */ +public final class DoubleArraySimpledCoder extends SimpledCoder { + + 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; + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/DoubleSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/DoubleSimpledCoder.java new file mode 100644 index 000000000..a56456562 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/DoubleSimpledCoder.java @@ -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 + * @param + */ +public final class DoubleSimpledCoder extends SimpledCoder { + + 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(); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/EnumSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/EnumSimpledCoder.java new file mode 100644 index 000000000..323b2b25e --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/EnumSimpledCoder.java @@ -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 + * @param + * @param + */ +public final class EnumSimpledCoder extends SimpledCoder { + + private final Class type; + + public EnumSimpledCoder(Class 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); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/FloatArraySimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/FloatArraySimpledCoder.java new file mode 100644 index 000000000..ccba72bae --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/FloatArraySimpledCoder.java @@ -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 + * @param + */ +public final class FloatArraySimpledCoder extends SimpledCoder { + + 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; + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/FloatSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/FloatSimpledCoder.java new file mode 100644 index 000000000..a2b9cbed5 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/FloatSimpledCoder.java @@ -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 + * @param + */ +public final class FloatSimpledCoder extends SimpledCoder { + + 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(); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/InetAddressSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/InetAddressSimpledCoder.java new file mode 100644 index 000000000..92c2050a1 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/InetAddressSimpledCoder.java @@ -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 + * @param + */ +public final class InetAddressSimpledCoder extends SimpledCoder { + + 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 extends SimpledCoder { + + 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; + } + } + + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/IntArraySimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/IntArraySimpledCoder.java new file mode 100644 index 000000000..8a8c9248a --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/IntArraySimpledCoder.java @@ -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 + * @param + */ +public final class IntArraySimpledCoder extends SimpledCoder { + + 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; + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/IntSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/IntSimpledCoder.java new file mode 100644 index 000000000..e67c1d710 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/IntSimpledCoder.java @@ -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 + * @param + */ +public final class IntSimpledCoder extends SimpledCoder { + + 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(); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/LongArraySimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/LongArraySimpledCoder.java new file mode 100644 index 000000000..2ea858b96 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/LongArraySimpledCoder.java @@ -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 + * @param + */ +public final class LongArraySimpledCoder extends SimpledCoder { + + 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; + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/LongSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/LongSimpledCoder.java new file mode 100644 index 000000000..203523b0b --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/LongSimpledCoder.java @@ -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 + * @param + */ +public final class LongSimpledCoder extends SimpledCoder { + + 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(); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/NumberSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/NumberSimpledCoder.java new file mode 100644 index 000000000..aa9e369c7 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/NumberSimpledCoder.java @@ -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 + * @param + */ +public final class NumberSimpledCoder extends SimpledCoder { + + 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(); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/PatternSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/PatternSimpledCoder.java new file mode 100644 index 000000000..a225ff9cf --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/PatternSimpledCoder.java @@ -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 + * @param + */ +public class PatternSimpledCoder extends SimpledCoder { + + 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))); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/ShortArraySimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/ShortArraySimpledCoder.java new file mode 100644 index 000000000..8c73f94e1 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/ShortArraySimpledCoder.java @@ -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 + * @param + */ +public final class ShortArraySimpledCoder extends SimpledCoder { + + 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; + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/ShortSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/ShortSimpledCoder.java new file mode 100644 index 000000000..50c91b1c9 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/ShortSimpledCoder.java @@ -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 + * @param + */ +public final class ShortSimpledCoder extends SimpledCoder { + + 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(); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/StringArraySimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/StringArraySimpledCoder.java new file mode 100644 index 000000000..8cbc06cf7 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/StringArraySimpledCoder.java @@ -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 + * @param + */ +public final class StringArraySimpledCoder extends SimpledCoder { + + 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; + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/StringSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/StringSimpledCoder.java new file mode 100644 index 000000000..aeafee793 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/StringSimpledCoder.java @@ -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 + * @param + */ +public final class StringSimpledCoder extends SimpledCoder { + + 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(); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/ext/TypeSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/ext/TypeSimpledCoder.java new file mode 100644 index 000000000..dc6397252 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/ext/TypeSimpledCoder.java @@ -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 + * @param + */ +public class TypeSimpledCoder extends SimpledCoder { + + 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; + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/json/InetAddressJsonSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/json/InetAddressJsonSimpledCoder.java new file mode 100644 index 000000000..0e0e95eb8 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/json/InetAddressJsonSimpledCoder.java @@ -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 + * @param + */ +public final class InetAddressJsonSimpledCoder extends SimpledCoder { + + 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 extends SimpledCoder { + + 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; + } + } + + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/json/JsonConvert.java b/convert-jdk6/src/com/wentch/redkale/convert/json/JsonConvert.java new file mode 100644 index 000000000..d965935e3 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/json/JsonConvert.java @@ -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 { + + public static final Type TYPE_MAP_STRING_STRING = new TypeToken>() { + }.getType(); + + private static final ObjectPool readerPool = JsonReader.createPool(Integer.getInteger("convert.json.pool.size", 16)); + + private static final ObjectPool 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 convertFrom(final Type type, final String text) { + if (text == null) return null; + return convertFrom(type, Utility.charArray(text)); + } + + public T convertFrom(final Type type, final char[] text) { + if (text == null) return null; + return convertFrom(type, text, 0, text.length); + } + + public 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; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/json/JsonFactory.java b/convert-jdk6/src/com/wentch/redkale/convert/json/JsonFactory.java new file mode 100644 index 000000000..0b7f5c9f7 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/json/JsonFactory.java @@ -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 { + + 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; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/json/JsonReader.java b/convert-jdk6/src/com/wentch/redkale/convert/json/JsonReader.java new file mode 100644 index 000000000..2e399e3bb --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/json/JsonReader.java @@ -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 createPool(int max) { + return new ObjectPool(max, new Creator() { + + @Override + public JsonReader create(Object... params) { + return new JsonReader(); + } + }, null, new Predicate() { + + @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); + } + } + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/json/JsonSimpledCoder.java b/convert-jdk6/src/com/wentch/redkale/convert/json/JsonSimpledCoder.java new file mode 100644 index 000000000..cd28528ff --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/json/JsonSimpledCoder.java @@ -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 + */ +public abstract class JsonSimpledCoder extends SimpledCoder { + +} diff --git a/convert-jdk6/src/com/wentch/redkale/convert/json/JsonWriter.java b/convert-jdk6/src/com/wentch/redkale/convert/json/JsonWriter.java new file mode 100644 index 000000000..34f6481a5 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/convert/json/JsonWriter.java @@ -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 createPool(int max) { + return new ObjectPool(max, new Creator() { + + @Override + public JsonWriter create(Object... params) { + return new JsonWriter(); + } + }, null, new Predicate() { + + @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; + } + + /** + * 注意: 该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); + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/Attribute.java b/convert-jdk6/src/com/wentch/redkale/util/Attribute.java new file mode 100644 index 000000000..7bbae9781 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/Attribute.java @@ -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 + * @param + */ +public interface Attribute { + + 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 Attribute create(final Field field) { + return create((Class) field.getDeclaringClass(), field.getName(), field, null, null); + } + + public static Attribute create(String fieldname, final Field field) { + return create((Class) field.getDeclaringClass(), fieldname, field, null, null); + } + + public static Attribute create(Class 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 Attribute create(Class clazz, final java.lang.reflect.Field field) { + return create(clazz, field.getName(), field); + } + + public static Attribute create(Class clazz, final String fieldname, final java.lang.reflect.Field field) { + return create(clazz, fieldname, field, null, null); + } + + public static Attribute create(final Method getter, final Method setter) { + return create((Class) (getter == null ? setter.getDeclaringClass() : getter.getDeclaringClass()), null, null, getter, setter); + } + + public static Attribute create(Class clazz, final Method getter, final Method setter) { + return create(clazz, null, null, getter, setter); + } + + public static Attribute create(Class clazz, final String fieldalias, final Method getter, final Method setter) { + return create(clazz, fieldalias, null, getter, setter); + } + + @SuppressWarnings("unchecked") + public static Attribute create(final Class 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, "", "()V", null, null); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()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 creatorClazz = (Class) 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); + } + } + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/BiPredicate.java b/convert-jdk6/src/com/wentch/redkale/util/BiPredicate.java new file mode 100644 index 000000000..20624a6c4 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/BiPredicate.java @@ -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 + * @param + */ +public interface BiPredicate { + + /** + * 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); + +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/ByteArray.java b/convert-jdk6/src/com/wentch/redkale/util/ByteArray.java new file mode 100644 index 000000000..4dc85bbbf --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/ByteArray.java @@ -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; + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/Consumer.java b/convert-jdk6/src/com/wentch/redkale/util/Consumer.java new file mode 100644 index 000000000..2ae5f6af6 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/Consumer.java @@ -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 + */ +public interface Consumer { + + /** + * Performs this operation on the given argument. + * + * @param t the input argument + */ + void accept(T t); +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/Creator.java b/convert-jdk6/src/com/wentch/redkale/util/Creator.java new file mode 100644 index 000000000..23efe455f --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/Creator.java @@ -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 + */ +public interface Creator { +// +// static class PooledCreator implements Creator { +// +// private final T defValue; +// +// private final Reproduce reproduce; +// +// private final ReferenceQueue refQueue = new ReferenceQueue(); +// +// private final Queue queue; +// +// private final Creator creator; +// +// public PooledCreator(int max, Class clazz, Creator 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 Creator create(int max, Class clazz) { +// return new PooledCreator<>(max, clazz, create(clazz)); +// } +// +// @SuppressWarnings("unchecked") +// public static Creator create(int max, Class clazz, Creator creator) { +// return new PooledCreator<>(max, clazz, creator); +// } + + public T create(Object... params); + + public static final class Creators { + + @SuppressWarnings("unchecked") + public static Creator create(Class clazz) { + if (clazz.isAssignableFrom(ArrayList.class)) { + clazz = (Class) ArrayList.class; + } else if (clazz.isAssignableFrom(HashMap.class)) { + clazz = (Class) HashMap.class; + } else if (clazz.isAssignableFrom(HashSet.class)) { + clazz = (Class) 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 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, "", "()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", "", "()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, "", 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); + } + } + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/DLong.java b/convert-jdk6/src/com/wentch/redkale/util/DLong.java new file mode 100644 index 000000000..919e31568 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/DLong.java @@ -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 { + + 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)); + } + +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/DebugMethodVisitor.java b/convert-jdk6/src/com/wentch/redkale/util/DebugMethodVisitor.java new file mode 100644 index 000000000..7c8cc848b --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/DebugMethodVisitor.java @@ -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 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"); + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/ObjectPool.java b/convert-jdk6/src/com/wentch/redkale/util/ObjectPool.java new file mode 100644 index 000000000..44e74496e --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/ObjectPool.java @@ -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 + */ +public final class ObjectPool { + + private static final Logger logger = Logger.getLogger(ObjectPool.class.getSimpleName()); + + private final boolean debug; + + private final Queue queue; + + private Creator creator; + + private final Consumer prepare; + + private final Predicate recycler; + + private final AtomicLong creatCounter; + + private final AtomicLong cycleCounter; + + public ObjectPool(Class clazz, Consumer prepare, Predicate recycler) { + this(2, clazz, prepare, recycler); + } + + public ObjectPool(int max, Class clazz, Consumer prepare, Predicate recycler) { + this(max, Creators.create(clazz), prepare, recycler); + } + + public ObjectPool(Creator creator, Consumer prepare, Predicate recycler) { + this(2, creator, prepare, recycler); + } + + public ObjectPool(int max, Creator creator, Consumer prepare, Predicate recycler) { + this(null, null, max, creator, prepare, recycler); + } + + public ObjectPool(AtomicLong creatCounter, AtomicLong cycleCounter, int max, Creator creator, Consumer prepare, Predicate 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 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(); + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/Predicate.java b/convert-jdk6/src/com/wentch/redkale/util/Predicate.java new file mode 100644 index 000000000..9bf0b0639 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/Predicate.java @@ -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 + */ +public interface Predicate { + + /** + * 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); +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/TypeToken.java b/convert-jdk6/src/com/wentch/redkale/util/TypeToken.java new file mode 100644 index 000000000..63b67ed02 --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/TypeToken.java @@ -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 + */ +public abstract class TypeToken { + + private final Type type; + + public TypeToken() { + type = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + } + + public final Type getType() { + return type; + } +} diff --git a/convert-jdk6/src/com/wentch/redkale/util/Utility.java b/convert-jdk6/src/com/wentch/redkale/util/Utility.java new file mode 100644 index 000000000..71ef6054a --- /dev/null +++ b/convert-jdk6/src/com/wentch/redkale/util/Utility.java @@ -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 + *

+ * @return + */ + public static InetAddress localInetAddress() { + InetAddress back = null; + try { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface nif = nifs.nextElement(); + if (!nif.isUp()) continue; + Enumeration 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 + *

+ * @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 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 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 headers, String body) throws IOException { + return remoteHttpContent(null, "POST", url, headers, body).toByteArray(); + } + + public static byte[] postHttpBytesContent(SSLContext ctx, String url, Map 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 headers, String body) throws IOException { + return remoteHttpContent(ctx, "GET", url, headers, body).toString("UTF-8"); + } + + public static String getHttpContent(String url, Map 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 headers, String body) throws IOException { + return remoteHttpContent(null, "GET", url, headers, body).toByteArray(); + } + + public static byte[] getHttpBytesContent(SSLContext ctx, String url, Map headers, String body) throws IOException { + return remoteHttpContent(ctx, "GET", url, headers, body).toByteArray(); + } + + protected static ByteArrayOutputStream remoteHttpContent(SSLContext ctx, String method, String url, Map 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 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); + } +}