| @@ -42,7 +42,6 @@ public class ContractSerializeUtils { | |||
| } | |||
| Class<?>[] classTypes = method.getParameterTypes(); | |||
| Annotation [][] annotations = method.getParameterAnnotations(); | |||
| byte[][] result = new byte[classTypes.length][]; | |||
| //将method中形参转换为实体对象,每个形参都必须为@DataContract类型;每个形参使用系统的BinaryProtocol来进行序列化,如果有5个参数,则使用5次序列化; | |||
| int sum = 0; | |||
| @@ -2,6 +2,8 @@ package com.jd.blockchain.transaction; | |||
| import com.jd.blockchain.contract.ContractSerializeUtils; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.IllegalDataException; | |||
| import java.lang.reflect.InvocationHandler; | |||
| import java.lang.reflect.Method; | |||
| @@ -18,17 +20,15 @@ public class ContractInvocationProxy implements InvocationHandler { | |||
| public ContractInvocationProxy(Bytes contractAddress, ContractType contractType, | |||
| ContractEventSendOperationBuilder sendOpBuilder) { | |||
| this.contractAddress = contractAddress; | |||
| if(contractType == null){ | |||
| throw new IllegalDataException("contractType == null, no invoke really."); | |||
| } | |||
| this.contractType = contractType; | |||
| this.sendOpBuilder = sendOpBuilder; | |||
| } | |||
| @Override | |||
| public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { | |||
| if(contractType == null){ | |||
| return "contractType == null, no invoke really."; | |||
| } | |||
| String event = contractType.getEvent(method); | |||
| if (event == null) { | |||
| // 适配 Object 对象的方法; | |||
| @@ -4,16 +4,18 @@ import com.jd.blockchain.contract.Contract; | |||
| import com.jd.blockchain.contract.ContractEvent; | |||
| import com.jd.blockchain.utils.BaseConstant; | |||
| import com.jd.blockchain.utils.Bytes; | |||
| import com.jd.blockchain.utils.IllegalDataException; | |||
| import java.lang.annotation.Annotation; | |||
| import java.lang.reflect.Method; | |||
| import java.lang.reflect.Proxy; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| import java.util.concurrent.ConcurrentHashMap; | |||
| public class ContractInvocationProxyBuilder { | |||
| private Map<Class<?>, ContractType> contractTypes = new HashMap<Class<?>, ContractType>(); | |||
| private Map<Class<?>, ContractType> contractTypes = new ConcurrentHashMap<>(); | |||
| public <T> T create(String address, Class<T> contractIntf, ContractEventSendOperationBuilder contractEventBuilder) { | |||
| return create(Bytes.fromBase58(address), contractIntf, contractEventBuilder); | |||
| @@ -39,12 +41,12 @@ public class ContractInvocationProxyBuilder { | |||
| // 判断是否是标注了合约的接口类型; | |||
| if (!isContractType(contractIntf)){ | |||
| return null; | |||
| throw new IllegalDataException("is not Contract Type, becaust there is not @Contract."); | |||
| } | |||
| // 解析合约事件处理方法,检查是否有重名; | |||
| if(!isUniqueEvent(contractIntf)){ | |||
| return null; | |||
| throw new IllegalDataException("there is repeat definition of contractEvent to @ContractEvent."); | |||
| } | |||
| // TODO 检查是否不支持的参数类型; | |||
| @@ -63,22 +65,21 @@ public class ContractInvocationProxyBuilder { | |||
| Map<Method, Annotation[]> methodAnnoMap = new HashMap<Method, Annotation[]>(); | |||
| Map<String, Method> annoMethodMap = new HashMap<String, Method>(); | |||
| for (int i = 0; i < classMethods.length; i++) { | |||
| Annotation[] a = classMethods[i].getDeclaredAnnotations(); | |||
| methodAnnoMap.put(classMethods[i], a); | |||
| Annotation[] annotations = classMethods[i].getDeclaredAnnotations(); | |||
| methodAnnoMap.put(classMethods[i], annotations); | |||
| // if current method contains @ContractEvent,then put it in this map; | |||
| for (Annotation annotation_ : a) { | |||
| if (classMethods[i].isAnnotationPresent(ContractEvent.class)) { | |||
| Object obj = classMethods[i].getAnnotation(ContractEvent.class); | |||
| String annoAllName = obj.toString(); | |||
| // format:@com.jd.blockchain.contract.model.ContractEvent(name=transfer-asset) | |||
| String eventName_ = obj.toString().substring(BaseConstant.CONTRACT_EVENT_PREFIX.length(), | |||
| annoAllName.length() - 1); | |||
| //if annoMethodMap has contained the eventName, too many same eventNames exists probably, say NO! | |||
| if(annoMethodMap.containsKey(eventName_)){ | |||
| isUnique = false; | |||
| } | |||
| annoMethodMap.put(eventName_, classMethods[i]); | |||
| Method curMethod = classMethods[i]; | |||
| ContractEvent contractEvent = curMethod.getAnnotation(ContractEvent.class); | |||
| if (contractEvent != null) { | |||
| Object obj = classMethods[i].getAnnotation(ContractEvent.class); | |||
| String annoAllName = obj.toString(); | |||
| // format:@com.jd.blockchain.contract.model.ContractEvent(name=transfer-asset) | |||
| String eventName_ = contractEvent.name(); | |||
| //if annoMethodMap has contained the eventName, too many same eventNames exists probably, say NO! | |||
| if(annoMethodMap.containsKey(eventName_)){ | |||
| isUnique = false; | |||
| } | |||
| annoMethodMap.put(eventName_, classMethods[i]); | |||
| } | |||
| } | |||
| @@ -2,16 +2,17 @@ package com.jd.blockchain.transaction; | |||
| import com.jd.blockchain.contract.ContractEvent; | |||
| import com.jd.blockchain.contract.ContractException; | |||
| import com.jd.blockchain.utils.BaseConstant; | |||
| import java.lang.reflect.Method; | |||
| import java.util.*; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| import java.util.Set; | |||
| public class ContractType { | |||
| private String name; | |||
| private SortedMap<String, Method> events = Collections.synchronizedSortedMap(new TreeMap<>()); | |||
| private Map<String, Method> events = new HashMap<>(); | |||
| private Map<Method, String> handleMethods = new HashMap<>();; | |||
| @@ -57,12 +58,9 @@ public class ContractType { | |||
| Method[] classMethods = contractIntf.getDeclaredMethods(); | |||
| for (Method method : classMethods) { | |||
| // if current method contains @ContractEvent,then put it in this map; | |||
| if (method.isAnnotationPresent(ContractEvent.class)) { | |||
| Object obj = method.getAnnotation(ContractEvent.class); | |||
| String annoAllName = obj.toString(); | |||
| // format:@com.jd.blockchain.contract.model.ContractEvent(name=transfer-asset) | |||
| String eventName_ = obj.toString().substring(BaseConstant.CONTRACT_EVENT_PREFIX.length(), | |||
| annoAllName.length() - 1); | |||
| ContractEvent contractEvent = method.getAnnotation(ContractEvent.class); | |||
| if (contractEvent != null) { | |||
| String eventName_ = contractEvent.name(); | |||
| //if annoMethodMap has contained the eventName, too many same eventNames exists probably, say NO! | |||
| if(contractType.events.containsKey(eventName_)){ | |||
| throw new ContractException("too many same eventNames exists in the contract, check it."); | |||
| @@ -68,7 +68,7 @@ public class SDK_Contract_Test { | |||
| public void demoContract1() { | |||
| // 发起交易; | |||
| TransactionTemplate txTemp = bcsrv.newTransaction(ledgerHash); | |||
| String contractAddress = "LdeNmSdtUqVfURfcVxmJda252HC4FYHYfGTQv"; | |||
| String contractAddress = "LdeNw7PsVrXTrffQMfYLTvqscDyQ8QCUPruTS"; | |||
| AssetContract2 assetContract = txTemp.contract(contractAddress, AssetContract2.class); | |||
| TransactionContentBody transactionContentBody = new TransactionContentBody() { | |||
| @Override | |||
| @@ -22,7 +22,7 @@ public class BaseConstant { | |||
| public static final String SYS_CONTRACT_PROPS_NAME = "sys-contract.properties"; | |||
| public static final String CONTRACT_MAIN_CLASS_KEY = "contract"; | |||
| public static final String CONTRACT_EVENT_PREFIX="@com.jd.blockchain.contract.ContractEvent(name="; | |||
| // public static final String CONTRACT_EVENT_PREFIX="@com.jd.blockchain.contract.ContractEvent(name="; | |||
| // 编译时引用包黑名单 | |||
| public static final String PACKAGE_BLACKLIST = "BLACKLIST"; | |||