From 541d1b3c8c36b42e14e38ba896af9c1a9edcbf27 Mon Sep 17 00:00:00 2001 From: shaozhuguang Date: Thu, 20 Jun 2019 09:38:10 +0800 Subject: [PATCH] Modify Operation return result resolver !!! --- .../contract/jvm/AbstractContractCode.java | 2 +- source/ledger/ledger-model/pom.xml | 1 - .../blockchain/ledger/BytesValueEncoding.java | 155 +++- .../resolver/AbstractBytesValueResolver.java | 54 ++ .../resolver/BytesToBytesValueResolver.java | 58 ++ .../ledger/resolver/BytesValueResolver.java | 80 ++ .../resolver/IntegerToBytesValueResolver.java | 58 ++ .../resolver/LongToBytesValueResolver.java | 58 ++ .../resolver/ShortToBytesValueResolver.java | 57 ++ .../resolver/StringToBytesValueResolver.java | 66 ++ .../ContractInvocationHandler.java | 2 +- .../data/BytesToBytesValueResolverTest.java | 43 ++ .../ledger/data/BytesValueEncodingTest.java | 24 + .../data/IntegerToBytesValueResolverTest.java | 51 ++ .../data/LongToBytesValueResolverTest.java | 52 ++ .../data/ShortToBytesValueResolverTest.java | 43 ++ .../data/StringToBytesValueResolverTest.java | 79 ++ .../sdk/converters/ClientResolveUtil.java | 687 +++++++++--------- .../sdk/samples/SDK_Contract_Demo.java | 3 +- .../composite/CompositeConnectionFactory.java | 2 +- .../handler/MockerContractExeHandle.java | 9 +- .../mocker/proxy/ContractProxy.java | 2 +- .../jd/blockchain/utils/io/BytesUtils.java | 5 + 23 files changed, 1220 insertions(+), 371 deletions(-) create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesValueResolver.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java create mode 100644 source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java create mode 100644 source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesToBytesValueResolverTest.java create mode 100644 source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesValueEncodingTest.java create mode 100644 source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/IntegerToBytesValueResolverTest.java create mode 100644 source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/LongToBytesValueResolverTest.java create mode 100644 source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ShortToBytesValueResolverTest.java create mode 100644 source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/StringToBytesValueResolverTest.java diff --git a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/AbstractContractCode.java b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/AbstractContractCode.java index e8ebb6a3..dd6276ba 100644 --- a/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/AbstractContractCode.java +++ b/source/contract/contract-jvm/src/main/java/com/jd/blockchain/contract/jvm/AbstractContractCode.java @@ -96,7 +96,7 @@ public abstract class AbstractContractCode implements ContractCode { eventContext.getEvent(), address.toString(), error.getMessage()), error); } - BytesValue retnBytes = BytesValueEncoding.encode(retn, handleMethod.getReturnType()); + BytesValue retnBytes = BytesValueEncoding.encodeSingle(retn, handleMethod.getReturnType()); return retnBytes; } diff --git a/source/ledger/ledger-model/pom.xml b/source/ledger/ledger-model/pom.xml index d9df06a7..f15cafbe 100644 --- a/source/ledger/ledger-model/pom.xml +++ b/source/ledger/ledger-model/pom.xml @@ -39,7 +39,6 @@ ${project.version} test - \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java index f21918fb..c7e4738d 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BytesValueEncoding.java @@ -1,24 +1,131 @@ package com.jd.blockchain.ledger; +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.ledger.resolver.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + public class BytesValueEncoding { - - - - - public static BytesValue encode(Object value, Class type) { - throw new IllegalStateException("Not implemented!"); + + private static final Map, BytesValueResolver> CLASS_RESOLVER_MAP = new ConcurrentHashMap<>(); + + private static final Map DATA_TYPE_RESOLVER_MAP = new ConcurrentHashMap<>(); + + static { + init(); } - - public static BytesValueList encode(Object[] values, Class[] types) { - throw new IllegalStateException("Not implemented!"); + + private static void init() { + BytesValueResolver[] resolvers = new BytesValueResolver[]{ + new BytesToBytesValueResolver(), + new IntegerToBytesValueResolver(), + new LongToBytesValueResolver(), + new ShortToBytesValueResolver(), + new StringToBytesValueResolver() + }; + + for (BytesValueResolver currResolver : resolvers) { + // 填充classMAP + Class[] supportClasses = currResolver.supportClasses(); + if (supportClasses != null && supportClasses.length > 0) { + for (Class clazz : supportClasses) { + CLASS_RESOLVER_MAP.put(clazz, currResolver); + } + } + + // 填充dataTypeMap + DataType[] supportDataTypes = currResolver.supportDataTypes(); + if (supportDataTypes != null && supportDataTypes.length > 0) { + for (DataType dataType : supportDataTypes) { + DATA_TYPE_RESOLVER_MAP.put(dataType, currResolver); + } + } + } + } + + + public static BytesValue encodeSingle(Object value, Class type) { + if (type == null) { + type = value.getClass(); + } + if (type.isInterface()) { + // 判断是否含有DataContract注解 + if (!type.isAnnotationPresent(DataContract.class)) { + throw new IllegalStateException(String.format("Interface[%s] can not be serialize !!!", type.getName())); + } + // 将对象序列化 + byte[] serialBytes = BinaryProtocol.encode(value, type); + return BytesData.fromType(DataType.DATA_CONTRACT, serialBytes); + } + BytesValueResolver bytesValueResolver = CLASS_RESOLVER_MAP.get(type); + if (bytesValueResolver == null) { + throw new IllegalStateException(String.format("Class[%s] can not find encoder !!!", type.getName())); + } + return bytesValueResolver.encode(value, type); } + public static BytesValueList encodeArray(Object[] values, Class[] types) { + if (values == null || values.length == 0) { + return null; + } + if (types != null && types.length != values.length) { + throw new IllegalStateException("Types can be null, or types's length must be equal BytesValue[]'s !!!"); + } + + BytesValueListData bytesValueListData = new BytesValueListData(); + for (int i = 0; i < values.length; i++) { + BytesValue bytesValue = encodeSingle(values[i], types == null ? null : types[i]); + bytesValueListData.add(bytesValue); + } + return bytesValueListData; + } + + public static Object decode(BytesValue value) { + return decode(value, null); + } + public static Object decode(BytesValue value, Class type) { - throw new IllegalStateException("Not implemented!"); + DataType dataType = value.getType(); + BytesValueResolver valueResolver = DATA_TYPE_RESOLVER_MAP.get(dataType); + if (valueResolver == null) { + throw new IllegalStateException(String.format("DataType[%s] can not find encoder !!!", dataType.name())); + } + return type == null ? valueResolver.decode(value) : valueResolver.decode(value, type); } public static Object[] decode(BytesValueList values, Class[] types) { - throw new IllegalStateException("Not implemented!"); + BytesValue[] bytesValues = values.getValues(); + if (bytesValues == null || bytesValues.length == 0) { + return null; + } + // 允许types为null,此时每个BytesValue按照当前的对象来处理 + // 若types不为null,则types's长度必须和bytesValues一致 + if (types != null && types.length != bytesValues.length) { + throw new IllegalStateException("Types can be null, or types's length must be equal BytesValue[]'s !!!"); + } + Object[] resolveObjs = new Object[bytesValues.length]; + if (types == null) { + // 按照默认方式解析 + for (int i = 0; i < bytesValues.length; i++) { + BytesValue bytesValue = bytesValues[i]; + DataType dataType = bytesValue.getType(); + BytesValueResolver valueResolver = DATA_TYPE_RESOLVER_MAP.get(dataType); + if (valueResolver == null) { + throw new IllegalStateException(String.format("DataType[%s] can not find encoder !!!", dataType.name())); + } + resolveObjs[i] = valueResolver.decode(bytesValue); + } + return resolveObjs; + } + // 按照输入的Class进行解析 + for (int i = 0; i < bytesValues.length; i++) { + resolveObjs[i] = decode(bytesValues[i], types[i]); + } + return resolveObjs; } public static Object getDefaultValue(Class type) { @@ -54,7 +161,29 @@ public class BytesValueEncoding { } public static boolean supportType(Class currParamType) { - // TODO Auto-generated method stub - return false; + if (currParamType.isInterface()) { + // 接口序列化必须实现DataContract注解 + if (!currParamType.isAnnotationPresent(DataContract.class)) { + throw new IllegalStateException(String.format("Interface[%s] can not be serialize !!!", currParamType.getName())); + } + return true; + } + return CLASS_RESOLVER_MAP.containsKey(currParamType); + } + + + public static class BytesValueListData implements BytesValueList { + + private List bytesValues = new ArrayList<>(); + + public void add(BytesValue bytesValue) { + bytesValues.add(bytesValue); + } + + @Override + public BytesValue[] getValues() { + BytesValue[] bytesValueArray = new BytesValue[bytesValues.size()]; + return bytesValues.toArray(bytesValueArray); + } } } diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java new file mode 100644 index 00000000..995d5522 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/AbstractBytesValueResolver.java @@ -0,0 +1,54 @@ +package com.jd.blockchain.ledger.resolver; + +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.utils.Bytes; + +public abstract class AbstractBytesValueResolver implements BytesValueResolver { + + protected boolean isSupport(Class type) { + if (type == null) { + return false; + } + Class[] supports = supportClasses(); + if (supports != null && supports.length > 0) { + for (Class clazz : supports) { + if (type.equals(clazz)) { + return true; + } + } + } + return false; + } + + protected boolean isSupport(DataType dataType) { + if (dataType == null) { + return false; + } + DataType[] supports = supportDataTypes(); + if (supports != null && supports.length > 0) { + for (DataType dt : supports) { + if (dataType.equals(dt)) { + return true; + } + } + } + return false; + } + + @Override + public BytesValue encode(Object value) { + return encode(value, value.getClass()); + } + + @Override + public Object decode(BytesValue value) { + DataType dataType = value.getType(); + if (!isSupport(dataType)) { + throw new IllegalStateException(String.format("Un-support encode DataType[%s] Object !!!", dataType.name())); + } + return decode(value.getValue()); + } + + protected abstract Object decode(Bytes value); +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java new file mode 100644 index 00000000..f4871515 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesToBytesValueResolver.java @@ -0,0 +1,58 @@ +package com.jd.blockchain.ledger.resolver; + +import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.utils.Bytes; + +import java.util.Set; + +public class BytesToBytesValueResolver extends AbstractBytesValueResolver { + + private final Class[] supportClasses = {Bytes.class, byte[].class}; + + private final DataType[] supportDataTypes = {DataType.BYTES}; + + private final Set> convertClasses = initByteConvertSet(); + + @Override + public BytesValue encode(Object value, Class type) { + if (!isSupport(type)) { + throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); + } + if (type.equals(byte[].class)) { + return BytesData.fromBytes((byte[]) value); + } + return BytesData.fromBytes((Bytes) value); + } + + @Override + public Class[] supportClasses() { + return supportClasses; + } + + @Override + public DataType[] supportDataTypes() { + return supportDataTypes; + } + + @Override + protected Object decode(Bytes value) { + return value; + } + + @Override + public Object decode(BytesValue value, Class clazz) { + Bytes bytesVal = (Bytes) decode(value); + if (!convertClasses.contains(clazz)) { + throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName())); + } + + if (clazz.equals(String.class)) { + return bytesVal.toUTF8String(); + } else if (clazz.equals(byte[].class)) { + return bytesVal.toBytes(); + } + return bytesVal; + } +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesValueResolver.java new file mode 100644 index 00000000..08e48658 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/BytesValueResolver.java @@ -0,0 +1,80 @@ +package com.jd.blockchain.ledger.resolver; + +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.utils.Bytes; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public interface BytesValueResolver { + + /** + * Int相关的可转换Class集合 + */ + Class[] supportIntConvertClasses = { + short.class, Short.class, int.class, Integer.class, long.class, Long.class}; + + /** + * 字节数组(字符串)相关可转换的Class集合 + */ + Class[] supportByteConvertClasses = { + String.class, Bytes.class, byte[].class}; + + default Set> initIntConvertSet() { + return new HashSet<>(Arrays.asList(supportIntConvertClasses)); + } + + default Set> initByteConvertSet() { + return new HashSet<>(Arrays.asList(supportByteConvertClasses)); + } + + /** + * 将对象转换为BytesValue + * + * @param value + * @return + */ + BytesValue encode(Object value); + + /** + * 将对象转换为BytesValue + * + * @param value + * @param type + * @return + */ + BytesValue encode(Object value, Class type); + + /** + * 当前解析器支持的Class列表 + * + * @return + */ + Class[] supportClasses(); + + /** + * 当前解析器支持的DataType列表 + * + * @return + */ + DataType[] supportDataTypes(); + + /** + * 将BytesValue解析为对应的Object + * + * @param value + * @return + */ + Object decode(BytesValue value); + + /** + * 将BytesValue转换为指定Class的Object + * + * @param value + * @param clazz + * @return + */ + Object decode(BytesValue value, Class clazz); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java new file mode 100644 index 00000000..a8400f02 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/IntegerToBytesValueResolver.java @@ -0,0 +1,58 @@ +package com.jd.blockchain.ledger.resolver; + +import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.BytesUtils; + +import java.util.Set; + +public class IntegerToBytesValueResolver extends AbstractBytesValueResolver { + + private final Class[] supportClasses = {Integer.class, int.class}; + + private final DataType[] supportDataTypes = {DataType.INT32}; + + private final Set> convertClasses = initIntConvertSet(); + + @Override + public BytesValue encode(Object value, Class type) { + if (!isSupport(type)) { + throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); + } + return BytesData.fromInt32((int) value); + } + + @Override + public Class[] supportClasses() { + return supportClasses; + } + + @Override + public DataType[] supportDataTypes() { + return supportDataTypes; + } + + @Override + protected Object decode(Bytes value) { + return BytesUtils.toInt(value.toBytes()); + } + + @Override + public Object decode(BytesValue value, Class clazz) { + // 支持转换为short、int、long + int intVal = (int)decode(value); + if (convertClasses.contains(clazz)) { + // 对于short和Short需要强制类型转换 + if (clazz.equals(short.class) || clazz.equals(Short.class)) { + return (short) intVal; + } else if (clazz.equals(long.class) || clazz.equals(Long.class)) { + return (long) intVal; + } + return intVal; + } else { + throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName())); + } + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java new file mode 100644 index 00000000..fa11bcf4 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/LongToBytesValueResolver.java @@ -0,0 +1,58 @@ +package com.jd.blockchain.ledger.resolver; + +import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.BytesUtils; + +import java.util.Set; + +public class LongToBytesValueResolver extends AbstractBytesValueResolver { + + private final Class[] supportClasses = {Long.class, long.class}; + + private final DataType[] supportDataTypes = {DataType.INT64}; + + private final Set> convertClasses = initIntConvertSet(); + + @Override + public BytesValue encode(Object value, Class type) { + if (!isSupport(type)) { + throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); + } + return BytesData.fromInt64((long)value); + } + + @Override + public Class[] supportClasses() { + return supportClasses; + } + + @Override + public DataType[] supportDataTypes() { + return supportDataTypes; + } + + @Override + protected Object decode(Bytes value) { + return BytesUtils.toLong(value.toBytes()); + } + + @Override + public Object decode(BytesValue value, Class clazz) { + // 支持转换为short、int、long + long longVal = (long)decode(value); + if (convertClasses.contains(clazz)) { + // 对于short和Short需要强制类型转换 + if (clazz.equals(short.class) || clazz.equals(Short.class)) { + return (short) longVal; + } else if (clazz.equals(int.class) || clazz.equals(Integer.class)) { + return (int) longVal; + } + return longVal; + } else { + throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName())); + } + } +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java new file mode 100644 index 00000000..b8eea38c --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/ShortToBytesValueResolver.java @@ -0,0 +1,57 @@ +package com.jd.blockchain.ledger.resolver; + +import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.BytesUtils; + +import java.util.Set; + +public class ShortToBytesValueResolver extends AbstractBytesValueResolver { + + private final Class[] supportClasses = {Short.class, short.class}; + + private final DataType[] supportDataTypes = {DataType.INT16}; + + private final Set> convertClasses = initIntConvertSet(); + + @Override + public BytesValue encode(Object value, Class type) { + if (!isSupport(type)) { + throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); + } + return BytesData.fromInt16((short)value); + } + + @Override + public Class[] supportClasses() { + return supportClasses; + } + + @Override + public DataType[] supportDataTypes() { + return supportDataTypes; + } + + @Override + protected Object decode(Bytes value) { + return BytesUtils.toShort(value.toBytes()); + } + + @Override + public Object decode(BytesValue value, Class clazz) { + // 支持转换为short、int、long,由short转int、long无需转换 + short shortVal = (short)decode(value); + if (convertClasses.contains(clazz)) { + if (clazz.equals(int.class) || clazz.equals(Integer.class)) { + return (int) shortVal; + } else if (clazz.equals(long.class) || clazz.equals(Long.class)) { + return (long) shortVal; + } + return shortVal; + } else { + throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName())); + } + } +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java new file mode 100644 index 00000000..dca8e5d1 --- /dev/null +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/resolver/StringToBytesValueResolver.java @@ -0,0 +1,66 @@ +package com.jd.blockchain.ledger.resolver; + +import com.jd.blockchain.ledger.BytesData; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.BytesUtils; +import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; + +import java.util.Set; + + +public class StringToBytesValueResolver extends AbstractBytesValueResolver { + + private final Class[] supportClasses = {String.class}; + + private final DataType[] supportDataTypes = {DataType.TEXT, DataType.XML, DataType.JSON}; + + private final Set> convertClasses = initByteConvertSet(); + + @Override + public BytesValue encode(Object value, Class type) { + if (!isSupport(type)) { + throw new IllegalStateException(String.format("Un-support encode Class[%s] Object !!!", type.getName())); + } + // 类型判断 + String valString = (String)value; + if (JSONSerializeUtils.isJSON(valString)) { + return BytesData.fromJSON(valString); + } + // 暂不处理XML格式 + return BytesData.fromText(valString); + } + + @Override + public Class[] supportClasses() { + return supportClasses; + } + + @Override + public DataType[] supportDataTypes() { + return supportDataTypes; + } + + @Override + protected Object decode(Bytes value) { + return BytesUtils.toString(value.toBytes()); + } + + @Override + public Object decode(BytesValue value, Class clazz) { + // 支持三种类型对象返回,String.class,byte[].class,Bytes.class + String textValue = (String)decode(value); + + if (!convertClasses.contains(clazz)) { + throw new IllegalStateException(String.format("Un-Support decode value to class[%s] !!!", clazz.getName())); + } + + if (clazz.equals(byte[].class)) { + return BytesUtils.toBytes(textValue); + } else if (clazz.equals(Bytes.class)) { + return Bytes.fromString(textValue); + } + return textValue; + } +} \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationHandler.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationHandler.java index 744eab47..8b48d509 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationHandler.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationHandler.java @@ -53,7 +53,7 @@ public class ContractInvocationHandler implements InvocationHandler { } // 序列化调用参数; Class[] argTypes = method.getParameterTypes(); - BytesValueList argBytes = BytesValueEncoding.encode(args, argTypes); + BytesValueList argBytes = BytesValueEncoding.encodeArray(args, argTypes); // 定义合约调用操作; ContractEventSendOpTemplate opTemplate = (ContractEventSendOpTemplate) sendOpBuilder.send(contractAddress, diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesToBytesValueResolverTest.java new file mode 100644 index 00000000..fb470200 --- /dev/null +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesToBytesValueResolverTest.java @@ -0,0 +1,43 @@ +package test.com.jd.blockchain.ledger.data; + +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.ledger.resolver.BytesToBytesValueResolver; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.BytesUtils; +import static org.junit.Assert.*; +import org.junit.Test; + +public class BytesToBytesValueResolverTest { + + private BytesToBytesValueResolver resolver = new BytesToBytesValueResolver(); + + @Test + public void test() { + String text = "www.jd.com"; + + byte[] bytes = BytesUtils.toBytes(text); + + Bytes bytesObj = Bytes.fromString(text); + + BytesValue bytesValue = resolver.encode(bytes); + + assertNotNull(bytesValue); + + assertEquals(bytesValue.getType(), DataType.BYTES); + + assertEquals(bytesObj, bytesValue.getValue()); + + Bytes resolveBytesObj = (Bytes)resolver.decode(bytesValue); + + assertEquals(bytesObj, resolveBytesObj); + + byte[] resolveBytes = (byte[])resolver.decode(bytesValue, byte[].class); + + assertArrayEquals(bytes, resolveBytes); + + String resolveText = (String)resolver.decode(bytesValue, String.class); + + assertEquals(text, resolveText); + } +} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesValueEncodingTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesValueEncodingTest.java new file mode 100644 index 00000000..d6bde510 --- /dev/null +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/BytesValueEncodingTest.java @@ -0,0 +1,24 @@ +package test.com.jd.blockchain.ledger.data; + +import com.jd.blockchain.ledger.BytesValueEncoding; +import com.jd.blockchain.utils.Bytes; +import static org.junit.Assert.*; +import org.junit.Test; + +public class BytesValueEncodingTest { + @Test + public void testSupport() { + assertTrue(BytesValueEncoding.supportType(byte[].class)); + assertTrue(BytesValueEncoding.supportType(int.class)); + assertTrue(BytesValueEncoding.supportType(Integer.class)); + assertTrue(BytesValueEncoding.supportType(short.class)); + assertTrue(BytesValueEncoding.supportType(Short.class)); + assertTrue(BytesValueEncoding.supportType(long.class)); + assertTrue(BytesValueEncoding.supportType(Long.class)); + assertTrue(BytesValueEncoding.supportType(String.class)); + assertTrue(BytesValueEncoding.supportType(Bytes.class)); + + + + } +} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/IntegerToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/IntegerToBytesValueResolverTest.java new file mode 100644 index 00000000..4b65ae16 --- /dev/null +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/IntegerToBytesValueResolverTest.java @@ -0,0 +1,51 @@ +package test.com.jd.blockchain.ledger.data; + +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.ledger.resolver.IntegerToBytesValueResolver; +import static org.junit.Assert.*; + +import com.jd.blockchain.utils.Bytes; +import org.junit.Test; + +public class IntegerToBytesValueResolverTest { + + private IntegerToBytesValueResolver resolver = new IntegerToBytesValueResolver(); + + @Test + public void test() { + int intVal = 1024; + + BytesValue intBytesValue = resolver.encode(intVal); + + BytesValue intBytesValue1 = resolver.encode(intVal, int.class); + + BytesValue intBytesValue2 = resolver.encode(intVal, Integer.class); + + assertEquals(intBytesValue.getValue(), intBytesValue1.getValue()); + + assertEquals(intBytesValue.getValue(), intBytesValue2.getValue()); + + Bytes intBytes = Bytes.fromInt(intVal); + + assertEquals(intBytes, intBytesValue.getValue()); + + assertEquals(intBytesValue.getType(), DataType.INT32); + + int resolveInt = (int)resolver.decode(intBytesValue); + + assertEquals(intVal, resolveInt); + + short resolveShort = (short) resolver.decode(intBytesValue, short.class); + assertEquals(resolveShort, 1024); + Short resolveShortObj = (Short) resolver.decode(intBytesValue, Short.class); + assertEquals((short)resolveShortObj, resolveShort); + + long resolveLong = (long) resolver.decode(intBytesValue, long.class); + assertEquals(resolveLong, 1024L); + + Long resolveLongObj = (Long) resolver.decode(intBytesValue, Long.class); + assertEquals(resolveLong, (long) resolveLongObj); + + } +} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/LongToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/LongToBytesValueResolverTest.java new file mode 100644 index 00000000..19cbdcbd --- /dev/null +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/LongToBytesValueResolverTest.java @@ -0,0 +1,52 @@ +package test.com.jd.blockchain.ledger.data; + +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.ledger.resolver.IntegerToBytesValueResolver; +import com.jd.blockchain.ledger.resolver.LongToBytesValueResolver; +import com.jd.blockchain.utils.Bytes; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class LongToBytesValueResolverTest { + + private LongToBytesValueResolver resolver = new LongToBytesValueResolver(); + + @Test + public void test() { + long longVal = 65536L; + + BytesValue longBytesValue = resolver.encode(longVal); + + BytesValue longBytesValue1 = resolver.encode(longVal, long.class); + + BytesValue longBytesValue2 = resolver.encode(longVal, Long.class); + + assertEquals(longBytesValue.getValue(), longBytesValue1.getValue()); + + assertEquals(longBytesValue.getValue(), longBytesValue2.getValue()); + + Bytes longBytes = Bytes.fromLong(longVal); + + assertEquals(longBytes, longBytesValue.getValue()); + + assertEquals(longBytesValue.getType(), DataType.INT64); + + long resolveLong = (long)resolver.decode(longBytesValue); + + assertEquals(longVal, resolveLong); + + short resolveShort = (short) resolver.decode(longBytesValue, short.class); + assertEquals(resolveShort, (short)65536); + + Short resolveShortObj = (Short) resolver.decode(longBytesValue, Short.class); + assertEquals((short)resolveShortObj, resolveShort); + + int resolveInt = (int) resolver.decode(longBytesValue, int.class); + assertEquals(resolveInt, 65536); + + Integer resolveIntObj = (Integer) resolver.decode(longBytesValue, Integer.class); + assertEquals(resolveInt, (int) resolveIntObj); + } +} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ShortToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ShortToBytesValueResolverTest.java new file mode 100644 index 00000000..6c4ef0c8 --- /dev/null +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/ShortToBytesValueResolverTest.java @@ -0,0 +1,43 @@ +package test.com.jd.blockchain.ledger.data; + +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.ledger.resolver.ShortToBytesValueResolver; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.BytesUtils; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class ShortToBytesValueResolverTest { + + private ShortToBytesValueResolver resolver = new ShortToBytesValueResolver(); + + @Test + public void test() { + short shortVal = 64; + + BytesValue shortBytesValue = resolver.encode(shortVal); + + Bytes shortBytes = new Bytes(BytesUtils.toBytes(shortVal)); + + assertEquals(shortBytes, shortBytesValue.getValue()); + + assertEquals(shortBytesValue.getType(), DataType.INT16); + + short resolveShort = (short)resolver.decode(shortBytesValue); + + assertEquals(shortVal, resolveShort); + + int resolveInt = (int) resolver.decode(shortBytesValue, int.class); + assertEquals(resolveInt, 64); + Integer resolveIntObj = (Integer) resolver.decode(shortBytesValue, Integer.class); + assertEquals((int)resolveIntObj, resolveShort); + + long resolveLong = (long) resolver.decode(shortBytesValue, long.class); + assertEquals(resolveLong, 64L); + + Long resolveLongObj = (Long) resolver.decode(shortBytesValue, Long.class); + assertEquals(resolveLong, (long) resolveLongObj); + } +} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/StringToBytesValueResolverTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/StringToBytesValueResolverTest.java new file mode 100644 index 00000000..6538e88e --- /dev/null +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/data/StringToBytesValueResolverTest.java @@ -0,0 +1,79 @@ +package test.com.jd.blockchain.ledger.data; + +import com.alibaba.fastjson.JSON; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataType; +import com.jd.blockchain.ledger.resolver.StringToBytesValueResolver; +import com.jd.blockchain.utils.Bytes; +import static org.junit.Assert.*; + +import com.jd.blockchain.utils.io.BytesUtils; +import org.junit.Test; + +public class StringToBytesValueResolverTest { + + private StringToBytesValueResolver resolver = new StringToBytesValueResolver(); + + @Test + public void testText() { + String textVal = "JDChain"; + + BytesValue textBytesValue = resolver.encode(textVal); + + assertEquals(Bytes.fromString(textVal), textBytesValue.getValue()); + + assertEquals(textBytesValue.getType(), DataType.TEXT); + + String resolveText = (String)resolver.decode(textBytesValue); + + assertEquals(resolveText, textVal); + + byte[] resolveBytes = (byte[]) resolver.decode(textBytesValue, byte[].class); + + assertArrayEquals(resolveBytes, BytesUtils.toBytes(textVal)); + + Bytes resolveBytesObj = (Bytes) resolver.decode(textBytesValue, Bytes.class); + + assertEquals(resolveBytesObj, Bytes.fromString(textVal)); + + } + + @Test + public void testJson() { + Person person = new Person("zhangsan", 80); + String personJson = JSON.toJSONString(person); + BytesValue textBytesValue = resolver.encode(personJson); + assertEquals(Bytes.fromString(personJson), textBytesValue.getValue()); + assertEquals(textBytesValue.getType(), DataType.JSON); + } + + public static class Person { + private String name; + + private int age; + + public Person() { + } + + public Person(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + } +} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java index 5419a531..f0f904ad 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/converters/ClientResolveUtil.java @@ -31,348 +31,347 @@ import java.lang.reflect.Field; public class ClientResolveUtil { - public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) { - if (kvDataEntries == null || kvDataEntries.length == 0) { - return kvDataEntries; - } - KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length]; - // kvDataEntries是代理对象,需要处理 - for (int i = 0; i < kvDataEntries.length; i++) { - KVDataEntry kvDataEntry = kvDataEntries[i]; - String key = kvDataEntry.getKey(); - long version = kvDataEntry.getVersion(); - DataType dataType = kvDataEntry.getType(); - KvData innerKvData = new KvData(key, version, dataType); - Object valueObj = kvDataEntry.getValue(); - switch (dataType) { - case NIL: - break; - case BYTES: - case TEXT: - case JSON: - innerKvData.setValue(valueObj.toString()); - break; - case INT32: - innerKvData.setValue(Integer.parseInt(valueObj.toString())); - break; - case INT64: - innerKvData.setValue(Long.parseLong(valueObj.toString())); - break; - default: - throw new IllegalStateException("Unsupported value type[" + dataType + "] to resolve!"); - } - resolveKvDataEntries[i] = innerKvData; - } - return resolveKvDataEntries; - } - - public static Operation read(Operation operation) { - - try { - // Class - Class clazz = operation.getClass(); - Field field = clazz.getSuperclass().getDeclaredField("h"); - field.setAccessible(true); - Object object = field.get(operation); - if (object instanceof JSONObject) { - JSONObject jsonObject = (JSONObject) object; - if (jsonObject.containsKey("accountID")) { - return convertDataAccountRegisterOperation(jsonObject); - } else if (jsonObject.containsKey("userID")) { - return convertUserRegisterOperation(jsonObject); - } else if (jsonObject.containsKey("contractID")) { - return convertContractCodeDeployOperation(jsonObject); - } else if (jsonObject.containsKey("writeSet")) { - return convertDataAccountKVSetOperation(jsonObject); - } else if (jsonObject.containsKey("initSetting")) { - return convertLedgerInitOperation(jsonObject); - } else if (jsonObject.containsKey("contractAddress")) { - return convertContractEventSendOperation(jsonObject); - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - - return null; - } - - public static Object readValueByBytesValue(BytesValue bytesValue) { - DataType dataType = bytesValue.getType(); - Bytes saveVal = bytesValue.getValue(); - Object showVal; - switch (dataType) { - case BYTES: - // return hex - showVal = HexUtils.encode(saveVal.toBytes()); - break; - case TEXT: - case JSON: - showVal = saveVal.toUTF8String(); - break; - case INT64: - showVal = BytesUtils.toLong(saveVal.toBytes()); - break; - default: - showVal = HexUtils.encode(saveVal.toBytes()); - break; - } - return showVal; - } - - public static DataAccountRegisterOperation convertDataAccountRegisterOperation(JSONObject jsonObject) { - JSONObject account = jsonObject.getJSONObject("accountID"); - return new DataAccountRegisterOpTemplate(blockchainIdentity(account)); - } - - public static DataAccountKVSetOperation convertDataAccountKVSetOperation(JSONObject jsonObject) { - // 写入集合处理 - JSONArray writeSetObj = jsonObject.getJSONArray("writeSet"); - JSONObject accountAddrObj = jsonObject.getJSONObject("accountAddress"); - String addressBase58 = accountAddrObj.getString("value"); - Bytes address = Bytes.fromBase58(addressBase58); - - DataAccountKVSetOpTemplate kvOperation = new DataAccountKVSetOpTemplate(address); - for (int i = 0; i < writeSetObj.size(); i++) { - JSONObject currWriteSetObj = writeSetObj.getJSONObject(i); - long expectedVersion = currWriteSetObj.getLong("expectedVersion"); - JSONObject valueObj = currWriteSetObj.getJSONObject("value"); - String typeStr = valueObj.getString("type"); - String realValBase58 = valueObj.getString("value"); - String key = currWriteSetObj.getString("key"); - DataType dataType = DataType.valueOf(typeStr); - BytesValue bytesValue = BytesData.fromType(dataType, Base58Utils.decode(realValBase58)); - KVData kvData = new KVData(key, bytesValue, expectedVersion); - kvOperation.set(kvData); - } - - return kvOperation; - } - - public static LedgerInitOperation convertLedgerInitOperation(JSONObject jsonObject) { - JSONObject legerInitObj = jsonObject.getJSONObject("initSetting"); - LedgerInitSettingData ledgerInitSettingData = new LedgerInitSettingData(); - String ledgerSeedStr = legerInitObj.getString("ledgerSeed"); - - // 种子需要做Base64转换 - ledgerInitSettingData.setLedgerSeed(Base64.decodeBase64(BytesUtils.toBytes(ledgerSeedStr))); - - String consensusProvider = legerInitObj.getString("consensusProvider"); - - ledgerInitSettingData.setConsensusProvider(consensusProvider); - - JSONObject cryptoSettingObj = legerInitObj.getJSONObject("cryptoSetting"); - boolean autoVerifyHash = cryptoSettingObj.getBoolean("autoVerifyHash"); - short hashAlgorithm = cryptoSettingObj.getShort("hashAlgorithm"); - - CryptoConfig cryptoConfig = new CryptoConfig(); - - cryptoConfig.setAutoVerifyHash(autoVerifyHash); - - cryptoConfig.setHashAlgorithm(hashAlgorithm); - - ledgerInitSettingData.setCryptoSetting(cryptoConfig); - - JSONObject consensusSettingsObj = legerInitObj.getJSONObject("consensusSettings"); - Bytes consensusSettings = Bytes.fromBase58(consensusSettingsObj.getString("value")); - - ledgerInitSettingData.setConsensusSettings(consensusSettings); - - JSONArray consensusParticipantsArray = legerInitObj.getJSONArray("consensusParticipants"); - - if (!consensusParticipantsArray.isEmpty()) { - ParticipantNode[] participantNodes = new ParticipantNode[consensusParticipantsArray.size()]; - for (int i = 0; i < consensusParticipantsArray.size(); i++) { - JSONObject currConsensusParticipant = consensusParticipantsArray.getJSONObject(i); - String addressBase58 = currConsensusParticipant.getString("address"); - String name = currConsensusParticipant.getString("name"); - int id = currConsensusParticipant.getInteger("id"); - JSONObject pubKeyObj = currConsensusParticipant.getJSONObject("pubKey"); - String pubKeyBase58 = pubKeyObj.getString("value"); - // 生成ParticipantNode对象 - ParticipantCertData participantCertData = new ParticipantCertData(id, addressBase58, name, - new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes())); - participantNodes[i] = participantCertData; - } - ledgerInitSettingData.setConsensusParticipants(participantNodes); - } - - return new LedgerInitOpTemplate(ledgerInitSettingData); - } - - public static UserRegisterOperation convertUserRegisterOperation(JSONObject jsonObject) { - JSONObject user = jsonObject.getJSONObject("userID"); - return new UserRegisterOpTemplate(blockchainIdentity(user)); - } - - public static ContractCodeDeployOperation convertContractCodeDeployOperation(JSONObject jsonObject) { - JSONObject contract = jsonObject.getJSONObject("contractID"); - BlockchainIdentityData blockchainIdentity = blockchainIdentity(contract); - - String chainCodeStr = jsonObject.getString("chainCode"); - ContractCodeDeployOpTemplate contractCodeDeployOpTemplate = new ContractCodeDeployOpTemplate(blockchainIdentity, - BytesUtils.toBytes(chainCodeStr)); - return contractCodeDeployOpTemplate; - } - - public static ContractEventSendOperation convertContractEventSendOperation(JSONObject jsonObject) { - JSONObject contractAddressObj = jsonObject.getJSONObject("contractAddress"); - String contractAddress = contractAddressObj.getString("value"); - String argsStr = jsonObject.getString("args"); - String event = jsonObject.getString("event"); - return new ContractEventSendOpTemplate(Bytes.fromBase58(contractAddress), event, - BytesDataList.singleText(argsStr)); - } - - private static BlockchainIdentityData blockchainIdentity(JSONObject jsonObject) { - JSONObject addressObj = jsonObject.getJSONObject("address"); - // base58值 - String addressBase58 = addressObj.getString("value"); - Bytes address = Bytes.fromBase58(addressBase58); - - JSONObject pubKeyObj = jsonObject.getJSONObject("pubKey"); - // base58值 - String pubKeyBase58 = pubKeyObj.getString("value"); - PubKey pubKey = new PubKey(Bytes.fromBase58(pubKeyBase58).toBytes()); - - // 生成对应的对象 - return new BlockchainIdentityData(address, pubKey); - } - - public static class CryptoConfig implements CryptoSetting { - - private short hashAlgorithm; - - private boolean autoVerifyHash; - - @Override - public CryptoProvider[] getSupportedProviders() { - return new CryptoProvider[0]; - } - - @Override - public short getHashAlgorithm() { - return hashAlgorithm; - } - - @Override - public boolean getAutoVerifyHash() { - return autoVerifyHash; - } - - public void setHashAlgorithm(short hashAlgorithm) { - this.hashAlgorithm = hashAlgorithm; - } - - public void setAutoVerifyHash(boolean autoVerifyHash) { - this.autoVerifyHash = autoVerifyHash; - } - } - - public static class ParticipantCertData implements ParticipantNode { - private int id; - private String address; - private String name; - private PubKey pubKey; - - public ParticipantCertData() { - } - - public ParticipantCertData(ParticipantNode participantNode) { - this.address = participantNode.getAddress(); - this.name = participantNode.getName(); - this.pubKey = participantNode.getPubKey(); - } - - public ParticipantCertData(int id, String address, String name, PubKey pubKey) { - this.id = id; - this.address = address; - this.name = name; - this.pubKey = pubKey; - } - - @Override - public String getAddress() { - return address; - } - - @Override - public String getName() { - return name; - } - - @Override - public PubKey getPubKey() { - return pubKey; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - } - - public static class KvData implements KVDataEntry { - - private String key; - - private long version; - - private DataType dataType; - - private Object value; - - public KvData() { - } - - public KvData(String key, long version, DataType dataType) { - this(key, version, dataType, null); - } - - public KvData(String key, long version, DataType dataType, Object value) { - this.key = key; - this.version = version; - this.dataType = dataType; - this.value = value; - } - - public void setKey(String key) { - this.key = key; - } - - public void setVersion(long version) { - this.version = version; - } - - public void setDataType(DataType dataType) { - this.dataType = dataType; - } - - public void setValue(Object value) { - this.value = value; - } - - @Override - public String getKey() { - return key; - } - - @Override - public long getVersion() { - return version; - } - - @Override - public DataType getType() { - return dataType; - } - - @Override - public Object getValue() { - return value; - } - } + public static KVDataEntry[] read(KVDataEntry[] kvDataEntries) { + if (kvDataEntries == null || kvDataEntries.length == 0) { + return kvDataEntries; + } + KVDataEntry[] resolveKvDataEntries = new KVDataEntry[kvDataEntries.length]; + // kvDataEntries是代理对象,需要处理 + for (int i = 0; i < kvDataEntries.length; i++) { + KVDataEntry kvDataEntry = kvDataEntries[i]; + String key = kvDataEntry.getKey(); + long version = kvDataEntry.getVersion(); + DataType dataType = kvDataEntry.getType(); + KvData innerKvData = new KvData(key, version, dataType); + Object valueObj = kvDataEntry.getValue(); + switch (dataType) { + case NIL: + break; + case BYTES: + case TEXT: + case JSON: + innerKvData.setValue(valueObj.toString()); + break; + case INT32: + innerKvData.setValue(Integer.parseInt(valueObj.toString())); + break; + case INT64: + innerKvData.setValue(Long.parseLong(valueObj.toString())); + break; + default: + throw new IllegalStateException("Unsupported value type[" + dataType + "] to resolve!"); + } + resolveKvDataEntries[i] = innerKvData; + } + return resolveKvDataEntries; + } + + public static Operation read(Operation operation) { + + try { + // Class + Class clazz = operation.getClass(); + Field field = clazz.getSuperclass().getDeclaredField("h"); + field.setAccessible(true); + Object object = field.get(operation); + if (object instanceof JSONObject) { + JSONObject jsonObject = (JSONObject) object; + if (jsonObject.containsKey("accountID")) { + return convertDataAccountRegisterOperation(jsonObject); + } else if (jsonObject.containsKey("userID")) { + return convertUserRegisterOperation(jsonObject); + } else if (jsonObject.containsKey("contractID")) { + return convertContractCodeDeployOperation(jsonObject); + } else if (jsonObject.containsKey("writeSet")) { + return convertDataAccountKVSetOperation(jsonObject); + } else if (jsonObject.containsKey("initSetting")) { + return convertLedgerInitOperation(jsonObject); + } else if (jsonObject.containsKey("contractAddress")) { + return convertContractEventSendOperation(jsonObject); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + return null; + } + + public static Object readValueByBytesValue(BytesValue bytesValue) { + DataType dataType = bytesValue.getType(); + Bytes saveVal = bytesValue.getValue(); + Object showVal; + switch (dataType) { + case BYTES: + // return hex + showVal = HexUtils.encode(saveVal.toBytes()); + break; + case TEXT: + case JSON: + showVal = saveVal.toUTF8String(); + break; + case INT64: + showVal = BytesUtils.toLong(saveVal.toBytes()); + break; + default: + showVal = HexUtils.encode(saveVal.toBytes()); + break; + } + return showVal; + } + + public static DataAccountRegisterOperation convertDataAccountRegisterOperation(JSONObject jsonObject) { + JSONObject account = jsonObject.getJSONObject("accountID"); + return new DataAccountRegisterOpTemplate(blockchainIdentity(account)); + } + + public static DataAccountKVSetOperation convertDataAccountKVSetOperation(JSONObject jsonObject) { + // 写入集合处理 + JSONArray writeSetObj = jsonObject.getJSONArray("writeSet"); + JSONObject accountAddrObj = jsonObject.getJSONObject("accountAddress"); + String addressBase58 = accountAddrObj.getString("value"); + Bytes address = Bytes.fromBase58(addressBase58); + + DataAccountKVSetOpTemplate kvOperation = new DataAccountKVSetOpTemplate(address); + for (int i = 0; i implements InvocationHandler { OperationResult opResult = operationResults[0]; // 处理返回值 - return BytesValueEncoding.encode(opResult.getResult(), method.getReturnType()); + return BytesValueEncoding.encodeSingle(opResult.getResult(), method.getReturnType()); } private boolean isExecuteContractMethod(Method method) { diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesUtils.java index 255ebd2a..93520e0e 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesUtils.java @@ -6,6 +6,7 @@ import java.io.InputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; +import java.math.BigInteger; import com.jd.blockchain.utils.IllegalDataException; @@ -370,6 +371,10 @@ public class BytesUtils { return value; } + public static short toShort(byte[] bytes) { + return toShort(bytes, 0); + } + public static char toChar(byte[] bytes, int offset) { char value = 0; value = (char) ((value | (bytes[offset] & 0xFF)) << 8);