From 58a19e473b82cc33301f4490b6dc3b9ef861f5de Mon Sep 17 00:00:00 2001 From: zhaoguangwei Date: Mon, 2 Mar 2020 15:05:10 +0800 Subject: [PATCH] all: LF; --- .../blockchain/binaryproto/PrimitiveType.java | 132 +- .../blockchain/consensus/ActionMessage.java | 50 +- .../consensus/ConsensusSecurityException.java | 36 +- .../consensus/ConsensusService.java | 24 +- .../blockchain/consensus/OrderedAction.java | 70 +- .../blockchain/consensus/UnorderedAction.java | 44 +- .../consensus/action/ActionResponseData.java | 98 +- source/contract/pom.xml | 36 +- .../jd/blockchain/crypto/AddressEncoding.java | 130 +- .../jd/blockchain/crypto/AddressVersion.java | 48 +- .../com/jd/blockchain/crypto/CryptoKey.java | 48 +- .../com/jd/blockchain/crypto/PrivKey.java | 56 +- .../gateway/GatewayConfiguration.java | 28 +- .../gateway/GatewayServerBooter.java | 354 +-- .../web/GatewayWebSecurityConfigurer.java | 34 +- .../gateway/src/main/resources/gateway.conf | 60 +- .../gateway/data/HashDigestDeserializer.java | 62 +- .../gateway/data/HashDigestSerializer.java | 54 +- .../ledger/core/ContractAccount.java | 144 +- .../ledger/core/ContractAccountSet.java | 260 +- .../blockchain/ledger/core/DataAccount.java | 466 ++-- .../ledger/core/DataAccountSet.java | 224 +- .../ledger/core/LedgerAdminDataset.java | 960 ++++---- .../ledger/core/MerkleAccountSet.java | 820 +++---- .../blockchain/ledger/core/MerkleDataSet.java | 1478 ++++++------ .../com/jd/blockchain/ledger/core/Node.java | 20 +- .../ledger/core/ParticipantCertData.java | 144 +- .../com/jd/blockchain/ledger/core/Peer.java | 42 +- .../blockchain/ledger/core/UserAccount.java | 168 +- .../ledger/core/UserAccountSet.java | 240 +- source/ledger/ledger-model/pom.xml | 84 +- .../com/jd/blockchain/contract/Contract.java | 28 +- .../jd/blockchain/contract/ContractEvent.java | 28 +- .../jd/blockchain/contract/EventHandle.java | 30 +- .../ledger/BlockRollbackException.java | 66 +- .../ledger/BlockchainEventType.java | 166 +- .../ledger/BlockchainIdentityData.java | 432 ++-- .../ledger/BlockchainKeyGenerator.java | 80 +- .../blockchain/ledger/BlockchainKeypair.java | 92 +- .../ledger/CodeDeployOperation.java | 46 +- .../ledger/ContractCodeDeployOperation.java | 62 +- .../ledger/DataAccountKVSetOperation.java | 64 +- .../ledger/DataAccountRegisterOperation.java | 52 +- .../com/jd/blockchain/ledger/DataType.java | 370 +-- .../ledger/DataVersionConflictException.java | 54 +- .../blockchain/ledger/DigitalSignature.java | 30 +- .../jd/blockchain/ledger/EndpointRequest.java | 60 +- .../jd/blockchain/ledger/HashAlgorithm.java | 92 +- .../com/jd/blockchain/ledger/HashObject.java | 74 +- .../java/com/jd/blockchain/ledger/Ledger.java | 118 +- .../com/jd/blockchain/ledger/LedgerImpl.java | 646 ++--- .../ledger/LedgerInitOperation.java | 26 +- .../com/jd/blockchain/ledger/MagicNumber.java | 134 +- .../com/jd/blockchain/ledger/NodeRequest.java | 44 +- .../blockchain/ledger/OperationArgument.java | 54 +- .../jd/blockchain/ledger/PermissionType.java | 136 +- .../ledger/RolesConfigureOperation.java | 78 +- .../jd/blockchain/ledger/SignatureInfo.java | 42 +- .../com/jd/blockchain/ledger/StateOpType.java | 74 +- .../com/jd/blockchain/ledger/Transaction.java | 108 +- .../blockchain/ledger/TransactionBuilder.java | 102 +- .../ledger/TransactionRequestBuilder.java | 162 +- .../ledger/TransactionResponse.java | 134 +- .../ledger/TransactionRollbackException.java | 32 +- .../ledger/TransactionTemplate.java | 54 +- .../ledger/UserAuthorizeOperation.java | 114 +- .../ledger/UserInfoSetOperation.java | 58 +- .../ledger/UserRegisterOperation.java | 26 +- .../setting/GatewayIncomingSetting.java | 52 +- .../BlockchainOperationFactory.java | 716 +++--- .../transaction/BlockchainQueryService.java | 660 +++--- .../ContractCodeDeployOpTemplate.java | 82 +- .../ContractCodeDeployOperationBuilder.java | 38 +- ...ontractCodeDeployOperationBuilderImpl.java | 28 +- .../ContractEventSendOperationBuilder.java | 48 +- ...ContractEventSendOperationBuilderImpl.java | 42 +- .../ContractInvocationProxyBuilder.java | 88 +- .../DataAccountKVSetOpTemplate.java | 130 +- .../DataAccountKVSetOperationBuilder.java | 302 +-- .../DataAccountKVSetOperationBuilderImpl.java | 176 +- .../DataAccountRegisterOpTemplate.java | 68 +- .../DataAccountRegisterOperationBuilder.java | 28 +- ...taAccountRegisterOperationBuilderImpl.java | 30 +- .../transaction/DigitalSignatureBlob.java | 232 +- .../transaction/LedgerInitOpTemplate.java | 52 +- .../LedgerInitOperationBuilder.java | 34 +- .../LedgerInitOperationBuilderImpl.java | 26 +- .../transaction/NewLedgerOpBlob.java | 76 +- .../PrivilegeSettingOperationBuilder.java | 50 +- .../jd/blockchain/transaction/PubKeyData.java | 60 +- .../transaction/RolesConfigureOpTemplate.java | 278 +-- .../transaction/SecurityOperationBuilder.java | 38 +- .../transaction/SignatureEncoding.java | 54 +- .../transaction/TransactionService.java | 20 +- .../transaction/TxRequestBuilder.java | 212 +- .../transaction/TxRequestMessage.java | 770 +++--- .../transaction/TxResponseMessage.java | 172 +- .../jd/blockchain/transaction/TxTemplate.java | 222 +- .../transaction/UserAuthorizeOpTemplate.java | 260 +- .../transaction/UserRegisterOpTemplate.java | 54 +- .../UserRegisterOperationBuilder.java | 38 +- .../UserRegisterOperationBuilderImpl.java | 30 +- .../blockchain/ledger/BytesEncodingTest.java | 168 +- .../com/jd/blockchain/ledger/OpBlobTest.java | 166 +- .../blockchain/ledger/SizeHeaderMaskTest.java | 80 +- .../blockchain/ledger/TxContentBlobTest.java | 232 +- source/peer/config/hosts.config | 72 +- source/peer/config/system.config | 242 +- source/peer/pom.xml | 194 +- .../jd/blockchain/peer/PeerConfiguration.java | 30 +- .../BlockchainConsensusServiceImpl.java | 426 ++-- .../consensus/ConsensusViewDefinition.java | 186 +- .../web/PeerWebSecurityConfiguration.java | 40 +- .../peer/web/PeerWebServerConfigurer.java | 102 +- .../service/ConsensusViewDefinitionTest.java | 94 +- .../service/LedgerInitCordinatorTest.java | 300 +-- .../peer/web/ControllerTestConfiguration.java | 74 +- .../web/LedgerInitializingControllerTest.java | 490 ++-- .../peer/web/LedgerInitializingTest.java | 504 ++-- .../peer/web/PeerKeyStorageServiceImpl.java | 280 +-- source/sdk/pom.xml | 38 +- .../sdk/AbstractBlockchainServiceFactory.java | 102 +- .../blockchain/sdk/BlockchainEventHandle.java | 90 +- .../sdk/BlockchainEventListener.java | 14 +- .../sdk/BlockchainEventMessage.java | 90 +- .../sdk/BlockchainEventService.java | 38 +- .../jd/blockchain/sdk/BlockchainService.java | 32 +- .../sdk/BlockchainTransactionService.java | 50 +- .../blockchain/sdk/ManagementHttpService.java | 40 +- .../jd/blockchain/sdk/PrivilegeSetting.java | 42 +- .../com/jd/blockchain/sdk/TxCommiter.java | 22 +- .../sdk/proxy/CodeDeployOperationBuilder.java | 148 +- .../sdk/proxy/CodeInvokeOperationBuilder.java | 146 +- .../sdk/proxy/HttpQueryServiceAdapter.java | 272 +-- .../blockchain/sdk/proxy/TxMessageTest.java | 128 +- source/sdk/sdk-client/pom.xml | 46 +- .../sdk/client/GatewayIncomingInfo.java | 74 +- .../sdk/client/GatewayServiceFactory.java | 450 ++-- .../sdk/client/HttpConsensusService.java | 38 +- source/sdk/sdk-samples/pom.xml | 104 +- .../sdk/samples/SDKDemo_EventListener.java | 148 +- .../sdk/samples/SDKDemo_PrivilegeSetting.java | 150 +- .../blockchain/sdk/samples/SDKDemo_Query.java | 172 +- .../sdk/samples/SDKDemo_RegisterAccount.java | 114 +- .../service/impl/redis/JedisProperties.java | 70 +- .../impl/redis/RedisStorageService.java | 78 +- .../main/resources/META-INF/spring.factories | 2 +- .../impl/rocksdb/RocksDBStorageService.java | 60 +- .../storage/service/VersioningKVStorage.java | 160 +- source/test/pom.xml | 62 +- .../blockchain/consensus/client/Settings.java | 284 +-- .../consensus/client/WebConfiguration.java | 22 +- .../src/main/resources/application.properties | 56 +- .../config/bft-system.config | 242 +- .../blockchain/consensus/node/Settings.java | 114 +- .../consensus/node/WebConfiguration.java | 22 +- .../src/main/resources/application.properties | 36 +- .../web/DecisionRequestBodyConverter.java | 38 +- .../web/DecisionResponseConverter.java | 46 +- .../web/InitServiceExceptionHandler.java | 50 +- .../web/InitWebSecurityConfiguration.java | 38 +- .../web/InitWebServerConfiguration.java | 76 +- .../web/LedgerInitMessageConverter.java | 226 +- .../web/PermissionResponseConverter.java | 48 +- .../SignatureDigestRequestBodyConverter.java | 36 +- .../main/resources/META-INF/spring.factories | 2 +- .../src/main/resources/application.properties | 24 +- source/utils/.gitignore | 46 +- source/utils/pom.xml | 116 +- source/utils/utils-common/.gitignore | 2 +- source/utils/utils-common/pom.xml | 204 +- .../com/jd/blockchain/utils/ArrayUtils.java | 244 +- .../com/jd/blockchain/utils/AttributeMap.java | 70 +- .../com/jd/blockchain/utils/Attributes.java | 50 +- .../com/jd/blockchain/utils/BaseConstant.java | 66 +- .../blockchain/utils/BusinessException.java | 94 +- .../com/jd/blockchain/utils/DataEntry.java | 32 +- .../com/jd/blockchain/utils/Disposable.java | 14 +- .../jd/blockchain/utils/EmptyProperties.java | 222 +- .../utils/IllegalDataException.java | 46 +- .../jd/blockchain/utils/IteratorWrapper.java | 66 +- .../com/jd/blockchain/utils/PathUtils.java | 234 +- .../jd/blockchain/utils/PrimitiveUtils.java | 836 +++---- .../jd/blockchain/utils/PropertiesUtils.java | 674 +++--- .../utils/ReadonlyArrayListWrapper.java | 110 +- .../jd/blockchain/utils/ServiceFactory.java | 16 +- .../blockchain/utils/codec/Base58Utils.java | 338 +-- .../utils/codec/DataDecodeException.java | 46 +- .../jd/blockchain/utils/codec/HexUtils.java | 98 +- .../utils/concurrent/AsyncFuture.java | 116 +- .../utils/concurrent/AsyncFutureListener.java | 14 +- .../concurrent/CompletableAsyncFuture.java | 378 +-- .../utils/concurrent/NamedThreadFactory.java | 150 +- .../concurrent/RuntimeExecutionException.java | 48 +- .../RuntimeInterruptedException.java | 48 +- .../concurrent/RuntimeTimeoutException.java | 48 +- .../utils/concurrent/SyncFutureAdaptor.java | 270 +-- .../utils/concurrent/ThreadUtils.java | 46 +- .../utils/console/CommandConsole.java | 282 +-- .../utils/console/CommondProcessor.java | 30 +- .../utils/event/DefaultExceptionHandle.java | 54 +- .../utils/event/EventMulticaster.java | 262 +- .../utils/event/ExceptionHandle.java | 54 +- .../utils/event/ExceptionLoggingHandle.java | 64 +- .../utils/event/RethrowExceptionHandler.java | 46 +- .../com/jd/blockchain/utils/hash/Hashing.java | 34 +- .../jd/blockchain/utils/hash/MurmurHash3.java | 640 ++--- .../jd/blockchain/utils/id/KeyGenerator.java | 14 +- .../utils/id/KeyGeneratorFactory.java | 184 +- .../com/jd/blockchain/utils/io/ByteArray.java | 634 ++--- .../com/jd/blockchain/utils/io/BytesBlob.java | 10 +- .../blockchain/utils/io/BytesChunkReader.java | 324 +-- .../blockchain/utils/io/BytesChunkWriter.java | 314 +-- .../jd/blockchain/utils/io/BytesEncoding.java | 342 +-- .../jd/blockchain/utils/io/BytesReader.java | 20 +- .../jd/blockchain/utils/io/BytesUtils.java | 1378 +++++------ .../jd/blockchain/utils/io/BytesWriter.java | 16 +- .../blockchain/utils/io/EmptyInputStream.java | 36 +- .../utils/io/ForwardReadonlyInputStream.java | 80 +- .../jd/blockchain/utils/io/NumberMask.java | 740 +++--- .../utils/io/RuntimeIOException.java | 30 +- .../utils/io/UnclosableOutputStream.java | 46 +- .../blockchain/utils/net/NetworkAddress.java | 220 +- .../utils/net/NetworkException.java | 34 +- .../blockchain/utils/security/AESUtils.java | 336 +-- .../security/AuthenticationException.java | 42 +- .../blockchain/utils/security/DESUtils.java | 124 +- .../utils/security/DecryptionException.java | 42 +- .../utils/security/Ed25519Utils.java | 170 +- .../utils/security/EncryptionException.java | 42 +- .../security/KeyGenerationException.java | 36 +- .../utils/security/KeyStoreException.java | 36 +- .../utils/security/KeyStoreUtils.java | 60 +- .../blockchain/utils/security/RSAKeyPair.java | 82 +- .../blockchain/utils/security/RSAUtils.java | 262 +- .../utils/security/RandomUtils.java | 84 +- .../utils/security/RipeMD160Utils.java | 50 +- .../blockchain/utils/security/ShaUtils.java | 300 +-- .../utils/transfer/AsyncSendable.java | 44 +- .../blockchain/utils/transfer/Sendable.java | 36 +- .../test/my/utils/io/BytesEncodingTest.java | 172 +- .../java/test/my/utils/io/BytesUtilsTest.java | 514 ++-- .../test/my/utils/security/AESUtilsTest.java | 306 +-- .../test/my/utils/security/RSAUtilsTest.java | 176 +- .../my/utils/security/RandomUtilsTest.java | 102 +- .../test/my/utils/security/ShaUtilsTest.java | 204 +- source/utils/utils-http/.gitignore | 2 +- source/utils/utils-http/pom.xml | 152 +- .../jd/blockchain/utils/http/HttpAction.java | 132 +- .../jd/blockchain/utils/http/HttpMethod.java | 38 +- .../jd/blockchain/utils/http/HttpService.java | 100 +- .../utils/http/HttpServiceConsts.java | 18 +- .../utils/http/HttpServiceContext.java | 46 +- .../utils/http/HttpServiceException.java | 54 +- .../utils/http/HttpStatusException.java | 78 +- .../jd/blockchain/utils/http/PathParam.java | 84 +- .../utils/http/PropertiesConverter.java | 14 +- .../jd/blockchain/utils/http/RequestBody.java | 74 +- .../utils/http/RequestBodyConverter.java | 50 +- .../blockchain/utils/http/RequestParam.java | 148 +- .../utils/http/RequestParamFilter.java | 26 +- .../utils/http/RequestParamMap.java | 116 +- .../http/ResponseBodyConverterFactory.java | 18 +- .../utils/http/ResponseConverter.java | 44 +- .../utils/http/StringConverter.java | 30 +- .../utils/http/agent/ArgDefEntry.java | 56 +- .../utils/http/agent/AuthorizationAlgs.java | 22 +- .../utils/http/agent/AuthorizationHeader.java | 118 +- .../agent/AuthorizationHeaderResovler.java | 26 +- .../utils/http/agent/CustomHeader.java | 48 +- .../DefaultResponseConverterFactory.java | 68 +- .../utils/http/agent/HttpServiceAgent.java | 2102 ++++++++--------- .../http/agent/HttpServiceConnection.java | 86 +- ...IllegalHttpServiceDefinitionException.java | 42 +- .../utils/http/agent/LocalHttpDelete.java | 66 +- .../http/agent/NullRequestParamFilter.java | 36 +- .../utils/http/agent/PathParamDefinition.java | 46 +- .../utils/http/agent/PathParamResolver.java | 42 +- .../utils/http/agent/PathParamResolvers.java | 112 +- .../http/agent/PojoPropertiesConverter.java | 144 +- .../agent/PropertiesConverterFactory.java | 48 +- .../http/agent/RequestBodyDefinition.java | 48 +- .../utils/http/agent/RequestBodyResolver.java | 18 +- .../agent/RequestBodyResolverComposite.java | 42 +- .../http/agent/RequestBodyResolvers.java | 126 +- .../utils/http/agent/RequestHeader.java | 18 +- .../http/agent/RequestParamDefinition.java | 148 +- .../http/agent/RequestParamMapDefinition.java | 114 +- .../http/agent/RequestParamResolver.java | 42 +- .../http/agent/RequestParamResolvers.java | 440 ++-- .../utils/http/agent/RequestPathTemplate.java | 174 +- .../utils/http/agent/RequestUtils.java | 54 +- .../http/agent/ServiceActionContext.java | 296 +-- .../utils/http/agent/ServiceConnection.java | 24 +- .../http/agent/ServiceConnectionManager.java | 274 +-- .../utils/http/agent/ServiceEndpoint.java | 100 +- .../utils/http/agent/ServiceRequest.java | 50 +- .../http/agent/StringConverterFactory.java | 56 +- .../TypeAutoAdaptingRequestBodyConverter.java | 124 +- .../utils/http/auth/Securities.java | 16 +- .../converters/ByteArrayBodyConverter.java | 30 +- .../ByteArrayResponseConverter.java | 62 +- .../http/converters/EmptyBodyConverter.java | 30 +- .../converters/InputStreamBodyConverter.java | 34 +- .../http/converters/JsonBodyConverter.java | 58 +- .../utils/http/converters/JsonConverter.java | 54 +- .../converters/JsonResponseConverter.java | 60 +- .../converters/NullResponseConverter.java | 42 +- .../ObjectToStringBodyConverter.java | 46 +- .../converters/ObjectToStringConverter.java | 24 +- .../converters/StringResponseConverter.java | 120 +- .../utils/http/agent/BaseRequestSetting.java | 62 +- .../http/agent/ContentRequestSetting.java | 96 +- .../http/agent/CustomBooleanConverter.java | 26 +- .../my/utils/http/agent/DataResponse.java | 88 +- .../utils/http/agent/GetContentException.java | 30 +- .../agent/GetContentResponseConverter.java | 40 +- ...ContentResponseConverterWithException.java | 46 +- .../http/agent/HttpRequestCollector.java | 298 +-- .../my/utils/http/agent/HttpRequestInfo.java | 56 +- .../http/agent/HttpServiceAgentTest.java | 1152 ++++----- .../my/utils/http/agent/HttpTestService.java | 262 +- ...BodiesWithDefaultConverterTestService.java | 36 +- .../java/test/my/utils/http/agent/OpType.java | 50 +- .../my/utils/http/agent/RequestContent.java | 74 +- .../test/my/utils/http/agent/TestData.java | 58 +- source/utils/utils-serialize/pom.xml | 42 +- .../binary/BinarySerializeUtils.java | 126 +- .../serialize/json/ArrayMergeStrategy.java | 52 +- .../utils/serialize/json/GenericType.java | 40 +- .../utils/serialize/json/JSONBean.java | 1104 ++++----- .../serialize/json/JSONBeanDeserializer.java | 76 +- .../serialize/json/JSONBeanSerializer.java | 48 +- .../serialize/json/JSONSerializeUtils.java | 718 +++--- .../utils/serialize/json/JSONString.java | 84 +- .../json/JSONStringDeserializer.java | 52 +- .../serialize/json/JSONStringSerializer.java | 48 +- .../serialize/json/RuntimeDeserializer.java | 72 +- .../serialize/json/ToStringSerializer.java | 48 +- .../serialize/BinarySerializeUtilsTest.java | 194 +- .../java/test/my/utils/serialize/Car.java | 90 +- .../java/test/my/utils/serialize/Entity.java | 128 +- .../test/my/utils/serialize/JSONBeanTest.java | 654 ++--- .../serialize/JSONSerializeUtilsTest.java | 524 ++-- .../java/test/my/utils/serialize/Level.java | 36 +- source/utils/utils-test/.gitignore | 2 +- source/utils/utils-test/pom.xml | 148 +- .../utils/test/JunitAssertMatcher.java | 68 +- .../utils/test/ServletRegister.java | 88 +- .../com/jd/blockchain/utils/test/WebBoot.java | 244 +- .../com/jd/blockchain/utils/test/WebTest.java | 114 +- source/utils/utils-web-server/.gitignore | 2 +- source/utils/utils-web-server/pom.xml | 66 +- .../utils/web/server/ServletSetting.java | 80 +- .../utils/web/server/WebServer.java | 508 ++-- .../utils/web/server/WebServerDemo.java | 122 +- .../utils/web/server/WebServerException.java | 36 +- source/utils/utils-web/.gitignore | 2 +- source/utils/utils-web/pom.xml | 48 +- .../web/client/WebResponseConverter.java | 146 +- .../client/WebResponseConverterFactory.java | 32 +- .../utils/web/client/WebServiceException.java | 66 +- .../web/model/BinaryMessageConverter.java | 122 +- .../blockchain/utils/web/model/ErrorCode.java | 90 +- .../JsonWebResponseMessageConverter.java | 144 +- .../utils/web/model/WebResponse.java | 206 +- 366 files changed, 26636 insertions(+), 26636 deletions(-) diff --git a/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/PrimitiveType.java b/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/PrimitiveType.java index b43f743e..fdfa77ae 100644 --- a/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/PrimitiveType.java +++ b/source/binary-proto/src/main/java/com/jd/blockchain/binaryproto/PrimitiveType.java @@ -1,66 +1,66 @@ -package com.jd.blockchain.binaryproto; - -/** - * 键值操作的数据类型; - * - * @author huanghaiquan - * - */ -public enum PrimitiveType { - - /** - * 空; - */ - NIL(BaseType.NIL), - - /** - * 布尔型; - */ - BOOLEAN(BaseType.BOOLEAN), - - /** - * 8位的整数: - */ - INT8(BaseType.INT8), - - /** - * 16位整数; - */ - INT16(BaseType.INT16), - - /** - * 32位整数; - */ - INT32(BaseType.INT32), - - /** - * 64位整数; - */ - INT64(BaseType.INT64), - - /** - * 文本; - */ - TEXT(BaseType.TEXT), - - /** - * 二进制数据; - */ - BYTES(BaseType.BYTES); - - public final byte CODE; - - private PrimitiveType(byte code) { - this.CODE = code; - } - - public static PrimitiveType valueOf(byte code) { - for (PrimitiveType dataType : PrimitiveType.values()) { - if (dataType.CODE == code) { - return dataType; - } - } - throw new IllegalArgumentException("Code[" + code + "] not suppported by PrimitiveType!"); - } - -} +package com.jd.blockchain.binaryproto; + +/** + * 键值操作的数据类型; + * + * @author huanghaiquan + * + */ +public enum PrimitiveType { + + /** + * 空; + */ + NIL(BaseType.NIL), + + /** + * 布尔型; + */ + BOOLEAN(BaseType.BOOLEAN), + + /** + * 8位的整数: + */ + INT8(BaseType.INT8), + + /** + * 16位整数; + */ + INT16(BaseType.INT16), + + /** + * 32位整数; + */ + INT32(BaseType.INT32), + + /** + * 64位整数; + */ + INT64(BaseType.INT64), + + /** + * 文本; + */ + TEXT(BaseType.TEXT), + + /** + * 二进制数据; + */ + BYTES(BaseType.BYTES); + + public final byte CODE; + + private PrimitiveType(byte code) { + this.CODE = code; + } + + public static PrimitiveType valueOf(byte code) { + for (PrimitiveType dataType : PrimitiveType.values()) { + if (dataType.CODE == code) { + return dataType; + } + } + throw new IllegalArgumentException("Code[" + code + "] not suppported by PrimitiveType!"); + } + +} diff --git a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ActionMessage.java b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ActionMessage.java index 6b99fe9e..32645701 100644 --- a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ActionMessage.java +++ b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ActionMessage.java @@ -1,25 +1,25 @@ -package com.jd.blockchain.consensus; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author huanghaiquan - * - */ -@Target({ ElementType.PARAMETER }) -@Retention(RetentionPolicy.RUNTIME) -public @interface ActionMessage { - - /** - * 请求参数转换器; - *

- * 指定一个 {@link BinaryMessageConverter} 接口的实现类; - * - * @return - */ - Class converter(); - -} +package com.jd.blockchain.consensus; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author huanghaiquan + * + */ +@Target({ ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ActionMessage { + + /** + * 请求参数转换器; + *

+ * 指定一个 {@link BinaryMessageConverter} 接口的实现类; + * + * @return + */ + Class converter(); + +} diff --git a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusSecurityException.java b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusSecurityException.java index 36968fd6..26850b29 100644 --- a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusSecurityException.java +++ b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusSecurityException.java @@ -1,18 +1,18 @@ -package com.jd.blockchain.consensus; - -public class ConsensusSecurityException extends Exception{ - - private static final long serialVersionUID = -164820276123627155L; - - public ConsensusSecurityException() { - } - - public ConsensusSecurityException(String message) { - super(message); - } - - public ConsensusSecurityException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.consensus; + +public class ConsensusSecurityException extends Exception{ + + private static final long serialVersionUID = -164820276123627155L; + + public ConsensusSecurityException() { + } + + public ConsensusSecurityException(String message) { + super(message); + } + + public ConsensusSecurityException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusService.java b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusService.java index f7cf1cf8..2326f5bb 100644 --- a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusService.java +++ b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/ConsensusService.java @@ -1,12 +1,12 @@ -package com.jd.blockchain.consensus; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -public @interface ConsensusService { - -} +package com.jd.blockchain.consensus; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ConsensusService { + +} diff --git a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/OrderedAction.java b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/OrderedAction.java index f9415d64..be7f6014 100644 --- a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/OrderedAction.java +++ b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/OrderedAction.java @@ -1,35 +1,35 @@ -package com.jd.blockchain.consensus; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 标识一个共识方法调用模式为“有序的消息调用”; - * - * @author huanghaiquan - * - */ -@Target({ ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -public @interface OrderedAction { - - /** - * 请求分组的索引器;
- * - * 指定一个 {@link GroupIndexer} 接口的实现类,用于根据请求消息列表来生成共识的分组ID; - * @return - */ - Class groupIndexer() ; - - /** - * 回复消息转换器; - *

- * 指定一个 {@link BinaryMessageConverter} 接口的实现类; - * - * @return - */ - Class responseConverter(); - -} +package com.jd.blockchain.consensus; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 标识一个共识方法调用模式为“有序的消息调用”; + * + * @author huanghaiquan + * + */ +@Target({ ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface OrderedAction { + + /** + * 请求分组的索引器;
+ * + * 指定一个 {@link GroupIndexer} 接口的实现类,用于根据请求消息列表来生成共识的分组ID; + * @return + */ + Class groupIndexer() ; + + /** + * 回复消息转换器; + *

+ * 指定一个 {@link BinaryMessageConverter} 接口的实现类; + * + * @return + */ + Class responseConverter(); + +} diff --git a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/UnorderedAction.java b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/UnorderedAction.java index aa62b9fe..3d7531ee 100644 --- a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/UnorderedAction.java +++ b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/UnorderedAction.java @@ -1,22 +1,22 @@ -package com.jd.blockchain.consensus; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @author huanghaiquan - * - */ -@Target({ ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -public @interface UnorderedAction { - /** - * 请求分组的索引器;
- * - * 指定一个 {@link GroupIndexer} 接口的实现类,用于根据请求消息列表来生成共识的分组ID; - * @return - */ - Class groupIndexer() ; -} +package com.jd.blockchain.consensus; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author huanghaiquan + * + */ +@Target({ ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface UnorderedAction { + /** + * 请求分组的索引器;
+ * + * 指定一个 {@link GroupIndexer} 接口的实现类,用于根据请求消息列表来生成共识的分组ID; + * @return + */ + Class groupIndexer() ; +} diff --git a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/action/ActionResponseData.java b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/action/ActionResponseData.java index 3a8e3ffb..948269d0 100644 --- a/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/action/ActionResponseData.java +++ b/source/consensus/consensus-framework/src/main/java/com/jd/blockchain/consensus/action/ActionResponseData.java @@ -1,49 +1,49 @@ -package com.jd.blockchain.consensus.action; - -public class ActionResponseData implements ActionResponse { - - private byte[] message; - - private boolean error = false; - - private String errorMessage; - - private String errorType; - - @Override - public byte[] getMessage() { - return message; - } - - public void setMessage(byte[] message) { - this.message = message; - } - - @Override - public boolean getError() { - return error; - } - - public void setError(boolean error) { - this.error = error; - } - - @Override - public String getErrorMessage() { - return errorMessage; - } - - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } - - @Override - public String getErrorType() { - return errorType; - } - - public void setErrorType(String errorType) { - this.errorType = errorType; - } - -} +package com.jd.blockchain.consensus.action; + +public class ActionResponseData implements ActionResponse { + + private byte[] message; + + private boolean error = false; + + private String errorMessage; + + private String errorType; + + @Override + public byte[] getMessage() { + return message; + } + + public void setMessage(byte[] message) { + this.message = message; + } + + @Override + public boolean getError() { + return error; + } + + public void setError(boolean error) { + this.error = error; + } + + @Override + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + @Override + public String getErrorType() { + return errorType; + } + + public void setErrorType(String errorType) { + this.errorType = errorType; + } + +} diff --git a/source/contract/pom.xml b/source/contract/pom.xml index d88eb189..daee178f 100644 --- a/source/contract/pom.xml +++ b/source/contract/pom.xml @@ -1,19 +1,19 @@ - - 4.0.0 - - com.jd.blockchain - jdchain-root - 1.1.2.RELEASE - - contract - pom - - - contract-framework - contract-jvm - contract-maven-plugin - contract-samples - - + + 4.0.0 + + com.jd.blockchain + jdchain-root + 1.1.2.RELEASE + + contract + pom + + + contract-framework + contract-jvm + contract-maven-plugin + contract-samples + + \ No newline at end of file diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/AddressEncoding.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/AddressEncoding.java index a1bf5e9c..98d3af79 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/AddressEncoding.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/AddressEncoding.java @@ -1,65 +1,65 @@ -package com.jd.blockchain.crypto; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; - -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.io.BytesEncoding; -import com.jd.blockchain.utils.io.BytesUtils; -import com.jd.blockchain.utils.io.NumberMask; -import com.jd.blockchain.utils.security.RipeMD160Utils; -import com.jd.blockchain.utils.security.ShaUtils; - -public class AddressEncoding { - - /** - * 将区块链地址写入到输出流;
- * - * 现将地址按 Base58 解码为字节数组,并将字节数组以 {@link BytesEncoding} 的方式写入输出流;
- * - * 如果指定的地址为 null,则仅写入空字节数组;注:此种情况下,输出流并不是完全没有写入,而是实际上会被写入一个表示内容长度为 0 的头部字节;
- * - * @param address - * 要写入的区块链地址; - * @param out - * 输出流; - * @return 写入的地址的字节数;如果指定地址为 null,则返回值为写入的头部字节数;; - */ - public static int writeAddress(Bytes address, OutputStream out) { - return address.writeTo(out); - } - - /** - * 从流中读取区块链地址; - * - * @param in - * @return - * @throws IOException - */ - public static Bytes readAddress(InputStream in) throws IOException { - byte[] bytesAddress = BytesEncoding.read(NumberMask.TINY, in); - if (bytesAddress.length == 0) { - return null; - } - return new Bytes(bytesAddress); - } - - /** - * 从公钥生成地址; - * - * @param pubKey - * @return - */ - public static Bytes generateAddress(PubKey pubKey) { - byte[] h1Bytes = ShaUtils.hash_256(pubKey.getRawKeyBytes()); - byte[] h2Bytes = RipeMD160Utils.hash(h1Bytes); - byte[] xBytes = BytesUtils.concat(new byte[] { AddressVersion.V1.CODE}, BytesUtils.toBytes(pubKey.getAlgorithm()), h2Bytes); - byte[] checksum = Arrays.copyOf(ShaUtils.hash_256(ShaUtils.hash_256(xBytes)), 4); - byte[] addressBytes = BytesUtils.concat(xBytes, checksum); - - return new Bytes(addressBytes); - } - -} +package com.jd.blockchain.crypto; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; + +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.BytesEncoding; +import com.jd.blockchain.utils.io.BytesUtils; +import com.jd.blockchain.utils.io.NumberMask; +import com.jd.blockchain.utils.security.RipeMD160Utils; +import com.jd.blockchain.utils.security.ShaUtils; + +public class AddressEncoding { + + /** + * 将区块链地址写入到输出流;
+ * + * 现将地址按 Base58 解码为字节数组,并将字节数组以 {@link BytesEncoding} 的方式写入输出流;
+ * + * 如果指定的地址为 null,则仅写入空字节数组;注:此种情况下,输出流并不是完全没有写入,而是实际上会被写入一个表示内容长度为 0 的头部字节;
+ * + * @param address + * 要写入的区块链地址; + * @param out + * 输出流; + * @return 写入的地址的字节数;如果指定地址为 null,则返回值为写入的头部字节数;; + */ + public static int writeAddress(Bytes address, OutputStream out) { + return address.writeTo(out); + } + + /** + * 从流中读取区块链地址; + * + * @param in + * @return + * @throws IOException + */ + public static Bytes readAddress(InputStream in) throws IOException { + byte[] bytesAddress = BytesEncoding.read(NumberMask.TINY, in); + if (bytesAddress.length == 0) { + return null; + } + return new Bytes(bytesAddress); + } + + /** + * 从公钥生成地址; + * + * @param pubKey + * @return + */ + public static Bytes generateAddress(PubKey pubKey) { + byte[] h1Bytes = ShaUtils.hash_256(pubKey.getRawKeyBytes()); + byte[] h2Bytes = RipeMD160Utils.hash(h1Bytes); + byte[] xBytes = BytesUtils.concat(new byte[] { AddressVersion.V1.CODE}, BytesUtils.toBytes(pubKey.getAlgorithm()), h2Bytes); + byte[] checksum = Arrays.copyOf(ShaUtils.hash_256(ShaUtils.hash_256(xBytes)), 4); + byte[] addressBytes = BytesUtils.concat(xBytes, checksum); + + return new Bytes(addressBytes); + } + +} diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/AddressVersion.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/AddressVersion.java index 5e741abc..720214f9 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/AddressVersion.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/AddressVersion.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.crypto; - -/** - * The version of Blockchain Address generation rule;
- * - * - * - * @author huanghaiquan - * - */ -public enum AddressVersion { - - V1((byte) 0x91); - - // Note: Implementor can only add new enum items, cann't remove or modify - // existing enum items; - - public final byte CODE; - - AddressVersion(byte code) { - CODE = code; - } - -} +package com.jd.blockchain.crypto; + +/** + * The version of Blockchain Address generation rule;
+ * + * + * + * @author huanghaiquan + * + */ +public enum AddressVersion { + + V1((byte) 0x91); + + // Note: Implementor can only add new enum items, cann't remove or modify + // existing enum items; + + public final byte CODE; + + AddressVersion(byte code) { + CODE = code; + } + +} diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoKey.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoKey.java index ea73ef25..69c3b422 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoKey.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/CryptoKey.java @@ -1,25 +1,25 @@ -package com.jd.blockchain.crypto; - -/** - * 密钥; - * - * @author huanghaiquan - * - */ -public interface CryptoKey extends CryptoBytes { - - /** - * 密钥的类型; - * @return - */ - CryptoKeyType getKeyType(); - - /** - * 原始的密钥数据; - * - * @return - */ - byte[] getRawKeyBytes(); - - +package com.jd.blockchain.crypto; + +/** + * 密钥; + * + * @author huanghaiquan + * + */ +public interface CryptoKey extends CryptoBytes { + + /** + * 密钥的类型; + * @return + */ + CryptoKeyType getKeyType(); + + /** + * 原始的密钥数据; + * + * @return + */ + byte[] getRawKeyBytes(); + + } \ No newline at end of file diff --git a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PrivKey.java b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PrivKey.java index 78af68c4..0aee8d26 100644 --- a/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PrivKey.java +++ b/source/crypto/crypto-framework/src/main/java/com/jd/blockchain/crypto/PrivKey.java @@ -1,29 +1,29 @@ -package com.jd.blockchain.crypto; - -/** - * 私钥; - * - * @author huanghaiquan - * - */ -public class PrivKey extends BaseCryptoKey { - - private static final long serialVersionUID = 6265440395252295646L; - - public PrivKey(short algorithm, byte[] rawCryptoBytes) { - super(algorithm, rawCryptoBytes, CryptoKeyType.PRIVATE); - } - - public PrivKey(CryptoAlgorithm algorithm, byte[] rawCryptoBytes) { - super(algorithm, rawCryptoBytes, CryptoKeyType.PRIVATE); - } - - public PrivKey(byte[] cryptoBytes) { - super(cryptoBytes); - } - - @Override - public CryptoKeyType getKeyType() { - return CryptoKeyType.PRIVATE; - } +package com.jd.blockchain.crypto; + +/** + * 私钥; + * + * @author huanghaiquan + * + */ +public class PrivKey extends BaseCryptoKey { + + private static final long serialVersionUID = 6265440395252295646L; + + public PrivKey(short algorithm, byte[] rawCryptoBytes) { + super(algorithm, rawCryptoBytes, CryptoKeyType.PRIVATE); + } + + public PrivKey(CryptoAlgorithm algorithm, byte[] rawCryptoBytes) { + super(algorithm, rawCryptoBytes, CryptoKeyType.PRIVATE); + } + + public PrivKey(byte[] cryptoBytes) { + super(cryptoBytes); + } + + @Override + public CryptoKeyType getKeyType() { + return CryptoKeyType.PRIVATE; + } } \ No newline at end of file diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayConfiguration.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayConfiguration.java index c498d29a..704bf3ab 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayConfiguration.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayConfiguration.java @@ -1,14 +1,14 @@ -package com.jd.blockchain.gateway; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.ComponentScan; - -@EnableAutoConfiguration -@EnableConfigurationProperties -@SpringBootApplication -@ComponentScan -public class GatewayConfiguration { -} - +package com.jd.blockchain.gateway; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; + +@EnableAutoConfiguration +@EnableConfigurationProperties +@SpringBootApplication +@ComponentScan +public class GatewayConfiguration { +} + diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java index 18866f76..f743b4ac 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/GatewayServerBooter.java @@ -1,178 +1,178 @@ -package com.jd.blockchain.gateway; - -import java.io.File; -import java.io.InputStream; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.io.FileUtils; -import org.springframework.boot.SpringApplication; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.io.ClassPathResource; - -import com.jd.blockchain.crypto.AsymmetricKeypair; -import com.jd.blockchain.crypto.KeyGenUtils; -import com.jd.blockchain.crypto.PrivKey; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.gateway.web.BlockBrowserController; -import com.jd.blockchain.utils.ArgumentSet; -import com.jd.blockchain.utils.ArgumentSet.ArgEntry; -import com.jd.blockchain.utils.BaseConstant; -import com.jd.blockchain.utils.ConsoleUtils; - - -public class GatewayServerBooter { - - private static final String DEFAULT_GATEWAY_PROPS = "application-gw.properties"; - - // 当前参与方在初始化配置中的参与方列表的编号; - private static final String HOST_ARG = "-c"; - - //sp;针对spring.config.location这个参数进行包装; - private static final String SPRING_CF_LOCATION = BaseConstant.SPRING_CF_LOCATION; - - // 是否输出调试信息; - private static final String DEBUG_OPT = "-debug"; - - public static void main(String[] args) { - boolean debug = false; - try { - ArgumentSet arguments = ArgumentSet.resolve(args, ArgumentSet.setting().prefix(HOST_ARG, SPRING_CF_LOCATION).option(DEBUG_OPT)); - debug = arguments.hasOption(DEBUG_OPT); - ArgEntry argHost = arguments.getArg(HOST_ARG); - String configFile = argHost == null ? null : argHost.getValue(); - GatewayConfigProperties configProps; - if (configFile == null) { - ConsoleUtils.info("Load build-in default configuration ..."); - ClassPathResource configResource = new ClassPathResource("gateway.conf"); - try (InputStream in = configResource.getInputStream()) { - configProps = GatewayConfigProperties.resolve(in); - } - } else { - ConsoleUtils.info("Load configuration ..."); - configProps = GatewayConfigProperties.resolve(argHost.getValue()); - } - - //spring config location; - String springConfigLocation=null; - ArgumentSet.ArgEntry spConfigLocation = arguments.getArg(SPRING_CF_LOCATION); - if (spConfigLocation != null) { - springConfigLocation = spConfigLocation.getValue(); - }else { - //if no the config file, then should tip as follows. but it's not a good feeling, so we create it by inputStream; - ConsoleUtils.info("no param:-sp, format: -sp /x/xx.properties, use the default application-gw.properties "); - ClassPathResource configResource = new ClassPathResource(DEFAULT_GATEWAY_PROPS); - InputStream in = configResource.getInputStream(); - - // 将文件写入至config目录下 - String configPath = bootPath() + "config" + File.separator + DEFAULT_GATEWAY_PROPS; - File targetFile = new File(configPath); - - // 先将原来文件删除再Copy - if (targetFile.exists()) { - FileUtils.forceDelete(targetFile); - } - - FileUtils.copyInputStreamToFile(in, targetFile); - springConfigLocation = "file:" + targetFile.getAbsolutePath(); - } - - // 启动服务器; - ConsoleUtils.info("Starting web server......"); - GatewayServerBooter booter = new GatewayServerBooter(configProps,springConfigLocation); - booter.start(); - - ConsoleUtils.info("Peer[%s] is connected success!", configProps.masterPeerAddress().toString()); - } catch (Exception e) { - ConsoleUtils.error("Error!! %s", e.getMessage()); - if (debug) { - e.printStackTrace(); - } - } - } - - private volatile ConfigurableApplicationContext appCtx; - private GatewayConfigProperties config; - private AsymmetricKeypair defaultKeyPair; - private String springConfigLocation; - public GatewayServerBooter(GatewayConfigProperties config, String springConfigLocation) { - this.config = config; - this.springConfigLocation = springConfigLocation; - - String base58Pwd = config.keys().getDefault().getPrivKeyPassword(); - if (base58Pwd == null || base58Pwd.length() == 0) { - base58Pwd = KeyGenUtils.readPasswordString(); - } - - // 加载密钥; - PubKey pubKey = KeyGenUtils.decodePubKey(config.keys().getDefault().getPubKeyValue()); - - PrivKey privKey = null; - String base58PrivKey = config.keys().getDefault().getPrivKeyValue(); - if (base58PrivKey == null) { - //注:GatewayConfigProperties 确保了 PrivKeyValue 和 PrivKeyPath 必有其一; - privKey = KeyGenUtils.readPrivKey(config.keys().getDefault().getPrivKeyPath(), base58Pwd); - } else { - privKey = KeyGenUtils.decodePrivKey(base58PrivKey, base58Pwd); - } - defaultKeyPair = new AsymmetricKeypair(pubKey, privKey); - } - - public synchronized void start() { - if (this.appCtx != null) { - throw new IllegalStateException("Gateway server is running already."); - } - this.appCtx = startServer(config.http().getHost(), config.http().getPort(), springConfigLocation, - config.http().getContextPath()); - - ConsoleUtils.info("\r\n\r\nStart connecting to peer ...."); - BlockBrowserController blockBrowserController = appCtx.getBean(BlockBrowserController.class); - blockBrowserController.setDataRetrievalUrl(config.dataRetrievalUrl()); - blockBrowserController.setSchemaRetrievalUrl(config.getSchemaRetrievalUrl()); - PeerConnector peerConnector = appCtx.getBean(PeerConnector.class); - peerConnector.connect(config.masterPeerAddress(), defaultKeyPair, config.providerConfig().getProviders()); - ConsoleUtils.info("Peer[%s] is connected success!", config.masterPeerAddress().toString()); - } - - public synchronized void close() { - if (this.appCtx == null) { - return; - } - this.appCtx.close(); - } - - private static ConfigurableApplicationContext startServer(String host, int port, String springConfigLocation, String contextPath) { - List argList = new ArrayList(); - argList.add(String.format("--server.address=%s", host)); - argList.add(String.format("--server.port=%s", port)); - - if(springConfigLocation != null){ - argList.add(String.format("--spring.config.location=%s", springConfigLocation)); - } - - if (contextPath != null) { - argList.add(String.format("--server.context-path=%s", contextPath)); - } - - String[] args = argList.toArray(new String[argList.size()]); - - // 启动服务器; - ConfigurableApplicationContext appCtx = SpringApplication.run(GatewayConfiguration.class, args); - return appCtx; - } - - private static String bootPath() throws Exception { - URL url = GatewayServerBooter.class.getProtectionDomain().getCodeSource().getLocation(); - String currPath = java.net.URLDecoder.decode(url.getPath(), "UTF-8"); - // 处理打包至SpringBoot问题 - if (currPath.contains("!/")) { - currPath = currPath.substring(5, currPath.indexOf("!/")); - } - if (currPath.endsWith(".jar")) { - currPath = currPath.substring(0, currPath.lastIndexOf("/") + 1); - } - System.out.printf("Current Project Boot Path = %s \r\n", currPath); - return new File(currPath).getParent() + File.separator; - } +package com.jd.blockchain.gateway; + +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.io.FileUtils; +import org.springframework.boot.SpringApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.io.ClassPathResource; + +import com.jd.blockchain.crypto.AsymmetricKeypair; +import com.jd.blockchain.crypto.KeyGenUtils; +import com.jd.blockchain.crypto.PrivKey; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.gateway.web.BlockBrowserController; +import com.jd.blockchain.utils.ArgumentSet; +import com.jd.blockchain.utils.ArgumentSet.ArgEntry; +import com.jd.blockchain.utils.BaseConstant; +import com.jd.blockchain.utils.ConsoleUtils; + + +public class GatewayServerBooter { + + private static final String DEFAULT_GATEWAY_PROPS = "application-gw.properties"; + + // 当前参与方在初始化配置中的参与方列表的编号; + private static final String HOST_ARG = "-c"; + + //sp;针对spring.config.location这个参数进行包装; + private static final String SPRING_CF_LOCATION = BaseConstant.SPRING_CF_LOCATION; + + // 是否输出调试信息; + private static final String DEBUG_OPT = "-debug"; + + public static void main(String[] args) { + boolean debug = false; + try { + ArgumentSet arguments = ArgumentSet.resolve(args, ArgumentSet.setting().prefix(HOST_ARG, SPRING_CF_LOCATION).option(DEBUG_OPT)); + debug = arguments.hasOption(DEBUG_OPT); + ArgEntry argHost = arguments.getArg(HOST_ARG); + String configFile = argHost == null ? null : argHost.getValue(); + GatewayConfigProperties configProps; + if (configFile == null) { + ConsoleUtils.info("Load build-in default configuration ..."); + ClassPathResource configResource = new ClassPathResource("gateway.conf"); + try (InputStream in = configResource.getInputStream()) { + configProps = GatewayConfigProperties.resolve(in); + } + } else { + ConsoleUtils.info("Load configuration ..."); + configProps = GatewayConfigProperties.resolve(argHost.getValue()); + } + + //spring config location; + String springConfigLocation=null; + ArgumentSet.ArgEntry spConfigLocation = arguments.getArg(SPRING_CF_LOCATION); + if (spConfigLocation != null) { + springConfigLocation = spConfigLocation.getValue(); + }else { + //if no the config file, then should tip as follows. but it's not a good feeling, so we create it by inputStream; + ConsoleUtils.info("no param:-sp, format: -sp /x/xx.properties, use the default application-gw.properties "); + ClassPathResource configResource = new ClassPathResource(DEFAULT_GATEWAY_PROPS); + InputStream in = configResource.getInputStream(); + + // 将文件写入至config目录下 + String configPath = bootPath() + "config" + File.separator + DEFAULT_GATEWAY_PROPS; + File targetFile = new File(configPath); + + // 先将原来文件删除再Copy + if (targetFile.exists()) { + FileUtils.forceDelete(targetFile); + } + + FileUtils.copyInputStreamToFile(in, targetFile); + springConfigLocation = "file:" + targetFile.getAbsolutePath(); + } + + // 启动服务器; + ConsoleUtils.info("Starting web server......"); + GatewayServerBooter booter = new GatewayServerBooter(configProps,springConfigLocation); + booter.start(); + + ConsoleUtils.info("Peer[%s] is connected success!", configProps.masterPeerAddress().toString()); + } catch (Exception e) { + ConsoleUtils.error("Error!! %s", e.getMessage()); + if (debug) { + e.printStackTrace(); + } + } + } + + private volatile ConfigurableApplicationContext appCtx; + private GatewayConfigProperties config; + private AsymmetricKeypair defaultKeyPair; + private String springConfigLocation; + public GatewayServerBooter(GatewayConfigProperties config, String springConfigLocation) { + this.config = config; + this.springConfigLocation = springConfigLocation; + + String base58Pwd = config.keys().getDefault().getPrivKeyPassword(); + if (base58Pwd == null || base58Pwd.length() == 0) { + base58Pwd = KeyGenUtils.readPasswordString(); + } + + // 加载密钥; + PubKey pubKey = KeyGenUtils.decodePubKey(config.keys().getDefault().getPubKeyValue()); + + PrivKey privKey = null; + String base58PrivKey = config.keys().getDefault().getPrivKeyValue(); + if (base58PrivKey == null) { + //注:GatewayConfigProperties 确保了 PrivKeyValue 和 PrivKeyPath 必有其一; + privKey = KeyGenUtils.readPrivKey(config.keys().getDefault().getPrivKeyPath(), base58Pwd); + } else { + privKey = KeyGenUtils.decodePrivKey(base58PrivKey, base58Pwd); + } + defaultKeyPair = new AsymmetricKeypair(pubKey, privKey); + } + + public synchronized void start() { + if (this.appCtx != null) { + throw new IllegalStateException("Gateway server is running already."); + } + this.appCtx = startServer(config.http().getHost(), config.http().getPort(), springConfigLocation, + config.http().getContextPath()); + + ConsoleUtils.info("\r\n\r\nStart connecting to peer ...."); + BlockBrowserController blockBrowserController = appCtx.getBean(BlockBrowserController.class); + blockBrowserController.setDataRetrievalUrl(config.dataRetrievalUrl()); + blockBrowserController.setSchemaRetrievalUrl(config.getSchemaRetrievalUrl()); + PeerConnector peerConnector = appCtx.getBean(PeerConnector.class); + peerConnector.connect(config.masterPeerAddress(), defaultKeyPair, config.providerConfig().getProviders()); + ConsoleUtils.info("Peer[%s] is connected success!", config.masterPeerAddress().toString()); + } + + public synchronized void close() { + if (this.appCtx == null) { + return; + } + this.appCtx.close(); + } + + private static ConfigurableApplicationContext startServer(String host, int port, String springConfigLocation, String contextPath) { + List argList = new ArrayList(); + argList.add(String.format("--server.address=%s", host)); + argList.add(String.format("--server.port=%s", port)); + + if(springConfigLocation != null){ + argList.add(String.format("--spring.config.location=%s", springConfigLocation)); + } + + if (contextPath != null) { + argList.add(String.format("--server.context-path=%s", contextPath)); + } + + String[] args = argList.toArray(new String[argList.size()]); + + // 启动服务器; + ConfigurableApplicationContext appCtx = SpringApplication.run(GatewayConfiguration.class, args); + return appCtx; + } + + private static String bootPath() throws Exception { + URL url = GatewayServerBooter.class.getProtectionDomain().getCodeSource().getLocation(); + String currPath = java.net.URLDecoder.decode(url.getPath(), "UTF-8"); + // 处理打包至SpringBoot问题 + if (currPath.contains("!/")) { + currPath = currPath.substring(5, currPath.indexOf("!/")); + } + if (currPath.endsWith(".jar")) { + currPath = currPath.substring(0, currPath.lastIndexOf("/") + 1); + } + System.out.printf("Current Project Boot Path = %s \r\n", currPath); + return new File(currPath).getParent() + File.separator; + } } \ No newline at end of file diff --git a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebSecurityConfigurer.java b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebSecurityConfigurer.java index 857d18ae..504f09b8 100644 --- a/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebSecurityConfigurer.java +++ b/source/gateway/src/main/java/com/jd/blockchain/gateway/web/GatewayWebSecurityConfigurer.java @@ -1,17 +1,17 @@ -package com.jd.blockchain.gateway.web; - -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; - -@Configuration -@EnableWebSecurity -public class GatewayWebSecurityConfigurer extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests().anyRequest().permitAll(); - http.csrf().disable(); - } -} +package com.jd.blockchain.gateway.web; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class GatewayWebSecurityConfigurer extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().permitAll(); + http.csrf().disable(); + } +} diff --git a/source/gateway/src/main/resources/gateway.conf b/source/gateway/src/main/resources/gateway.conf index 6b1a723e..c4262cc5 100644 --- a/source/gateway/src/main/resources/gateway.conf +++ b/source/gateway/src/main/resources/gateway.conf @@ -1,31 +1,31 @@ -#网关的HTTP服务地址; -http.host=0.0.0.0 -#网关的HTTP服务端口; -http.port=8081 -#网关的HTTP服务上下文路径,可选; -#http.context-path= - -#共识节点的服务地址(与该网关节点连接的Peer节点的IP地址); -peer.host=127.0.0.1 -#共识节点的服务端口(与该网关节点连接的Peer节点的端口); -peer.port=12000 -#共识节点的服务是否启用安全证书; -peer.secure=false -#共识节点的服务提供解析器 -#BftSmart共识Provider:com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider -#简单消息共识Provider:com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider -peer.providers=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider - -#数据检索服务对应URL,格式:http://{ip}:{port},例如:http://127.0.0.1:10001 -#若该值不配置或配置不正确,则浏览器模糊查询部分无法正常显示 -data.retrieval.url=http://127.0.0.1:10001 -schema.retrieval.url=http://192.168.151.39:8082 - -#默认公钥的内容(Base58编码数据); -keys.default.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9 -#默认私钥的路径;在 pk-path 和 pk 之间必须设置其一; -keys.default.privkey-path= -#默认私钥的内容(加密的Base58编码数据);在 pk-path 和 pk 之间必须设置其一; -keys.default.privkey=177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x -#默认私钥的解码密码; +#网关的HTTP服务地址; +http.host=0.0.0.0 +#网关的HTTP服务端口; +http.port=8081 +#网关的HTTP服务上下文路径,可选; +#http.context-path= + +#共识节点的服务地址(与该网关节点连接的Peer节点的IP地址); +peer.host=127.0.0.1 +#共识节点的服务端口(与该网关节点连接的Peer节点的端口); +peer.port=12000 +#共识节点的服务是否启用安全证书; +peer.secure=false +#共识节点的服务提供解析器 +#BftSmart共识Provider:com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider +#简单消息共识Provider:com.jd.blockchain.consensus.mq.MsgQueueConsensusProvider +peer.providers=com.jd.blockchain.consensus.bftsmart.BftsmartConsensusProvider + +#数据检索服务对应URL,格式:http://{ip}:{port},例如:http://127.0.0.1:10001 +#若该值不配置或配置不正确,则浏览器模糊查询部分无法正常显示 +data.retrieval.url=http://127.0.0.1:10001 +schema.retrieval.url=http://192.168.151.39:8082 + +#默认公钥的内容(Base58编码数据); +keys.default.pubkey=3snPdw7i7PjVKiTH2VnXZu5H8QmNaSXpnk4ei533jFpuifyjS5zzH9 +#默认私钥的路径;在 pk-path 和 pk 之间必须设置其一; +keys.default.privkey-path= +#默认私钥的内容(加密的Base58编码数据);在 pk-path 和 pk 之间必须设置其一; +keys.default.privkey=177gjzHTznYdPgWqZrH43W3yp37onm74wYXT4v9FukpCHBrhRysBBZh7Pzdo5AMRyQGJD7x +#默认私钥的解码密码; keys.default.privkey-password=DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY \ No newline at end of file diff --git a/source/gateway/src/test/java/test/com/jd/blockchain/gateway/data/HashDigestDeserializer.java b/source/gateway/src/test/java/test/com/jd/blockchain/gateway/data/HashDigestDeserializer.java index 448cd365..c6781f40 100644 --- a/source/gateway/src/test/java/test/com/jd/blockchain/gateway/data/HashDigestDeserializer.java +++ b/source/gateway/src/test/java/test/com/jd/blockchain/gateway/data/HashDigestDeserializer.java @@ -1,31 +1,31 @@ -package test.com.jd.blockchain.gateway.data; - -import java.lang.reflect.Type; - -import com.alibaba.fastjson.parser.DefaultJSONParser; -import com.alibaba.fastjson.parser.JSONToken; -import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.utils.codec.Base58Utils; - -public class HashDigestDeserializer implements ObjectDeserializer{ - - public static final HashDigestDeserializer INSTANCE = new HashDigestDeserializer(); - - @SuppressWarnings("unchecked") - @Override - public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { - if (type instanceof Class && HashDigest.class.isAssignableFrom((Class) type)) { - String base58Str = parser.parseObject(String.class); - byte[] hashBytes = Base58Utils.decode(base58Str); - return (T) new HashDigest(hashBytes); - } - return (T) parser.parse(fieldName); - } - - @Override - public int getFastMatchToken() { - return JSONToken.LBRACE; - } - -} +package test.com.jd.blockchain.gateway.data; + +import java.lang.reflect.Type; + +import com.alibaba.fastjson.parser.DefaultJSONParser; +import com.alibaba.fastjson.parser.JSONToken; +import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.utils.codec.Base58Utils; + +public class HashDigestDeserializer implements ObjectDeserializer{ + + public static final HashDigestDeserializer INSTANCE = new HashDigestDeserializer(); + + @SuppressWarnings("unchecked") + @Override + public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { + if (type instanceof Class && HashDigest.class.isAssignableFrom((Class) type)) { + String base58Str = parser.parseObject(String.class); + byte[] hashBytes = Base58Utils.decode(base58Str); + return (T) new HashDigest(hashBytes); + } + return (T) parser.parse(fieldName); + } + + @Override + public int getFastMatchToken() { + return JSONToken.LBRACE; + } + +} diff --git a/source/gateway/src/test/java/test/com/jd/blockchain/gateway/data/HashDigestSerializer.java b/source/gateway/src/test/java/test/com/jd/blockchain/gateway/data/HashDigestSerializer.java index 14200484..58207dc7 100644 --- a/source/gateway/src/test/java/test/com/jd/blockchain/gateway/data/HashDigestSerializer.java +++ b/source/gateway/src/test/java/test/com/jd/blockchain/gateway/data/HashDigestSerializer.java @@ -1,27 +1,27 @@ -package test.com.jd.blockchain.gateway.data; - -import java.io.IOException; -import java.lang.reflect.Type; - -import com.alibaba.fastjson.serializer.JSONSerializer; -import com.alibaba.fastjson.serializer.ObjectSerializer; -import com.alibaba.fastjson.serializer.SerializeWriter; -import com.jd.blockchain.crypto.HashDigest; - -public class HashDigestSerializer implements ObjectSerializer { - - public static HashDigestSerializer INSTANCE = new HashDigestSerializer(); - - @Override - public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) - throws IOException { - SerializeWriter out = serializer.out; - if (object == null) { - out.writeNull(); - return; - } - HashDigest hash = (HashDigest) object; - out.writeString(hash.toBase58()); - } - -} +package test.com.jd.blockchain.gateway.data; + +import java.io.IOException; +import java.lang.reflect.Type; + +import com.alibaba.fastjson.serializer.JSONSerializer; +import com.alibaba.fastjson.serializer.ObjectSerializer; +import com.alibaba.fastjson.serializer.SerializeWriter; +import com.jd.blockchain.crypto.HashDigest; + +public class HashDigestSerializer implements ObjectSerializer { + + public static HashDigestSerializer INSTANCE = new HashDigestSerializer(); + + @Override + public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) + throws IOException { + SerializeWriter out = serializer.out; + if (object == null) { + out.writeNull(); + return; + } + HashDigest hash = (HashDigest) object; + out.writeString(hash.toBase58()); + } + +} diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java index 19c76463..d8a716bc 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccount.java @@ -1,73 +1,73 @@ -package com.jd.blockchain.ledger.core; - -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.ContractInfo; -import com.jd.blockchain.ledger.TypedValue; -import com.jd.blockchain.utils.Bytes; - -public class ContractAccount extends AccountDecorator implements ContractInfo { - - private static final String CONTRACT_INFO_PREFIX = "INFO" + LedgerConsts.KEY_SEPERATOR; - - private static final String CHAIN_CODE_KEY = "CHAIN-CODE"; - - public ContractAccount(CompositeAccount mklAccount) { - super(mklAccount); - } - - @Override - public Bytes getAddress() { - return getID().getAddress(); - } - - @Override - public PubKey getPubKey() { - return getID().getPubKey(); - } - -// public MerkleProof getChaincodeProof() { -// return getHeaders().getProof(CHAIN_CODE_KEY); -// } -// -// public MerkleProof getPropertyProof(Bytes key) { -// return getHeaders().getProof(encodePropertyKey(key)); -// } - - public long setChaincode(byte[] chaincode, long version) { - TypedValue bytesValue = TypedValue.fromBytes(chaincode); - return getHeaders().setValue(CHAIN_CODE_KEY, bytesValue, version); - } - - public byte[] getChainCode() { - return getHeaders().getValue(CHAIN_CODE_KEY).getBytes().toBytes(); - } - - public byte[] getChainCode(long version) { - return getHeaders().getValue(CHAIN_CODE_KEY, version).getBytes().toBytes(); - } - - public long getChaincodeVersion() { - return getHeaders().getVersion(CHAIN_CODE_KEY); - } - - public long setProperty(String key, String value, long version) { - TypedValue bytesValue = TypedValue.fromText(value); - return getHeaders().setValue(encodePropertyKey(key), bytesValue, version); - } - - public String getProperty(String key) { - BytesValue bytesValue = getHeaders().getValue(encodePropertyKey(key)); - return TypedValue.wrap(bytesValue).stringValue(); - } - - public String getProperty(String key, long version) { - BytesValue bytesValue = getHeaders().getValue(encodePropertyKey(key), version); - return TypedValue.wrap(bytesValue).stringValue(); - } - - private String encodePropertyKey(String key) { - return CONTRACT_INFO_PREFIX.concat(key); - } - +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.ContractInfo; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.utils.Bytes; + +public class ContractAccount extends AccountDecorator implements ContractInfo { + + private static final String CONTRACT_INFO_PREFIX = "INFO" + LedgerConsts.KEY_SEPERATOR; + + private static final String CHAIN_CODE_KEY = "CHAIN-CODE"; + + public ContractAccount(CompositeAccount mklAccount) { + super(mklAccount); + } + + @Override + public Bytes getAddress() { + return getID().getAddress(); + } + + @Override + public PubKey getPubKey() { + return getID().getPubKey(); + } + +// public MerkleProof getChaincodeProof() { +// return getHeaders().getProof(CHAIN_CODE_KEY); +// } +// +// public MerkleProof getPropertyProof(Bytes key) { +// return getHeaders().getProof(encodePropertyKey(key)); +// } + + public long setChaincode(byte[] chaincode, long version) { + TypedValue bytesValue = TypedValue.fromBytes(chaincode); + return getHeaders().setValue(CHAIN_CODE_KEY, bytesValue, version); + } + + public byte[] getChainCode() { + return getHeaders().getValue(CHAIN_CODE_KEY).getBytes().toBytes(); + } + + public byte[] getChainCode(long version) { + return getHeaders().getValue(CHAIN_CODE_KEY, version).getBytes().toBytes(); + } + + public long getChaincodeVersion() { + return getHeaders().getVersion(CHAIN_CODE_KEY); + } + + public long setProperty(String key, String value, long version) { + TypedValue bytesValue = TypedValue.fromText(value); + return getHeaders().setValue(encodePropertyKey(key), bytesValue, version); + } + + public String getProperty(String key) { + BytesValue bytesValue = getHeaders().getValue(encodePropertyKey(key)); + return TypedValue.wrap(bytesValue).stringValue(); + } + + public String getProperty(String key, long version) { + BytesValue bytesValue = getHeaders().getValue(encodePropertyKey(key), version); + return TypedValue.wrap(bytesValue).stringValue(); + } + + private String encodePropertyKey(String key) { + return CONTRACT_INFO_PREFIX.concat(key); + } + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java index c4ee0408..ae11cb0e 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ContractAccountSet.java @@ -1,131 +1,131 @@ -package com.jd.blockchain.ledger.core; - -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.CryptoSetting; -import com.jd.blockchain.ledger.DigitalSignature; -import com.jd.blockchain.ledger.MerkleProof; -import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.VersioningKVStorage; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.Transactional; - -public class ContractAccountSet implements Transactional, ContractAccountQuery { - - private MerkleAccountSet accountSet; - - public ContractAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, - VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, accessPolicy); - } - - public ContractAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix, - ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, - AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, - readonly, accessPolicy); - } - - @Override - public BlockchainIdentity[] getHeaders(int fromIndex, int count) { - return accountSet.getHeaders(fromIndex, count); - } - - public boolean isReadonly() { - return accountSet.isReadonly(); - } - - void setReadonly() { - accountSet.setReadonly(); - } - - @Override - public HashDigest getRootHash() { - return accountSet.getRootHash(); - } - - /** - * 返回合约总数; - * - * @return - */ - @Override - public long getTotal() { - return accountSet.getTotal(); - } - - @Override - public MerkleProof getProof(Bytes address) { - return accountSet.getProof(address); - } - - @Override - public boolean contains(Bytes address) { - return accountSet.contains(address); - } - - @Override - public ContractAccount getAccount(Bytes address) { - CompositeAccount accBase = accountSet.getAccount(address); - return new ContractAccount(accBase); - } - - @Override - public ContractAccount getAccount(String address) { - return getAccount(Bytes.fromBase58(address)); - } - - @Override - public ContractAccount getAccount(Bytes address, long version) { - CompositeAccount accBase = accountSet.getAccount(address, version); - return new ContractAccount(accBase); - } - - /** - * 部署一项新的合约链码; - * - * @param address 合约账户地址; - * @param pubKey 合约账户公钥; - * @param addressSignature 地址签名;合约账户的私钥对地址的签名; - * @param chaincode 链码内容; - * @return 合约账户; - */ - public ContractAccount deploy(Bytes address, PubKey pubKey, DigitalSignature addressSignature, byte[] chaincode) { - // TODO: 校验和记录合约地址签名; - CompositeAccount accBase = accountSet.register(address, pubKey); - ContractAccount contractAcc = new ContractAccount(accBase); - contractAcc.setChaincode(chaincode, -1); - return contractAcc; - } - - /** - * 更新指定账户的链码; - * - * @param address 合约账户地址; - * @param chaincode 链码内容; - * @param version 链码版本; - * @return 返回链码的新版本号; - */ - public long update(Bytes address, byte[] chaincode, long version) { - CompositeAccount accBase = accountSet.getAccount(address); - ContractAccount contractAcc = new ContractAccount(accBase); - return contractAcc.setChaincode(chaincode, version); - } - - @Override - public boolean isUpdated() { - return accountSet.isUpdated(); - } - - @Override - public void commit() { - accountSet.commit(); - } - - @Override - public void cancel() { - accountSet.cancel(); - } - +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.DigitalSignature; +import com.jd.blockchain.ledger.MerkleProof; +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.Transactional; + +public class ContractAccountSet implements Transactional, ContractAccountQuery { + + private MerkleAccountSet accountSet; + + public ContractAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, + VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { + accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, accessPolicy); + } + + public ContractAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix, + ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, + AccountAccessPolicy accessPolicy) { + accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, + readonly, accessPolicy); + } + + @Override + public BlockchainIdentity[] getHeaders(int fromIndex, int count) { + return accountSet.getHeaders(fromIndex, count); + } + + public boolean isReadonly() { + return accountSet.isReadonly(); + } + + void setReadonly() { + accountSet.setReadonly(); + } + + @Override + public HashDigest getRootHash() { + return accountSet.getRootHash(); + } + + /** + * 返回合约总数; + * + * @return + */ + @Override + public long getTotal() { + return accountSet.getTotal(); + } + + @Override + public MerkleProof getProof(Bytes address) { + return accountSet.getProof(address); + } + + @Override + public boolean contains(Bytes address) { + return accountSet.contains(address); + } + + @Override + public ContractAccount getAccount(Bytes address) { + CompositeAccount accBase = accountSet.getAccount(address); + return new ContractAccount(accBase); + } + + @Override + public ContractAccount getAccount(String address) { + return getAccount(Bytes.fromBase58(address)); + } + + @Override + public ContractAccount getAccount(Bytes address, long version) { + CompositeAccount accBase = accountSet.getAccount(address, version); + return new ContractAccount(accBase); + } + + /** + * 部署一项新的合约链码; + * + * @param address 合约账户地址; + * @param pubKey 合约账户公钥; + * @param addressSignature 地址签名;合约账户的私钥对地址的签名; + * @param chaincode 链码内容; + * @return 合约账户; + */ + public ContractAccount deploy(Bytes address, PubKey pubKey, DigitalSignature addressSignature, byte[] chaincode) { + // TODO: 校验和记录合约地址签名; + CompositeAccount accBase = accountSet.register(address, pubKey); + ContractAccount contractAcc = new ContractAccount(accBase); + contractAcc.setChaincode(chaincode, -1); + return contractAcc; + } + + /** + * 更新指定账户的链码; + * + * @param address 合约账户地址; + * @param chaincode 链码内容; + * @param version 链码版本; + * @return 返回链码的新版本号; + */ + public long update(Bytes address, byte[] chaincode, long version) { + CompositeAccount accBase = accountSet.getAccount(address); + ContractAccount contractAcc = new ContractAccount(accBase); + return contractAcc.setChaincode(chaincode, version); + } + + @Override + public boolean isUpdated() { + return accountSet.isUpdated(); + } + + @Override + public void commit() { + accountSet.commit(); + } + + @Override + public void cancel() { + accountSet.cancel(); + } + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java index 4814cdf6..6f99bf51 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccount.java @@ -1,234 +1,234 @@ -package com.jd.blockchain.ledger.core; - -public class DataAccount extends AccountDecorator { - - public DataAccount(CompositeAccount mklAccount) { - super(mklAccount); - } - -// /** -// * Create or update the value associated the specified key if the version -// * checking is passed.
-// * -// * The value of the key will be updated only if it's latest version equals the -// * specified version argument.
-// * If the key doesn't exist, the version checking will be ignored, and key will -// * be created with a new sequence number as id.
-// * It also could specify the version argument to -1 to ignore the version -// * checking. -// *

-// * If updating is performed, the version of the key increase by 1.
-// * If creating is performed, the version of the key initialize by 0.
-// * -// * @param key The key of data; -// * @param value The value of data; -// * @param version The expected version of the key. -// * @return The new version of the key.
-// * If the key is new created success, then return 0;
-// * If the key is updated success, then return the new version;
-// * If this operation fail by version checking or other reason, then -// * return -1; -// */ -// public long setBytes(Bytes key, BytesValue value, long version) { -// return super.getDataset().setValue(key, value, version); -// } - -// -// /** -// * Create or update the value associated the specified key if the version -// * checking is passed.
-// * -// * The value of the key will be updated only if it's latest version equals the -// * specified version argument.
-// * If the key doesn't exist, the version checking will be ignored, and key will -// * be created with a new sequence number as id.
-// * It also could specify the version argument to -1 to ignore the version -// * checking. -// *

-// * If updating is performed, the version of the key increase by 1.
-// * If creating is performed, the version of the key initialize by 0.
-// * -// * @param key The key of data; -// * @param value The value of data; -// * @param version The expected version of the key. -// * @return The new version of the key.
-// * If the key is new created success, then return 0;
-// * If the key is updated success, then return the new version;
-// * If this operation fail by version checking or other reason, then -// * return -1; -// */ -// public long setBytes(Bytes key, String value, long version) { -// BytesValue bytesValue = TypedValue.fromText(value); -// return baseAccount.setValue(key, bytesValue, version); -// } -// -// /** -// * Create or update the value associated the specified key if the version -// * checking is passed.
-// * -// * The value of the key will be updated only if it's latest version equals the -// * specified version argument.
-// * If the key doesn't exist, the version checking will be ignored, and key will -// * be created with a new sequence number as id.
-// * It also could specify the version argument to -1 to ignore the version -// * checking. -// *

-// * If updating is performed, the version of the key increase by 1.
-// * If creating is performed, the version of the key initialize by 0.
-// * -// * @param key The key of data; -// * @param value The value of data; -// * @param version The expected version of the key. -// * @return The new version of the key.
-// * If the key is new created success, then return 0;
-// * If the key is updated success, then return the new version;
-// * If this operation fail by version checking or other reason, then -// * return -1; -// */ -// public long setBytes(Bytes key, byte[] value, long version) { -// BytesValue bytesValue = TypedValue.fromBytes(value); -// return baseAccount.setValue(key, bytesValue, version); -// } -// -// /** -// * Return the latest version entry associated the specified key; If the key -// * doesn't exist, then return -1; -// * -// * @param key -// * @return -// */ -// public long getDataVersion(String key) { -// return baseAccount.getVersion(Bytes.fromString(key)); -// } -// -// /** -// * Return the latest version entry associated the specified key; If the key -// * doesn't exist, then return -1; -// * -// * @param key -// * @return -// */ -// public long getDataVersion(Bytes key) { -// return baseAccount.getVersion(key); -// } -// -// /** -// * return the latest version's value; -// * -// * @param key -// * @return return null if not exist; -// */ -// public BytesValue getBytes(String key) { -// return baseAccount.getValue(Bytes.fromString(key)); -// } -// -// /** -// * return the latest version's value; -// * -// * @param key -// * @return return null if not exist; -// */ -// public BytesValue getBytes(Bytes key) { -// return baseAccount.getValue(key); -// } -// -// /** -// * return the specified version's value; -// * -// * @param key -// * @param version -// * @return return null if not exist; -// */ -// public BytesValue getBytes(String key, long version) { -// return baseAccount.getValue(Bytes.fromString(key), version); -// } -// -// /** -// * return the specified version's value; -// * -// * @param key -// * @param version -// * @return return null if not exist; -// */ -// public BytesValue getBytes(Bytes key, long version) { -// return baseAccount.getValue(key, version); -// } - - - - -// /** -// * @param key -// * @param version -// * @return -// */ -// public KVDataEntry getDataEntry(String key, long version) { -// return getDataEntry(Bytes.fromString(key), version); -// } -// -// /** -// * @param key -// * @param version -// * @return -// */ -// public KVDataEntry getDataEntry(Bytes key, long version) { -// BytesValue value = baseAccount.getValue(key, version); -// if (value == null) { -// return new KVDataObject(key.toUTF8String(), -1, null); -// }else { -// return new KVDataObject(key.toUTF8String(), version, value); -// } -// } -// -// /** -// * return the specified index's KVDataEntry; -// * -// * @param fromIndex -// * @param count -// * @return return null if not exist; -// */ -// -// public KVDataEntry[] getDataEntries(int fromIndex, int count) { -// if (count == 0 || getDataEntriesTotalCount() == 0) { -// return null; -// } -// -// if (count == -1 || count > getDataEntriesTotalCount()) { -// fromIndex = 0; -// count = (int)getDataEntriesTotalCount(); -// } -// -// if (fromIndex < 0 || fromIndex > getDataEntriesTotalCount() - 1) { -// fromIndex = 0; -// } -// -// KVDataEntry[] kvDataEntries = new KVDataEntry[count]; -// byte[] value; -// String key; -// long ver; -// for (int i = 0; i < count; i++) { -// value = baseAccount.dataset.getValuesAtIndex(fromIndex); -// key = baseAccount.dataset.getKeyAtIndex(fromIndex); -// ver = baseAccount.dataset.getVersion(key); -// BytesValue decodeData = BinaryProtocol.decode(value); -// kvDataEntries[i] = new KVDataObject(key, ver, decodeData); -// fromIndex++; -// } -// -// return kvDataEntries; -// } -// -// /** -// * return the dataAccount's kv total count; -// * -// * @param -// * @param -// * @return return total count; -// */ -// public long getDataEntriesTotalCount() { -// if(baseAccount == null){ -// return 0; -// } -// return baseAccount.dataset.getDataCount(); -// } +package com.jd.blockchain.ledger.core; + +public class DataAccount extends AccountDecorator { + + public DataAccount(CompositeAccount mklAccount) { + super(mklAccount); + } + +// /** +// * Create or update the value associated the specified key if the version +// * checking is passed.
+// * +// * The value of the key will be updated only if it's latest version equals the +// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will +// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version +// * checking. +// *

+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// * +// * @param key The key of data; +// * @param value The value of data; +// * @param version The expected version of the key. +// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then +// * return -1; +// */ +// public long setBytes(Bytes key, BytesValue value, long version) { +// return super.getDataset().setValue(key, value, version); +// } + +// +// /** +// * Create or update the value associated the specified key if the version +// * checking is passed.
+// * +// * The value of the key will be updated only if it's latest version equals the +// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will +// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version +// * checking. +// *

+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// * +// * @param key The key of data; +// * @param value The value of data; +// * @param version The expected version of the key. +// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then +// * return -1; +// */ +// public long setBytes(Bytes key, String value, long version) { +// BytesValue bytesValue = TypedValue.fromText(value); +// return baseAccount.setValue(key, bytesValue, version); +// } +// +// /** +// * Create or update the value associated the specified key if the version +// * checking is passed.
+// * +// * The value of the key will be updated only if it's latest version equals the +// * specified version argument.
+// * If the key doesn't exist, the version checking will be ignored, and key will +// * be created with a new sequence number as id.
+// * It also could specify the version argument to -1 to ignore the version +// * checking. +// *

+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// * +// * @param key The key of data; +// * @param value The value of data; +// * @param version The expected version of the key. +// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then +// * return -1; +// */ +// public long setBytes(Bytes key, byte[] value, long version) { +// BytesValue bytesValue = TypedValue.fromBytes(value); +// return baseAccount.setValue(key, bytesValue, version); +// } +// +// /** +// * Return the latest version entry associated the specified key; If the key +// * doesn't exist, then return -1; +// * +// * @param key +// * @return +// */ +// public long getDataVersion(String key) { +// return baseAccount.getVersion(Bytes.fromString(key)); +// } +// +// /** +// * Return the latest version entry associated the specified key; If the key +// * doesn't exist, then return -1; +// * +// * @param key +// * @return +// */ +// public long getDataVersion(Bytes key) { +// return baseAccount.getVersion(key); +// } +// +// /** +// * return the latest version's value; +// * +// * @param key +// * @return return null if not exist; +// */ +// public BytesValue getBytes(String key) { +// return baseAccount.getValue(Bytes.fromString(key)); +// } +// +// /** +// * return the latest version's value; +// * +// * @param key +// * @return return null if not exist; +// */ +// public BytesValue getBytes(Bytes key) { +// return baseAccount.getValue(key); +// } +// +// /** +// * return the specified version's value; +// * +// * @param key +// * @param version +// * @return return null if not exist; +// */ +// public BytesValue getBytes(String key, long version) { +// return baseAccount.getValue(Bytes.fromString(key), version); +// } +// +// /** +// * return the specified version's value; +// * +// * @param key +// * @param version +// * @return return null if not exist; +// */ +// public BytesValue getBytes(Bytes key, long version) { +// return baseAccount.getValue(key, version); +// } + + + + +// /** +// * @param key +// * @param version +// * @return +// */ +// public KVDataEntry getDataEntry(String key, long version) { +// return getDataEntry(Bytes.fromString(key), version); +// } +// +// /** +// * @param key +// * @param version +// * @return +// */ +// public KVDataEntry getDataEntry(Bytes key, long version) { +// BytesValue value = baseAccount.getValue(key, version); +// if (value == null) { +// return new KVDataObject(key.toUTF8String(), -1, null); +// }else { +// return new KVDataObject(key.toUTF8String(), version, value); +// } +// } +// +// /** +// * return the specified index's KVDataEntry; +// * +// * @param fromIndex +// * @param count +// * @return return null if not exist; +// */ +// +// public KVDataEntry[] getDataEntries(int fromIndex, int count) { +// if (count == 0 || getDataEntriesTotalCount() == 0) { +// return null; +// } +// +// if (count == -1 || count > getDataEntriesTotalCount()) { +// fromIndex = 0; +// count = (int)getDataEntriesTotalCount(); +// } +// +// if (fromIndex < 0 || fromIndex > getDataEntriesTotalCount() - 1) { +// fromIndex = 0; +// } +// +// KVDataEntry[] kvDataEntries = new KVDataEntry[count]; +// byte[] value; +// String key; +// long ver; +// for (int i = 0; i < count; i++) { +// value = baseAccount.dataset.getValuesAtIndex(fromIndex); +// key = baseAccount.dataset.getKeyAtIndex(fromIndex); +// ver = baseAccount.dataset.getVersion(key); +// BytesValue decodeData = BinaryProtocol.decode(value); +// kvDataEntries[i] = new KVDataObject(key, ver, decodeData); +// fromIndex++; +// } +// +// return kvDataEntries; +// } +// +// /** +// * return the dataAccount's kv total count; +// * +// * @param +// * @param +// * @return return total count; +// */ +// public long getDataEntriesTotalCount() { +// if(baseAccount == null){ +// return 0; +// } +// return baseAccount.dataset.getDataCount(); +// } } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java index 0f849c1d..312d2f45 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/DataAccountSet.java @@ -1,113 +1,113 @@ -package com.jd.blockchain.ledger.core; - -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.CryptoSetting; -import com.jd.blockchain.ledger.DigitalSignature; -import com.jd.blockchain.ledger.MerkleProof; -import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.VersioningKVStorage; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.Transactional; - -public class DataAccountSet implements Transactional, DataAccountQuery { - - private MerkleAccountSet accountSet; - - public DataAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, - VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, accessPolicy); - } - - public DataAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix, - ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, - AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, - readonly, accessPolicy); - } - - @Override - public BlockchainIdentity[] getHeaders(int fromIndex, int count) { - return accountSet.getHeaders(fromIndex, count); - } - - public boolean isReadonly() { - return accountSet.isReadonly(); - } - - void setReadonly() { - accountSet.setReadonly(); - } - - @Override - public HashDigest getRootHash() { - return accountSet.getRootHash(); - } - - @Override - public long getTotal() { - return accountSet.getTotal(); - } - - @Override - public boolean contains(Bytes address) { - return accountSet.contains(address); - } - - /** - * 返回账户的存在性证明; - */ - @Override - public MerkleProof getProof(Bytes address) { - return accountSet.getProof(address); - } - - public DataAccount register(Bytes address, PubKey pubKey, DigitalSignature addressSignature) { - // TODO: 未实现对地址签名的校验和记录; - CompositeAccount accBase = accountSet.register(address, pubKey); - return new DataAccount(accBase); - } - - @Override - public DataAccount getAccount(String address) { - return getAccount(Bytes.fromBase58(address)); - } - - /** - * 返回数据账户;
- * 如果不存在,则返回 null; - * - * @param address - * @return - */ - @Override - public DataAccount getAccount(Bytes address) { - CompositeAccount accBase = accountSet.getAccount(address); - if (accBase == null) { - return null; - } - return new DataAccount(accBase); - } - - @Override - public DataAccount getAccount(Bytes address, long version) { - CompositeAccount accBase = accountSet.getAccount(address, version); - return new DataAccount(accBase); - } - - @Override - public boolean isUpdated() { - return accountSet.isUpdated(); - } - - @Override - public void commit() { - accountSet.commit(); - } - - @Override - public void cancel() { - accountSet.cancel(); - } +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.DigitalSignature; +import com.jd.blockchain.ledger.MerkleProof; +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.Transactional; + +public class DataAccountSet implements Transactional, DataAccountQuery { + + private MerkleAccountSet accountSet; + + public DataAccountSet(CryptoSetting cryptoSetting, String prefix, ExPolicyKVStorage exStorage, + VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { + accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, accessPolicy); + } + + public DataAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String prefix, + ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, + AccountAccessPolicy accessPolicy) { + accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(prefix), exStorage, verStorage, + readonly, accessPolicy); + } + + @Override + public BlockchainIdentity[] getHeaders(int fromIndex, int count) { + return accountSet.getHeaders(fromIndex, count); + } + + public boolean isReadonly() { + return accountSet.isReadonly(); + } + + void setReadonly() { + accountSet.setReadonly(); + } + + @Override + public HashDigest getRootHash() { + return accountSet.getRootHash(); + } + + @Override + public long getTotal() { + return accountSet.getTotal(); + } + + @Override + public boolean contains(Bytes address) { + return accountSet.contains(address); + } + + /** + * 返回账户的存在性证明; + */ + @Override + public MerkleProof getProof(Bytes address) { + return accountSet.getProof(address); + } + + public DataAccount register(Bytes address, PubKey pubKey, DigitalSignature addressSignature) { + // TODO: 未实现对地址签名的校验和记录; + CompositeAccount accBase = accountSet.register(address, pubKey); + return new DataAccount(accBase); + } + + @Override + public DataAccount getAccount(String address) { + return getAccount(Bytes.fromBase58(address)); + } + + /** + * 返回数据账户;
+ * 如果不存在,则返回 null; + * + * @param address + * @return + */ + @Override + public DataAccount getAccount(Bytes address) { + CompositeAccount accBase = accountSet.getAccount(address); + if (accBase == null) { + return null; + } + return new DataAccount(accBase); + } + + @Override + public DataAccount getAccount(Bytes address, long version) { + CompositeAccount accBase = accountSet.getAccount(address, version); + return new DataAccount(accBase); + } + + @Override + public boolean isUpdated() { + return accountSet.isUpdated(); + } + + @Override + public void commit() { + accountSet.commit(); + } + + @Override + public void cancel() { + accountSet.cancel(); + } } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java index dfd06a1e..f73a5ccb 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/LedgerAdminDataset.java @@ -1,481 +1,481 @@ -package com.jd.blockchain.ledger.core; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.Crypto; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.crypto.HashFunction; -import com.jd.blockchain.ledger.LedgerAdminSettings; -import com.jd.blockchain.ledger.LedgerException; -import com.jd.blockchain.ledger.LedgerInitSetting; -import com.jd.blockchain.ledger.LedgerMetadata; -import com.jd.blockchain.ledger.LedgerMetadata_V2; -import com.jd.blockchain.ledger.LedgerSettings; -import com.jd.blockchain.ledger.ParticipantNode; -import com.jd.blockchain.ledger.RolePrivilegeSettings; -import com.jd.blockchain.ledger.UserAuthorizationSettings; -import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; -import com.jd.blockchain.storage.service.VersioningKVStorage; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.Transactional; - -public class LedgerAdminDataset implements Transactional, LedgerAdminDataQuery, LedgerAdminSettings { - - static { - DataContractRegistry.register(LedgerMetadata.class); - DataContractRegistry.register(LedgerMetadata_V2.class); - } - - private static Logger LOGGER = LoggerFactory.getLogger(LedgerAdminDataset.class); - - public static final String LEDGER_META_PREFIX = "MTA" + LedgerConsts.KEY_SEPERATOR; - public static final String LEDGER_PARTICIPANT_PREFIX = "PAR" + LedgerConsts.KEY_SEPERATOR; - public static final String LEDGER_SETTING_PREFIX = "SET" + LedgerConsts.KEY_SEPERATOR; - public static final String ROLE_PRIVILEGE_PREFIX = "RPV" + LedgerConsts.KEY_SEPERATOR; - public static final String USER_ROLE_PREFIX = "URO" + LedgerConsts.KEY_SEPERATOR; - - private final Bytes metaPrefix; - private final Bytes settingPrefix; - - private LedgerMetadata_V2 origMetadata; - - private LedgerMetadataInfo metadata; - - /** - * 原来的账本设置; - * - *
- * 对 LedgerMetadata 修改的新配置不能立即生效,需要达成共识后,在下一次区块计算中才生效; - */ - private LedgerSettings previousSettings; - - private HashDigest previousSettingHash; - - /** - * 账本的参与节点; - */ - private ParticipantDataset participants; - - /** - * “角色-权限”数据集; - */ - private RolePrivilegeDataset rolePrivileges; - - /** - * “用户-角色”数据集; - */ - private UserRoleDataset userRoles; - - /** - * 账本参数配置; - */ - private LedgerSettings settings; - - private ExPolicyKVStorage storage; - - private HashDigest adminDataHash; - - private boolean readonly; - - private boolean updated; - - public HashDigest getHash() { - return adminDataHash; - } - - public boolean isReadonly() { - return readonly; - } - - void setReadonly() { - this.readonly = true; - } - - public LedgerSettings getPreviousSetting() { - return previousSettings; - } - - @Override - public RolePrivilegeSettings getRolePrivileges() { - return rolePrivileges; - } - - @Override - public UserAuthorizationSettings getAuthorizations() { - return userRoles; - } - - @Override - public LedgerAdminSettings getAdminInfo() { - return this; - } - - /** - * 初始化账本的管理账户; - * - *
- * - * 只在新建账本时调用此方法; - * - * @param ledgerSeed - * @param settings - * @param partiList - * @param exPolicyStorage - * @param versioningStorage - */ - public LedgerAdminDataset(LedgerInitSetting initSetting, String keyPrefix, ExPolicyKVStorage exPolicyStorage, - VersioningKVStorage versioningStorage) { - this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX); - this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX); - - ParticipantNode[] parties = initSetting.getConsensusParticipants(); - if (parties.length == 0) { - throw new LedgerException("No participant!"); - } - - // 初始化元数据; - this.metadata = new LedgerMetadataInfo(); - this.metadata.setSeed(initSetting.getLedgerSeed()); - // 新配置; - this.settings = new LedgerConfiguration(initSetting.getConsensusProvider(), initSetting.getConsensusSettings(), - initSetting.getCryptoSetting()); - this.previousSettings = new LedgerConfiguration(settings); - this.previousSettingHash = null; - this.adminDataHash = null; - - // 基于原配置初始化参与者列表; - String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX; - this.participants = new ParticipantDataset(previousSettings.getCryptoSetting(), partiPrefix, exPolicyStorage, - versioningStorage); - - for (ParticipantNode p : parties) { - this.participants.addConsensusParticipant(p); - } - - String rolePrivilegePrefix = keyPrefix + ROLE_PRIVILEGE_PREFIX; - this.rolePrivileges = new RolePrivilegeDataset(this.settings.getCryptoSetting(), rolePrivilegePrefix, - exPolicyStorage, versioningStorage); - - String userRolePrefix = keyPrefix + USER_ROLE_PREFIX; - this.userRoles = new UserRoleDataset(this.settings.getCryptoSetting(), userRolePrefix, exPolicyStorage, - versioningStorage); - - // 初始化其它属性; - this.storage = exPolicyStorage; - this.readonly = false; - } - - public LedgerAdminDataset(HashDigest adminAccountHash, String keyPrefix, ExPolicyKVStorage kvStorage, - VersioningKVStorage versioningKVStorage, boolean readonly) { - this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX); - this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX); - this.storage = kvStorage; - this.readonly = readonly; - this.origMetadata = loadAndVerifyMetadata(adminAccountHash); - this.metadata = new LedgerMetadataInfo(origMetadata); - this.settings = loadAndVerifySettings(metadata.getSettingsHash()); - // 复制记录一份配置作为上一个区块的原始配置,该实例仅供读取,不做修改,也不会回写到存储; - this.previousSettings = new LedgerConfiguration(settings); - this.previousSettingHash = metadata.getSettingsHash(); - this.adminDataHash = adminAccountHash; - - String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX; - this.participants = new ParticipantDataset(metadata.getParticipantsHash(), previousSettings.getCryptoSetting(), - partiPrefix, kvStorage, versioningKVStorage, readonly); - - String rolePrivilegePrefix = keyPrefix + ROLE_PRIVILEGE_PREFIX; - this.rolePrivileges = new RolePrivilegeDataset(metadata.getRolePrivilegesHash(), - previousSettings.getCryptoSetting(), rolePrivilegePrefix, kvStorage, versioningKVStorage, readonly); - - String userRolePrefix = keyPrefix + USER_ROLE_PREFIX; - this.userRoles = new UserRoleDataset(metadata.getUserRolesHash(), previousSettings.getCryptoSetting(), - userRolePrefix, kvStorage, versioningKVStorage, readonly); - } - - private LedgerSettings loadAndVerifySettings(HashDigest settingsHash) { - if (settingsHash == null) { - return null; - } - Bytes key = encodeSettingsKey(settingsHash); - byte[] bytes = storage.get(key); - HashFunction hashFunc = Crypto.getHashFunction(settingsHash.getAlgorithm()); - if (!hashFunc.verify(settingsHash, bytes)) { - String errorMsg = "Verification of the hash for ledger setting failed! --[HASH=" + key + "]"; - LOGGER.error(errorMsg); - throw new LedgerException(errorMsg); - } - return deserializeSettings(bytes); - } - - private LedgerSettings deserializeSettings(byte[] bytes) { - return BinaryProtocol.decode(bytes); - } - - private byte[] serializeSetting(LedgerSettings setting) { - return BinaryProtocol.encode(setting, LedgerSettings.class); - } - - private LedgerMetadata_V2 loadAndVerifyMetadata(HashDigest adminAccountHash) { - Bytes key = encodeMetadataKey(adminAccountHash); - byte[] bytes = storage.get(key); - HashFunction hashFunc = Crypto.getHashFunction(adminAccountHash.getAlgorithm()); - if (!hashFunc.verify(adminAccountHash, bytes)) { - String errorMsg = "Verification of the hash for ledger metadata failed! --[HASH=" + key + "]"; - LOGGER.error(errorMsg); - throw new LedgerException(errorMsg); - } - return deserializeMetadata(bytes); - } - - private Bytes encodeSettingsKey(HashDigest settingsHash) { - return settingPrefix.concat(settingsHash); - } - - private Bytes encodeMetadataKey(HashDigest metadataHash) { - // return LEDGER_META_PREFIX + metadataHash; - // return metaPrefix + metadataHash; - return metaPrefix.concat(metadataHash); - } - - /* - * (non-Javadoc) - * - * @see com.jd.blockchain.ledger.core.LedgerAdministration#getMetadata() - */ - @Override - public LedgerMetadata_V2 getMetadata() { - return metadata; - } - -// /** -// * 返回原来的账本配置; -// * -// *
-// * 此方法总是返回从上一个区块加载的账本配置,即时调用 {@link #setLedgerSetting(LedgerSettings)} 做出了新的更改; -// * -// * @return -// */ -// public LedgerSettings getPreviousSetting() { -// return previousSettings; -// } - - /** - * 返回当前设置的账本配置; - * - * @return - */ - - @Override - public LedgerSettings getSettings() { - return settings; - } - - /** - * 更新账本配置; - * - * @param ledgerSetting - */ - public void setLedgerSetting(LedgerSettings ledgerSetting) { - if (readonly) { - throw new IllegalArgumentException("This merkle dataset is readonly!"); - } - settings = ledgerSetting; - updated = true; - } - - @Override - public long getParticipantCount() { - return participants.getParticipantCount(); - } - - @Override - public ParticipantNode[] getParticipants() { - return participants.getParticipants(); - } - - @Override - public ParticipantDataset getParticipantDataset() { - return participants; - } - - /** - * 加入新的参与方; 如果指定的参与方已经存在,则引发 LedgerException 异常; - * - * @param participant - */ - public void addParticipant(ParticipantNode participant) { - participants.addConsensusParticipant(participant); - } - - - /** - * 更新参与方的状态参数; - * - * @param participant - */ - public void updateParticipant(ParticipantNode participant) { - participants.updateConsensusParticipant(participant); - } - - @Override - public boolean isUpdated() { - return updated || participants.isUpdated() || rolePrivileges.isUpdated() || userRoles.isUpdated(); - } - - @Override - public void commit() { - if (!isUpdated()) { - return; - } - // 计算并更新参与方集合的根哈希; - participants.commit(); - metadata.setParticipantsHash(participants.getRootHash()); - - // 计算并更新角色权限集合的根哈希; - rolePrivileges.commit(); - metadata.setRolePrivilegesHash(rolePrivileges.getRootHash()); - - // 计算并更新用户角色授权集合的根哈希; - userRoles.commit(); - metadata.setUserRolesHash(userRoles.getRootHash()); - - // 当前区块上下文的密码参数设置的哈希函数; - HashFunction hashFunc = Crypto.getHashFunction(previousSettings.getCryptoSetting().getHashAlgorithm()); - - // 计算并更新参数配置的哈希; - if (settings == null) { - throw new LedgerException("Missing ledger settings!"); - } - byte[] settingsBytes = serializeSetting(settings); - HashDigest settingsHash = hashFunc.hash(settingsBytes); - metadata.setSettingsHash(settingsHash); - if (previousSettingHash == null || !previousSettingHash.equals(settingsHash)) { - Bytes settingsKey = encodeSettingsKey(settingsHash); - boolean nx = storage.set(settingsKey, settingsBytes, ExPolicy.NOT_EXISTING); - if (!nx) { - String base58MetadataHash = settingsHash.toBase58(); - // 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据; - String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]"; - LOGGER.warn(errMsg); - throw new LedgerException(errMsg); - } - } - - // 基于之前的密码配置来计算元数据的哈希; - byte[] metadataBytes = serializeMetadata(metadata); - - HashDigest metadataHash = hashFunc.hash(metadataBytes); - if (adminDataHash == null || !adminDataHash.equals(metadataHash)) { - // update modify; - // String base58MetadataHash = metadataHash.toBase58(); - // String metadataKey = encodeMetadataKey(base58MetadataHash); - Bytes metadataKey = encodeMetadataKey(metadataHash); - - boolean nx = storage.set(metadataKey, metadataBytes, ExPolicy.NOT_EXISTING); - if (!nx) { - String base58MetadataHash = metadataHash.toBase58(); - // 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据; - String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]"; - LOGGER.warn(errMsg); - throw new LedgerException(errMsg); - } - - adminDataHash = metadataHash; - } - - updated = false; - } - - private LedgerMetadata_V2 deserializeMetadata(byte[] bytes) { - return BinaryProtocol.decode(bytes); - } - - private byte[] serializeMetadata(LedgerMetadataInfo config) { - return BinaryProtocol.encode(config, LedgerMetadata_V2.class); - } - - @Override - public void cancel() { - if (!isUpdated()) { - return; - } - participants.cancel(); - metadata =origMetadata == null ? new LedgerMetadataInfo() : new LedgerMetadataInfo(origMetadata); - } - - public static class LedgerMetadataInfo implements LedgerMetadata_V2 { - - private byte[] seed; - -// private LedgerSetting setting; - - private HashDigest participantsHash; - - private HashDigest settingsHash; - - private HashDigest rolePrivilegesHash; - - private HashDigest userRolesHash; - - public LedgerMetadataInfo() { - } - - public LedgerMetadataInfo(LedgerMetadata_V2 metadata) { - this.seed = metadata.getSeed(); - this.participantsHash = metadata.getParticipantsHash(); - this.settingsHash = metadata.getSettingsHash(); - this.rolePrivilegesHash = metadata.getRolePrivilegesHash(); - this.userRolesHash = metadata.getUserRolesHash(); - } - - @Override - public byte[] getSeed() { - return seed; - } - - @Override - public HashDigest getSettingsHash() { - return settingsHash; - } - - @Override - public HashDigest getParticipantsHash() { - return participantsHash; - } - - @Override - public HashDigest getRolePrivilegesHash() { - return rolePrivilegesHash; - } - - @Override - public HashDigest getUserRolesHash() { - return userRolesHash; - } - - public void setSeed(byte[] seed) { - this.seed = seed; - } - - public void setSettingsHash(HashDigest settingHash) { - this.settingsHash = settingHash; - } - - public void setParticipantsHash(HashDigest participantsHash) { - this.participantsHash = participantsHash; - } - - public void setRolePrivilegesHash(HashDigest rolePrivilegesHash) { - this.rolePrivilegesHash = rolePrivilegesHash; - } - - public void setUserRolesHash(HashDigest userRolesHash) { - this.userRolesHash = userRolesHash; - } - } - +package com.jd.blockchain.ledger.core; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.HashFunction; +import com.jd.blockchain.ledger.LedgerAdminSettings; +import com.jd.blockchain.ledger.LedgerException; +import com.jd.blockchain.ledger.LedgerInitSetting; +import com.jd.blockchain.ledger.LedgerMetadata; +import com.jd.blockchain.ledger.LedgerMetadata_V2; +import com.jd.blockchain.ledger.LedgerSettings; +import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.ledger.RolePrivilegeSettings; +import com.jd.blockchain.ledger.UserAuthorizationSettings; +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.Transactional; + +public class LedgerAdminDataset implements Transactional, LedgerAdminDataQuery, LedgerAdminSettings { + + static { + DataContractRegistry.register(LedgerMetadata.class); + DataContractRegistry.register(LedgerMetadata_V2.class); + } + + private static Logger LOGGER = LoggerFactory.getLogger(LedgerAdminDataset.class); + + public static final String LEDGER_META_PREFIX = "MTA" + LedgerConsts.KEY_SEPERATOR; + public static final String LEDGER_PARTICIPANT_PREFIX = "PAR" + LedgerConsts.KEY_SEPERATOR; + public static final String LEDGER_SETTING_PREFIX = "SET" + LedgerConsts.KEY_SEPERATOR; + public static final String ROLE_PRIVILEGE_PREFIX = "RPV" + LedgerConsts.KEY_SEPERATOR; + public static final String USER_ROLE_PREFIX = "URO" + LedgerConsts.KEY_SEPERATOR; + + private final Bytes metaPrefix; + private final Bytes settingPrefix; + + private LedgerMetadata_V2 origMetadata; + + private LedgerMetadataInfo metadata; + + /** + * 原来的账本设置; + * + *
+ * 对 LedgerMetadata 修改的新配置不能立即生效,需要达成共识后,在下一次区块计算中才生效; + */ + private LedgerSettings previousSettings; + + private HashDigest previousSettingHash; + + /** + * 账本的参与节点; + */ + private ParticipantDataset participants; + + /** + * “角色-权限”数据集; + */ + private RolePrivilegeDataset rolePrivileges; + + /** + * “用户-角色”数据集; + */ + private UserRoleDataset userRoles; + + /** + * 账本参数配置; + */ + private LedgerSettings settings; + + private ExPolicyKVStorage storage; + + private HashDigest adminDataHash; + + private boolean readonly; + + private boolean updated; + + public HashDigest getHash() { + return adminDataHash; + } + + public boolean isReadonly() { + return readonly; + } + + void setReadonly() { + this.readonly = true; + } + + public LedgerSettings getPreviousSetting() { + return previousSettings; + } + + @Override + public RolePrivilegeSettings getRolePrivileges() { + return rolePrivileges; + } + + @Override + public UserAuthorizationSettings getAuthorizations() { + return userRoles; + } + + @Override + public LedgerAdminSettings getAdminInfo() { + return this; + } + + /** + * 初始化账本的管理账户; + * + *
+ * + * 只在新建账本时调用此方法; + * + * @param ledgerSeed + * @param settings + * @param partiList + * @param exPolicyStorage + * @param versioningStorage + */ + public LedgerAdminDataset(LedgerInitSetting initSetting, String keyPrefix, ExPolicyKVStorage exPolicyStorage, + VersioningKVStorage versioningStorage) { + this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX); + this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX); + + ParticipantNode[] parties = initSetting.getConsensusParticipants(); + if (parties.length == 0) { + throw new LedgerException("No participant!"); + } + + // 初始化元数据; + this.metadata = new LedgerMetadataInfo(); + this.metadata.setSeed(initSetting.getLedgerSeed()); + // 新配置; + this.settings = new LedgerConfiguration(initSetting.getConsensusProvider(), initSetting.getConsensusSettings(), + initSetting.getCryptoSetting()); + this.previousSettings = new LedgerConfiguration(settings); + this.previousSettingHash = null; + this.adminDataHash = null; + + // 基于原配置初始化参与者列表; + String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX; + this.participants = new ParticipantDataset(previousSettings.getCryptoSetting(), partiPrefix, exPolicyStorage, + versioningStorage); + + for (ParticipantNode p : parties) { + this.participants.addConsensusParticipant(p); + } + + String rolePrivilegePrefix = keyPrefix + ROLE_PRIVILEGE_PREFIX; + this.rolePrivileges = new RolePrivilegeDataset(this.settings.getCryptoSetting(), rolePrivilegePrefix, + exPolicyStorage, versioningStorage); + + String userRolePrefix = keyPrefix + USER_ROLE_PREFIX; + this.userRoles = new UserRoleDataset(this.settings.getCryptoSetting(), userRolePrefix, exPolicyStorage, + versioningStorage); + + // 初始化其它属性; + this.storage = exPolicyStorage; + this.readonly = false; + } + + public LedgerAdminDataset(HashDigest adminAccountHash, String keyPrefix, ExPolicyKVStorage kvStorage, + VersioningKVStorage versioningKVStorage, boolean readonly) { + this.metaPrefix = Bytes.fromString(keyPrefix + LEDGER_META_PREFIX); + this.settingPrefix = Bytes.fromString(keyPrefix + LEDGER_SETTING_PREFIX); + this.storage = kvStorage; + this.readonly = readonly; + this.origMetadata = loadAndVerifyMetadata(adminAccountHash); + this.metadata = new LedgerMetadataInfo(origMetadata); + this.settings = loadAndVerifySettings(metadata.getSettingsHash()); + // 复制记录一份配置作为上一个区块的原始配置,该实例仅供读取,不做修改,也不会回写到存储; + this.previousSettings = new LedgerConfiguration(settings); + this.previousSettingHash = metadata.getSettingsHash(); + this.adminDataHash = adminAccountHash; + + String partiPrefix = keyPrefix + LEDGER_PARTICIPANT_PREFIX; + this.participants = new ParticipantDataset(metadata.getParticipantsHash(), previousSettings.getCryptoSetting(), + partiPrefix, kvStorage, versioningKVStorage, readonly); + + String rolePrivilegePrefix = keyPrefix + ROLE_PRIVILEGE_PREFIX; + this.rolePrivileges = new RolePrivilegeDataset(metadata.getRolePrivilegesHash(), + previousSettings.getCryptoSetting(), rolePrivilegePrefix, kvStorage, versioningKVStorage, readonly); + + String userRolePrefix = keyPrefix + USER_ROLE_PREFIX; + this.userRoles = new UserRoleDataset(metadata.getUserRolesHash(), previousSettings.getCryptoSetting(), + userRolePrefix, kvStorage, versioningKVStorage, readonly); + } + + private LedgerSettings loadAndVerifySettings(HashDigest settingsHash) { + if (settingsHash == null) { + return null; + } + Bytes key = encodeSettingsKey(settingsHash); + byte[] bytes = storage.get(key); + HashFunction hashFunc = Crypto.getHashFunction(settingsHash.getAlgorithm()); + if (!hashFunc.verify(settingsHash, bytes)) { + String errorMsg = "Verification of the hash for ledger setting failed! --[HASH=" + key + "]"; + LOGGER.error(errorMsg); + throw new LedgerException(errorMsg); + } + return deserializeSettings(bytes); + } + + private LedgerSettings deserializeSettings(byte[] bytes) { + return BinaryProtocol.decode(bytes); + } + + private byte[] serializeSetting(LedgerSettings setting) { + return BinaryProtocol.encode(setting, LedgerSettings.class); + } + + private LedgerMetadata_V2 loadAndVerifyMetadata(HashDigest adminAccountHash) { + Bytes key = encodeMetadataKey(adminAccountHash); + byte[] bytes = storage.get(key); + HashFunction hashFunc = Crypto.getHashFunction(adminAccountHash.getAlgorithm()); + if (!hashFunc.verify(adminAccountHash, bytes)) { + String errorMsg = "Verification of the hash for ledger metadata failed! --[HASH=" + key + "]"; + LOGGER.error(errorMsg); + throw new LedgerException(errorMsg); + } + return deserializeMetadata(bytes); + } + + private Bytes encodeSettingsKey(HashDigest settingsHash) { + return settingPrefix.concat(settingsHash); + } + + private Bytes encodeMetadataKey(HashDigest metadataHash) { + // return LEDGER_META_PREFIX + metadataHash; + // return metaPrefix + metadataHash; + return metaPrefix.concat(metadataHash); + } + + /* + * (non-Javadoc) + * + * @see com.jd.blockchain.ledger.core.LedgerAdministration#getMetadata() + */ + @Override + public LedgerMetadata_V2 getMetadata() { + return metadata; + } + +// /** +// * 返回原来的账本配置; +// * +// *
+// * 此方法总是返回从上一个区块加载的账本配置,即时调用 {@link #setLedgerSetting(LedgerSettings)} 做出了新的更改; +// * +// * @return +// */ +// public LedgerSettings getPreviousSetting() { +// return previousSettings; +// } + + /** + * 返回当前设置的账本配置; + * + * @return + */ + + @Override + public LedgerSettings getSettings() { + return settings; + } + + /** + * 更新账本配置; + * + * @param ledgerSetting + */ + public void setLedgerSetting(LedgerSettings ledgerSetting) { + if (readonly) { + throw new IllegalArgumentException("This merkle dataset is readonly!"); + } + settings = ledgerSetting; + updated = true; + } + + @Override + public long getParticipantCount() { + return participants.getParticipantCount(); + } + + @Override + public ParticipantNode[] getParticipants() { + return participants.getParticipants(); + } + + @Override + public ParticipantDataset getParticipantDataset() { + return participants; + } + + /** + * 加入新的参与方; 如果指定的参与方已经存在,则引发 LedgerException 异常; + * + * @param participant + */ + public void addParticipant(ParticipantNode participant) { + participants.addConsensusParticipant(participant); + } + + + /** + * 更新参与方的状态参数; + * + * @param participant + */ + public void updateParticipant(ParticipantNode participant) { + participants.updateConsensusParticipant(participant); + } + + @Override + public boolean isUpdated() { + return updated || participants.isUpdated() || rolePrivileges.isUpdated() || userRoles.isUpdated(); + } + + @Override + public void commit() { + if (!isUpdated()) { + return; + } + // 计算并更新参与方集合的根哈希; + participants.commit(); + metadata.setParticipantsHash(participants.getRootHash()); + + // 计算并更新角色权限集合的根哈希; + rolePrivileges.commit(); + metadata.setRolePrivilegesHash(rolePrivileges.getRootHash()); + + // 计算并更新用户角色授权集合的根哈希; + userRoles.commit(); + metadata.setUserRolesHash(userRoles.getRootHash()); + + // 当前区块上下文的密码参数设置的哈希函数; + HashFunction hashFunc = Crypto.getHashFunction(previousSettings.getCryptoSetting().getHashAlgorithm()); + + // 计算并更新参数配置的哈希; + if (settings == null) { + throw new LedgerException("Missing ledger settings!"); + } + byte[] settingsBytes = serializeSetting(settings); + HashDigest settingsHash = hashFunc.hash(settingsBytes); + metadata.setSettingsHash(settingsHash); + if (previousSettingHash == null || !previousSettingHash.equals(settingsHash)) { + Bytes settingsKey = encodeSettingsKey(settingsHash); + boolean nx = storage.set(settingsKey, settingsBytes, ExPolicy.NOT_EXISTING); + if (!nx) { + String base58MetadataHash = settingsHash.toBase58(); + // 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据; + String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]"; + LOGGER.warn(errMsg); + throw new LedgerException(errMsg); + } + } + + // 基于之前的密码配置来计算元数据的哈希; + byte[] metadataBytes = serializeMetadata(metadata); + + HashDigest metadataHash = hashFunc.hash(metadataBytes); + if (adminDataHash == null || !adminDataHash.equals(metadataHash)) { + // update modify; + // String base58MetadataHash = metadataHash.toBase58(); + // String metadataKey = encodeMetadataKey(base58MetadataHash); + Bytes metadataKey = encodeMetadataKey(metadataHash); + + boolean nx = storage.set(metadataKey, metadataBytes, ExPolicy.NOT_EXISTING); + if (!nx) { + String base58MetadataHash = metadataHash.toBase58(); + // 有可能发生了并发写入冲突,不同的节点都向同一个存储服务器上写入数据; + String errMsg = "Ledger metadata already exist! --[MetadataHash=" + base58MetadataHash + "]"; + LOGGER.warn(errMsg); + throw new LedgerException(errMsg); + } + + adminDataHash = metadataHash; + } + + updated = false; + } + + private LedgerMetadata_V2 deserializeMetadata(byte[] bytes) { + return BinaryProtocol.decode(bytes); + } + + private byte[] serializeMetadata(LedgerMetadataInfo config) { + return BinaryProtocol.encode(config, LedgerMetadata_V2.class); + } + + @Override + public void cancel() { + if (!isUpdated()) { + return; + } + participants.cancel(); + metadata =origMetadata == null ? new LedgerMetadataInfo() : new LedgerMetadataInfo(origMetadata); + } + + public static class LedgerMetadataInfo implements LedgerMetadata_V2 { + + private byte[] seed; + +// private LedgerSetting setting; + + private HashDigest participantsHash; + + private HashDigest settingsHash; + + private HashDigest rolePrivilegesHash; + + private HashDigest userRolesHash; + + public LedgerMetadataInfo() { + } + + public LedgerMetadataInfo(LedgerMetadata_V2 metadata) { + this.seed = metadata.getSeed(); + this.participantsHash = metadata.getParticipantsHash(); + this.settingsHash = metadata.getSettingsHash(); + this.rolePrivilegesHash = metadata.getRolePrivilegesHash(); + this.userRolesHash = metadata.getUserRolesHash(); + } + + @Override + public byte[] getSeed() { + return seed; + } + + @Override + public HashDigest getSettingsHash() { + return settingsHash; + } + + @Override + public HashDigest getParticipantsHash() { + return participantsHash; + } + + @Override + public HashDigest getRolePrivilegesHash() { + return rolePrivilegesHash; + } + + @Override + public HashDigest getUserRolesHash() { + return userRolesHash; + } + + public void setSeed(byte[] seed) { + this.seed = seed; + } + + public void setSettingsHash(HashDigest settingHash) { + this.settingsHash = settingHash; + } + + public void setParticipantsHash(HashDigest participantsHash) { + this.participantsHash = participantsHash; + } + + public void setRolePrivilegesHash(HashDigest rolePrivilegesHash) { + this.rolePrivilegesHash = rolePrivilegesHash; + } + + public void setUserRolesHash(HashDigest userRolesHash) { + this.userRolesHash = userRolesHash; + } + } + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java index 8f46e235..ea0159fa 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleAccountSet.java @@ -1,411 +1,411 @@ -package com.jd.blockchain.ledger.core; - -import java.util.HashMap; -import java.util.Map; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.AddressEncoding; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.BlockchainIdentityData; -import com.jd.blockchain.ledger.CryptoSetting; -import com.jd.blockchain.ledger.LedgerException; -import com.jd.blockchain.ledger.MerkleProof; -import com.jd.blockchain.ledger.MerkleSnapshot; -import com.jd.blockchain.ledger.TypedValue; -import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.VersioningKVStorage; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.DataEntry; -import com.jd.blockchain.utils.Transactional; - -public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery { - - static { - DataContractRegistry.register(MerkleSnapshot.class); - DataContractRegistry.register(BlockchainIdentity.class); - } - - private final Bytes keyPrefix; - - /** - * 账户根哈希的数据集; - */ - private MerkleDataSet merkleDataset; - - /** - * The cache of latest version accounts, including accounts getting by querying - * and by new regiestering ; - * - */ - // TODO:未考虑大数据量时,由于缺少过期策略,会导致内存溢出的问题; - private Map latestAccountsCache = new HashMap<>(); - - private ExPolicyKVStorage baseExStorage; - - private VersioningKVStorage baseVerStorage; - - private CryptoSetting cryptoSetting; - - private volatile boolean updated; - - private AccountAccessPolicy accessPolicy; - - public boolean isReadonly() { - return merkleDataset.isReadonly(); - } - - void setReadonly() { - merkleDataset.setReadonly(); - } - - public MerkleAccountSet(CryptoSetting cryptoSetting, Bytes keyPrefix, ExPolicyKVStorage exStorage, - VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { - this(null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy); - } - - public MerkleAccountSet(HashDigest rootHash, CryptoSetting cryptoSetting, Bytes keyPrefix, - ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, - AccountAccessPolicy accessPolicy) { - this.keyPrefix = keyPrefix; - this.cryptoSetting = cryptoSetting; - this.baseExStorage = exStorage; - this.baseVerStorage = verStorage; - this.merkleDataset = new MerkleDataSet(rootHash, cryptoSetting, keyPrefix, this.baseExStorage, - this.baseVerStorage, readonly); - - this.accessPolicy = accessPolicy; - } - - @Override - public HashDigest getRootHash() { - return merkleDataset.getRootHash(); - } - - @Override - public MerkleProof getProof(Bytes key) { - return merkleDataset.getProof(key); - } - - @Override - public BlockchainIdentity[] getHeaders(int fromIndex, int count) { - DataEntry[] results = merkleDataset.getLatestDataEntries(fromIndex, count); - - BlockchainIdentity[] ids = new BlockchainIdentity[results.length]; - for (int i = 0; i < results.length; i++) { - InnerMerkleAccount account = createAccount(results[i].getKey(), new HashDigest(results[i].getValue()), - results[i].getVersion(), true); - ids[i] = account.getID(); - } - return ids; - } - - /** - * 返回账户的总数量; - * - * @return - */ - public long getTotal() { - return merkleDataset.getDataCount(); - } - - @Override - public CompositeAccount getAccount(String address) { - return getAccount(Bytes.fromBase58(address)); - } - - /** - * 返回最新版本的 Account; - * - * @param address - * @return - */ - @Override - public CompositeAccount getAccount(Bytes address) { - return this.getAccount(address, -1); - } - - /** - * 账户是否存在;
- * - * 如果指定的账户已经注册(通过 {@link #register(String, PubKey)} 方法),但尚未提交(通过 - * {@link #commit()} 方法),此方法对该账户仍然返回 false; - * - * @param address - * @return - */ - public boolean contains(Bytes address) { - InnerMerkleAccount acc = latestAccountsCache.get(address); - if (acc != null) { - // 无论是新注册未提交的,还是缓存已提交的账户实例,都认为是存在; - return true; - } - long latestVersion = merkleDataset.getVersion(address); - return latestVersion > -1; - } - - /** - * 返回指定账户的版本;
- * 如果账户已经注册,则返回该账户的最新版本,值大于等于 0;
- * 如果账户不存在,则返回 -1;
- * 如果账户已经注册(通过 {@link #register(String, PubKey)} 方法),但尚未提交(通过 {@link #commit()} - * 方法),则返回 -1;
- * - * @param address - * @return - */ - public long getVersion(Bytes address) { - InnerMerkleAccount acc = latestAccountsCache.get(address); - if (acc != null) { - // 已注册尚未提交,也返回 -1; - return acc.getVersion(); - } - - return merkleDataset.getVersion(address); - } - - /** - * 返回指定版本的 Account; - * - * 只有最新版本的账户才能可写的,其它都是只读; - * - * @param address 账户地址; - * @param version 账户版本;如果指定为 -1,则返回最新版本; - * @return - */ - public CompositeAccount getAccount(Bytes address, long version) { - version = version < 0 ? -1 : version; - InnerMerkleAccount acc = latestAccountsCache.get(address); - if (acc != null && version == -1) { - return acc; - } else if (acc != null && acc.getVersion() == version) { - return acc; - } - - long latestVersion = merkleDataset.getVersion(address); - if (latestVersion < 0) { - // Not exist; - return null; - } - if (version > latestVersion) { - return null; - } - - // 如果是不存在的,或者刚刚新增未提交的账户,则前面一步查询到的 latestVersion 小于 0, 代码不会执行到此; - if (acc != null && acc.getVersion() != latestVersion) { - // 当执行到此处时,并且缓冲列表中缓存了最新的版本, - // 如果当前缓存的最新账户的版本和刚刚从存储中检索得到的最新版本不一致,可能存在外部的并发更新,这超出了系统设计的逻辑; - - // TODO:如果是今后扩展至集群方案时,这种不一致的原因可能是由其它集群节点实例执行了更新,这种情况下,最好是放弃旧缓存,并重新加载和缓存最新版本; - // by huanghaiquan at 2018-9-2 23:03:00; - throw new IllegalStateException("The latest version in cache is not equals the latest version in storage! " - + "Mybe some asynchronzing updating are performed out of current server."); - } - - // Now, be sure that "acc == null", so get account from storage; - // Set readonly for the old version account; - boolean readonly = (version > -1 && version < latestVersion) || isReadonly(); - - long qVersion = version == -1 ? latestVersion : version; - // load account from storage; - acc = loadAccount(address, readonly, qVersion); - if (acc == null) { - return null; - } - if (!readonly) { - // cache the latest version witch enable reading and writing; - // readonly version of account not necessary to be cached; - latestAccountsCache.put(address, acc); - } - return acc; - } - - public CompositeAccount register(Bytes address, PubKey pubKey) { - return register(new BlockchainIdentityData(address, pubKey)); - } - - /** - * 注册一个新账户;
- * - * 如果账户已经存在,则会引发 {@link LedgerException} 异常;
- * - * 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常; - * - * @param address 区块链地址; - * @param pubKey 公钥; - * @return 注册成功的账户对象; - */ - public CompositeAccount register(BlockchainIdentity accountId) { - if (isReadonly()) { - throw new IllegalArgumentException("This AccountSet is readonly!"); - } - - Bytes address = accountId.getAddress(); - PubKey pubKey = accountId.getPubKey(); - verifyAddressEncoding(address, pubKey); - - InnerMerkleAccount cachedAcc = latestAccountsCache.get(address); - if (cachedAcc != null) { - if (cachedAcc.getVersion() < 0) { - // 同一个新账户已经注册,但尚未提交,所以重复注册不会引起任何变化; - return cachedAcc; - } - // 相同的账户已经存在; - throw new LedgerException("The registering account already exist!"); - } - long version = merkleDataset.getVersion(address); - if (version >= 0) { - throw new LedgerException("The registering account already exist!"); - } - - if (!accessPolicy.checkRegistering(address, pubKey)) { - throw new LedgerException("Account Registering was rejected for the access policy!"); - } - - Bytes prefix = keyPrefix.concat(address); - InnerMerkleAccount acc = createInstance(accountId, cryptoSetting, prefix); - latestAccountsCache.put(address, acc); - updated = true; - - return acc; - } - - private void verifyAddressEncoding(Bytes address, PubKey pubKey) { - Bytes chAddress = AddressEncoding.generateAddress(pubKey); - if (!chAddress.equals(address)) { - throw new LedgerException("The registering Address mismatch the specified PubKey!"); - } - } - - private InnerMerkleAccount createInstance(BlockchainIdentity header, CryptoSetting cryptoSetting, Bytes keyPrefix) { - return new InnerMerkleAccount(header, cryptoSetting, keyPrefix, baseExStorage, baseVerStorage); - } - - /** - * 加载指定版本的账户; - * - * @param address 账户地址; - * @param readonly 是否只读; - * @param version 账户的版本;大于等于 0 ; - * @return - */ - private InnerMerkleAccount loadAccount(Bytes address, boolean readonly, long version) { - byte[] rootHashBytes = merkleDataset.getValue(address, version); - if (rootHashBytes == null) { - return null; - } - HashDigest rootHash = new HashDigest(rootHashBytes); - - return createAccount(address, rootHash, version, readonly); - } - - private InnerMerkleAccount createAccount(Bytes address, HashDigest rootHash, long version, boolean readonly) { - // prefix; - Bytes prefix = keyPrefix.concat(address); - - return new InnerMerkleAccount(address, version, rootHash, cryptoSetting, prefix, baseExStorage, baseVerStorage, - readonly); - } - - // TODO:优化:区块链身份(地址+公钥)与其Merkle树根哈希分开独立存储; - // 不必作为一个整块,避免状态数据写入时频繁重写公钥,尤其某些算法的公钥可能很大; - - /** - * 保存账户的根哈希,返回账户的新版本; - * - * @param account - * @return - */ - private long saveAccount(InnerMerkleAccount account) { - // 提交更改,更新哈希; - account.commit(); - - return account.getVersion(); - } - - @Override - public boolean isUpdated() { - return updated; - } - - @Override - public void commit() { - if (!updated) { - return; - } - try { - for (InnerMerkleAccount acc : latestAccountsCache.values()) { - // updated or new created; - if (acc.isUpdated() || acc.getVersion() < 0) { - saveAccount(acc); - } - } - merkleDataset.commit(); - } finally { - updated = false; - latestAccountsCache.clear(); - } - } - - @Override - public void cancel() { - if (!updated) { - return; - } - Bytes[] addresses = new Bytes[latestAccountsCache.size()]; - latestAccountsCache.keySet().toArray(addresses); - for (Bytes address : addresses) { - InnerMerkleAccount acc = latestAccountsCache.remove(address); - // cancel; - if (acc.isUpdated()) { - acc.cancel(); - } - } - updated = false; - } - - /** - * 内部实现的账户,监听和同步账户数据的变更; - * - * @author huanghaiquan - * - */ - private class InnerMerkleAccount extends MerkleAccount { - - private long version; - - public InnerMerkleAccount(BlockchainIdentity accountID, CryptoSetting cryptoSetting, Bytes keyPrefix, - ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { - super(accountID, cryptoSetting, keyPrefix, exStorage, verStorage); - this.version = -1; - } - - public InnerMerkleAccount(Bytes address, long version, HashDigest dataRootHash, CryptoSetting cryptoSetting, - Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { - super(address, dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); - this.version = version; - } - - @Override - protected void onUpdated(String key, TypedValue value, long expectedVersion, long newVersion) { - updated = true; - } - - @Override - protected void onCommited(HashDigest previousRootHash, HashDigest newRootHash) { - long newVersion = merkleDataset.setValue(this.getAddress(), newRootHash.toBytes(), version); - if (newVersion < 0) { - // Update fail; - throw new LedgerException("Account updating fail! --[Address=" + this.getAddress() + "]"); - } - this.version = newVersion; - } - - public long getVersion() { - return version; - } - - } - +package com.jd.blockchain.ledger.core; + +import java.util.HashMap; +import java.util.Map; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.BlockchainIdentityData; +import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.LedgerException; +import com.jd.blockchain.ledger.MerkleProof; +import com.jd.blockchain.ledger.MerkleSnapshot; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; +import com.jd.blockchain.utils.Transactional; + +public class MerkleAccountSet implements Transactional, MerkleProvable, AccountQuery { + + static { + DataContractRegistry.register(MerkleSnapshot.class); + DataContractRegistry.register(BlockchainIdentity.class); + } + + private final Bytes keyPrefix; + + /** + * 账户根哈希的数据集; + */ + private MerkleDataSet merkleDataset; + + /** + * The cache of latest version accounts, including accounts getting by querying + * and by new regiestering ; + * + */ + // TODO:未考虑大数据量时,由于缺少过期策略,会导致内存溢出的问题; + private Map latestAccountsCache = new HashMap<>(); + + private ExPolicyKVStorage baseExStorage; + + private VersioningKVStorage baseVerStorage; + + private CryptoSetting cryptoSetting; + + private volatile boolean updated; + + private AccountAccessPolicy accessPolicy; + + public boolean isReadonly() { + return merkleDataset.isReadonly(); + } + + void setReadonly() { + merkleDataset.setReadonly(); + } + + public MerkleAccountSet(CryptoSetting cryptoSetting, Bytes keyPrefix, ExPolicyKVStorage exStorage, + VersioningKVStorage verStorage, AccountAccessPolicy accessPolicy) { + this(null, cryptoSetting, keyPrefix, exStorage, verStorage, false, accessPolicy); + } + + public MerkleAccountSet(HashDigest rootHash, CryptoSetting cryptoSetting, Bytes keyPrefix, + ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, + AccountAccessPolicy accessPolicy) { + this.keyPrefix = keyPrefix; + this.cryptoSetting = cryptoSetting; + this.baseExStorage = exStorage; + this.baseVerStorage = verStorage; + this.merkleDataset = new MerkleDataSet(rootHash, cryptoSetting, keyPrefix, this.baseExStorage, + this.baseVerStorage, readonly); + + this.accessPolicy = accessPolicy; + } + + @Override + public HashDigest getRootHash() { + return merkleDataset.getRootHash(); + } + + @Override + public MerkleProof getProof(Bytes key) { + return merkleDataset.getProof(key); + } + + @Override + public BlockchainIdentity[] getHeaders(int fromIndex, int count) { + DataEntry[] results = merkleDataset.getLatestDataEntries(fromIndex, count); + + BlockchainIdentity[] ids = new BlockchainIdentity[results.length]; + for (int i = 0; i < results.length; i++) { + InnerMerkleAccount account = createAccount(results[i].getKey(), new HashDigest(results[i].getValue()), + results[i].getVersion(), true); + ids[i] = account.getID(); + } + return ids; + } + + /** + * 返回账户的总数量; + * + * @return + */ + public long getTotal() { + return merkleDataset.getDataCount(); + } + + @Override + public CompositeAccount getAccount(String address) { + return getAccount(Bytes.fromBase58(address)); + } + + /** + * 返回最新版本的 Account; + * + * @param address + * @return + */ + @Override + public CompositeAccount getAccount(Bytes address) { + return this.getAccount(address, -1); + } + + /** + * 账户是否存在;
+ * + * 如果指定的账户已经注册(通过 {@link #register(String, PubKey)} 方法),但尚未提交(通过 + * {@link #commit()} 方法),此方法对该账户仍然返回 false; + * + * @param address + * @return + */ + public boolean contains(Bytes address) { + InnerMerkleAccount acc = latestAccountsCache.get(address); + if (acc != null) { + // 无论是新注册未提交的,还是缓存已提交的账户实例,都认为是存在; + return true; + } + long latestVersion = merkleDataset.getVersion(address); + return latestVersion > -1; + } + + /** + * 返回指定账户的版本;
+ * 如果账户已经注册,则返回该账户的最新版本,值大于等于 0;
+ * 如果账户不存在,则返回 -1;
+ * 如果账户已经注册(通过 {@link #register(String, PubKey)} 方法),但尚未提交(通过 {@link #commit()} + * 方法),则返回 -1;
+ * + * @param address + * @return + */ + public long getVersion(Bytes address) { + InnerMerkleAccount acc = latestAccountsCache.get(address); + if (acc != null) { + // 已注册尚未提交,也返回 -1; + return acc.getVersion(); + } + + return merkleDataset.getVersion(address); + } + + /** + * 返回指定版本的 Account; + * + * 只有最新版本的账户才能可写的,其它都是只读; + * + * @param address 账户地址; + * @param version 账户版本;如果指定为 -1,则返回最新版本; + * @return + */ + public CompositeAccount getAccount(Bytes address, long version) { + version = version < 0 ? -1 : version; + InnerMerkleAccount acc = latestAccountsCache.get(address); + if (acc != null && version == -1) { + return acc; + } else if (acc != null && acc.getVersion() == version) { + return acc; + } + + long latestVersion = merkleDataset.getVersion(address); + if (latestVersion < 0) { + // Not exist; + return null; + } + if (version > latestVersion) { + return null; + } + + // 如果是不存在的,或者刚刚新增未提交的账户,则前面一步查询到的 latestVersion 小于 0, 代码不会执行到此; + if (acc != null && acc.getVersion() != latestVersion) { + // 当执行到此处时,并且缓冲列表中缓存了最新的版本, + // 如果当前缓存的最新账户的版本和刚刚从存储中检索得到的最新版本不一致,可能存在外部的并发更新,这超出了系统设计的逻辑; + + // TODO:如果是今后扩展至集群方案时,这种不一致的原因可能是由其它集群节点实例执行了更新,这种情况下,最好是放弃旧缓存,并重新加载和缓存最新版本; + // by huanghaiquan at 2018-9-2 23:03:00; + throw new IllegalStateException("The latest version in cache is not equals the latest version in storage! " + + "Mybe some asynchronzing updating are performed out of current server."); + } + + // Now, be sure that "acc == null", so get account from storage; + // Set readonly for the old version account; + boolean readonly = (version > -1 && version < latestVersion) || isReadonly(); + + long qVersion = version == -1 ? latestVersion : version; + // load account from storage; + acc = loadAccount(address, readonly, qVersion); + if (acc == null) { + return null; + } + if (!readonly) { + // cache the latest version witch enable reading and writing; + // readonly version of account not necessary to be cached; + latestAccountsCache.put(address, acc); + } + return acc; + } + + public CompositeAccount register(Bytes address, PubKey pubKey) { + return register(new BlockchainIdentityData(address, pubKey)); + } + + /** + * 注册一个新账户;
+ * + * 如果账户已经存在,则会引发 {@link LedgerException} 异常;
+ * + * 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常; + * + * @param address 区块链地址; + * @param pubKey 公钥; + * @return 注册成功的账户对象; + */ + public CompositeAccount register(BlockchainIdentity accountId) { + if (isReadonly()) { + throw new IllegalArgumentException("This AccountSet is readonly!"); + } + + Bytes address = accountId.getAddress(); + PubKey pubKey = accountId.getPubKey(); + verifyAddressEncoding(address, pubKey); + + InnerMerkleAccount cachedAcc = latestAccountsCache.get(address); + if (cachedAcc != null) { + if (cachedAcc.getVersion() < 0) { + // 同一个新账户已经注册,但尚未提交,所以重复注册不会引起任何变化; + return cachedAcc; + } + // 相同的账户已经存在; + throw new LedgerException("The registering account already exist!"); + } + long version = merkleDataset.getVersion(address); + if (version >= 0) { + throw new LedgerException("The registering account already exist!"); + } + + if (!accessPolicy.checkRegistering(address, pubKey)) { + throw new LedgerException("Account Registering was rejected for the access policy!"); + } + + Bytes prefix = keyPrefix.concat(address); + InnerMerkleAccount acc = createInstance(accountId, cryptoSetting, prefix); + latestAccountsCache.put(address, acc); + updated = true; + + return acc; + } + + private void verifyAddressEncoding(Bytes address, PubKey pubKey) { + Bytes chAddress = AddressEncoding.generateAddress(pubKey); + if (!chAddress.equals(address)) { + throw new LedgerException("The registering Address mismatch the specified PubKey!"); + } + } + + private InnerMerkleAccount createInstance(BlockchainIdentity header, CryptoSetting cryptoSetting, Bytes keyPrefix) { + return new InnerMerkleAccount(header, cryptoSetting, keyPrefix, baseExStorage, baseVerStorage); + } + + /** + * 加载指定版本的账户; + * + * @param address 账户地址; + * @param readonly 是否只读; + * @param version 账户的版本;大于等于 0 ; + * @return + */ + private InnerMerkleAccount loadAccount(Bytes address, boolean readonly, long version) { + byte[] rootHashBytes = merkleDataset.getValue(address, version); + if (rootHashBytes == null) { + return null; + } + HashDigest rootHash = new HashDigest(rootHashBytes); + + return createAccount(address, rootHash, version, readonly); + } + + private InnerMerkleAccount createAccount(Bytes address, HashDigest rootHash, long version, boolean readonly) { + // prefix; + Bytes prefix = keyPrefix.concat(address); + + return new InnerMerkleAccount(address, version, rootHash, cryptoSetting, prefix, baseExStorage, baseVerStorage, + readonly); + } + + // TODO:优化:区块链身份(地址+公钥)与其Merkle树根哈希分开独立存储; + // 不必作为一个整块,避免状态数据写入时频繁重写公钥,尤其某些算法的公钥可能很大; + + /** + * 保存账户的根哈希,返回账户的新版本; + * + * @param account + * @return + */ + private long saveAccount(InnerMerkleAccount account) { + // 提交更改,更新哈希; + account.commit(); + + return account.getVersion(); + } + + @Override + public boolean isUpdated() { + return updated; + } + + @Override + public void commit() { + if (!updated) { + return; + } + try { + for (InnerMerkleAccount acc : latestAccountsCache.values()) { + // updated or new created; + if (acc.isUpdated() || acc.getVersion() < 0) { + saveAccount(acc); + } + } + merkleDataset.commit(); + } finally { + updated = false; + latestAccountsCache.clear(); + } + } + + @Override + public void cancel() { + if (!updated) { + return; + } + Bytes[] addresses = new Bytes[latestAccountsCache.size()]; + latestAccountsCache.keySet().toArray(addresses); + for (Bytes address : addresses) { + InnerMerkleAccount acc = latestAccountsCache.remove(address); + // cancel; + if (acc.isUpdated()) { + acc.cancel(); + } + } + updated = false; + } + + /** + * 内部实现的账户,监听和同步账户数据的变更; + * + * @author huanghaiquan + * + */ + private class InnerMerkleAccount extends MerkleAccount { + + private long version; + + public InnerMerkleAccount(BlockchainIdentity accountID, CryptoSetting cryptoSetting, Bytes keyPrefix, + ExPolicyKVStorage exStorage, VersioningKVStorage verStorage) { + super(accountID, cryptoSetting, keyPrefix, exStorage, verStorage); + this.version = -1; + } + + public InnerMerkleAccount(Bytes address, long version, HashDigest dataRootHash, CryptoSetting cryptoSetting, + Bytes keyPrefix, ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly) { + super(address, dataRootHash, cryptoSetting, keyPrefix, exStorage, verStorage, readonly); + this.version = version; + } + + @Override + protected void onUpdated(String key, TypedValue value, long expectedVersion, long newVersion) { + updated = true; + } + + @Override + protected void onCommited(HashDigest previousRootHash, HashDigest newRootHash) { + long newVersion = merkleDataset.setValue(this.getAddress(), newRootHash.toBytes(), version); + if (newVersion < 0) { + // Update fail; + throw new LedgerException("Account updating fail! --[Address=" + this.getAddress() + "]"); + } + this.version = newVersion; + } + + public long getVersion() { + return version; + } + + } + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java index 80217efe..4b546404 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/MerkleDataSet.java @@ -1,740 +1,740 @@ -package com.jd.blockchain.ledger.core; - -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.CryptoSetting; -import com.jd.blockchain.ledger.LedgerException; -import com.jd.blockchain.ledger.MerkleDataNode; -import com.jd.blockchain.ledger.MerkleProof; -import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; -import com.jd.blockchain.storage.service.VersioningKVStorage; -import com.jd.blockchain.storage.service.utils.BufferedKVStorage; -import com.jd.blockchain.storage.service.utils.VersioningKVData; -import com.jd.blockchain.utils.ArrayUtils; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.DataEntry; -import com.jd.blockchain.utils.DataIterator; -import com.jd.blockchain.utils.Dataset; -import com.jd.blockchain.utils.Transactional; -import com.jd.blockchain.utils.io.BytesUtils; - -/** - * 对新的数据项按顺序递增进行编号的 Merkle 数据集;
- * - * 注:此实现不是线程安全的; - * - * @author huanghaiquan - * - */ -public class MerkleDataSet implements Transactional, MerkleProvable, Dataset { - - /** - * 4 MB MaxSize of value; - */ - public static final int MAX_SIZE_OF_VALUE = 4 * 1024 * 1024; - - public static final Bytes SN_PREFIX = Bytes.fromString("SN" + LedgerConsts.KEY_SEPERATOR); - public static final Bytes DATA_PREFIX = Bytes.fromString("KV" + LedgerConsts.KEY_SEPERATOR); - public static final Bytes MERKLE_TREE_PREFIX = Bytes.fromString("MKL" + LedgerConsts.KEY_SEPERATOR); - - private final Bytes snKeyPrefix; - private final Bytes dataKeyPrefix; - private final Bytes merkleKeyPrefix; - - @SuppressWarnings("unchecked") - private static final DataEntry[] EMPTY_ENTRIES = new DataEntry[0]; - - private BufferedKVStorage bufferedStorage; - - private VersioningKVStorage valueStorage; - - private ExPolicyKVStorage snStorage; - - private MerkleTree merkleTree; - - private SNGenerator snGenerator; - - private boolean readonly; - - /* - * (non-Javadoc) - * - * @see com.jd.blockchain.ledger.core.MerkleProvable#getRootHash() - */ - @Override - public HashDigest getRootHash() { - return merkleTree.getRootHash(); - } - - /** - * 创建一个新的 MerkleDataSet; - * - * @param setting 密码设置; - * @param exPolicyStorage 默克尔树的存储; - * @param versioningStorage 数据的存储; - */ - public MerkleDataSet(CryptoSetting setting, String keyPrefix, ExPolicyKVStorage exPolicyStorage, - VersioningKVStorage versioningStorage) { - this(setting, Bytes.fromString(keyPrefix), exPolicyStorage, versioningStorage); - } - - /** - * 创建一个新的 MerkleDataSet; - * - * @param setting 密码设置; - * @param exPolicyStorage 默克尔树的存储; - * @param versioningStorage 数据的存储; - */ - public MerkleDataSet(CryptoSetting setting, Bytes keyPrefix, ExPolicyKVStorage exPolicyStorage, - VersioningKVStorage versioningStorage) { - // 缓冲对KV的写入; - this.bufferedStorage = new BufferedKVStorage(exPolicyStorage, versioningStorage, false); - - // 把存储数据值、SN、Merkle节点的 key 分别加入独立的前缀,避免针对 key 的注入攻击; - // this.valueStorage = PrefixAppender.prefix(DATA_PREFIX, (VersioningKVStorage) - // bufferedStorage); - // this.snStorage = PrefixAppender.prefix(SN_PREFIX, (ExPolicyKVStorage) - // bufferedStorage); - snKeyPrefix = keyPrefix.concat(SN_PREFIX); - dataKeyPrefix = keyPrefix.concat(DATA_PREFIX); - this.valueStorage = bufferedStorage; - this.snStorage = bufferedStorage; - - // MerkleTree 本身是可缓冲的; - // ExPolicyKVStorage merkleTreeStorage = - // PrefixAppender.prefix(MERKLE_TREE_PREFIX, exPolicyStorage); - merkleKeyPrefix = keyPrefix.concat(MERKLE_TREE_PREFIX); - ExPolicyKVStorage merkleTreeStorage = exPolicyStorage; - this.merkleTree = new MerkleTree(setting, merkleKeyPrefix, merkleTreeStorage); - this.snGenerator = new MerkleSequenceSNGenerator(merkleTree); - } - - /** - * 从指定的 Merkle 根构建的 MerkleDataSet; - * - * @param dataStorage - * @param defaultMerkleHashAlgorithm - * @param verifyMerkleHashOnLoad - * @param merkleTreeStorage - * @param snGenerator - */ - public MerkleDataSet(HashDigest merkleRootHash, CryptoSetting setting, String keyPrefix, - ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) { - this(merkleRootHash, setting, Bytes.fromString(keyPrefix), exPolicyStorage, versioningStorage, readonly); - } - - /** - * 从指定的 Merkle 根构建的 MerkleDataSet; - * - * @param dataStorage - * @param defaultMerkleHashAlgorithm - * @param verifyMerkleHashOnLoad - * @param merkleTreeStorage - * @param snGenerator - */ - public MerkleDataSet(HashDigest merkleRootHash, CryptoSetting setting, Bytes keyPrefix, - ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) { - // 缓冲对KV的写入; - this.bufferedStorage = new BufferedKVStorage(exPolicyStorage, versioningStorage, false); - - // 把存储数据值、SN、Merkle节点的 key 分别加入独立的前缀,避免针对 key 的注入攻击; -// snKeyPrefix = Bytes.fromString(keyPrefix + SN_PREFIX); -// dataKeyPrefix = Bytes.fromString(keyPrefix + DATA_PREFIX); - snKeyPrefix = keyPrefix.concat(SN_PREFIX); - dataKeyPrefix = keyPrefix.concat(DATA_PREFIX); - this.valueStorage = bufferedStorage; - this.snStorage = bufferedStorage; - - // MerkleTree 本身是可缓冲的; - merkleKeyPrefix = keyPrefix.concat(MERKLE_TREE_PREFIX); - ExPolicyKVStorage merkleTreeStorage = exPolicyStorage; - this.merkleTree = new MerkleTree(merkleRootHash, setting, merkleKeyPrefix, merkleTreeStorage, readonly); - - this.snGenerator = new MerkleSequenceSNGenerator(merkleTree); - this.readonly = readonly; - } - - public boolean isReadonly() { - return readonly; - } - - void setReadonly() { - this.readonly = true; - } - - @Override - public long getDataCount() { - return merkleTree.getDataCount(); - } - - /** - * 返回理论上允许的最大数据索引; - * - * @return - */ - public long getMaxIndex() { - return merkleTree.getMaxSn(); - } - - public byte[][] getLatestValues(long fromIndex, int count) { - if (count > LedgerConsts.MAX_LIST_COUNT) { - throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); - } - if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) { - throw new IllegalArgumentException("Index out of bound!"); - } - byte[][] values = new byte[count][]; - for (int i = 0; i < count; i++) { - MerkleDataNode dataNode = merkleTree.getData(fromIndex + i); - Bytes dataKey = encodeDataKey(dataNode.getKey()); - values[i] = valueStorage.get(dataKey, dataNode.getVersion()); - } - return values; - } - - public DataEntry[] getLatestDataEntries(long fromIndex, int count) { - if (count > LedgerConsts.MAX_LIST_COUNT) { - throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); - } - if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) { - throw new IllegalArgumentException("Index out of bound!"); - } - if (count == 0) { - return EMPTY_ENTRIES; - } - @SuppressWarnings("unchecked") - DataEntry[] values = new DataEntry[count]; - byte[] bytesValue; - for (int i = 0; i < count; i++) { - MerkleDataNode dataNode = merkleTree.getData(fromIndex + i); - Bytes dataKey = encodeDataKey(dataNode.getKey()); - bytesValue = valueStorage.get(dataKey, dataNode.getVersion()); - values[i] = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), bytesValue); - } - return values; - } - - public DataEntry getLatestDataEntry(long index) { - if (index < 0 || index + 1 > merkleTree.getDataCount()) { - throw new IllegalArgumentException("Index out of bound!"); - } - byte[] bytesValue; - MerkleDataNode dataNode = merkleTree.getData(index); - Bytes dataKey = encodeDataKey(dataNode.getKey()); - bytesValue = valueStorage.get(dataKey, dataNode.getVersion()); - DataEntry entry = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), - bytesValue); - return entry; - } - - /** - * get the data at the specific index; - * - * @param fromIndex - * @return - */ - public byte[] getValuesAtIndex(int fromIndex) { - MerkleDataNode dataNode = merkleTree.getData(fromIndex); - Bytes dataKey = encodeDataKey(dataNode.getKey()); - return valueStorage.get(dataKey, dataNode.getVersion()); - } - - /** - * get the key at the specific index; - * - * @param fromIndex - * @return - */ - public String getKeyAtIndex(int fromIndex) { - MerkleDataNode dataNode = merkleTree.getData(fromIndex); - // TODO: 未去掉前缀; - return dataNode.getKey().toUTF8String(); - } - -// /** -// * Create or update the value associated the specified key if the version -// * checking is passed.
-// * -// * The value of the key will be updated only if it's latest version equals the -// * specified version argument.
-// * If the key doesn't exist, it will be created when the version arg was -1. -// *

-// * If updating is performed, the version of the key increase by 1.
-// * If creating is performed, the version of the key initialize by 0.
-// * -// * @param key The key of data; -// * @param value The value of data; -// * @param version The expected latest version of the key. -// * @return The new version of the key.
-// * If the key is new created success, then return 0;
-// * If the key is updated success, then return the new version;
-// * If this operation fail by version checking or other reason, then -// * return -1; -// */ -// @Override -// public long setValue(String key, byte[] value, long version) { -// return setValue(Bytes.fromString(key), value, version); -// } - - /** - * Create or update the value associated the specified key if the version - * checking is passed.
- * - * The value of the key will be updated only if it's latest version equals the - * specified version argument.
- * If the key doesn't exist, it will be created when the version arg was -1. - *

- * If updating is performed, the version of the key increase by 1.
- * If creating is performed, the version of the key initialize by 0.
- * - * @param key The key of data; - * @param value The value of data; - * @param version The expected latest version of the key. - * @return The new version of the key.
- * If the key is new created success, then return 0;
- * If the key is updated success, then return the new version;
- * If this operation fail by version checking or other reason, then - * return -1; - */ - @Override - public long setValue(Bytes key, byte[] value, long version) { - if (readonly) { - throw new IllegalArgumentException("This merkle dataset is readonly!"); - } - if (value.length > MAX_SIZE_OF_VALUE) { - throw new IllegalArgumentException( - "The size of value is great than the max size[" + MAX_SIZE_OF_VALUE + "]!"); - } - Bytes dataKey = encodeDataKey(key); - long latestVersion = valueStorage.getVersion(dataKey); - if (version != latestVersion) { - return -1; - } - - // set into versioning kv storage before adding to merkle tree, in order to - // check version confliction first; - long sn; - long newVersion; - if (version < 0) { - // creating ; - sn = snGenerator.generate(key); - newVersion = valueStorage.set(dataKey, value, -1); - if (newVersion < 0) { - return -1; - } - byte[] snBytes = BytesUtils.toBytes(sn); - Bytes snKey = encodeSNKey(key); - boolean nx = snStorage.set(snKey, snBytes, ExPolicy.NOT_EXISTING); - if (!nx) { - throw new LedgerException("SN already exist! --[KEY=" + key + "]"); - } - } else { - // updating; - - // TODO: 未在当前实例的层面,实现对输入键-值的缓冲,而直接写入了存储,而 MerkleTree 在未调用 commit - // 之前是缓冲的,这使得在存储层面的数据会不一致,而未来需要优化; - newVersion = valueStorage.set(dataKey, value, version); - if (newVersion < 0) { - return -1; - } - - sn = getSN(key); - } - - // update merkle tree; - merkleTree.setData(sn, key, newVersion, value); - // TODO: 未在当前实例的层面,实现对输入键-值的缓冲,而直接写入了存储,而 MerkleTree 在未调用 commit - // 之前是缓冲的,这使得在存储层面的数据会不一致,而未来需要优化; - - return newVersion; - } - - private Bytes encodeSNKey(Bytes key) { - return new Bytes(snKeyPrefix, key); - } - - private Bytes encodeDataKey(Bytes key) { - return new Bytes(dataKeyPrefix, key); - } - - /** - * 返回指定 key 对应的序号,如果不存在,则返回 -1; - * - * @param key - * @return - */ - private long getSN(Bytes key) { - // SN-KEY index entry has never changed; - Bytes snKey = encodeSNKey(key); - byte[] snBytes = snStorage.get(snKey); - if (snBytes == null) { - // throw new IllegalStateException("Cann't found SN of key[" + key + "] from - // data storage!"); - return -1; - } - return BytesUtils.toLong(snBytes); - } - - /** - * 返回默克尔树中记录的指定键的版本,在由默克尔树表示的数据集的快照中,这是指定键的最新版本,
- * 但该版本有可能小于实际存储的最新版本(由于后续追加的新修改被之后生成的快照维护); - * - * @param key - * @return 返回指定的键的版本;如果不存在,则返回 -1; - */ - private long getMerkleVersion(Bytes key) { - long sn = getSN(key); - if (sn < 0) { - return -1; - } - MerkleDataNode mdn = merkleTree.getData(sn); - if (mdn == null) { - return -1; - } - return mdn.getVersion(); - } - -// /** -// * Return the specified version's value;
-// * -// * If the key with the specified version doesn't exist, then return null;
-// * If the version is specified to -1, then return the latest version's value; -// * -// * @param key -// * @param version -// */ -// @Override -// public byte[] getValue(String key, long version) { -// return getValue(Bytes.fromString(key), version); -// } - - /** - * Return the specified version's value;
- * - * If the key with the specified version doesn't exist, then return null;
- * If the version is specified to -1, then return the latest version's value; - * - * @param key - * @param version - */ - @Override - public byte[] getValue(Bytes key, long version) { - long latestVersion = getMerkleVersion(key); - if (latestVersion < 0 || version > latestVersion) { - // key not exist, or the specified version is out of the latest version indexed - // by the current merkletree; - return null; - } - version = version < 0 ? latestVersion : version; - Bytes dataKey = encodeDataKey(key); - return valueStorage.get(dataKey, version); - } - -// /** -// * Return the latest version's value; -// * -// * @param key -// * @return return null if not exist; -// */ -// @Override -// public byte[] getValue(String key) { -// return getValue(Bytes.fromString(key)); -// } - - /** - * Return the latest version's value; - * - * @param key - * @return return null if not exist; - */ - @Override - public byte[] getValue(Bytes key) { - long latestVersion = getMerkleVersion(key); - if (latestVersion < 0) { - return null; - } - Bytes dataKey = encodeDataKey(key); - return valueStorage.get(dataKey, latestVersion); - } - -// /** -// * Return the latest version entry associated the specified key; If the key -// * doesn't exist, then return -1; -// * -// * @param key -// * @return -// */ -// @Override -// public long getVersion(String key) { -// return getMerkleVersion(Bytes.fromString(key)); -// } - - /** - * Return the latest version entry associated the specified key; If the key - * doesn't exist, then return -1; - * - * @param key - * @return - */ - @Override - public long getVersion(Bytes key) { - return getMerkleVersion(key); - } - -// @Override -// public VersioningKVEntry getDataEntry(String key) { -// return getDataEntry(key, -1); -// } - - /** - * - * @param key - * @return Null if the key doesn't exist! - */ - @Override - public DataEntry getDataEntry(Bytes key) { - return getDataEntry(key, -1); - } - -// @Override -// public VersioningKVEntry getDataEntry(String key, long version) { -// Bytes keyBytes = Bytes.fromString(key); -// long latestVersion = getMerkleVersion(keyBytes); -// if (latestVersion < 0 || version > latestVersion) { -// // key not exist, or the specified version is out of the latest version indexed -// // by the current merkletree; -// return null; -// } -// version = version < 0 ? latestVersion : version; -// Bytes dataKey = encodeDataKey(keyBytes); -// byte[] value = valueStorage.get(dataKey, version); -// if (value == null) { -// return null; -// } -// return new VersioningKVData(key, version, value); -// } - - @Override - public DataEntry getDataEntry(Bytes key, long version) { - long latestVersion = getMerkleVersion(key); - if (latestVersion < 0 || version > latestVersion) { - // key not exist, or the specified version is out of the latest version indexed - // by the current merkletree; - return null; - } - version = version < 0 ? latestVersion : version; - Bytes dataKey = encodeDataKey(key); - byte[] value = valueStorage.get(dataKey, version); - if (value == null) { - return null; - } - return new VersioningKVData(key, version, value); - } - - @Override - public DataIterator iterator() { - return new AscDataInterator(getDataCount()); - } - - @Override - public DataIterator iteratorDesc() { - return new DescDataInterator(getDataCount()); - } - - public MerkleDataEntry getMerkleEntry(Bytes key, long version) { - DataEntry dataEntry = getDataEntry(key, version); - if (dataEntry == null) { - return null; - } - MerkleProof proof = getProof(key); - return new MerkleDataEntryWrapper(dataEntry, proof); - } - - public MerkleDataEntry getMerkleEntry(Bytes key) { - DataEntry dataEntry = getDataEntry(key); - if (dataEntry == null) { - return null; - } - MerkleProof proof = getProof(key); - return new MerkleDataEntryWrapper(dataEntry, proof); - } - - public MerkleProof getProof(String key) { - return getProof(Bytes.fromString(key)); - } - - /* - * (non-Javadoc) - * - * @see com.jd.blockchain.ledger.core.MerkleProvable#getProof(java.lang.String) - */ - @Override - public MerkleProof getProof(Bytes key) { - long sn = getSN(key); - if (sn < 0) { - return null; - } - return merkleTree.getProof(sn); - } - - /** - * A wrapper for {@link DataEntry} and {@link MerkleProof}; - * - * @author huanghaiquan - * - */ - private static class MerkleDataEntryWrapper implements MerkleDataEntry { - - private DataEntry data; - private MerkleProof proof; - - public MerkleDataEntryWrapper(DataEntry data, MerkleProof proof) { - this.data = data; - this.proof = proof; - } - - @Override - public DataEntry getData() { - return data; - } - - @Override - public MerkleProof getProof() { - return proof; - } - - } - - @Override - public boolean isUpdated() { - return bufferedStorage.isUpdated() || merkleTree.isUpdated(); - } - - @Override - public void commit() { - bufferedStorage.commit(); - merkleTree.commit(); - } - - @Override - public void cancel() { - bufferedStorage.cancel(); - merkleTree.cancel(); - snGenerator = new MerkleSequenceSNGenerator(merkleTree); - } - - // ---------------------------------------------------------- - - private class AscDataInterator implements DataIterator { - - private final long total; - - private long cursor = 0; - - public AscDataInterator(long total) { - this.total = total; - } - - @Override - public void skip(long count) { - cursor = nextCursor(count); - } - - private long nextCursor(long skippingCount) { - long c = cursor + skippingCount; - return c > total ? total : c; - } - - @Override - public DataEntry next() { - if (hasNext()) { - DataEntry entry = getLatestDataEntry(cursor); - cursor = nextCursor(1); - return entry; - } - return null; - } - - @Override - public DataEntry[] next(int count) { - if (hasNext()) { - long from = cursor; - long nextCursor = nextCursor(count); - long c = nextCursor - cursor; - if (c > LedgerConsts.MAX_LIST_COUNT) { - throw new IllegalArgumentException( - "Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); - } - DataEntry[] entries = getLatestDataEntries(from, (int) c); - cursor = nextCursor; - return entries; - } - return EMPTY_ENTRIES; - } - - @Override - public boolean hasNext() { - return cursor < total; - } - - } - - private class DescDataInterator implements DataIterator { - - private final long total; - - private long cursor; - - public DescDataInterator(long total) { - this.total = total; - this.cursor = total - 1; - } - - @Override - public void skip(long count) { - cursor = nextCursor(count); - } - - private long nextCursor(long skippingCount) { - long c = cursor - skippingCount; - return c < 0 ? -1 : c; - } - - @Override - public DataEntry next() { - if (hasNext()) { - DataEntry entry = getLatestDataEntry(cursor); - cursor = nextCursor(1); - return entry; - } - return null; - } - - @Override - public DataEntry[] next(int count) { - if (hasNext()) { - long nextCursor = nextCursor(count); - long from = nextCursor + 1; - long c = cursor - nextCursor; - if (c > LedgerConsts.MAX_LIST_COUNT) { - throw new IllegalArgumentException( - "Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); - } - DataEntry[] entries = getLatestDataEntries(from, (int) c); - // reverse; - ArrayUtils.reverse(entries); - - cursor = nextCursor; - return entries; - } - return EMPTY_ENTRIES; - } - - @Override - public boolean hasNext() { - return cursor < total; - } - - } - +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.LedgerException; +import com.jd.blockchain.ledger.MerkleDataNode; +import com.jd.blockchain.ledger.MerkleProof; +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.ExPolicyKVStorage.ExPolicy; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.storage.service.utils.BufferedKVStorage; +import com.jd.blockchain.storage.service.utils.VersioningKVData; +import com.jd.blockchain.utils.ArrayUtils; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; +import com.jd.blockchain.utils.DataIterator; +import com.jd.blockchain.utils.Dataset; +import com.jd.blockchain.utils.Transactional; +import com.jd.blockchain.utils.io.BytesUtils; + +/** + * 对新的数据项按顺序递增进行编号的 Merkle 数据集;
+ * + * 注:此实现不是线程安全的; + * + * @author huanghaiquan + * + */ +public class MerkleDataSet implements Transactional, MerkleProvable, Dataset { + + /** + * 4 MB MaxSize of value; + */ + public static final int MAX_SIZE_OF_VALUE = 4 * 1024 * 1024; + + public static final Bytes SN_PREFIX = Bytes.fromString("SN" + LedgerConsts.KEY_SEPERATOR); + public static final Bytes DATA_PREFIX = Bytes.fromString("KV" + LedgerConsts.KEY_SEPERATOR); + public static final Bytes MERKLE_TREE_PREFIX = Bytes.fromString("MKL" + LedgerConsts.KEY_SEPERATOR); + + private final Bytes snKeyPrefix; + private final Bytes dataKeyPrefix; + private final Bytes merkleKeyPrefix; + + @SuppressWarnings("unchecked") + private static final DataEntry[] EMPTY_ENTRIES = new DataEntry[0]; + + private BufferedKVStorage bufferedStorage; + + private VersioningKVStorage valueStorage; + + private ExPolicyKVStorage snStorage; + + private MerkleTree merkleTree; + + private SNGenerator snGenerator; + + private boolean readonly; + + /* + * (non-Javadoc) + * + * @see com.jd.blockchain.ledger.core.MerkleProvable#getRootHash() + */ + @Override + public HashDigest getRootHash() { + return merkleTree.getRootHash(); + } + + /** + * 创建一个新的 MerkleDataSet; + * + * @param setting 密码设置; + * @param exPolicyStorage 默克尔树的存储; + * @param versioningStorage 数据的存储; + */ + public MerkleDataSet(CryptoSetting setting, String keyPrefix, ExPolicyKVStorage exPolicyStorage, + VersioningKVStorage versioningStorage) { + this(setting, Bytes.fromString(keyPrefix), exPolicyStorage, versioningStorage); + } + + /** + * 创建一个新的 MerkleDataSet; + * + * @param setting 密码设置; + * @param exPolicyStorage 默克尔树的存储; + * @param versioningStorage 数据的存储; + */ + public MerkleDataSet(CryptoSetting setting, Bytes keyPrefix, ExPolicyKVStorage exPolicyStorage, + VersioningKVStorage versioningStorage) { + // 缓冲对KV的写入; + this.bufferedStorage = new BufferedKVStorage(exPolicyStorage, versioningStorage, false); + + // 把存储数据值、SN、Merkle节点的 key 分别加入独立的前缀,避免针对 key 的注入攻击; + // this.valueStorage = PrefixAppender.prefix(DATA_PREFIX, (VersioningKVStorage) + // bufferedStorage); + // this.snStorage = PrefixAppender.prefix(SN_PREFIX, (ExPolicyKVStorage) + // bufferedStorage); + snKeyPrefix = keyPrefix.concat(SN_PREFIX); + dataKeyPrefix = keyPrefix.concat(DATA_PREFIX); + this.valueStorage = bufferedStorage; + this.snStorage = bufferedStorage; + + // MerkleTree 本身是可缓冲的; + // ExPolicyKVStorage merkleTreeStorage = + // PrefixAppender.prefix(MERKLE_TREE_PREFIX, exPolicyStorage); + merkleKeyPrefix = keyPrefix.concat(MERKLE_TREE_PREFIX); + ExPolicyKVStorage merkleTreeStorage = exPolicyStorage; + this.merkleTree = new MerkleTree(setting, merkleKeyPrefix, merkleTreeStorage); + this.snGenerator = new MerkleSequenceSNGenerator(merkleTree); + } + + /** + * 从指定的 Merkle 根构建的 MerkleDataSet; + * + * @param dataStorage + * @param defaultMerkleHashAlgorithm + * @param verifyMerkleHashOnLoad + * @param merkleTreeStorage + * @param snGenerator + */ + public MerkleDataSet(HashDigest merkleRootHash, CryptoSetting setting, String keyPrefix, + ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) { + this(merkleRootHash, setting, Bytes.fromString(keyPrefix), exPolicyStorage, versioningStorage, readonly); + } + + /** + * 从指定的 Merkle 根构建的 MerkleDataSet; + * + * @param dataStorage + * @param defaultMerkleHashAlgorithm + * @param verifyMerkleHashOnLoad + * @param merkleTreeStorage + * @param snGenerator + */ + public MerkleDataSet(HashDigest merkleRootHash, CryptoSetting setting, Bytes keyPrefix, + ExPolicyKVStorage exPolicyStorage, VersioningKVStorage versioningStorage, boolean readonly) { + // 缓冲对KV的写入; + this.bufferedStorage = new BufferedKVStorage(exPolicyStorage, versioningStorage, false); + + // 把存储数据值、SN、Merkle节点的 key 分别加入独立的前缀,避免针对 key 的注入攻击; +// snKeyPrefix = Bytes.fromString(keyPrefix + SN_PREFIX); +// dataKeyPrefix = Bytes.fromString(keyPrefix + DATA_PREFIX); + snKeyPrefix = keyPrefix.concat(SN_PREFIX); + dataKeyPrefix = keyPrefix.concat(DATA_PREFIX); + this.valueStorage = bufferedStorage; + this.snStorage = bufferedStorage; + + // MerkleTree 本身是可缓冲的; + merkleKeyPrefix = keyPrefix.concat(MERKLE_TREE_PREFIX); + ExPolicyKVStorage merkleTreeStorage = exPolicyStorage; + this.merkleTree = new MerkleTree(merkleRootHash, setting, merkleKeyPrefix, merkleTreeStorage, readonly); + + this.snGenerator = new MerkleSequenceSNGenerator(merkleTree); + this.readonly = readonly; + } + + public boolean isReadonly() { + return readonly; + } + + void setReadonly() { + this.readonly = true; + } + + @Override + public long getDataCount() { + return merkleTree.getDataCount(); + } + + /** + * 返回理论上允许的最大数据索引; + * + * @return + */ + public long getMaxIndex() { + return merkleTree.getMaxSn(); + } + + public byte[][] getLatestValues(long fromIndex, int count) { + if (count > LedgerConsts.MAX_LIST_COUNT) { + throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); + } + if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) { + throw new IllegalArgumentException("Index out of bound!"); + } + byte[][] values = new byte[count][]; + for (int i = 0; i < count; i++) { + MerkleDataNode dataNode = merkleTree.getData(fromIndex + i); + Bytes dataKey = encodeDataKey(dataNode.getKey()); + values[i] = valueStorage.get(dataKey, dataNode.getVersion()); + } + return values; + } + + public DataEntry[] getLatestDataEntries(long fromIndex, int count) { + if (count > LedgerConsts.MAX_LIST_COUNT) { + throw new IllegalArgumentException("Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); + } + if (fromIndex < 0 || (fromIndex + count) > merkleTree.getDataCount()) { + throw new IllegalArgumentException("Index out of bound!"); + } + if (count == 0) { + return EMPTY_ENTRIES; + } + @SuppressWarnings("unchecked") + DataEntry[] values = new DataEntry[count]; + byte[] bytesValue; + for (int i = 0; i < count; i++) { + MerkleDataNode dataNode = merkleTree.getData(fromIndex + i); + Bytes dataKey = encodeDataKey(dataNode.getKey()); + bytesValue = valueStorage.get(dataKey, dataNode.getVersion()); + values[i] = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), bytesValue); + } + return values; + } + + public DataEntry getLatestDataEntry(long index) { + if (index < 0 || index + 1 > merkleTree.getDataCount()) { + throw new IllegalArgumentException("Index out of bound!"); + } + byte[] bytesValue; + MerkleDataNode dataNode = merkleTree.getData(index); + Bytes dataKey = encodeDataKey(dataNode.getKey()); + bytesValue = valueStorage.get(dataKey, dataNode.getVersion()); + DataEntry entry = new VersioningKVData(dataNode.getKey(), dataNode.getVersion(), + bytesValue); + return entry; + } + + /** + * get the data at the specific index; + * + * @param fromIndex + * @return + */ + public byte[] getValuesAtIndex(int fromIndex) { + MerkleDataNode dataNode = merkleTree.getData(fromIndex); + Bytes dataKey = encodeDataKey(dataNode.getKey()); + return valueStorage.get(dataKey, dataNode.getVersion()); + } + + /** + * get the key at the specific index; + * + * @param fromIndex + * @return + */ + public String getKeyAtIndex(int fromIndex) { + MerkleDataNode dataNode = merkleTree.getData(fromIndex); + // TODO: 未去掉前缀; + return dataNode.getKey().toUTF8String(); + } + +// /** +// * Create or update the value associated the specified key if the version +// * checking is passed.
+// * +// * The value of the key will be updated only if it's latest version equals the +// * specified version argument.
+// * If the key doesn't exist, it will be created when the version arg was -1. +// *

+// * If updating is performed, the version of the key increase by 1.
+// * If creating is performed, the version of the key initialize by 0.
+// * +// * @param key The key of data; +// * @param value The value of data; +// * @param version The expected latest version of the key. +// * @return The new version of the key.
+// * If the key is new created success, then return 0;
+// * If the key is updated success, then return the new version;
+// * If this operation fail by version checking or other reason, then +// * return -1; +// */ +// @Override +// public long setValue(String key, byte[] value, long version) { +// return setValue(Bytes.fromString(key), value, version); +// } + + /** + * Create or update the value associated the specified key if the version + * checking is passed.
+ * + * The value of the key will be updated only if it's latest version equals the + * specified version argument.
+ * If the key doesn't exist, it will be created when the version arg was -1. + *

+ * If updating is performed, the version of the key increase by 1.
+ * If creating is performed, the version of the key initialize by 0.
+ * + * @param key The key of data; + * @param value The value of data; + * @param version The expected latest version of the key. + * @return The new version of the key.
+ * If the key is new created success, then return 0;
+ * If the key is updated success, then return the new version;
+ * If this operation fail by version checking or other reason, then + * return -1; + */ + @Override + public long setValue(Bytes key, byte[] value, long version) { + if (readonly) { + throw new IllegalArgumentException("This merkle dataset is readonly!"); + } + if (value.length > MAX_SIZE_OF_VALUE) { + throw new IllegalArgumentException( + "The size of value is great than the max size[" + MAX_SIZE_OF_VALUE + "]!"); + } + Bytes dataKey = encodeDataKey(key); + long latestVersion = valueStorage.getVersion(dataKey); + if (version != latestVersion) { + return -1; + } + + // set into versioning kv storage before adding to merkle tree, in order to + // check version confliction first; + long sn; + long newVersion; + if (version < 0) { + // creating ; + sn = snGenerator.generate(key); + newVersion = valueStorage.set(dataKey, value, -1); + if (newVersion < 0) { + return -1; + } + byte[] snBytes = BytesUtils.toBytes(sn); + Bytes snKey = encodeSNKey(key); + boolean nx = snStorage.set(snKey, snBytes, ExPolicy.NOT_EXISTING); + if (!nx) { + throw new LedgerException("SN already exist! --[KEY=" + key + "]"); + } + } else { + // updating; + + // TODO: 未在当前实例的层面,实现对输入键-值的缓冲,而直接写入了存储,而 MerkleTree 在未调用 commit + // 之前是缓冲的,这使得在存储层面的数据会不一致,而未来需要优化; + newVersion = valueStorage.set(dataKey, value, version); + if (newVersion < 0) { + return -1; + } + + sn = getSN(key); + } + + // update merkle tree; + merkleTree.setData(sn, key, newVersion, value); + // TODO: 未在当前实例的层面,实现对输入键-值的缓冲,而直接写入了存储,而 MerkleTree 在未调用 commit + // 之前是缓冲的,这使得在存储层面的数据会不一致,而未来需要优化; + + return newVersion; + } + + private Bytes encodeSNKey(Bytes key) { + return new Bytes(snKeyPrefix, key); + } + + private Bytes encodeDataKey(Bytes key) { + return new Bytes(dataKeyPrefix, key); + } + + /** + * 返回指定 key 对应的序号,如果不存在,则返回 -1; + * + * @param key + * @return + */ + private long getSN(Bytes key) { + // SN-KEY index entry has never changed; + Bytes snKey = encodeSNKey(key); + byte[] snBytes = snStorage.get(snKey); + if (snBytes == null) { + // throw new IllegalStateException("Cann't found SN of key[" + key + "] from + // data storage!"); + return -1; + } + return BytesUtils.toLong(snBytes); + } + + /** + * 返回默克尔树中记录的指定键的版本,在由默克尔树表示的数据集的快照中,这是指定键的最新版本,
+ * 但该版本有可能小于实际存储的最新版本(由于后续追加的新修改被之后生成的快照维护); + * + * @param key + * @return 返回指定的键的版本;如果不存在,则返回 -1; + */ + private long getMerkleVersion(Bytes key) { + long sn = getSN(key); + if (sn < 0) { + return -1; + } + MerkleDataNode mdn = merkleTree.getData(sn); + if (mdn == null) { + return -1; + } + return mdn.getVersion(); + } + +// /** +// * Return the specified version's value;
+// * +// * If the key with the specified version doesn't exist, then return null;
+// * If the version is specified to -1, then return the latest version's value; +// * +// * @param key +// * @param version +// */ +// @Override +// public byte[] getValue(String key, long version) { +// return getValue(Bytes.fromString(key), version); +// } + + /** + * Return the specified version's value;
+ * + * If the key with the specified version doesn't exist, then return null;
+ * If the version is specified to -1, then return the latest version's value; + * + * @param key + * @param version + */ + @Override + public byte[] getValue(Bytes key, long version) { + long latestVersion = getMerkleVersion(key); + if (latestVersion < 0 || version > latestVersion) { + // key not exist, or the specified version is out of the latest version indexed + // by the current merkletree; + return null; + } + version = version < 0 ? latestVersion : version; + Bytes dataKey = encodeDataKey(key); + return valueStorage.get(dataKey, version); + } + +// /** +// * Return the latest version's value; +// * +// * @param key +// * @return return null if not exist; +// */ +// @Override +// public byte[] getValue(String key) { +// return getValue(Bytes.fromString(key)); +// } + + /** + * Return the latest version's value; + * + * @param key + * @return return null if not exist; + */ + @Override + public byte[] getValue(Bytes key) { + long latestVersion = getMerkleVersion(key); + if (latestVersion < 0) { + return null; + } + Bytes dataKey = encodeDataKey(key); + return valueStorage.get(dataKey, latestVersion); + } + +// /** +// * Return the latest version entry associated the specified key; If the key +// * doesn't exist, then return -1; +// * +// * @param key +// * @return +// */ +// @Override +// public long getVersion(String key) { +// return getMerkleVersion(Bytes.fromString(key)); +// } + + /** + * Return the latest version entry associated the specified key; If the key + * doesn't exist, then return -1; + * + * @param key + * @return + */ + @Override + public long getVersion(Bytes key) { + return getMerkleVersion(key); + } + +// @Override +// public VersioningKVEntry getDataEntry(String key) { +// return getDataEntry(key, -1); +// } + + /** + * + * @param key + * @return Null if the key doesn't exist! + */ + @Override + public DataEntry getDataEntry(Bytes key) { + return getDataEntry(key, -1); + } + +// @Override +// public VersioningKVEntry getDataEntry(String key, long version) { +// Bytes keyBytes = Bytes.fromString(key); +// long latestVersion = getMerkleVersion(keyBytes); +// if (latestVersion < 0 || version > latestVersion) { +// // key not exist, or the specified version is out of the latest version indexed +// // by the current merkletree; +// return null; +// } +// version = version < 0 ? latestVersion : version; +// Bytes dataKey = encodeDataKey(keyBytes); +// byte[] value = valueStorage.get(dataKey, version); +// if (value == null) { +// return null; +// } +// return new VersioningKVData(key, version, value); +// } + + @Override + public DataEntry getDataEntry(Bytes key, long version) { + long latestVersion = getMerkleVersion(key); + if (latestVersion < 0 || version > latestVersion) { + // key not exist, or the specified version is out of the latest version indexed + // by the current merkletree; + return null; + } + version = version < 0 ? latestVersion : version; + Bytes dataKey = encodeDataKey(key); + byte[] value = valueStorage.get(dataKey, version); + if (value == null) { + return null; + } + return new VersioningKVData(key, version, value); + } + + @Override + public DataIterator iterator() { + return new AscDataInterator(getDataCount()); + } + + @Override + public DataIterator iteratorDesc() { + return new DescDataInterator(getDataCount()); + } + + public MerkleDataEntry getMerkleEntry(Bytes key, long version) { + DataEntry dataEntry = getDataEntry(key, version); + if (dataEntry == null) { + return null; + } + MerkleProof proof = getProof(key); + return new MerkleDataEntryWrapper(dataEntry, proof); + } + + public MerkleDataEntry getMerkleEntry(Bytes key) { + DataEntry dataEntry = getDataEntry(key); + if (dataEntry == null) { + return null; + } + MerkleProof proof = getProof(key); + return new MerkleDataEntryWrapper(dataEntry, proof); + } + + public MerkleProof getProof(String key) { + return getProof(Bytes.fromString(key)); + } + + /* + * (non-Javadoc) + * + * @see com.jd.blockchain.ledger.core.MerkleProvable#getProof(java.lang.String) + */ + @Override + public MerkleProof getProof(Bytes key) { + long sn = getSN(key); + if (sn < 0) { + return null; + } + return merkleTree.getProof(sn); + } + + /** + * A wrapper for {@link DataEntry} and {@link MerkleProof}; + * + * @author huanghaiquan + * + */ + private static class MerkleDataEntryWrapper implements MerkleDataEntry { + + private DataEntry data; + private MerkleProof proof; + + public MerkleDataEntryWrapper(DataEntry data, MerkleProof proof) { + this.data = data; + this.proof = proof; + } + + @Override + public DataEntry getData() { + return data; + } + + @Override + public MerkleProof getProof() { + return proof; + } + + } + + @Override + public boolean isUpdated() { + return bufferedStorage.isUpdated() || merkleTree.isUpdated(); + } + + @Override + public void commit() { + bufferedStorage.commit(); + merkleTree.commit(); + } + + @Override + public void cancel() { + bufferedStorage.cancel(); + merkleTree.cancel(); + snGenerator = new MerkleSequenceSNGenerator(merkleTree); + } + + // ---------------------------------------------------------- + + private class AscDataInterator implements DataIterator { + + private final long total; + + private long cursor = 0; + + public AscDataInterator(long total) { + this.total = total; + } + + @Override + public void skip(long count) { + cursor = nextCursor(count); + } + + private long nextCursor(long skippingCount) { + long c = cursor + skippingCount; + return c > total ? total : c; + } + + @Override + public DataEntry next() { + if (hasNext()) { + DataEntry entry = getLatestDataEntry(cursor); + cursor = nextCursor(1); + return entry; + } + return null; + } + + @Override + public DataEntry[] next(int count) { + if (hasNext()) { + long from = cursor; + long nextCursor = nextCursor(count); + long c = nextCursor - cursor; + if (c > LedgerConsts.MAX_LIST_COUNT) { + throw new IllegalArgumentException( + "Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); + } + DataEntry[] entries = getLatestDataEntries(from, (int) c); + cursor = nextCursor; + return entries; + } + return EMPTY_ENTRIES; + } + + @Override + public boolean hasNext() { + return cursor < total; + } + + } + + private class DescDataInterator implements DataIterator { + + private final long total; + + private long cursor; + + public DescDataInterator(long total) { + this.total = total; + this.cursor = total - 1; + } + + @Override + public void skip(long count) { + cursor = nextCursor(count); + } + + private long nextCursor(long skippingCount) { + long c = cursor - skippingCount; + return c < 0 ? -1 : c; + } + + @Override + public DataEntry next() { + if (hasNext()) { + DataEntry entry = getLatestDataEntry(cursor); + cursor = nextCursor(1); + return entry; + } + return null; + } + + @Override + public DataEntry[] next(int count) { + if (hasNext()) { + long nextCursor = nextCursor(count); + long from = nextCursor + 1; + long c = cursor - nextCursor; + if (c > LedgerConsts.MAX_LIST_COUNT) { + throw new IllegalArgumentException( + "Count exceed the upper limit[" + LedgerConsts.MAX_LIST_COUNT + "]!"); + } + DataEntry[] entries = getLatestDataEntries(from, (int) c); + // reverse; + ArrayUtils.reverse(entries); + + cursor = nextCursor; + return entries; + } + return EMPTY_ENTRIES; + } + + @Override + public boolean hasNext() { + return cursor < total; + } + + } + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Node.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Node.java index fd8df0cd..d9db7e70 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Node.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Node.java @@ -1,11 +1,11 @@ -package com.jd.blockchain.ledger.core; - - -public class Node { - - public Node(){ - - } - - +package com.jd.blockchain.ledger.core; + + +public class Node { + + public Node(){ + + } + + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java index c9212bb2..ff03355d 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/ParticipantCertData.java @@ -1,73 +1,73 @@ -package com.jd.blockchain.ledger.core; - -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.ParticipantNode; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.ledger.ParticipantNodeState; - -/** - * 参与方证书数据对象; - * - * @author huanghaiquan - * - */ -public class ParticipantCertData implements ParticipantNode { - - private int id; - private Bytes address; - private String name; - private PubKey pubKey; - private ParticipantNodeState participantNodeState; - - public ParticipantCertData() { - } - - public ParticipantCertData(ParticipantNode participantNode) { - this.id = participantNode.getId(); - this.address = participantNode.getAddress(); - this.name = participantNode.getName(); - this.pubKey = participantNode.getPubKey(); - this.participantNodeState = participantNode.getParticipantNodeState(); - } - - public ParticipantCertData(Bytes address, String name, PubKey pubKey, ParticipantNodeState participantNodeState) { - this.address = address; - this.name = name; - this.pubKey = pubKey; - this.participantNodeState = participantNodeState; - } - - @Override - public Bytes getAddress() { - return address; - } - - @Override - public String getName() { - return name; - } - - @Override - public PubKey getPubKey() { - return pubKey; - } - - @Override - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - @Override - public ParticipantNodeState getParticipantNodeState() { - return participantNodeState; - } - - public void setParticipantNodeState(ParticipantNodeState participantNodeState) { - this.participantNodeState = participantNodeState; - } - +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.ledger.ParticipantNodeState; + +/** + * 参与方证书数据对象; + * + * @author huanghaiquan + * + */ +public class ParticipantCertData implements ParticipantNode { + + private int id; + private Bytes address; + private String name; + private PubKey pubKey; + private ParticipantNodeState participantNodeState; + + public ParticipantCertData() { + } + + public ParticipantCertData(ParticipantNode participantNode) { + this.id = participantNode.getId(); + this.address = participantNode.getAddress(); + this.name = participantNode.getName(); + this.pubKey = participantNode.getPubKey(); + this.participantNodeState = participantNode.getParticipantNodeState(); + } + + public ParticipantCertData(Bytes address, String name, PubKey pubKey, ParticipantNodeState participantNodeState) { + this.address = address; + this.name = name; + this.pubKey = pubKey; + this.participantNodeState = participantNodeState; + } + + @Override + public Bytes getAddress() { + return address; + } + + @Override + public String getName() { + return name; + } + + @Override + public PubKey getPubKey() { + return pubKey; + } + + @Override + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public ParticipantNodeState getParticipantNodeState() { + return participantNodeState; + } + + public void setParticipantNodeState(ParticipantNodeState participantNodeState) { + this.participantNodeState = participantNodeState; + } + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Peer.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Peer.java index 2ef46c99..19a4dcbc 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Peer.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/Peer.java @@ -1,22 +1,22 @@ -package com.jd.blockchain.ledger.core; - -import com.jd.blockchain.ledger.ParticipantNode; - -/** - * @author hhq - * @version 1.0 - * @created 14-6��-2018 12:13:33 - */ -public class Peer extends Node { - - public ParticipantNode m_Participant; - - public Peer(){ - - } - - public void finalize() throws Throwable { - super.finalize(); - } - +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.ledger.ParticipantNode; + +/** + * @author hhq + * @version 1.0 + * @created 14-6��-2018 12:13:33 + */ +public class Peer extends Node { + + public ParticipantNode m_Participant; + + public Peer(){ + + } + + public void finalize() throws Throwable { + super.finalize(); + } + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java index 87696e86..08d7c248 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccount.java @@ -1,85 +1,85 @@ -package com.jd.blockchain.ledger.core; - -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.LedgerException; -import com.jd.blockchain.ledger.TypedValue; -import com.jd.blockchain.ledger.UserInfo; -import com.jd.blockchain.utils.Bytes; - -/** - * 用户账户; - * - * @author huanghaiquan - * - */ -public class UserAccount extends AccountDecorator implements UserInfo { // implements UserInfo { - - private static final String USER_INFO_PREFIX = "PROP" + LedgerConsts.KEY_SEPERATOR; - - private static final String DATA_PUB_KEY = "DATA-PUBKEY"; - - public UserAccount(CompositeAccount baseAccount) { - super(baseAccount); - } - - private PubKey dataPubKey; - - - @Override - public Bytes getAddress() { - return getID().getAddress(); - } - - @Override - public PubKey getPubKey() { - return getID().getPubKey(); - } - - @Override - public PubKey getDataPubKey() { - if (dataPubKey == null) { - BytesValue pkBytes = getHeaders().getValue(DATA_PUB_KEY); - if (pkBytes == null) { - return null; - } - dataPubKey = new PubKey(pkBytes.getBytes().toBytes()); - } - return dataPubKey; - } - - public void setDataPubKey(PubKey pubKey) { - long version = getHeaders().getVersion(DATA_PUB_KEY); - setDataPubKey(pubKey, version); - } - - public void setDataPubKey(PubKey pubKey, long version) { - TypedValue value = TypedValue.fromPubKey(dataPubKey); - long newVersion = getHeaders().setValue(DATA_PUB_KEY, value, version); - if (newVersion > -1) { - dataPubKey = pubKey; - } else { - throw new LedgerException("Data public key was updated failed!"); - } - } - - public long setProperty(String key, String value, long version) { - return getHeaders().setValue(encodePropertyKey(key), TypedValue.fromText(value), version); - } - - public String getProperty(String key) { - BytesValue value = getHeaders().getValue(encodePropertyKey(key)); - return value == null ? null : value.getBytes().toUTF8String(); - } - - public String getProperty(String key, long version) { - BytesValue value = getHeaders().getValue(encodePropertyKey(key), version); - return value == null ? null : value.getBytes().toUTF8String(); - } - - private String encodePropertyKey(String key) { - return USER_INFO_PREFIX+key; - } - - +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.LedgerException; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.ledger.UserInfo; +import com.jd.blockchain.utils.Bytes; + +/** + * 用户账户; + * + * @author huanghaiquan + * + */ +public class UserAccount extends AccountDecorator implements UserInfo { // implements UserInfo { + + private static final String USER_INFO_PREFIX = "PROP" + LedgerConsts.KEY_SEPERATOR; + + private static final String DATA_PUB_KEY = "DATA-PUBKEY"; + + public UserAccount(CompositeAccount baseAccount) { + super(baseAccount); + } + + private PubKey dataPubKey; + + + @Override + public Bytes getAddress() { + return getID().getAddress(); + } + + @Override + public PubKey getPubKey() { + return getID().getPubKey(); + } + + @Override + public PubKey getDataPubKey() { + if (dataPubKey == null) { + BytesValue pkBytes = getHeaders().getValue(DATA_PUB_KEY); + if (pkBytes == null) { + return null; + } + dataPubKey = new PubKey(pkBytes.getBytes().toBytes()); + } + return dataPubKey; + } + + public void setDataPubKey(PubKey pubKey) { + long version = getHeaders().getVersion(DATA_PUB_KEY); + setDataPubKey(pubKey, version); + } + + public void setDataPubKey(PubKey pubKey, long version) { + TypedValue value = TypedValue.fromPubKey(dataPubKey); + long newVersion = getHeaders().setValue(DATA_PUB_KEY, value, version); + if (newVersion > -1) { + dataPubKey = pubKey; + } else { + throw new LedgerException("Data public key was updated failed!"); + } + } + + public long setProperty(String key, String value, long version) { + return getHeaders().setValue(encodePropertyKey(key), TypedValue.fromText(value), version); + } + + public String getProperty(String key) { + BytesValue value = getHeaders().getValue(encodePropertyKey(key)); + return value == null ? null : value.getBytes().toUTF8String(); + } + + public String getProperty(String key, long version) { + BytesValue value = getHeaders().getValue(encodePropertyKey(key), version); + return value == null ? null : value.getBytes().toUTF8String(); + } + + private String encodePropertyKey(String key) { + return USER_INFO_PREFIX+key; + } + + } \ No newline at end of file diff --git a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java index bc71711d..25256480 100644 --- a/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java +++ b/source/ledger/ledger-core/src/main/java/com/jd/blockchain/ledger/core/UserAccountSet.java @@ -1,121 +1,121 @@ -package com.jd.blockchain.ledger.core; - -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.CryptoSetting; -import com.jd.blockchain.ledger.LedgerException; -import com.jd.blockchain.ledger.MerkleProof; -import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.VersioningKVStorage; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.Transactional; - -/** - * @author huanghaiquan - * - */ -public class UserAccountSet implements Transactional, UserAccountQuery { - - private MerkleAccountSet accountSet; - - public UserAccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage simpleStorage, - VersioningKVStorage versioningStorage, AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(keyPrefix), simpleStorage, versioningStorage, - accessPolicy); - } - - public UserAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, - ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, - AccountAccessPolicy accessPolicy) { - accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(keyPrefix), exStorage, - verStorage, readonly, accessPolicy); - } - - @Override - public BlockchainIdentity[] getHeaders(int fromIndex, int count) { - return accountSet.getHeaders(fromIndex, count); - } - - /** - * 返回用户总数; - * - * @return - */ - @Override - public long getTotal() { - return accountSet.getTotal(); - } - - public boolean isReadonly() { - return accountSet.isReadonly(); - } - - void setReadonly() { - accountSet.setReadonly(); - } - - @Override - public HashDigest getRootHash() { - return accountSet.getRootHash(); - } - - @Override - public MerkleProof getProof(Bytes key) { - return accountSet.getProof(key); - } - - @Override - public UserAccount getAccount(String address) { - return getAccount(Bytes.fromBase58(address)); - } - - @Override - public UserAccount getAccount(Bytes address) { - CompositeAccount baseAccount = accountSet.getAccount(address); - return new UserAccount(baseAccount); - } - - @Override - public boolean contains(Bytes address) { - return accountSet.contains(address); - } - - @Override - public UserAccount getAccount(Bytes address, long version) { - CompositeAccount baseAccount = accountSet.getAccount(address, version); - return new UserAccount(baseAccount); - } - - /** - * 注册一个新用户;
- * - * 如果用户已经存在,则会引发 {@link LedgerException} 异常;
- * - * 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常; - * - * @param address 区块链地址; - * @param pubKey 公钥; - * @return 注册成功的用户对象; - */ - public UserAccount register(Bytes address, PubKey pubKey) { - CompositeAccount baseAccount = accountSet.register(address, pubKey); - return new UserAccount(baseAccount); - } - - @Override - public boolean isUpdated() { - return accountSet.isUpdated(); - } - - @Override - public void commit() { - accountSet.commit(); - } - - @Override - public void cancel() { - accountSet.cancel(); - } - +package com.jd.blockchain.ledger.core; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.CryptoSetting; +import com.jd.blockchain.ledger.LedgerException; +import com.jd.blockchain.ledger.MerkleProof; +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.VersioningKVStorage; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.Transactional; + +/** + * @author huanghaiquan + * + */ +public class UserAccountSet implements Transactional, UserAccountQuery { + + private MerkleAccountSet accountSet; + + public UserAccountSet(CryptoSetting cryptoSetting, String keyPrefix, ExPolicyKVStorage simpleStorage, + VersioningKVStorage versioningStorage, AccountAccessPolicy accessPolicy) { + accountSet = new MerkleAccountSet(cryptoSetting, Bytes.fromString(keyPrefix), simpleStorage, versioningStorage, + accessPolicy); + } + + public UserAccountSet(HashDigest dataRootHash, CryptoSetting cryptoSetting, String keyPrefix, + ExPolicyKVStorage exStorage, VersioningKVStorage verStorage, boolean readonly, + AccountAccessPolicy accessPolicy) { + accountSet = new MerkleAccountSet(dataRootHash, cryptoSetting, Bytes.fromString(keyPrefix), exStorage, + verStorage, readonly, accessPolicy); + } + + @Override + public BlockchainIdentity[] getHeaders(int fromIndex, int count) { + return accountSet.getHeaders(fromIndex, count); + } + + /** + * 返回用户总数; + * + * @return + */ + @Override + public long getTotal() { + return accountSet.getTotal(); + } + + public boolean isReadonly() { + return accountSet.isReadonly(); + } + + void setReadonly() { + accountSet.setReadonly(); + } + + @Override + public HashDigest getRootHash() { + return accountSet.getRootHash(); + } + + @Override + public MerkleProof getProof(Bytes key) { + return accountSet.getProof(key); + } + + @Override + public UserAccount getAccount(String address) { + return getAccount(Bytes.fromBase58(address)); + } + + @Override + public UserAccount getAccount(Bytes address) { + CompositeAccount baseAccount = accountSet.getAccount(address); + return new UserAccount(baseAccount); + } + + @Override + public boolean contains(Bytes address) { + return accountSet.contains(address); + } + + @Override + public UserAccount getAccount(Bytes address, long version) { + CompositeAccount baseAccount = accountSet.getAccount(address, version); + return new UserAccount(baseAccount); + } + + /** + * 注册一个新用户;
+ * + * 如果用户已经存在,则会引发 {@link LedgerException} 异常;
+ * + * 如果指定的地址和公钥不匹配,则会引发 {@link LedgerException} 异常; + * + * @param address 区块链地址; + * @param pubKey 公钥; + * @return 注册成功的用户对象; + */ + public UserAccount register(Bytes address, PubKey pubKey) { + CompositeAccount baseAccount = accountSet.register(address, pubKey); + return new UserAccount(baseAccount); + } + + @Override + public boolean isUpdated() { + return accountSet.isUpdated(); + } + + @Override + public void commit() { + accountSet.commit(); + } + + @Override + public void cancel() { + accountSet.cancel(); + } + } \ No newline at end of file diff --git a/source/ledger/ledger-model/pom.xml b/source/ledger/ledger-model/pom.xml index 90b5a759..0a5a09eb 100644 --- a/source/ledger/ledger-model/pom.xml +++ b/source/ledger/ledger-model/pom.xml @@ -1,43 +1,43 @@ - - 4.0.0 - - - com.jd.blockchain - ledger - 1.1.2.RELEASE - - ledger-model - - - - - com.jd.blockchain - utils-common - ${project.version} - - - com.jd.blockchain - utils-web - ${project.version} - - - - com.jd.blockchain - binary-proto - ${project.version} - - - com.jd.blockchain - crypto-framework - ${project.version} - - - com.jd.blockchain - crypto-classic - ${project.version} - - - + + 4.0.0 + + + com.jd.blockchain + ledger + 1.1.2.RELEASE + + ledger-model + + + + + com.jd.blockchain + utils-common + ${project.version} + + + com.jd.blockchain + utils-web + ${project.version} + + + + com.jd.blockchain + binary-proto + ${project.version} + + + com.jd.blockchain + crypto-framework + ${project.version} + + + com.jd.blockchain + crypto-classic + ${project.version} + + + \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/Contract.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/Contract.java index e1b7ea4e..490c5782 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/Contract.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/Contract.java @@ -1,14 +1,14 @@ -package com.jd.blockchain.contract; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -public @interface Contract { - - String name() default ""; - -} +package com.jd.blockchain.contract; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Contract { + + String name() default ""; + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractEvent.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractEvent.java index 6249945e..b6467b4f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractEvent.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/ContractEvent.java @@ -1,14 +1,14 @@ -package com.jd.blockchain.contract; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -public @interface ContractEvent { - - String name() default ""; - -} +package com.jd.blockchain.contract; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ContractEvent { + + String name() default ""; + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventHandle.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventHandle.java index ac193ab9..37b419a2 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventHandle.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/contract/EventHandle.java @@ -1,15 +1,15 @@ -package com.jd.blockchain.contract; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -@Target({ ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -public @interface EventHandle { - - - -} +package com.jd.blockchain.contract; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +@Target({ ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface EventHandle { + + + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockRollbackException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockRollbackException.java index c64f9e42..8eb6c2ee 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockRollbackException.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockRollbackException.java @@ -1,33 +1,33 @@ -package com.jd.blockchain.ledger; - -public class BlockRollbackException extends LedgerException { - - private static final long serialVersionUID = 3583192000738807503L; - - private TransactionState state; - - public BlockRollbackException(String message) { - this(TransactionState.SYSTEM_ERROR, message); - } - - public BlockRollbackException(TransactionState state, String message) { - super(message); - assert TransactionState.SUCCESS != state; - this.state = state; - } - - public BlockRollbackException(String message, Throwable cause) { - this(TransactionState.SYSTEM_ERROR, message, cause); - } - - public BlockRollbackException(TransactionState state, String message, Throwable cause) { - super(message, cause); - assert TransactionState.SUCCESS != state; - this.state = state; - } - - public TransactionState getState() { - return state; - } - -} +package com.jd.blockchain.ledger; + +public class BlockRollbackException extends LedgerException { + + private static final long serialVersionUID = 3583192000738807503L; + + private TransactionState state; + + public BlockRollbackException(String message) { + this(TransactionState.SYSTEM_ERROR, message); + } + + public BlockRollbackException(TransactionState state, String message) { + super(message); + assert TransactionState.SUCCESS != state; + this.state = state; + } + + public BlockRollbackException(String message, Throwable cause) { + this(TransactionState.SYSTEM_ERROR, message, cause); + } + + public BlockRollbackException(TransactionState state, String message, Throwable cause) { + super(message, cause); + assert TransactionState.SUCCESS != state; + this.state = state; + } + + public TransactionState getState() { + return state; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainEventType.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainEventType.java index aa7449a0..5e05c545 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainEventType.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainEventType.java @@ -1,83 +1,83 @@ -package com.jd.blockchain.ledger; - -/** - * 区块链事件类型;

- * - * 每一种事件类型都包含一个事件码;

- * - * 在一次事件消息中,可以包含多种事件,而且事件之间具有嵌套关系;
- * - * 例如:

- * - * 一个区块生成事件 {@link #BLOCK_GENERATED} 含了交易提交事件 - * {@link #TRANSACTION_COMMITED};

- * - * 交易提交事件 {@link #TRANSACTION_COMMITED} 必然包含账户更新事件 {@link #ACCOUNT_UPDATED};

- * - * 更进一步,账户更新事件 {@link #ACCOUNT_UPDATED} 也必然包含了权限更新事件 - * {@link #PRIVILEGE_UPDATED}、负载数据更新事件 {@link #PAYLOAD_UPDATED} - * 、合约脚本更新事件{@link #SCRIPT_UPDATED} 、合约脚本执行事件{@link #SCRIPT_INVOKED} 这4种事件中的一种或者多种事件;

- * - * 这种嵌套关系,表现在事件的编码中是子事件码的比特位中包含了上级事件码; - * - * @author huanghaiquan - * - */ -public enum BlockchainEventType { - - /** - * 生成新区块;
- * - * 事件码:1 (0x01) - * - */ - BLOCK_GENERATED(1), - - /** - * 成功提交新交易;
- * - * 事件码:3 (0x03) - */ - TRANSACTION_COMMITED(3), - - /** - * 账户的版本已更新;
- * - * 事件码:259 (0x103) - */ - ACCOUNT_UPDATED(259), - - /** - * 账户权限已被更新;
- * - * 事件码:65795 (0x10103) - */ - PRIVILEGE_UPDATED(65795), - - /** - * 账户负载数据已被更新;
- * - * 事件码:131331 (0x20103) - */ - PAYLOAD_UPDATED(131331), - - /** - * 合约脚本已被更新;
- * - * 事件码:262403 (0x40103) - */ - SCRIPT_UPDATED(262403), - - /** - * 合约脚本已被调用;
- * - * 事件码:524547 (0x80103) - */ - SCRIPT_INVOKED(524547); - - public final int CODE; - - private BlockchainEventType(int code) { - this.CODE = code; - } -} +package com.jd.blockchain.ledger; + +/** + * 区块链事件类型;

+ * + * 每一种事件类型都包含一个事件码;

+ * + * 在一次事件消息中,可以包含多种事件,而且事件之间具有嵌套关系;
+ * + * 例如:

+ * + * 一个区块生成事件 {@link #BLOCK_GENERATED} 含了交易提交事件 + * {@link #TRANSACTION_COMMITED};

+ * + * 交易提交事件 {@link #TRANSACTION_COMMITED} 必然包含账户更新事件 {@link #ACCOUNT_UPDATED};

+ * + * 更进一步,账户更新事件 {@link #ACCOUNT_UPDATED} 也必然包含了权限更新事件 + * {@link #PRIVILEGE_UPDATED}、负载数据更新事件 {@link #PAYLOAD_UPDATED} + * 、合约脚本更新事件{@link #SCRIPT_UPDATED} 、合约脚本执行事件{@link #SCRIPT_INVOKED} 这4种事件中的一种或者多种事件;

+ * + * 这种嵌套关系,表现在事件的编码中是子事件码的比特位中包含了上级事件码; + * + * @author huanghaiquan + * + */ +public enum BlockchainEventType { + + /** + * 生成新区块;
+ * + * 事件码:1 (0x01) + * + */ + BLOCK_GENERATED(1), + + /** + * 成功提交新交易;
+ * + * 事件码:3 (0x03) + */ + TRANSACTION_COMMITED(3), + + /** + * 账户的版本已更新;
+ * + * 事件码:259 (0x103) + */ + ACCOUNT_UPDATED(259), + + /** + * 账户权限已被更新;
+ * + * 事件码:65795 (0x10103) + */ + PRIVILEGE_UPDATED(65795), + + /** + * 账户负载数据已被更新;
+ * + * 事件码:131331 (0x20103) + */ + PAYLOAD_UPDATED(131331), + + /** + * 合约脚本已被更新;
+ * + * 事件码:262403 (0x40103) + */ + SCRIPT_UPDATED(262403), + + /** + * 合约脚本已被调用;
+ * + * 事件码:524547 (0x80103) + */ + SCRIPT_INVOKED(524547); + + public final int CODE; + + private BlockchainEventType(int code) { + this.CODE = code; + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainIdentityData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainIdentityData.java index 19e3522a..50a1d996 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainIdentityData.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainIdentityData.java @@ -1,216 +1,216 @@ -package com.jd.blockchain.ledger; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.Externalizable; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -import com.jd.blockchain.crypto.AddressEncoding; -import com.jd.blockchain.crypto.CryptoAlgorithm; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.io.ByteArray; -import com.jd.blockchain.utils.io.BytesEncoding; -import com.jd.blockchain.utils.io.BytesReader; -import com.jd.blockchain.utils.io.BytesUtils; -import com.jd.blockchain.utils.io.BytesWriter; -import com.jd.blockchain.utils.io.RuntimeIOException; - -/** - * 区块链身份; - * - * @author huanghaiquan - * - */ -public class BlockchainIdentityData implements BytesWriter, BytesReader, Externalizable, BlockchainIdentity { - - private Bytes address; - - private PubKey pubKey; - - private BlockchainIdentityData() { - } - - public BlockchainIdentityData(PubKey pubKey) { - this.pubKey = pubKey; - this.address = AddressEncoding.generateAddress(pubKey); - } - - public BlockchainIdentityData(CryptoAlgorithm algorithm, ByteArray pubKeyBytes) { - this.pubKey = new PubKey(algorithm, pubKeyBytes.bytes()); - this.address = AddressEncoding.generateAddress(pubKey); - } - - public BlockchainIdentityData(Bytes address, PubKey pubKey) { - if (!verifyAddress(address, pubKey)) { - throw new IllegalArgumentException("Blockchain address is mismatch with the pub-key!"); - } - this.address = address; - this.pubKey = pubKey; - } - - public static boolean verifyAddress(Bytes address, PubKey pubKey) { - Bytes addr = AddressEncoding.generateAddress(pubKey); - return addr.equals(address); - } - - @Override - public void resolvFrom(InputStream in) throws IOException { - Bytes addr = AddressEncoding.readAddress(in); - byte[] value = BytesEncoding.readInShort(in); - PubKey pk = new PubKey(value); - this.address = addr; - this.pubKey = pk; - } - - @Override - public void writeTo(OutputStream out) throws IOException { - AddressEncoding.writeAddress(address, out); - BytesEncoding.writeInShort(pubKey.toBytes(), out); - } - - /* - * (non-Javadoc) - * - * @see com.jd.blockchain.ledger.BlockchainIdentity#getAddress() - */ - @Override - public Bytes getAddress() { - return address; - } - - /* - * (non-Javadoc) - * - * @see com.jd.blockchain.ledger.BlockchainIdentity#getPubKey() - */ - @Override - public PubKey getPubKey() { - return pubKey; - } - - public static BlockchainIdentity resolveFrom(ByteArray bytes) { - try { - BlockchainIdentityData id = new BlockchainIdentityData(); - id.resolvFrom(bytes.asInputStream()); - return id; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static ByteArray toBytes(List identities) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - BytesUtils.writeInt(identities.size(), out); - for (BlockchainIdentityData identity : identities) { - identity.writeTo(out); - } - - return ByteArray.wrap(out.toByteArray()); - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static List resolveIdentitiesFrom(ByteArray bytes) { - try { - InputStream in = bytes.asInputStream(); - int identitiesLen = BytesUtils.readInt(in); - List identities = new ArrayList<>(); - for (int i = 0; i < identitiesLen; i++) { - BlockchainIdentityData id = new BlockchainIdentityData(); - id.resolvFrom(in); - - identities.add(id); - } - - return identities; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public ByteArray toBytes() { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - writeTo(out); - return ByteArray.wrap(out.toByteArray()); - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - @Override - public int hashCode() { - return address.hashCode(); - } - - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } - if (!(other instanceof BlockchainIdentityData)) { - return false; - } - - BlockchainIdentity identity = (BlockchainIdentity) other; - - if (!getAddress().equals(identity.getAddress())) { - return false; - } - return pubKey.equals(identity.getPubKey()); - } - - /** - * The object implements the writeExternal method to save its contents by - * calling the methods of DataOutput for its primitive values or calling the - * writeObject method of ObjectOutput for objects, strings, and arrays. - * - * @param out - * the stream to write the object to - * @throws IOException - * Includes any I/O exceptions that may occur - * @serialData Overriding methods should use this tag to describe the data - * layout of this Externalizable object. List the sequence of - * element types and, if possible, relate the element to a - * public/protected field and/or method of this Externalizable - * class. - */ - @Override - public void writeExternal(ObjectOutput out) throws IOException { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - writeTo(os); - byte[] bts = os.toByteArray(); - out.writeInt(bts.length); - out.write(bts); - } - - /** - * The object implements the readExternal method to restore its contents by - * calling the methods of DataInput for primitive types and readObject for - * objects, strings and arrays. The readExternal method must read the values in - * the same sequence and with the same types as were written by writeExternal. - * - * @param in - * the stream to read data from in order to restore the object - * @throws IOException - * if I/O errors occur - * @throws ClassNotFoundException - * If the class for an object being restored cannot be found. - */ - @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - int len = in.readInt(); - byte[] bts = new byte[len]; - in.readFully(bts); - this.resolvFrom(new ByteArrayInputStream(bts)); - } -} +package com.jd.blockchain.ledger; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Externalizable; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.CryptoAlgorithm; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.io.ByteArray; +import com.jd.blockchain.utils.io.BytesEncoding; +import com.jd.blockchain.utils.io.BytesReader; +import com.jd.blockchain.utils.io.BytesUtils; +import com.jd.blockchain.utils.io.BytesWriter; +import com.jd.blockchain.utils.io.RuntimeIOException; + +/** + * 区块链身份; + * + * @author huanghaiquan + * + */ +public class BlockchainIdentityData implements BytesWriter, BytesReader, Externalizable, BlockchainIdentity { + + private Bytes address; + + private PubKey pubKey; + + private BlockchainIdentityData() { + } + + public BlockchainIdentityData(PubKey pubKey) { + this.pubKey = pubKey; + this.address = AddressEncoding.generateAddress(pubKey); + } + + public BlockchainIdentityData(CryptoAlgorithm algorithm, ByteArray pubKeyBytes) { + this.pubKey = new PubKey(algorithm, pubKeyBytes.bytes()); + this.address = AddressEncoding.generateAddress(pubKey); + } + + public BlockchainIdentityData(Bytes address, PubKey pubKey) { + if (!verifyAddress(address, pubKey)) { + throw new IllegalArgumentException("Blockchain address is mismatch with the pub-key!"); + } + this.address = address; + this.pubKey = pubKey; + } + + public static boolean verifyAddress(Bytes address, PubKey pubKey) { + Bytes addr = AddressEncoding.generateAddress(pubKey); + return addr.equals(address); + } + + @Override + public void resolvFrom(InputStream in) throws IOException { + Bytes addr = AddressEncoding.readAddress(in); + byte[] value = BytesEncoding.readInShort(in); + PubKey pk = new PubKey(value); + this.address = addr; + this.pubKey = pk; + } + + @Override + public void writeTo(OutputStream out) throws IOException { + AddressEncoding.writeAddress(address, out); + BytesEncoding.writeInShort(pubKey.toBytes(), out); + } + + /* + * (non-Javadoc) + * + * @see com.jd.blockchain.ledger.BlockchainIdentity#getAddress() + */ + @Override + public Bytes getAddress() { + return address; + } + + /* + * (non-Javadoc) + * + * @see com.jd.blockchain.ledger.BlockchainIdentity#getPubKey() + */ + @Override + public PubKey getPubKey() { + return pubKey; + } + + public static BlockchainIdentity resolveFrom(ByteArray bytes) { + try { + BlockchainIdentityData id = new BlockchainIdentityData(); + id.resolvFrom(bytes.asInputStream()); + return id; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static ByteArray toBytes(List identities) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BytesUtils.writeInt(identities.size(), out); + for (BlockchainIdentityData identity : identities) { + identity.writeTo(out); + } + + return ByteArray.wrap(out.toByteArray()); + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static List resolveIdentitiesFrom(ByteArray bytes) { + try { + InputStream in = bytes.asInputStream(); + int identitiesLen = BytesUtils.readInt(in); + List identities = new ArrayList<>(); + for (int i = 0; i < identitiesLen; i++) { + BlockchainIdentityData id = new BlockchainIdentityData(); + id.resolvFrom(in); + + identities.add(id); + } + + return identities; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public ByteArray toBytes() { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + writeTo(out); + return ByteArray.wrap(out.toByteArray()); + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + @Override + public int hashCode() { + return address.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!(other instanceof BlockchainIdentityData)) { + return false; + } + + BlockchainIdentity identity = (BlockchainIdentity) other; + + if (!getAddress().equals(identity.getAddress())) { + return false; + } + return pubKey.equals(identity.getPubKey()); + } + + /** + * The object implements the writeExternal method to save its contents by + * calling the methods of DataOutput for its primitive values or calling the + * writeObject method of ObjectOutput for objects, strings, and arrays. + * + * @param out + * the stream to write the object to + * @throws IOException + * Includes any I/O exceptions that may occur + * @serialData Overriding methods should use this tag to describe the data + * layout of this Externalizable object. List the sequence of + * element types and, if possible, relate the element to a + * public/protected field and/or method of this Externalizable + * class. + */ + @Override + public void writeExternal(ObjectOutput out) throws IOException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + writeTo(os); + byte[] bts = os.toByteArray(); + out.writeInt(bts.length); + out.write(bts); + } + + /** + * The object implements the readExternal method to restore its contents by + * calling the methods of DataInput for primitive types and readObject for + * objects, strings and arrays. The readExternal method must read the values in + * the same sequence and with the same types as were written by writeExternal. + * + * @param in + * the stream to read data from in order to restore the object + * @throws IOException + * if I/O errors occur + * @throws ClassNotFoundException + * If the class for an object being restored cannot be found. + */ + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + int len = in.readInt(); + byte[] bts = new byte[len]; + in.readFully(bts); + this.resolvFrom(new ByteArrayInputStream(bts)); + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainKeyGenerator.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainKeyGenerator.java index 6d751f87..0c1ce1aa 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainKeyGenerator.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainKeyGenerator.java @@ -1,40 +1,40 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.crypto.CryptoAlgorithm; -import com.jd.blockchain.crypto.AsymmetricKeypair; -import com.jd.blockchain.crypto.Crypto; -import com.jd.blockchain.crypto.SignatureFunction; - -/** - * 区块链密钥生成器; - * - * @author huanghaiquan - * - */ -public class BlockchainKeyGenerator { - - public static final String DEFAULT_ALGORITHM = "ED25519"; - - private BlockchainKeyGenerator() { - } - - public static BlockchainKeyGenerator getInstance() { - return new BlockchainKeyGenerator(); - } - - public BlockchainKeypair generate() { - return generate(DEFAULT_ALGORITHM); - } - - public BlockchainKeypair generate(String algorithmName) { - CryptoAlgorithm algorithm = Crypto.getAlgorithm(algorithmName); - return generate(algorithm); - } - - public BlockchainKeypair generate(CryptoAlgorithm signatureAlgorithm) { - SignatureFunction signFunc = Crypto.getSignatureFunction(signatureAlgorithm); - AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(); - return new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); - } - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.crypto.CryptoAlgorithm; +import com.jd.blockchain.crypto.AsymmetricKeypair; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.SignatureFunction; + +/** + * 区块链密钥生成器; + * + * @author huanghaiquan + * + */ +public class BlockchainKeyGenerator { + + public static final String DEFAULT_ALGORITHM = "ED25519"; + + private BlockchainKeyGenerator() { + } + + public static BlockchainKeyGenerator getInstance() { + return new BlockchainKeyGenerator(); + } + + public BlockchainKeypair generate() { + return generate(DEFAULT_ALGORITHM); + } + + public BlockchainKeypair generate(String algorithmName) { + CryptoAlgorithm algorithm = Crypto.getAlgorithm(algorithmName); + return generate(algorithm); + } + + public BlockchainKeypair generate(CryptoAlgorithm signatureAlgorithm) { + SignatureFunction signFunc = Crypto.getSignatureFunction(signatureAlgorithm); + AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(); + return new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey()); + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainKeypair.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainKeypair.java index 00001591..269c9eba 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainKeypair.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/BlockchainKeypair.java @@ -1,46 +1,46 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.crypto.AsymmetricKeypair; -import com.jd.blockchain.crypto.PrivKey; -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.utils.Bytes; - -/** - * 区块链密钥对; - * - * @author huanghaiquan - * - */ -public class BlockchainKeypair extends AsymmetricKeypair { - - private BlockchainIdentity id; - -// public BlockchainKeyPair(CryptoAlgorithm algorithm, ByteArray pubKeyBytes, ByteArray privKeyBytes) { -// this.id = new BlockchainIdentity(algorithm, pubKeyBytes); -// privKey = new PrivKey(algorithm, privKeyBytes.bytes()); -// } - - public BlockchainKeypair(String address, PubKey pubKey, PrivKey privKey) { - super(pubKey, privKey); - if (pubKey.getAlgorithm() != privKey.getAlgorithm()) { - throw new IllegalArgumentException("The PublicKey's algorithm is different from the PrivateKey's!"); - } - this.id = new BlockchainIdentityData(Bytes.fromBase58(address), pubKey); - } - - public BlockchainKeypair(PubKey pubKey, PrivKey privKey) { - super(pubKey, privKey); - if (pubKey.getAlgorithm() != privKey.getAlgorithm()) { - throw new IllegalArgumentException("The PublicKey's algorithm is different from the PrivateKey's!"); - } - this.id = new BlockchainIdentityData(pubKey); - } - - public Bytes getAddress() { - return id.getAddress(); - } - - public BlockchainIdentity getIdentity() { - return id; - } -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.crypto.AsymmetricKeypair; +import com.jd.blockchain.crypto.PrivKey; +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.utils.Bytes; + +/** + * 区块链密钥对; + * + * @author huanghaiquan + * + */ +public class BlockchainKeypair extends AsymmetricKeypair { + + private BlockchainIdentity id; + +// public BlockchainKeyPair(CryptoAlgorithm algorithm, ByteArray pubKeyBytes, ByteArray privKeyBytes) { +// this.id = new BlockchainIdentity(algorithm, pubKeyBytes); +// privKey = new PrivKey(algorithm, privKeyBytes.bytes()); +// } + + public BlockchainKeypair(String address, PubKey pubKey, PrivKey privKey) { + super(pubKey, privKey); + if (pubKey.getAlgorithm() != privKey.getAlgorithm()) { + throw new IllegalArgumentException("The PublicKey's algorithm is different from the PrivateKey's!"); + } + this.id = new BlockchainIdentityData(Bytes.fromBase58(address), pubKey); + } + + public BlockchainKeypair(PubKey pubKey, PrivKey privKey) { + super(pubKey, privKey); + if (pubKey.getAlgorithm() != privKey.getAlgorithm()) { + throw new IllegalArgumentException("The PublicKey's algorithm is different from the PrivateKey's!"); + } + this.id = new BlockchainIdentityData(pubKey); + } + + public Bytes getAddress() { + return id.getAddress(); + } + + public BlockchainIdentity getIdentity() { + return id; + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CodeDeployOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CodeDeployOperation.java index 2816b952..1e902c21 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CodeDeployOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/CodeDeployOperation.java @@ -1,23 +1,23 @@ -//package com.jd.blockchain.ledger; -// -//import com.jd.blockchain.ledger.data.AccountUpdateOperationBuilder; -// -///** -// * 合约代码部署操作; -// * -// * @author huanghaiquan -// * -// */ -//public interface CodeDeployOperation extends AccountUpdateOperationBuilder { -// -// /** -// * 修改脚本; -// * -// * @param code -// * 合约代码; -// * @param codeVersion -// * 预期的当前的代码的版本;如果指定为 -1,则不进行版本检查; -// */ -// void set(BlockchainIdentity id, String code, long codeVersion); -// -//} +//package com.jd.blockchain.ledger; +// +//import com.jd.blockchain.ledger.data.AccountUpdateOperationBuilder; +// +///** +// * 合约代码部署操作; +// * +// * @author huanghaiquan +// * +// */ +//public interface CodeDeployOperation extends AccountUpdateOperationBuilder { +// +// /** +// * 修改脚本; +// * +// * @param code +// * 合约代码; +// * @param codeVersion +// * 预期的当前的代码的版本;如果指定为 -1,则不进行版本检查; +// */ +// void set(BlockchainIdentity id, String code, long codeVersion); +// +//} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractCodeDeployOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractCodeDeployOperation.java index 48190979..bc27beef 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractCodeDeployOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/ContractCodeDeployOperation.java @@ -1,31 +1,31 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.binaryproto.PrimitiveType; -import com.jd.blockchain.consts.DataCodes; - -@DataContract(code= DataCodes.TX_OP_CONTRACT_DEPLOY) -public interface ContractCodeDeployOperation extends Operation { - - @DataField(order=2, refContract = true) - BlockchainIdentity getContractID(); - - @DataField(order=3, primitiveType=PrimitiveType.BYTES) - byte[] getChainCode(); - - - /** - * 地址签名; - * - *
- * 这是合约账户身份 ({@link #getContractID()}) 使用对应的私钥对地址做出的签名; - *
- * 在注册时将校验此签名与账户地址、公钥是否相匹配,以此保证只有私钥的持有者才能注册相应的合约账户,确保合约账户的唯一性; - * - * @return - */ - @DataField(order=4, refContract = true) - DigitalSignature getAddressSignature(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code= DataCodes.TX_OP_CONTRACT_DEPLOY) +public interface ContractCodeDeployOperation extends Operation { + + @DataField(order=2, refContract = true) + BlockchainIdentity getContractID(); + + @DataField(order=3, primitiveType=PrimitiveType.BYTES) + byte[] getChainCode(); + + + /** + * 地址签名; + * + *
+ * 这是合约账户身份 ({@link #getContractID()}) 使用对应的私钥对地址做出的签名; + *
+ * 在注册时将校验此签名与账户地址、公钥是否相匹配,以此保证只有私钥的持有者才能注册相应的合约账户,确保合约账户的唯一性; + * + * @return + */ + @DataField(order=4, refContract = true) + DigitalSignature getAddressSignature(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountKVSetOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountKVSetOperation.java index c83cea9a..8c5d115b 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountKVSetOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountKVSetOperation.java @@ -1,32 +1,32 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.binaryproto.PrimitiveType; -import com.jd.blockchain.consts.DataCodes; -import com.jd.blockchain.utils.Bytes; - -@DataContract(code= DataCodes.TX_OP_DATA_ACC_SET) -public interface DataAccountKVSetOperation extends Operation { - - @DataField(order=2, primitiveType=PrimitiveType.BYTES) - Bytes getAccountAddress(); - - @DataField(order=3, list=true, refContract=true) - KVWriteEntry[] getWriteSet(); - - - @DataContract(code=DataCodes.TX_OP_DATA_ACC_SET_KV) - public static interface KVWriteEntry{ - - @DataField(order=1, primitiveType=PrimitiveType.TEXT) - String getKey(); - - @DataField(order=2, refContract = true) - BytesValue getValue(); - - @DataField(order=3, primitiveType=PrimitiveType.INT64) - long getExpectedVersion(); - } - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; +import com.jd.blockchain.utils.Bytes; + +@DataContract(code= DataCodes.TX_OP_DATA_ACC_SET) +public interface DataAccountKVSetOperation extends Operation { + + @DataField(order=2, primitiveType=PrimitiveType.BYTES) + Bytes getAccountAddress(); + + @DataField(order=3, list=true, refContract=true) + KVWriteEntry[] getWriteSet(); + + + @DataContract(code=DataCodes.TX_OP_DATA_ACC_SET_KV) + public static interface KVWriteEntry{ + + @DataField(order=1, primitiveType=PrimitiveType.TEXT) + String getKey(); + + @DataField(order=2, refContract = true) + BytesValue getValue(); + + @DataField(order=3, primitiveType=PrimitiveType.INT64) + long getExpectedVersion(); + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountRegisterOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountRegisterOperation.java index f75621f7..a923494c 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountRegisterOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataAccountRegisterOperation.java @@ -1,26 +1,26 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.consts.DataCodes; - -@DataContract(code= DataCodes.TX_OP_DATA_ACC_REG) -public interface DataAccountRegisterOperation extends Operation { - - @DataField(order=1, refContract = true) - BlockchainIdentity getAccountID(); - - /** - * 地址签名; - * - *
- * 这是账户身份 ({@link #getAccountID()}) 使用对应的私钥对地址做出的签名; - *
- * 在注册时将校验此签名与账户地址、公钥是否相匹配,以此保证只有私钥的持有者才能注册数据账户,确保数据账户的唯一性; - * - * @return - */ - @DataField(order=2, refContract = true) - DigitalSignature getAddressSignature(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code= DataCodes.TX_OP_DATA_ACC_REG) +public interface DataAccountRegisterOperation extends Operation { + + @DataField(order=1, refContract = true) + BlockchainIdentity getAccountID(); + + /** + * 地址签名; + * + *
+ * 这是账户身份 ({@link #getAccountID()}) 使用对应的私钥对地址做出的签名; + *
+ * 在注册时将校验此签名与账户地址、公钥是否相匹配,以此保证只有私钥的持有者才能注册数据账户,确保数据账户的唯一性; + * + * @return + */ + @DataField(order=2, refContract = true) + DigitalSignature getAddressSignature(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java index 6395bcc2..2d5cda55 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataType.java @@ -1,185 +1,185 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.BaseType; -import com.jd.blockchain.binaryproto.EnumContract; -import com.jd.blockchain.binaryproto.EnumField; -import com.jd.blockchain.binaryproto.PrimitiveType; -import com.jd.blockchain.consts.DataCodes; - -/** - * 键值操作的数据类型; - * - * @author huanghaiquan - * - */ -@EnumContract(code = DataCodes.ENUM_TYPE_BYTES_VALUE_TYPE) -public enum DataType { - - /** - * 空; - */ - NIL(PrimitiveType.NIL.CODE), - - /** - * 布尔型; - */ - BOOLEAN(PrimitiveType.BOOLEAN.CODE), - - /** - * 数值型: - */ - - INT8(PrimitiveType.INT8.CODE), - - INT16(PrimitiveType.INT16.CODE), - - INT32(PrimitiveType.INT32.CODE), - - INT64(PrimitiveType.INT64.CODE), - - /** - * 文本数据; - */ - TEXT(PrimitiveType.TEXT.CODE), - - /** - * 二进制数据; - */ - BYTES(PrimitiveType.BYTES.CODE), - - /** - * 时间戳; - */ - TIMESTAMP((byte) (BaseType.INTEGER | 0x08)), - - /** - * 文本数据; - */ - JSON((byte) (BaseType.TEXT | 0x01)), - - /** - * 文本数据; - */ - XML((byte) (BaseType.TEXT | 0x02)), - - /** - * 大整数; - */ - BIG_INT((byte) (BaseType.BYTES | 0x01)), - - /** - * 图片; - */ - IMG((byte) (BaseType.BYTES | 0x02)), - - /** - * 视频; - */ - VIDEO((byte) (BaseType.BYTES | 0x03)), - - /** - * 位置坐标; - */ - LOCATION((byte) (BaseType.BYTES | 0x04)), - - /** - * 公钥; - */ - PUB_KEY((byte) (BaseType.BYTES | 0x05)), - - /** - * 签名摘要; - */ - SIGNATURE_DIGEST((byte) (BaseType.BYTES | 0x06)), - - /** - * 哈希摘要; - */ - HASH_DIGEST((byte) (BaseType.BYTES | 0x07)), - - /** - * 加密数据; - */ - ENCRYPTED_DATA((byte) (BaseType.BYTES | 0x08)), - - /** - * DataContract 数据; - */ - DATA_CONTRACT((byte) (BaseType.EXT | 0x01)); - - - - public static final boolean BOOLEAN_DEFAULT_VALUE = false; - - public static final byte INT8_DEFAULT_VALUE = 0; - - public static final short INT16_DEFAULT_VALUE = 0; - - public static final int INT32_DEFAULT_VALUE = 0; - - public static final long INT64_DEFAULT_VALUE = 0; - - - - @EnumField(type = PrimitiveType.INT8) - public final byte CODE; - - private DataType(byte code) { - this.CODE = code; - } - - /** - * 是否表示“文本类型”或“文本衍生类型”; - * - * @return - */ - public boolean isText() { - return BaseType.TEXT == (BaseType.TEXT & CODE); - } - - /** - * 是否表示“字节类型”或“字节衍生类型”; - * - * @return - */ - public boolean isBytes() { - return BaseType.BYTES == (BaseType.BYTES & CODE); - } - - /** - * 是否表示“整数类型”或“整数衍生类型”; - * - * @return - */ - public boolean isInteger() { - return BaseType.INTEGER == (BaseType.INTEGER & CODE); - } - - /** - * 是否表示“布尔类型”; - * - * @return - */ - public boolean isBoolean() { - return BaseType.BOOLEAN == (BaseType.BOOLEAN & CODE); - } - - /** - * 是否表示“扩展类型”; - * - * @return - */ - public boolean isExt() { - return BaseType.EXT == (BaseType.EXT & CODE); - } - - public static DataType valueOf(byte code) { - for (DataType dataType : DataType.values()) { - if (dataType.CODE == code) { - return dataType; - } - } - throw new IllegalArgumentException("Code [" + code + "] not supported by BytesValueType enum!"); - } - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.BaseType; +import com.jd.blockchain.binaryproto.EnumContract; +import com.jd.blockchain.binaryproto.EnumField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +/** + * 键值操作的数据类型; + * + * @author huanghaiquan + * + */ +@EnumContract(code = DataCodes.ENUM_TYPE_BYTES_VALUE_TYPE) +public enum DataType { + + /** + * 空; + */ + NIL(PrimitiveType.NIL.CODE), + + /** + * 布尔型; + */ + BOOLEAN(PrimitiveType.BOOLEAN.CODE), + + /** + * 数值型: + */ + + INT8(PrimitiveType.INT8.CODE), + + INT16(PrimitiveType.INT16.CODE), + + INT32(PrimitiveType.INT32.CODE), + + INT64(PrimitiveType.INT64.CODE), + + /** + * 文本数据; + */ + TEXT(PrimitiveType.TEXT.CODE), + + /** + * 二进制数据; + */ + BYTES(PrimitiveType.BYTES.CODE), + + /** + * 时间戳; + */ + TIMESTAMP((byte) (BaseType.INTEGER | 0x08)), + + /** + * 文本数据; + */ + JSON((byte) (BaseType.TEXT | 0x01)), + + /** + * 文本数据; + */ + XML((byte) (BaseType.TEXT | 0x02)), + + /** + * 大整数; + */ + BIG_INT((byte) (BaseType.BYTES | 0x01)), + + /** + * 图片; + */ + IMG((byte) (BaseType.BYTES | 0x02)), + + /** + * 视频; + */ + VIDEO((byte) (BaseType.BYTES | 0x03)), + + /** + * 位置坐标; + */ + LOCATION((byte) (BaseType.BYTES | 0x04)), + + /** + * 公钥; + */ + PUB_KEY((byte) (BaseType.BYTES | 0x05)), + + /** + * 签名摘要; + */ + SIGNATURE_DIGEST((byte) (BaseType.BYTES | 0x06)), + + /** + * 哈希摘要; + */ + HASH_DIGEST((byte) (BaseType.BYTES | 0x07)), + + /** + * 加密数据; + */ + ENCRYPTED_DATA((byte) (BaseType.BYTES | 0x08)), + + /** + * DataContract 数据; + */ + DATA_CONTRACT((byte) (BaseType.EXT | 0x01)); + + + + public static final boolean BOOLEAN_DEFAULT_VALUE = false; + + public static final byte INT8_DEFAULT_VALUE = 0; + + public static final short INT16_DEFAULT_VALUE = 0; + + public static final int INT32_DEFAULT_VALUE = 0; + + public static final long INT64_DEFAULT_VALUE = 0; + + + + @EnumField(type = PrimitiveType.INT8) + public final byte CODE; + + private DataType(byte code) { + this.CODE = code; + } + + /** + * 是否表示“文本类型”或“文本衍生类型”; + * + * @return + */ + public boolean isText() { + return BaseType.TEXT == (BaseType.TEXT & CODE); + } + + /** + * 是否表示“字节类型”或“字节衍生类型”; + * + * @return + */ + public boolean isBytes() { + return BaseType.BYTES == (BaseType.BYTES & CODE); + } + + /** + * 是否表示“整数类型”或“整数衍生类型”; + * + * @return + */ + public boolean isInteger() { + return BaseType.INTEGER == (BaseType.INTEGER & CODE); + } + + /** + * 是否表示“布尔类型”; + * + * @return + */ + public boolean isBoolean() { + return BaseType.BOOLEAN == (BaseType.BOOLEAN & CODE); + } + + /** + * 是否表示“扩展类型”; + * + * @return + */ + public boolean isExt() { + return BaseType.EXT == (BaseType.EXT & CODE); + } + + public static DataType valueOf(byte code) { + for (DataType dataType : DataType.values()) { + if (dataType.CODE == code) { + return dataType; + } + } + throw new IllegalArgumentException("Code [" + code + "] not supported by BytesValueType enum!"); + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java index 9831c0cc..29042200 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DataVersionConflictException.java @@ -1,27 +1,27 @@ -package com.jd.blockchain.ledger; - -public class DataVersionConflictException extends LedgerException { - - private static final long serialVersionUID = 3583192000738807503L; - - private TransactionState state; - - public DataVersionConflictException() { - this(TransactionState.DATA_VERSION_CONFLICT, null); - } - - public DataVersionConflictException(String message) { - this(TransactionState.DATA_VERSION_CONFLICT, message); - } - - private DataVersionConflictException(TransactionState state, String message) { - super(message); - assert TransactionState.SUCCESS != state; - this.state = state; - } - - public TransactionState getState() { - return state; - } - -} +package com.jd.blockchain.ledger; + +public class DataVersionConflictException extends LedgerException { + + private static final long serialVersionUID = 3583192000738807503L; + + private TransactionState state; + + public DataVersionConflictException() { + this(TransactionState.DATA_VERSION_CONFLICT, null); + } + + public DataVersionConflictException(String message) { + this(TransactionState.DATA_VERSION_CONFLICT, message); + } + + private DataVersionConflictException(TransactionState state, String message) { + super(message); + assert TransactionState.SUCCESS != state; + this.state = state; + } + + public TransactionState getState() { + return state; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DigitalSignature.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DigitalSignature.java index f5acef07..4616f7ee 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DigitalSignature.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/DigitalSignature.java @@ -1,15 +1,15 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.consts.DataCodes; - -/** - * 数字签名; - * - * @author huanghaiquan - * - */ -@DataContract(code= DataCodes.DIGITALSIGNATURE) -public interface DigitalSignature extends DigitalSignatureBody { - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.consts.DataCodes; + +/** + * 数字签名; + * + * @author huanghaiquan + * + */ +@DataContract(code= DataCodes.DIGITALSIGNATURE) +public interface DigitalSignature extends DigitalSignatureBody { + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/EndpointRequest.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/EndpointRequest.java index 00253b85..391ac609 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/EndpointRequest.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/EndpointRequest.java @@ -1,30 +1,30 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.binaryproto.PrimitiveType; -import com.jd.blockchain.consts.DataCodes; -import com.jd.blockchain.crypto.HashDigest; - -@DataContract(code= DataCodes.REQUEST_ENDPOINT) -public interface EndpointRequest { - - @DataField(order=1, primitiveType = PrimitiveType.BYTES) - HashDigest getHash(); - /** - * 交易内容; - * - * @return - */ - @DataField(order=2, refContract=true) - TransactionContent getTransactionContent(); - - /** - * 终端用户的签名列表; - * - * @return - */ - @DataField(order=3, list=true, refContract=true) - DigitalSignature[] getEndpointSignatures(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; +import com.jd.blockchain.crypto.HashDigest; + +@DataContract(code= DataCodes.REQUEST_ENDPOINT) +public interface EndpointRequest { + + @DataField(order=1, primitiveType = PrimitiveType.BYTES) + HashDigest getHash(); + /** + * 交易内容; + * + * @return + */ + @DataField(order=2, refContract=true) + TransactionContent getTransactionContent(); + + /** + * 终端用户的签名列表; + * + * @return + */ + @DataField(order=3, list=true, refContract=true) + DigitalSignature[] getEndpointSignatures(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashAlgorithm.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashAlgorithm.java index 03953c21..61674095 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashAlgorithm.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashAlgorithm.java @@ -1,46 +1,46 @@ -//package com.jd.blockchain.ledger; -// -///** -// * Hash 算法的代码常量; -// * -// * @author zhaoming9 -// * -// */ -//public enum HashAlgorithm { -// -// RIPE160((byte) 1), -// -// SHA256((byte) 2), -// -// SM3((byte) 4); -// -// public final byte CODE; -// -// private HashAlgorithm(byte algorithm) { -// CODE = algorithm; -// } -// -// public byte getAlgorithm() { -// return CODE; -// } -// -// public static HashAlgorithm valueOf(byte algorithm) { -// for (HashAlgorithm hashAlgorithm : HashAlgorithm.values()) { -// if (hashAlgorithm.CODE == algorithm) { -// return hashAlgorithm; -// } -// } -// throw new IllegalArgumentException("Unsupported hash algorithm [" + algorithm + "]!"); -// } -// -// public static void checkHashAlgorithm(HashAlgorithm algorithm) { -// switch (algorithm) { -// case RIPE160: -// break; -// case SHA256: -// break; -// default: -// throw new IllegalArgumentException("Unsupported hash algorithm [" + algorithm + "]!"); -// } -// } -//} +//package com.jd.blockchain.ledger; +// +///** +// * Hash 算法的代码常量; +// * +// * @author zhaoming9 +// * +// */ +//public enum HashAlgorithm { +// +// RIPE160((byte) 1), +// +// SHA256((byte) 2), +// +// SM3((byte) 4); +// +// public final byte CODE; +// +// private HashAlgorithm(byte algorithm) { +// CODE = algorithm; +// } +// +// public byte getAlgorithm() { +// return CODE; +// } +// +// public static HashAlgorithm valueOf(byte algorithm) { +// for (HashAlgorithm hashAlgorithm : HashAlgorithm.values()) { +// if (hashAlgorithm.CODE == algorithm) { +// return hashAlgorithm; +// } +// } +// throw new IllegalArgumentException("Unsupported hash algorithm [" + algorithm + "]!"); +// } +// +// public static void checkHashAlgorithm(HashAlgorithm algorithm) { +// switch (algorithm) { +// case RIPE160: +// break; +// case SHA256: +// break; +// default: +// throw new IllegalArgumentException("Unsupported hash algorithm [" + algorithm + "]!"); +// } +// } +//} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashObject.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashObject.java index ccba57aa..d5deae10 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashObject.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/HashObject.java @@ -1,37 +1,37 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.consts.DataCodes; -import com.jd.blockchain.crypto.HashDigest; - -/** - * HashObject 表示以“哈希值”作为唯一标识的对象; - * - * @author huanghaiquan - * - */ -@DataContract(code= DataCodes.HASH_OBJECT) -public interface HashObject { - - /** - * 哈希值; - * - * @return - */ - //no need annotation - HashDigest getHash(); - - // /** - // * 哈希算法; - // * - // * @return - // */ - // HashAlgorithm getHashAlgorithm(); - - // /** - // * 进行哈希运算的数据; - // * @return - // */ - // ByteArray getHashData(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.consts.DataCodes; +import com.jd.blockchain.crypto.HashDigest; + +/** + * HashObject 表示以“哈希值”作为唯一标识的对象; + * + * @author huanghaiquan + * + */ +@DataContract(code= DataCodes.HASH_OBJECT) +public interface HashObject { + + /** + * 哈希值; + * + * @return + */ + //no need annotation + HashDigest getHash(); + + // /** + // * 哈希算法; + // * + // * @return + // */ + // HashAlgorithm getHashAlgorithm(); + + // /** + // * 进行哈希运算的数据; + // * @return + // */ + // ByteArray getHashData(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Ledger.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Ledger.java index 073ea143..213b1170 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Ledger.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Ledger.java @@ -1,59 +1,59 @@ -//package com.jd.blockchain.ledger; -// -//import my.utils.io.ByteArray; -// -//import java.io.Serializable; -// -///** -// * Ledger 账本;
-// * -// * 账本只是一个逻辑上的对象,它是对一条区块的hash链的归纳抽象,而在存储上并没有具体的存在形式,而是具体化为由一个特定的创世区块作为开端的区块 hash -// * 链;
-// * -// * 账本的唯一标识也是其创世区块(GenisisBlock)的 hash;
-// * -// * @author huanghaiquan -// * -// */ -//public interface Ledger extends Serializable { -// -// /** -// * 账本的 hash;
-// * -// * 同时也是账本的唯一,等同于其创世区块(GenisisBlock)的 hash {@link GenesisBlock#getBlockHash()}; -// * -// * @return -// */ -// ByteArray getLedgerHash(); -// -// /** -// * 账本结构版本;
-// * -// * 等同于 {@link Block#getLedgerVersion()}; -// * -// * @return -// */ -// long getLedgerVersion(); -// -// /** -// * 由随机数构成的该账本的创世序列; -// * -// * @return -// */ -// ByteArray getGenesisKey(); -// -// /** -// * 当前最新区块的 hash; -// * -// * @return -// */ -// ByteArray getBlockHash(); -// -// /** -// * 账本的区块高度; -// * -// * @return -// */ -// long getBlockHeight(); -// -//} +//package com.jd.blockchain.ledger; +// +//import my.utils.io.ByteArray; +// +//import java.io.Serializable; +// +///** +// * Ledger 账本;
+// * +// * 账本只是一个逻辑上的对象,它是对一条区块的hash链的归纳抽象,而在存储上并没有具体的存在形式,而是具体化为由一个特定的创世区块作为开端的区块 hash +// * 链;
+// * +// * 账本的唯一标识也是其创世区块(GenisisBlock)的 hash;
+// * +// * @author huanghaiquan +// * +// */ +//public interface Ledger extends Serializable { +// +// /** +// * 账本的 hash;
+// * +// * 同时也是账本的唯一,等同于其创世区块(GenisisBlock)的 hash {@link GenesisBlock#getBlockHash()}; +// * +// * @return +// */ +// ByteArray getLedgerHash(); +// +// /** +// * 账本结构版本;
+// * +// * 等同于 {@link Block#getLedgerVersion()}; +// * +// * @return +// */ +// long getLedgerVersion(); +// +// /** +// * 由随机数构成的该账本的创世序列; +// * +// * @return +// */ +// ByteArray getGenesisKey(); +// +// /** +// * 当前最新区块的 hash; +// * +// * @return +// */ +// ByteArray getBlockHash(); +// +// /** +// * 账本的区块高度; +// * +// * @return +// */ +// long getBlockHeight(); +// +//} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerImpl.java index 50e307f5..e9caf22a 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerImpl.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerImpl.java @@ -1,323 +1,323 @@ -//package com.jd.blockchain.ledger; -// -//import com.jd.blockchain.ledger.data.HashEncoding; -// -//import my.utils.io.ByteArray; -//import my.utils.io.BytesEncoding; -//import my.utils.io.BytesReader; -//import my.utils.io.BytesUtils; -//import my.utils.io.BytesWriter; -//import my.utils.io.NumberMask; -// -//import java.io.IOException; -//import java.io.InputStream; -//import java.io.OutputStream; -//import java.util.Objects; -// -///** -// * Ledger 实现 -// * -// * @author zhaoming9 -// */ -//public class LedgerImpl implements Ledger, BytesWriter, BytesReader { -// -// private HashAlgorithm ledgerHashAlgorithm = HashAlgorithm.SHA256; // 账本hash算法 -// private ByteArray ledgerHash = ByteArray.EMPTY; // 账本hash -// -// private long blockHeight = 0; // 账本当前高度 -// private long blockVersion = 0; // 账本当前版本 -// -// private HashAlgorithm currentBlockHashAlgorithm = HashAlgorithm.SHA256; // 账本当前区块hash算法 -// private ByteArray currentBlockHash = ByteArray.EMPTY; // 账本当前区块hash -// -// private HashAlgorithm previousBlockHashAlgorithm = HashAlgorithm.SHA256; // 账本前一区块hash算法 -// private ByteArray previousBlockHash = ByteArray.EMPTY; // 账本前一区块hash -// -// private ByteArray accountRoot = ByteArray.EMPTY; // account mpt root hash -// private long accountCount; // 账户数量 -// private long txTotalCount; // 交易数量 -// -// private ByteArray genesisKey=ByteArray.EMPTY; // 创世块随机序列 -// -// public LedgerImpl() { -// } -// -// /** -// * 初始化一个新的账本; -// * @param genesisKey -// */ -// public LedgerImpl(ByteArray genesisKey) { -// this.genesisKey = genesisKey; -// } -// -// /** -// * @param ledgerHashAlgorithm -// * @param ledgerHash -// * @param height -// * @param version -// * @param currentBlockHashAlgorithm -// * @param currentBlockHash -// * @param previousBlockHashAlgorithm -// * @param previousBlockHash -// * @param accountRoot -// * @param accountCount -// * @param txTotalCount -// * @param genesisKey -// */ -// private LedgerImpl(HashAlgorithm ledgerHashAlgorithm, ByteArray ledgerHash, long height, long version, -// HashAlgorithm currentBlockHashAlgorithm, ByteArray currentBlockHash, -// HashAlgorithm previousBlockHashAlgorithm, ByteArray previousBlockHash, -// ByteArray accountRoot, long accountCount, long txTotalCount, ByteArray genesisKey) { -// this.ledgerHashAlgorithm = ledgerHashAlgorithm; -// this.ledgerHash = ledgerHash; -// this.blockHeight = height; -// this.blockVersion = version; -// this.currentBlockHashAlgorithm = currentBlockHashAlgorithm; -// this.currentBlockHash = currentBlockHash; -// this.previousBlockHashAlgorithm = previousBlockHashAlgorithm; -// this.previousBlockHash = previousBlockHash; -// this.accountRoot = accountRoot; -// this.accountCount = accountCount; -// this.txTotalCount = txTotalCount; -// this.genesisKey = genesisKey; -// } -// -// public LedgerImpl(ByteArray ledgerHash, long blockHeight, long blockVersion, ByteArray currentBlockHash, -// ByteArray previousBlockHash, ByteArray accountRoot, long accountCount, long txTotalCount, ByteArray genesisKey) { -// this(HashAlgorithm.SHA256, ledgerHash, blockHeight, blockVersion, HashAlgorithm.SHA256, currentBlockHash, -// HashAlgorithm.SHA256, previousBlockHash, accountRoot, accountCount, txTotalCount, genesisKey); -// } -// -// public LedgerImpl(LedgerImpl ledger) { -// this(ledger.getLedgerHashAlgorithm(), ledger.getLedgerHash(), ledger.getBlockHeight(), ledger.getBlockVersion(), -// ledger.getCurrentBlockHashAlgorithm(), ledger.getCurrentBlockHash(), -// ledger.getPreviousBlockHashAlgorithm(), ledger.getPreviousBlockHash(), -// ledger.getAccountRoot(), ledger.getAccountCount(), ledger.getTxTotalCount(),ledger.getGenesisKey()); -// } -// -// public LedgerImpl nextLedger(ByteArray nextBlockHash, ByteArray accountRoot, long newAccountCnt, long newTxCnt) { -// LedgerImpl nextLedger = new LedgerImpl(this); -// nextLedger.blockHeight+=1; -// nextLedger.previousBlockHash = nextLedger.currentBlockHash; -// nextLedger.currentBlockHash = nextBlockHash; -// nextLedger.accountRoot = accountRoot; -// nextLedger.accountCount += newAccountCnt; -// nextLedger.txTotalCount += newTxCnt; -// -// return nextLedger; -// } -// -// /** -// * 账本的 hash;
-// *

-// * 同时也是账本的唯一,等同于其创世区块(GenisisBlock)的 hash -// * -// * @return -// */ -// @Override -// public ByteArray getLedgerHash() { -// return ledgerHash; -// } -// -// /** -// * 由随机数构成的该账本的创世序列; -// * -// * @return -// */ -// @Override -// public ByteArray getGenesisKey() { -// return genesisKey; -// } -// -// /** -// * 当前最新区块的 hash; -// * -// * @return -// */ -// @Override -// public ByteArray getBlockHash() { -// return currentBlockHash; -// } -// -// public HashAlgorithm getBlockHashAlgorithm() { -// return currentBlockHashAlgorithm; -// } -// -// /** -// * 账本的区块高度; -// * -// * @return -// */ -// @Override -// public long getBlockHeight() { -// return blockHeight; -// } -// -// @Override -// public void resolvFrom(InputStream in) throws IOException { -// HashAlgorithm ledgerHashAlgorithm = HashAlgorithm.valueOf(BytesUtils.readByte(in)); -// HashAlgorithm.checkHashAlgorithm(ledgerHashAlgorithm); -// ByteArray ledgerHash = HashEncoding.read(in); -// -// long height = BytesUtils.readLong(in); -// long version = BytesUtils.readLong(in); -// -// HashAlgorithm currentBlockHashAlgorithm = HashAlgorithm.valueOf(BytesUtils.readByte(in)); -// HashAlgorithm.checkHashAlgorithm(currentBlockHashAlgorithm); -// ByteArray currentBlockHash = HashEncoding.read(in); -// -// HashAlgorithm previousBlockHashAlgorithm = HashAlgorithm.valueOf(BytesUtils.readByte(in)); -// HashAlgorithm.checkHashAlgorithm(previousBlockHashAlgorithm); -// ByteArray previousBlockHash = HashEncoding.read(in); -// -// ByteArray accountHash = HashEncoding.read(in); -// long accountCount = BytesUtils.readLong(in); -// long txTotalCount = BytesUtils.readLong(in); -// ByteArray key = BytesEncoding.readAsByteArray(NumberMask.SHORT, in); -// -// this.ledgerHashAlgorithm = ledgerHashAlgorithm; -// this.ledgerHash = ledgerHash; -// this.blockHeight = height; -// this.blockVersion = version; -// this.currentBlockHashAlgorithm = currentBlockHashAlgorithm; -// this.currentBlockHash = currentBlockHash; -// this.previousBlockHashAlgorithm = previousBlockHashAlgorithm; -// this.previousBlockHash = previousBlockHash; -// this.accountRoot = accountHash; -// this.accountCount = accountCount; -// this.txTotalCount = txTotalCount; -// this.genesisKey = key; -// } -// -// @Override -// public void writeTo(OutputStream out) throws IOException { -// BytesUtils.writeByte(ledgerHashAlgorithm.getAlgorithm(), out); -// HashEncoding.write(ledgerHash, out); -// -// BytesUtils.writeLong(blockHeight, out); -// BytesUtils.writeLong(blockVersion, out); -// -// BytesUtils.writeByte(currentBlockHashAlgorithm.getAlgorithm(), out); -// HashEncoding.write(currentBlockHash, out); -// -// BytesUtils.writeByte(previousBlockHashAlgorithm.getAlgorithm(), out); -// HashEncoding.write(previousBlockHash, out); -// -// HashEncoding.write(accountRoot, out); -// BytesUtils.writeLong(accountCount, out); -// BytesUtils.writeLong(txTotalCount, out); -// BytesEncoding.write(genesisKey, NumberMask.SHORT, out); -// } -// -// public HashAlgorithm getLedgerHashAlgorithm() { -// return ledgerHashAlgorithm; -// } -// -// public void setLedgerHashAlgorithm(HashAlgorithm ledgerHashAlgorithm) { -// this.ledgerHashAlgorithm = ledgerHashAlgorithm; -// } -// -// public void setLedgerHash(ByteArray ledgerHash) { -// this.ledgerHash = ledgerHash; -// } -// -// public void setBlockHeight(long blockHeight) { -// this.blockHeight = blockHeight; -// } -// -// public HashAlgorithm getCurrentBlockHashAlgorithm() { -// return currentBlockHashAlgorithm; -// } -// -// public void setCurrentBlockHashAlgorithm(HashAlgorithm currentBlockHashAlgorithm) { -// this.currentBlockHashAlgorithm = currentBlockHashAlgorithm; -// } -// -// public long getBlockVersion() { -// return blockVersion; -// } -// -// public void setBlockVersion(long blockVersion) { -// this.blockVersion = blockVersion; -// } -// -// public void setGenesisKey(ByteArray genesisKey) { -// this.genesisKey = genesisKey; -// } -// -// public ByteArray getCurrentBlockHash() { -// return currentBlockHash; -// } -// -// public void setCurrentBlockHash(ByteArray currentBlockHash) { -// this.currentBlockHash = currentBlockHash; -// } -// -// public HashAlgorithm getPreviousBlockHashAlgorithm() { -// return previousBlockHashAlgorithm; -// } -// -// public void setPreviousBlockHashAlgorithm(HashAlgorithm previousBlockHashAlgorithm) { -// this.previousBlockHashAlgorithm = previousBlockHashAlgorithm; -// } -// -// public ByteArray getAccountRoot() { -// return accountRoot; -// } -// -// public void setAccountRoot(ByteArray accountRoot) { -// this.accountRoot = accountRoot; -// } -// -// public long getAccountCount() { -// return accountCount; -// } -// -// public void setAccountCount(long accountCount) { -// this.accountCount = accountCount; -// } -// -// public long getTxTotalCount() { -// return txTotalCount; -// } -// -// public void setTxTotalCount(long txTotalCount) { -// this.txTotalCount = txTotalCount; -// } -// -// public ByteArray getPreviousBlockHash() { -// return previousBlockHash; -// } -// -// public void setPreviousBlockHash(ByteArray previousBlockHash) { -// this.previousBlockHash = previousBlockHash; -// } -// -// @Override -// public boolean equals(Object o) { -// if (this == o) return true; -// if (!(o instanceof LedgerImpl)) return false; -// LedgerImpl ledger = (LedgerImpl) o; -// return getBlockHeight() == ledger.getBlockHeight() && -// getBlockVersion() == ledger.getBlockVersion() && -// getLedgerHashAlgorithm() == ledger.getLedgerHashAlgorithm() && -// Objects.equals(getLedgerHash(), ledger.getLedgerHash()) && -// getCurrentBlockHashAlgorithm() == ledger.getCurrentBlockHashAlgorithm() && -// Objects.equals(getCurrentBlockHash(), ledger.getCurrentBlockHash()) && -// getPreviousBlockHashAlgorithm() == ledger.getPreviousBlockHashAlgorithm() && -// Objects.equals(getPreviousBlockHash(), ledger.getPreviousBlockHash()) && -// Objects.equals(getGenesisKey(), ledger.getGenesisKey()); -// } -// -// @Override -// public int hashCode() { -// -// return Objects.hash(getLedgerHashAlgorithm(), getLedgerHash(), getBlockHeight(), getBlockVersion(), getCurrentBlockHashAlgorithm(), getCurrentBlockHash(), getPreviousBlockHashAlgorithm(), getPreviousBlockHash(), getGenesisKey()); -// } -// -// @Override -// public long getLedgerVersion() { -// // TODO Auto-generated method stub -// return 0; -// } -//} +//package com.jd.blockchain.ledger; +// +//import com.jd.blockchain.ledger.data.HashEncoding; +// +//import my.utils.io.ByteArray; +//import my.utils.io.BytesEncoding; +//import my.utils.io.BytesReader; +//import my.utils.io.BytesUtils; +//import my.utils.io.BytesWriter; +//import my.utils.io.NumberMask; +// +//import java.io.IOException; +//import java.io.InputStream; +//import java.io.OutputStream; +//import java.util.Objects; +// +///** +// * Ledger 实现 +// * +// * @author zhaoming9 +// */ +//public class LedgerImpl implements Ledger, BytesWriter, BytesReader { +// +// private HashAlgorithm ledgerHashAlgorithm = HashAlgorithm.SHA256; // 账本hash算法 +// private ByteArray ledgerHash = ByteArray.EMPTY; // 账本hash +// +// private long blockHeight = 0; // 账本当前高度 +// private long blockVersion = 0; // 账本当前版本 +// +// private HashAlgorithm currentBlockHashAlgorithm = HashAlgorithm.SHA256; // 账本当前区块hash算法 +// private ByteArray currentBlockHash = ByteArray.EMPTY; // 账本当前区块hash +// +// private HashAlgorithm previousBlockHashAlgorithm = HashAlgorithm.SHA256; // 账本前一区块hash算法 +// private ByteArray previousBlockHash = ByteArray.EMPTY; // 账本前一区块hash +// +// private ByteArray accountRoot = ByteArray.EMPTY; // account mpt root hash +// private long accountCount; // 账户数量 +// private long txTotalCount; // 交易数量 +// +// private ByteArray genesisKey=ByteArray.EMPTY; // 创世块随机序列 +// +// public LedgerImpl() { +// } +// +// /** +// * 初始化一个新的账本; +// * @param genesisKey +// */ +// public LedgerImpl(ByteArray genesisKey) { +// this.genesisKey = genesisKey; +// } +// +// /** +// * @param ledgerHashAlgorithm +// * @param ledgerHash +// * @param height +// * @param version +// * @param currentBlockHashAlgorithm +// * @param currentBlockHash +// * @param previousBlockHashAlgorithm +// * @param previousBlockHash +// * @param accountRoot +// * @param accountCount +// * @param txTotalCount +// * @param genesisKey +// */ +// private LedgerImpl(HashAlgorithm ledgerHashAlgorithm, ByteArray ledgerHash, long height, long version, +// HashAlgorithm currentBlockHashAlgorithm, ByteArray currentBlockHash, +// HashAlgorithm previousBlockHashAlgorithm, ByteArray previousBlockHash, +// ByteArray accountRoot, long accountCount, long txTotalCount, ByteArray genesisKey) { +// this.ledgerHashAlgorithm = ledgerHashAlgorithm; +// this.ledgerHash = ledgerHash; +// this.blockHeight = height; +// this.blockVersion = version; +// this.currentBlockHashAlgorithm = currentBlockHashAlgorithm; +// this.currentBlockHash = currentBlockHash; +// this.previousBlockHashAlgorithm = previousBlockHashAlgorithm; +// this.previousBlockHash = previousBlockHash; +// this.accountRoot = accountRoot; +// this.accountCount = accountCount; +// this.txTotalCount = txTotalCount; +// this.genesisKey = genesisKey; +// } +// +// public LedgerImpl(ByteArray ledgerHash, long blockHeight, long blockVersion, ByteArray currentBlockHash, +// ByteArray previousBlockHash, ByteArray accountRoot, long accountCount, long txTotalCount, ByteArray genesisKey) { +// this(HashAlgorithm.SHA256, ledgerHash, blockHeight, blockVersion, HashAlgorithm.SHA256, currentBlockHash, +// HashAlgorithm.SHA256, previousBlockHash, accountRoot, accountCount, txTotalCount, genesisKey); +// } +// +// public LedgerImpl(LedgerImpl ledger) { +// this(ledger.getLedgerHashAlgorithm(), ledger.getLedgerHash(), ledger.getBlockHeight(), ledger.getBlockVersion(), +// ledger.getCurrentBlockHashAlgorithm(), ledger.getCurrentBlockHash(), +// ledger.getPreviousBlockHashAlgorithm(), ledger.getPreviousBlockHash(), +// ledger.getAccountRoot(), ledger.getAccountCount(), ledger.getTxTotalCount(),ledger.getGenesisKey()); +// } +// +// public LedgerImpl nextLedger(ByteArray nextBlockHash, ByteArray accountRoot, long newAccountCnt, long newTxCnt) { +// LedgerImpl nextLedger = new LedgerImpl(this); +// nextLedger.blockHeight+=1; +// nextLedger.previousBlockHash = nextLedger.currentBlockHash; +// nextLedger.currentBlockHash = nextBlockHash; +// nextLedger.accountRoot = accountRoot; +// nextLedger.accountCount += newAccountCnt; +// nextLedger.txTotalCount += newTxCnt; +// +// return nextLedger; +// } +// +// /** +// * 账本的 hash;
+// *

+// * 同时也是账本的唯一,等同于其创世区块(GenisisBlock)的 hash +// * +// * @return +// */ +// @Override +// public ByteArray getLedgerHash() { +// return ledgerHash; +// } +// +// /** +// * 由随机数构成的该账本的创世序列; +// * +// * @return +// */ +// @Override +// public ByteArray getGenesisKey() { +// return genesisKey; +// } +// +// /** +// * 当前最新区块的 hash; +// * +// * @return +// */ +// @Override +// public ByteArray getBlockHash() { +// return currentBlockHash; +// } +// +// public HashAlgorithm getBlockHashAlgorithm() { +// return currentBlockHashAlgorithm; +// } +// +// /** +// * 账本的区块高度; +// * +// * @return +// */ +// @Override +// public long getBlockHeight() { +// return blockHeight; +// } +// +// @Override +// public void resolvFrom(InputStream in) throws IOException { +// HashAlgorithm ledgerHashAlgorithm = HashAlgorithm.valueOf(BytesUtils.readByte(in)); +// HashAlgorithm.checkHashAlgorithm(ledgerHashAlgorithm); +// ByteArray ledgerHash = HashEncoding.read(in); +// +// long height = BytesUtils.readLong(in); +// long version = BytesUtils.readLong(in); +// +// HashAlgorithm currentBlockHashAlgorithm = HashAlgorithm.valueOf(BytesUtils.readByte(in)); +// HashAlgorithm.checkHashAlgorithm(currentBlockHashAlgorithm); +// ByteArray currentBlockHash = HashEncoding.read(in); +// +// HashAlgorithm previousBlockHashAlgorithm = HashAlgorithm.valueOf(BytesUtils.readByte(in)); +// HashAlgorithm.checkHashAlgorithm(previousBlockHashAlgorithm); +// ByteArray previousBlockHash = HashEncoding.read(in); +// +// ByteArray accountHash = HashEncoding.read(in); +// long accountCount = BytesUtils.readLong(in); +// long txTotalCount = BytesUtils.readLong(in); +// ByteArray key = BytesEncoding.readAsByteArray(NumberMask.SHORT, in); +// +// this.ledgerHashAlgorithm = ledgerHashAlgorithm; +// this.ledgerHash = ledgerHash; +// this.blockHeight = height; +// this.blockVersion = version; +// this.currentBlockHashAlgorithm = currentBlockHashAlgorithm; +// this.currentBlockHash = currentBlockHash; +// this.previousBlockHashAlgorithm = previousBlockHashAlgorithm; +// this.previousBlockHash = previousBlockHash; +// this.accountRoot = accountHash; +// this.accountCount = accountCount; +// this.txTotalCount = txTotalCount; +// this.genesisKey = key; +// } +// +// @Override +// public void writeTo(OutputStream out) throws IOException { +// BytesUtils.writeByte(ledgerHashAlgorithm.getAlgorithm(), out); +// HashEncoding.write(ledgerHash, out); +// +// BytesUtils.writeLong(blockHeight, out); +// BytesUtils.writeLong(blockVersion, out); +// +// BytesUtils.writeByte(currentBlockHashAlgorithm.getAlgorithm(), out); +// HashEncoding.write(currentBlockHash, out); +// +// BytesUtils.writeByte(previousBlockHashAlgorithm.getAlgorithm(), out); +// HashEncoding.write(previousBlockHash, out); +// +// HashEncoding.write(accountRoot, out); +// BytesUtils.writeLong(accountCount, out); +// BytesUtils.writeLong(txTotalCount, out); +// BytesEncoding.write(genesisKey, NumberMask.SHORT, out); +// } +// +// public HashAlgorithm getLedgerHashAlgorithm() { +// return ledgerHashAlgorithm; +// } +// +// public void setLedgerHashAlgorithm(HashAlgorithm ledgerHashAlgorithm) { +// this.ledgerHashAlgorithm = ledgerHashAlgorithm; +// } +// +// public void setLedgerHash(ByteArray ledgerHash) { +// this.ledgerHash = ledgerHash; +// } +// +// public void setBlockHeight(long blockHeight) { +// this.blockHeight = blockHeight; +// } +// +// public HashAlgorithm getCurrentBlockHashAlgorithm() { +// return currentBlockHashAlgorithm; +// } +// +// public void setCurrentBlockHashAlgorithm(HashAlgorithm currentBlockHashAlgorithm) { +// this.currentBlockHashAlgorithm = currentBlockHashAlgorithm; +// } +// +// public long getBlockVersion() { +// return blockVersion; +// } +// +// public void setBlockVersion(long blockVersion) { +// this.blockVersion = blockVersion; +// } +// +// public void setGenesisKey(ByteArray genesisKey) { +// this.genesisKey = genesisKey; +// } +// +// public ByteArray getCurrentBlockHash() { +// return currentBlockHash; +// } +// +// public void setCurrentBlockHash(ByteArray currentBlockHash) { +// this.currentBlockHash = currentBlockHash; +// } +// +// public HashAlgorithm getPreviousBlockHashAlgorithm() { +// return previousBlockHashAlgorithm; +// } +// +// public void setPreviousBlockHashAlgorithm(HashAlgorithm previousBlockHashAlgorithm) { +// this.previousBlockHashAlgorithm = previousBlockHashAlgorithm; +// } +// +// public ByteArray getAccountRoot() { +// return accountRoot; +// } +// +// public void setAccountRoot(ByteArray accountRoot) { +// this.accountRoot = accountRoot; +// } +// +// public long getAccountCount() { +// return accountCount; +// } +// +// public void setAccountCount(long accountCount) { +// this.accountCount = accountCount; +// } +// +// public long getTxTotalCount() { +// return txTotalCount; +// } +// +// public void setTxTotalCount(long txTotalCount) { +// this.txTotalCount = txTotalCount; +// } +// +// public ByteArray getPreviousBlockHash() { +// return previousBlockHash; +// } +// +// public void setPreviousBlockHash(ByteArray previousBlockHash) { +// this.previousBlockHash = previousBlockHash; +// } +// +// @Override +// public boolean equals(Object o) { +// if (this == o) return true; +// if (!(o instanceof LedgerImpl)) return false; +// LedgerImpl ledger = (LedgerImpl) o; +// return getBlockHeight() == ledger.getBlockHeight() && +// getBlockVersion() == ledger.getBlockVersion() && +// getLedgerHashAlgorithm() == ledger.getLedgerHashAlgorithm() && +// Objects.equals(getLedgerHash(), ledger.getLedgerHash()) && +// getCurrentBlockHashAlgorithm() == ledger.getCurrentBlockHashAlgorithm() && +// Objects.equals(getCurrentBlockHash(), ledger.getCurrentBlockHash()) && +// getPreviousBlockHashAlgorithm() == ledger.getPreviousBlockHashAlgorithm() && +// Objects.equals(getPreviousBlockHash(), ledger.getPreviousBlockHash()) && +// Objects.equals(getGenesisKey(), ledger.getGenesisKey()); +// } +// +// @Override +// public int hashCode() { +// +// return Objects.hash(getLedgerHashAlgorithm(), getLedgerHash(), getBlockHeight(), getBlockVersion(), getCurrentBlockHashAlgorithm(), getCurrentBlockHash(), getPreviousBlockHashAlgorithm(), getPreviousBlockHash(), getGenesisKey()); +// } +// +// @Override +// public long getLedgerVersion() { +// // TODO Auto-generated method stub +// return 0; +// } +//} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitOperation.java index 08b02e07..fed721b7 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/LedgerInitOperation.java @@ -1,13 +1,13 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.consts.DataCodes; - -@DataContract(code= DataCodes.TX_OP_LEDGER_INIT) -public interface LedgerInitOperation extends Operation{ - - @DataField(order=1, refContract=true) - LedgerInitSetting getInitSetting(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code= DataCodes.TX_OP_LEDGER_INIT) +public interface LedgerInitOperation extends Operation{ + + @DataField(order=1, refContract=true) + LedgerInitSetting getInitSetting(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MagicNumber.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MagicNumber.java index a738e3fb..c1a7a272 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MagicNumber.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/MagicNumber.java @@ -1,67 +1,67 @@ -package com.jd.blockchain.ledger; - -/** - * 魔数表; - * - * @author huanghaiquan - * - */ -public class MagicNumber { - - /** - * JD区块链系统标识的高位,即小写字母 j 的 ASCII; - * - */ - public static final byte JD_HIGH = 0x6A; - - /** - * JD区块链系统标识的低位, 即小写字母 d 的 ASCII; - */ - public static final byte JD_LOW = 0x64; - - /** - * 创世区块标识; - */ - public static final byte GENESIS_BLOCK = 0x00; - - /** - * 子区块标识; - * - * 注:“子区块”是除了“创世区块”之外其它的区块; - */ - public static final byte CHILD_BLOCK = 0x01; - - /** - * 交易内容标识; - */ - public static final byte TX_CONTENT = 0x10; - - /** - * 交易请求标识; - */ - public static final byte TX_REQUEST = 0x11; - - /** - * 交易持久标识; - */ - public static final byte TX_PERSISTENCE = 0x12; - - /** - * 数字签名标识; - */ - public static final byte SIGNATURE = 0x20; - -// /** -// * 公钥标识; -// */ -// public static final byte PUB_KEY = 0x21; -// -// /** -// * 私钥标识; -// */ -// public static final byte PRIV_KEY = 0x22; - - - - -} +package com.jd.blockchain.ledger; + +/** + * 魔数表; + * + * @author huanghaiquan + * + */ +public class MagicNumber { + + /** + * JD区块链系统标识的高位,即小写字母 j 的 ASCII; + * + */ + public static final byte JD_HIGH = 0x6A; + + /** + * JD区块链系统标识的低位, 即小写字母 d 的 ASCII; + */ + public static final byte JD_LOW = 0x64; + + /** + * 创世区块标识; + */ + public static final byte GENESIS_BLOCK = 0x00; + + /** + * 子区块标识; + * + * 注:“子区块”是除了“创世区块”之外其它的区块; + */ + public static final byte CHILD_BLOCK = 0x01; + + /** + * 交易内容标识; + */ + public static final byte TX_CONTENT = 0x10; + + /** + * 交易请求标识; + */ + public static final byte TX_REQUEST = 0x11; + + /** + * 交易持久标识; + */ + public static final byte TX_PERSISTENCE = 0x12; + + /** + * 数字签名标识; + */ + public static final byte SIGNATURE = 0x20; + +// /** +// * 公钥标识; +// */ +// public static final byte PUB_KEY = 0x21; +// +// /** +// * 私钥标识; +// */ +// public static final byte PRIV_KEY = 0x22; + + + + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/NodeRequest.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/NodeRequest.java index 4ccd8051..93eab0ba 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/NodeRequest.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/NodeRequest.java @@ -1,22 +1,22 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.consts.DataCodes; - -@DataContract(code = DataCodes.REQUEST_NODE) -public interface NodeRequest extends EndpointRequest { - - - /** - * 接入交易的节点的签名;
- * - * 注:能够提交交易的节点可以是共识节点或网关节点; - * - * @return - */ - - @DataField(order=1, list=true, refContract=true) - DigitalSignature[] getNodeSignatures(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code = DataCodes.REQUEST_NODE) +public interface NodeRequest extends EndpointRequest { + + + /** + * 接入交易的节点的签名;
+ * + * 注:能够提交交易的节点可以是共识节点或网关节点; + * + * @return + */ + + @DataField(order=1, list=true, refContract=true) + DigitalSignature[] getNodeSignatures(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationArgument.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationArgument.java index 5c2f3b3b..c0c87e7a 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationArgument.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/OperationArgument.java @@ -1,27 +1,27 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.utils.io.ByteArray; - -/** - * 操作参数; - * - * @author huanghaiquan - * - */ -public interface OperationArgument { - - /** - * 参数类型;
- * - * @return - */ - byte getKey(); - - /** - * 参数值; - * - * @return - */ - ByteArray getValue(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.utils.io.ByteArray; + +/** + * 操作参数; + * + * @author huanghaiquan + * + */ +public interface OperationArgument { + + /** + * 参数类型;
+ * + * @return + */ + byte getKey(); + + /** + * 参数值; + * + * @return + */ + ByteArray getValue(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PermissionType.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PermissionType.java index 3f6a4634..9176f36a 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PermissionType.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/PermissionType.java @@ -1,68 +1,68 @@ -package com.jd.blockchain.ledger; - -/** - * 权限类型; - * - * @author huanghaiquan - * - */ -public enum PermissionType { - - /** - * 账户权限配置; - */ - SET_PRIVILEGE(1), - - /** - * 注册参与方; - */ - REG_PARTICIPANT(2), - - /** - * 配置账本;包括除了{@link #SET_PRIVILEGE}、 {@link #REG_PARTICIPANT} 之外的其它账本设置,例如:设置密码参数、共识参数等; - */ - CONFIG_LEDGER(4), - - /** - * 用户注册; - */ - REG_USER(8), - - /** - * 注册数据账户; - */ - REG_DATA_ACCOUNT(16), - - /** - * 部署新的合约代码; - */ - DEPLOY_CONTRACT(32), - - /** - * 写入用户信息; - */ - SET_USER(1024), - - /** - * 写入数据; - */ - SET_DATA(2048), - - /** - * 写入数据; - */ - INVOKE_CONTRACT(4096), - - /** - * 升级合约代码; - */ - UPDATE_CONTRACT(8192); - - - public final int CODE; - - private PermissionType(int code) { - this.CODE = code; - } - -} +package com.jd.blockchain.ledger; + +/** + * 权限类型; + * + * @author huanghaiquan + * + */ +public enum PermissionType { + + /** + * 账户权限配置; + */ + SET_PRIVILEGE(1), + + /** + * 注册参与方; + */ + REG_PARTICIPANT(2), + + /** + * 配置账本;包括除了{@link #SET_PRIVILEGE}、 {@link #REG_PARTICIPANT} 之外的其它账本设置,例如:设置密码参数、共识参数等; + */ + CONFIG_LEDGER(4), + + /** + * 用户注册; + */ + REG_USER(8), + + /** + * 注册数据账户; + */ + REG_DATA_ACCOUNT(16), + + /** + * 部署新的合约代码; + */ + DEPLOY_CONTRACT(32), + + /** + * 写入用户信息; + */ + SET_USER(1024), + + /** + * 写入数据; + */ + SET_DATA(2048), + + /** + * 写入数据; + */ + INVOKE_CONTRACT(4096), + + /** + * 升级合约代码; + */ + UPDATE_CONTRACT(8192); + + + public final int CODE; + + private PermissionType(int code) { + this.CODE = code; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesConfigureOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesConfigureOperation.java index 1e448740..c26b3bc5 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesConfigureOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/RolesConfigureOperation.java @@ -1,39 +1,39 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.binaryproto.PrimitiveType; -import com.jd.blockchain.consts.DataCodes; - -/** - * 角色配置操作; - * - * @author huanghaiquan - * - */ -@DataContract(code = DataCodes.TX_OP_ROLE_CONFIGURE) -public interface RolesConfigureOperation extends Operation { - - @DataField(order = 2, refContract = true, list = true) - RolePrivilegeEntry[] getRoles(); - - @DataContract(code = DataCodes.TX_OP_ROLE_CONFIGURE_ENTRY) - public static interface RolePrivilegeEntry { - - @DataField(order = 1, primitiveType = PrimitiveType.TEXT) - String getRoleName(); - - @DataField(order = 2, refEnum = true, list = true) - LedgerPermission[] getEnableLedgerPermissions(); - - @DataField(order = 3, refEnum = true, list = true) - LedgerPermission[] getDisableLedgerPermissions(); - - @DataField(order = 4, refEnum = true, list = true) - TransactionPermission[] getEnableTransactionPermissions(); - - @DataField(order = 5, refEnum = true, list = true) - TransactionPermission[] getDisableTransactionPermissions(); - - } -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; + +/** + * 角色配置操作; + * + * @author huanghaiquan + * + */ +@DataContract(code = DataCodes.TX_OP_ROLE_CONFIGURE) +public interface RolesConfigureOperation extends Operation { + + @DataField(order = 2, refContract = true, list = true) + RolePrivilegeEntry[] getRoles(); + + @DataContract(code = DataCodes.TX_OP_ROLE_CONFIGURE_ENTRY) + public static interface RolePrivilegeEntry { + + @DataField(order = 1, primitiveType = PrimitiveType.TEXT) + String getRoleName(); + + @DataField(order = 2, refEnum = true, list = true) + LedgerPermission[] getEnableLedgerPermissions(); + + @DataField(order = 3, refEnum = true, list = true) + LedgerPermission[] getDisableLedgerPermissions(); + + @DataField(order = 4, refEnum = true, list = true) + TransactionPermission[] getEnableTransactionPermissions(); + + @DataField(order = 5, refEnum = true, list = true) + TransactionPermission[] getDisableTransactionPermissions(); + + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SignatureInfo.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SignatureInfo.java index 60b1532f..574c1038 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SignatureInfo.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/SignatureInfo.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.ledger; - -public interface SignatureInfo { - - /** - * 签署账户的地址; - * - * @return - */ - String getAddress(); - - /** - * 签名的摘要; - * - * 注:采用Base64编码; - * - * @return - */ - String getDigest(); - -} +package com.jd.blockchain.ledger; + +public interface SignatureInfo { + + /** + * 签署账户的地址; + * + * @return + */ + String getAddress(); + + /** + * 签名的摘要; + * + * 注:采用Base64编码; + * + * @return + */ + String getDigest(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/StateOpType.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/StateOpType.java index 342b20c3..74ad6851 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/StateOpType.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/StateOpType.java @@ -1,37 +1,37 @@ -package com.jd.blockchain.ledger; - -/** - * 状态操作类型; - * - * @author huanghaiquan - * - */ -public enum StateOpType { - - /** - * 设置状态值; - */ - SET((byte) 1), - - /** - * 移除状态值; - */ - REMOVE((byte) 0); - - public final byte CODE; - - private StateOpType(byte code) { - this.CODE = code; - } - - public static StateOpType valueOf(byte code) { - for (StateOpType opType : StateOpType.values()) { - if (opType.CODE == code) { - return opType; - } - } - throw new IllegalArgumentException("Unsupported code[" + code + "] of StateOpType!"); - - } - -} +package com.jd.blockchain.ledger; + +/** + * 状态操作类型; + * + * @author huanghaiquan + * + */ +public enum StateOpType { + + /** + * 设置状态值; + */ + SET((byte) 1), + + /** + * 移除状态值; + */ + REMOVE((byte) 0); + + public final byte CODE; + + private StateOpType(byte code) { + this.CODE = code; + } + + public static StateOpType valueOf(byte code) { + for (StateOpType opType : StateOpType.values()) { + if (opType.CODE == code) { + return opType; + } + } + throw new IllegalArgumentException("Unsupported code[" + code + "] of StateOpType!"); + + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Transaction.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Transaction.java index 542a3a49..2581c223 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Transaction.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/Transaction.java @@ -1,54 +1,54 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.binaryproto.PrimitiveType; -import com.jd.blockchain.consts.DataCodes; -import com.jd.blockchain.crypto.HashDigest; - -/** - * Transaction 区块链交易,是被原子执行的操作集合; - * - * @author huanghaiquan - * - */ -@DataContract(code = DataCodes.TX) -public interface Transaction extends NodeRequest, HashObject { - - /** - * 交易 Hash; - * - * 这是包含交易内容、签名列表、交易结果的完整性 hash; - * - * @return - */ - @DataField(order = 1, primitiveType = PrimitiveType.BYTES) - @Override - HashDigest getHash(); - - /** - * 交易被包含的区块高度; - * - * @return - */ - @DataField(order = 2, primitiveType = PrimitiveType.INT64) - long getBlockHeight(); - - /** - * 交易的执行结果; - * - * 值为枚举值 {@link TransactionState#CODE} 之一; - * - * @return - */ - @DataField(order = 3, refEnum = true) - TransactionState getExecutionState(); - - /** - * 交易的返回结果 - * - * @return - */ - @DataField(order=4, list = true, refContract=true) - OperationResult[] getOperationResults(); -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; +import com.jd.blockchain.crypto.HashDigest; + +/** + * Transaction 区块链交易,是被原子执行的操作集合; + * + * @author huanghaiquan + * + */ +@DataContract(code = DataCodes.TX) +public interface Transaction extends NodeRequest, HashObject { + + /** + * 交易 Hash; + * + * 这是包含交易内容、签名列表、交易结果的完整性 hash; + * + * @return + */ + @DataField(order = 1, primitiveType = PrimitiveType.BYTES) + @Override + HashDigest getHash(); + + /** + * 交易被包含的区块高度; + * + * @return + */ + @DataField(order = 2, primitiveType = PrimitiveType.INT64) + long getBlockHeight(); + + /** + * 交易的执行结果; + * + * 值为枚举值 {@link TransactionState#CODE} 之一; + * + * @return + */ + @DataField(order = 3, refEnum = true) + TransactionState getExecutionState(); + + /** + * 交易的返回结果 + * + * @return + */ + @DataField(order=4, list = true, refContract=true) + OperationResult[] getOperationResults(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionBuilder.java index 7f0c6c02..87251c33 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionBuilder.java @@ -1,51 +1,51 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.transaction.ClientOperator; -import com.jd.blockchain.transaction.LedgerInitOperator; - -/** - * 区块链交易模板; - * - * @author huanghaiquan - * - */ -public interface TransactionBuilder extends ClientOperator, LedgerInitOperator { - - HashDigest getLedgerHash(); - - /** - * 基于当前的系统时间完成交易定义,并生成就绪的交易数据;
- * - * 注:调用此方法后,不能再向当前对象加入更多的操作;
- * - * @return - */ - TransactionRequestBuilder prepareRequest(); - - /** - * 生成交易内容; - * - * @return - */ - TransactionContent prepareContent(); - - /** - * 基于当前的系统时间完成交易定义,并生成就绪的交易数据;
- * - * 注:调用此方法后,不能再向当前对象加入更多的操作; - * - * @param time 交易时间戳; - * @return - */ - TransactionRequestBuilder prepareRequest(long time); - - /** - * 生成交易内容; - * - * @param time 交易时间戳; - * @return - */ - TransactionContent prepareContent(long time); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.transaction.ClientOperator; +import com.jd.blockchain.transaction.LedgerInitOperator; + +/** + * 区块链交易模板; + * + * @author huanghaiquan + * + */ +public interface TransactionBuilder extends ClientOperator, LedgerInitOperator { + + HashDigest getLedgerHash(); + + /** + * 基于当前的系统时间完成交易定义,并生成就绪的交易数据;
+ * + * 注:调用此方法后,不能再向当前对象加入更多的操作;
+ * + * @return + */ + TransactionRequestBuilder prepareRequest(); + + /** + * 生成交易内容; + * + * @return + */ + TransactionContent prepareContent(); + + /** + * 基于当前的系统时间完成交易定义,并生成就绪的交易数据;
+ * + * 注:调用此方法后,不能再向当前对象加入更多的操作; + * + * @param time 交易时间戳; + * @return + */ + TransactionRequestBuilder prepareRequest(long time); + + /** + * 生成交易内容; + * + * @param time 交易时间戳; + * @return + */ + TransactionContent prepareContent(long time); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRequestBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRequestBuilder.java index 87c445ad..0a35155f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRequestBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRequestBuilder.java @@ -1,81 +1,81 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.crypto.AsymmetricKeypair; -import com.jd.blockchain.crypto.HashDigest; - -/** - * 已就绪的交易; - * - * @author huanghaiquan - * - */ -public interface TransactionRequestBuilder extends HashObject { - - /** - * 交易内容的 Hash; - * - * @return - */ - @Override - HashDigest getHash(); - - /** - * 交易数据内容;
- * - *
- * 如果需要对交易进行外部签名,可以将此数据块发送到外部进行签名; - * - * @return - */ - TransactionContent getTransactionContent(); - - /** - * 对交易进行签名; - * - * @param address - * 签名账户的地址; - * @param privKey - * 签名账户的私钥; - * @return - */ - DigitalSignature signAsEndpoint(AsymmetricKeypair keyPair); - - /** - * 对交易进行签名; - * - * @param address - * 签名账户的地址; - * @param privKey - * 签名账户的私钥; - * @return - */ - DigitalSignature signAsNode(AsymmetricKeypair keyPair); - - /** - * 加入签名; - * - * @param address - * 签名账户的地址; - * @param digest - * Base64格式的签名摘要; - * @return - */ - void addEndpointSignature(DigitalSignature... signature); - - /** - * 加入签名; - * - * @param address - * 签名账户的地址; - * @param digest - * Base64格式的签名摘要; - * @return - */ - void addNodeSignature(DigitalSignature... signatures); - - /** - * 生成交易请求; - * - */ - TransactionRequest buildRequest(); -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.crypto.AsymmetricKeypair; +import com.jd.blockchain.crypto.HashDigest; + +/** + * 已就绪的交易; + * + * @author huanghaiquan + * + */ +public interface TransactionRequestBuilder extends HashObject { + + /** + * 交易内容的 Hash; + * + * @return + */ + @Override + HashDigest getHash(); + + /** + * 交易数据内容;
+ * + *
+ * 如果需要对交易进行外部签名,可以将此数据块发送到外部进行签名; + * + * @return + */ + TransactionContent getTransactionContent(); + + /** + * 对交易进行签名; + * + * @param address + * 签名账户的地址; + * @param privKey + * 签名账户的私钥; + * @return + */ + DigitalSignature signAsEndpoint(AsymmetricKeypair keyPair); + + /** + * 对交易进行签名; + * + * @param address + * 签名账户的地址; + * @param privKey + * 签名账户的私钥; + * @return + */ + DigitalSignature signAsNode(AsymmetricKeypair keyPair); + + /** + * 加入签名; + * + * @param address + * 签名账户的地址; + * @param digest + * Base64格式的签名摘要; + * @return + */ + void addEndpointSignature(DigitalSignature... signature); + + /** + * 加入签名; + * + * @param address + * 签名账户的地址; + * @param digest + * Base64格式的签名摘要; + * @return + */ + void addNodeSignature(DigitalSignature... signatures); + + /** + * 生成交易请求; + * + */ + TransactionRequest buildRequest(); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionResponse.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionResponse.java index 662d595b..9c5d6b1b 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionResponse.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionResponse.java @@ -1,68 +1,68 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.binaryproto.PrimitiveType; -import com.jd.blockchain.consts.DataCodes; -import com.jd.blockchain.crypto.HashDigest; - -/** - * 交易请求 {@link TransactionRequest} 的回复; - * - * @author huanghaiquan - * - */ -@DataContract(code = DataCodes.TX_RESPONSE) -public interface TransactionResponse { - - /** - * 交易原始内容的哈希; - * - * @return - */ - @DataField(order = 1, primitiveType = PrimitiveType.BYTES) - HashDigest getContentHash(); - - /** - * 执行状态; - * - * @return - */ - @DataField(order = 2, refEnum = true) - TransactionState getExecutionState(); - - /** - * 交易被纳入的区块哈希; - * - * @return - */ - @DataField(order = 3, primitiveType = PrimitiveType.BYTES) - HashDigest getBlockHash(); - - /** - * 交易被纳入的区块高度; - * - *

- * 如果未生成区块,则返回 -1; - * - * @return - */ - @DataField(order = 4, primitiveType = PrimitiveType.INT64) - long getBlockHeight(); - - /** - * 交易是否执行成功 - * - * @return - */ - @DataField(order = 5, primitiveType = PrimitiveType.BOOLEAN) - boolean isSuccess(); - - /** - * 合约返回值 - * - * @return - */ - @DataField(order=6, list=true, refContract = true) - OperationResult[] getOperationResults(); +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; +import com.jd.blockchain.crypto.HashDigest; + +/** + * 交易请求 {@link TransactionRequest} 的回复; + * + * @author huanghaiquan + * + */ +@DataContract(code = DataCodes.TX_RESPONSE) +public interface TransactionResponse { + + /** + * 交易原始内容的哈希; + * + * @return + */ + @DataField(order = 1, primitiveType = PrimitiveType.BYTES) + HashDigest getContentHash(); + + /** + * 执行状态; + * + * @return + */ + @DataField(order = 2, refEnum = true) + TransactionState getExecutionState(); + + /** + * 交易被纳入的区块哈希; + * + * @return + */ + @DataField(order = 3, primitiveType = PrimitiveType.BYTES) + HashDigest getBlockHash(); + + /** + * 交易被纳入的区块高度; + * + *

+ * 如果未生成区块,则返回 -1; + * + * @return + */ + @DataField(order = 4, primitiveType = PrimitiveType.INT64) + long getBlockHeight(); + + /** + * 交易是否执行成功 + * + * @return + */ + @DataField(order = 5, primitiveType = PrimitiveType.BOOLEAN) + boolean isSuccess(); + + /** + * 合约返回值 + * + * @return + */ + @DataField(order=6, list=true, refContract = true) + OperationResult[] getOperationResults(); } \ No newline at end of file diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRollbackException.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRollbackException.java index 7694d898..731b2ed8 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRollbackException.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionRollbackException.java @@ -1,16 +1,16 @@ -package com.jd.blockchain.ledger; - -public class TransactionRollbackException extends RuntimeException { - - - private static final long serialVersionUID = -1223140447229570029L; - - public TransactionRollbackException(String message) { - super(message); - } - - public TransactionRollbackException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.ledger; + +public class TransactionRollbackException extends RuntimeException { + + + private static final long serialVersionUID = -1223140447229570029L; + + public TransactionRollbackException(String message) { + super(message); + } + + public TransactionRollbackException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionTemplate.java index 0696e768..f734e7e8 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/TransactionTemplate.java @@ -1,27 +1,27 @@ -package com.jd.blockchain.ledger; - -import java.io.Closeable; - -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.transaction.ClientOperator; - -/** - * 区块链交易模板; - * - * @author huanghaiquan - * - */ -public interface TransactionTemplate extends ClientOperator, Closeable { - - HashDigest getLedgerHash(); - - /** - * 完成交易定义,并生成就绪的交易数据;
- * - * 注:调用此方法后,不能再向当前对象加入更多的操作; - * - * @return - */ - PreparedTransaction prepare(); - -} +package com.jd.blockchain.ledger; + +import java.io.Closeable; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.transaction.ClientOperator; + +/** + * 区块链交易模板; + * + * @author huanghaiquan + * + */ +public interface TransactionTemplate extends ClientOperator, Closeable { + + HashDigest getLedgerHash(); + + /** + * 完成交易定义,并生成就绪的交易数据;
+ * + * 注:调用此方法后,不能再向当前对象加入更多的操作; + * + * @return + */ + PreparedTransaction prepare(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizeOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizeOperation.java index 67e37e17..8b396844 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizeOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserAuthorizeOperation.java @@ -1,57 +1,57 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.binaryproto.PrimitiveType; -import com.jd.blockchain.consts.DataCodes; -import com.jd.blockchain.utils.Bytes; - -/** - * 角色配置操作; - * - * @author huanghaiquan - * - */ -@DataContract(code = DataCodes.TX_OP_USER_ROLES_AUTHORIZE) -public interface UserAuthorizeOperation extends Operation { - - @DataField(order = 2, refContract = true, list = true) - UserRolesEntry[] getUserRolesAuthorizations(); - - @DataContract(code = DataCodes.TX_OP_USER_ROLE_AUTHORIZE_ENTRY) - public static interface UserRolesEntry { - - /** - * 用户地址; - * - * @return - */ - @DataField(order = 0, primitiveType = PrimitiveType.BYTES, list = true) - Bytes[] getUserAddresses(); - - /** - * 要更新的多角色权限策略; - * - * @return - */ - @DataField(order = 2, refEnum = true) - RolesPolicy getPolicy(); - - /** - * 授权的角色清单; - * - * @return - */ - @DataField(order = 3, primitiveType = PrimitiveType.TEXT, list = true) - String[] getAuthorizedRoles(); - - /** - * 取消授权的角色清单; - * - * @return - */ - @DataField(order = 4, primitiveType = PrimitiveType.TEXT, list = true) - String[] getUnauthorizedRoles(); - - } -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.binaryproto.PrimitiveType; +import com.jd.blockchain.consts.DataCodes; +import com.jd.blockchain.utils.Bytes; + +/** + * 角色配置操作; + * + * @author huanghaiquan + * + */ +@DataContract(code = DataCodes.TX_OP_USER_ROLES_AUTHORIZE) +public interface UserAuthorizeOperation extends Operation { + + @DataField(order = 2, refContract = true, list = true) + UserRolesEntry[] getUserRolesAuthorizations(); + + @DataContract(code = DataCodes.TX_OP_USER_ROLE_AUTHORIZE_ENTRY) + public static interface UserRolesEntry { + + /** + * 用户地址; + * + * @return + */ + @DataField(order = 0, primitiveType = PrimitiveType.BYTES, list = true) + Bytes[] getUserAddresses(); + + /** + * 要更新的多角色权限策略; + * + * @return + */ + @DataField(order = 2, refEnum = true) + RolesPolicy getPolicy(); + + /** + * 授权的角色清单; + * + * @return + */ + @DataField(order = 3, primitiveType = PrimitiveType.TEXT, list = true) + String[] getAuthorizedRoles(); + + /** + * 取消授权的角色清单; + * + * @return + */ + @DataField(order = 4, primitiveType = PrimitiveType.TEXT, list = true) + String[] getUnauthorizedRoles(); + + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java index c6372b78..491378ed 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserInfoSetOperation.java @@ -1,29 +1,29 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.consts.DataCodes; - -/** - * @author huanghaiquan - * - */ -@DataContract(code=DataCodes.TX_OP_USER_INFO_SET) -public interface UserInfoSetOperation extends Operation { - - String getUserAddress(); - - KVEntry[] getPropertiesWriteSet(); - - - @DataContract(code=DataCodes.TX_OP_USER_INFO_SET_KV) - public static interface KVEntry{ - - String getKey(); - - String getValue(); - - long getExpectedVersion(); - } - - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.consts.DataCodes; + +/** + * @author huanghaiquan + * + */ +@DataContract(code=DataCodes.TX_OP_USER_INFO_SET) +public interface UserInfoSetOperation extends Operation { + + String getUserAddress(); + + KVEntry[] getPropertiesWriteSet(); + + + @DataContract(code=DataCodes.TX_OP_USER_INFO_SET_KV) + public static interface KVEntry{ + + String getKey(); + + String getValue(); + + long getExpectedVersion(); + } + + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java index caa642de..59956645 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/ledger/UserRegisterOperation.java @@ -1,13 +1,13 @@ -package com.jd.blockchain.ledger; - -import com.jd.blockchain.binaryproto.DataContract; -import com.jd.blockchain.binaryproto.DataField; -import com.jd.blockchain.consts.DataCodes; - -@DataContract(code = DataCodes.TX_OP_USER_REG) -public interface UserRegisterOperation extends Operation { - - @DataField(order = 2, refContract = true) - BlockchainIdentity getUserID(); - -} +package com.jd.blockchain.ledger; + +import com.jd.blockchain.binaryproto.DataContract; +import com.jd.blockchain.binaryproto.DataField; +import com.jd.blockchain.consts.DataCodes; + +@DataContract(code = DataCodes.TX_OP_USER_REG) +public interface UserRegisterOperation extends Operation { + + @DataField(order = 2, refContract = true) + BlockchainIdentity getUserID(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/setting/GatewayIncomingSetting.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/setting/GatewayIncomingSetting.java index d6212fd7..e066d34c 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/setting/GatewayIncomingSetting.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/setting/GatewayIncomingSetting.java @@ -1,26 +1,26 @@ -package com.jd.blockchain.setting; - -/** - * 网关接入设置; - * - * @author huanghaiquan - * - */ -public class GatewayIncomingSetting { - - private LedgerIncomingSetting[] ledgers; - - /** - * 所有账本的接入设置; - * - * @return - */ - public LedgerIncomingSetting[] getLedgers() { - return ledgers; - } - - public void setLedgers(LedgerIncomingSetting[] ledgerSettings) { - this.ledgers = ledgerSettings; - } - -} +package com.jd.blockchain.setting; + +/** + * 网关接入设置; + * + * @author huanghaiquan + * + */ +public class GatewayIncomingSetting { + + private LedgerIncomingSetting[] ledgers; + + /** + * 所有账本的接入设置; + * + * @return + */ + public LedgerIncomingSetting[] getLedgers() { + return ledgers; + } + + public void setLedgers(LedgerIncomingSetting[] ledgerSettings) { + this.ledgers = ledgerSettings; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java index 66cec3b8..25e97d6d 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainOperationFactory.java @@ -1,358 +1,358 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.*; -import com.jd.blockchain.utils.Bytes; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.ledger.*; -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.net.NetworkAddress; - -/** - * @author huanghaiquan - * - */ -public class BlockchainOperationFactory implements ClientOperator, LedgerInitOperator { - - private static final SecurityOperationBuilderImpl SECURITY_OP_BUILDER = new SecurityOperationBuilderImpl(); - - private static final LedgerInitOperationBuilderImpl LEDGER_INIT_OP_BUILDER = new LedgerInitOperationBuilderImpl(); - - private static final UserRegisterOperationBuilderImpl USER_REG_OP_BUILDER = new UserRegisterOperationBuilderImpl(); - - private static final DataAccountRegisterOperationBuilderImpl DATA_ACC_REG_OP_BUILDER = new DataAccountRegisterOperationBuilderImpl(); - - private static final ContractCodeDeployOperationBuilderImpl CONTRACT_CODE_DEPLOY_OP_BUILDER = new ContractCodeDeployOperationBuilderImpl(); - -// private static final ContractEventSendOperationBuilderImpl CONTRACT_EVENT_SEND_OP_BUILDER = new ContractEventSendOperationBuilderImpl(); - - private SecurityOperationBuilderFilter securityOpBuilder = new SecurityOperationBuilderFilter(); - - private static final ParticipantRegisterOperationBuilderImpl PARTICIPANT_REG_OP_BUILDER = new ParticipantRegisterOperationBuilderImpl(); - - private static final ParticipantStateUpdateOperationBuilderImpl PARTICIPANT_STATE_UPDATE_OP_BUILDER = new ParticipantStateUpdateOperationBuilderImpl(); - - private LedgerInitOperationBuilder ledgerInitOpBuilder = new LedgerInitOperationBuilderFilter(); - - private UserRegisterOperationBuilder userRegOpBuilder = new UserRegisterOperationBuilderFilter(); - - private DataAccountRegisterOperationBuilder dataAccRegOpBuilder = new DataAccountRegisterOperationBuilderFilter(); - - private ContractCodeDeployOperationBuilder contractCodeDeployOpBuilder = new ContractCodeDeployOperationBuilderFilter(); - - private ContractEventSendOperationBuilder contractEventSendOpBuilder = new ContractEventSendOperationBuilderFilter(); - - private ContractInvocationProxyBuilder contractInvoProxyBuilder = new ContractInvocationProxyBuilder(); - - private ParticipantRegisterOperationBuilder participantRegOpBuilder = new ParticipantRegisterOperationBuilderFilter(); - - private ParticipantStateUpdateOperationBuilder participantStateModifyOpBuilder = new ParticipantStateUpdateOperationBuilderFilter(); - - // TODO: 暂时只支持单线程情形,未考虑多线程; - private List operationList = new ArrayList<>(); - - @Override - public LedgerInitOperationBuilder ledgers() { - return ledgerInitOpBuilder; - } - - @Override - public SecurityOperationBuilder security() { - return securityOpBuilder; - } - - @Override - public UserRegisterOperationBuilder users() { - return userRegOpBuilder; - } - - @Override - public DataAccountRegisterOperationBuilder dataAccounts() { - return dataAccRegOpBuilder; - } - - @Override - public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) { - return new DataAccountKVSetOperationBuilderFilter(Bytes.fromBase58(accountAddress)); - } - - @Override - public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) { - return new DataAccountKVSetOperationBuilderFilter(accountAddress); - } - - @Override - public ContractCodeDeployOperationBuilder contracts() { - return contractCodeDeployOpBuilder; - } - - public ContractEventSendOperationBuilder contractEvents() { - return contractEventSendOpBuilder; - } - - @Override - public ParticipantRegisterOperationBuilder participants() {return participantRegOpBuilder;} - - @Override - public ParticipantStateUpdateOperationBuilder states() {return participantStateModifyOpBuilder;} - - @Override - public T contract(String address, Class contractIntf) { - return contractInvoProxyBuilder.create(address, contractIntf, contractEventSendOpBuilder); - } - - @Override - public T contract(Bytes address, Class contractIntf) { - return contractInvoProxyBuilder.create(address, contractIntf, contractEventSendOpBuilder); - } - - /** - * 返回已经定义的操作列表; - * - * @return - */ - public Collection getOperations() { - return operationList; - } - - /** - * 返回与操作列表对应的返回值处理器; - * - * @return - */ - public Collection getReturnValuetHandlers() { - List resultHandlers = new ArrayList(); - int index = 0; - for (Operation op : operationList) { - if (op instanceof ContractEventSendOperation) { - // 操作具有返回值,创建对应的结果处理器; - ContractEventSendOpTemplate opTemp = (ContractEventSendOpTemplate) op; - ContractInvocation invocation = opTemp.getInvocation(); - OperationResultHandle retnHandler; - if (invocation == null) { - retnHandler = new NullOperationReturnValueHandler(index); - } else { - invocation.setOperationIndex(index); - retnHandler = invocation; - } - resultHandlers.add(retnHandler); - } - index++; - } - - return resultHandlers; - } - - public void clear() { - operationList.clear(); - } - - // --------------------------------- 内部类型 ----------------------------------- - - private class LedgerInitOperationBuilderFilter implements LedgerInitOperationBuilder { - - @Override - public LedgerInitOperation create(LedgerInitSetting initSetting) { - LedgerInitOperation op = LEDGER_INIT_OP_BUILDER.create(initSetting); - operationList.add(op); - return op; - } - - } - - private class UserRegisterOperationBuilderFilter implements UserRegisterOperationBuilder { - - @Override - public UserRegisterOperation register(BlockchainIdentity userID) { - UserRegisterOperation op = USER_REG_OP_BUILDER.register(userID); - operationList.add(op); - return op; - } - - } - - private class SecurityOperationBuilderFilter implements SecurityOperationBuilder { - - @Override - public RolesConfigurer roles() { - RolesConfigurer rolesConfigurer = SECURITY_OP_BUILDER.roles(); - operationList.add(rolesConfigurer.getOperation()); - return rolesConfigurer; - } - - @Override - public UserAuthorizer authorziations() { - UserAuthorizer userAuthorizer = SECURITY_OP_BUILDER.authorziations(); - operationList.add(userAuthorizer.getOperation()); - return userAuthorizer; - } - } - - private class DataAccountRegisterOperationBuilderFilter implements DataAccountRegisterOperationBuilder { - - @Override - public DataAccountRegisterOperation register(BlockchainIdentity accountID) { - DataAccountRegisterOperation op = DATA_ACC_REG_OP_BUILDER.register(accountID); - operationList.add(op); - return op; - } - } - - private class DataAccountKVSetOperationBuilderFilter implements DataAccountKVSetOperationBuilder { - - private DataAccountKVSetOperationBuilder innerBuilder; - - private DataAccountKVSetOperation op; - - public DataAccountKVSetOperationBuilderFilter(Bytes accountAddress) { - innerBuilder = new DataAccountKVSetOperationBuilderImpl(accountAddress); - } - - @Override - public DataAccountKVSetOperation getOperation() { - return innerBuilder.getOperation(); - } - - private void addOperation() { - if (op == null) { - op = innerBuilder.getOperation(); - operationList.add(op); - } - } - - @Override - public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { - innerBuilder.setText(key, value, expVersion); - addOperation(); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { - innerBuilder.setInt64(key, value, expVersion); - addOperation(); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { - innerBuilder.setBytes(key, value, expVersion); - addOperation(); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { - innerBuilder.setBytes(key, value, expVersion); - addOperation(); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { - innerBuilder.setImage(key, value, expVersion); - addOperation(); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { - innerBuilder.setJSON(key, value, expVersion); - addOperation(); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { - innerBuilder.setXML(key, value, expVersion); - addOperation(); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { - innerBuilder.setTimestamp(key, value, expVersion); - addOperation(); - return this; - } - - } - - private class ContractCodeDeployOperationBuilderFilter implements ContractCodeDeployOperationBuilder { - @Override - public ContractCodeDeployOperation deploy(BlockchainIdentity id, byte[] chainCode) { - ContractCodeDeployOperation op = CONTRACT_CODE_DEPLOY_OP_BUILDER.deploy(id, chainCode); - operationList.add(op); - return op; - } - } - - private class ParticipantRegisterOperationBuilderFilter implements ParticipantRegisterOperationBuilder { - @Override - public ParticipantRegisterOperation register(String participantName, BlockchainIdentity participantIdentity, NetworkAddress networkAddress) { - ParticipantRegisterOperation op = PARTICIPANT_REG_OP_BUILDER.register(participantName, participantIdentity, networkAddress); - operationList.add(op); - return op; - } - } - - private class ParticipantStateUpdateOperationBuilderFilter implements ParticipantStateUpdateOperationBuilder { - @Override - public ParticipantStateUpdateOperation update(BlockchainIdentity blockchainIdentity, NetworkAddress networkAddress, ParticipantNodeState participantNodeState) { - ParticipantStateUpdateOperation op = PARTICIPANT_STATE_UPDATE_OP_BUILDER.update(blockchainIdentity, networkAddress, participantNodeState); - operationList.add(op); - return op; - } - } - - private class ContractEventSendOperationBuilderFilter implements ContractEventSendOperationBuilder { - - @Override - public ContractEventSendOperation send(String address, String event, BytesValueList args) { - return send(Bytes.fromBase58(address), event, args); - } - - @Override - public synchronized ContractEventSendOperation send(Bytes address, String event, BytesValueList args) { - ContractEventSendOpTemplate op = new ContractEventSendOpTemplate(address, event, args); - operationList.add(op); - return op; - } - - } - - /** - * 不做任何操作的返回值处理器; - * - * @author huanghaiquan - * - */ - private static class NullOperationReturnValueHandler implements OperationResultHandle { - - private int operationIndex; - - public NullOperationReturnValueHandler(int operationIndex) { - this.operationIndex = operationIndex; - } - - @Override - public int getOperationIndex() { - return operationIndex; - } - - @Override - public Object complete(BytesValue bytesValue) { - return null; - } - - @Override - public void complete(Throwable error) { - } - - } - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.utils.Bytes; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.net.NetworkAddress; + +/** + * @author huanghaiquan + * + */ +public class BlockchainOperationFactory implements ClientOperator, LedgerInitOperator { + + private static final SecurityOperationBuilderImpl SECURITY_OP_BUILDER = new SecurityOperationBuilderImpl(); + + private static final LedgerInitOperationBuilderImpl LEDGER_INIT_OP_BUILDER = new LedgerInitOperationBuilderImpl(); + + private static final UserRegisterOperationBuilderImpl USER_REG_OP_BUILDER = new UserRegisterOperationBuilderImpl(); + + private static final DataAccountRegisterOperationBuilderImpl DATA_ACC_REG_OP_BUILDER = new DataAccountRegisterOperationBuilderImpl(); + + private static final ContractCodeDeployOperationBuilderImpl CONTRACT_CODE_DEPLOY_OP_BUILDER = new ContractCodeDeployOperationBuilderImpl(); + +// private static final ContractEventSendOperationBuilderImpl CONTRACT_EVENT_SEND_OP_BUILDER = new ContractEventSendOperationBuilderImpl(); + + private SecurityOperationBuilderFilter securityOpBuilder = new SecurityOperationBuilderFilter(); + + private static final ParticipantRegisterOperationBuilderImpl PARTICIPANT_REG_OP_BUILDER = new ParticipantRegisterOperationBuilderImpl(); + + private static final ParticipantStateUpdateOperationBuilderImpl PARTICIPANT_STATE_UPDATE_OP_BUILDER = new ParticipantStateUpdateOperationBuilderImpl(); + + private LedgerInitOperationBuilder ledgerInitOpBuilder = new LedgerInitOperationBuilderFilter(); + + private UserRegisterOperationBuilder userRegOpBuilder = new UserRegisterOperationBuilderFilter(); + + private DataAccountRegisterOperationBuilder dataAccRegOpBuilder = new DataAccountRegisterOperationBuilderFilter(); + + private ContractCodeDeployOperationBuilder contractCodeDeployOpBuilder = new ContractCodeDeployOperationBuilderFilter(); + + private ContractEventSendOperationBuilder contractEventSendOpBuilder = new ContractEventSendOperationBuilderFilter(); + + private ContractInvocationProxyBuilder contractInvoProxyBuilder = new ContractInvocationProxyBuilder(); + + private ParticipantRegisterOperationBuilder participantRegOpBuilder = new ParticipantRegisterOperationBuilderFilter(); + + private ParticipantStateUpdateOperationBuilder participantStateModifyOpBuilder = new ParticipantStateUpdateOperationBuilderFilter(); + + // TODO: 暂时只支持单线程情形,未考虑多线程; + private List operationList = new ArrayList<>(); + + @Override + public LedgerInitOperationBuilder ledgers() { + return ledgerInitOpBuilder; + } + + @Override + public SecurityOperationBuilder security() { + return securityOpBuilder; + } + + @Override + public UserRegisterOperationBuilder users() { + return userRegOpBuilder; + } + + @Override + public DataAccountRegisterOperationBuilder dataAccounts() { + return dataAccRegOpBuilder; + } + + @Override + public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) { + return new DataAccountKVSetOperationBuilderFilter(Bytes.fromBase58(accountAddress)); + } + + @Override + public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) { + return new DataAccountKVSetOperationBuilderFilter(accountAddress); + } + + @Override + public ContractCodeDeployOperationBuilder contracts() { + return contractCodeDeployOpBuilder; + } + + public ContractEventSendOperationBuilder contractEvents() { + return contractEventSendOpBuilder; + } + + @Override + public ParticipantRegisterOperationBuilder participants() {return participantRegOpBuilder;} + + @Override + public ParticipantStateUpdateOperationBuilder states() {return participantStateModifyOpBuilder;} + + @Override + public T contract(String address, Class contractIntf) { + return contractInvoProxyBuilder.create(address, contractIntf, contractEventSendOpBuilder); + } + + @Override + public T contract(Bytes address, Class contractIntf) { + return contractInvoProxyBuilder.create(address, contractIntf, contractEventSendOpBuilder); + } + + /** + * 返回已经定义的操作列表; + * + * @return + */ + public Collection getOperations() { + return operationList; + } + + /** + * 返回与操作列表对应的返回值处理器; + * + * @return + */ + public Collection getReturnValuetHandlers() { + List resultHandlers = new ArrayList(); + int index = 0; + for (Operation op : operationList) { + if (op instanceof ContractEventSendOperation) { + // 操作具有返回值,创建对应的结果处理器; + ContractEventSendOpTemplate opTemp = (ContractEventSendOpTemplate) op; + ContractInvocation invocation = opTemp.getInvocation(); + OperationResultHandle retnHandler; + if (invocation == null) { + retnHandler = new NullOperationReturnValueHandler(index); + } else { + invocation.setOperationIndex(index); + retnHandler = invocation; + } + resultHandlers.add(retnHandler); + } + index++; + } + + return resultHandlers; + } + + public void clear() { + operationList.clear(); + } + + // --------------------------------- 内部类型 ----------------------------------- + + private class LedgerInitOperationBuilderFilter implements LedgerInitOperationBuilder { + + @Override + public LedgerInitOperation create(LedgerInitSetting initSetting) { + LedgerInitOperation op = LEDGER_INIT_OP_BUILDER.create(initSetting); + operationList.add(op); + return op; + } + + } + + private class UserRegisterOperationBuilderFilter implements UserRegisterOperationBuilder { + + @Override + public UserRegisterOperation register(BlockchainIdentity userID) { + UserRegisterOperation op = USER_REG_OP_BUILDER.register(userID); + operationList.add(op); + return op; + } + + } + + private class SecurityOperationBuilderFilter implements SecurityOperationBuilder { + + @Override + public RolesConfigurer roles() { + RolesConfigurer rolesConfigurer = SECURITY_OP_BUILDER.roles(); + operationList.add(rolesConfigurer.getOperation()); + return rolesConfigurer; + } + + @Override + public UserAuthorizer authorziations() { + UserAuthorizer userAuthorizer = SECURITY_OP_BUILDER.authorziations(); + operationList.add(userAuthorizer.getOperation()); + return userAuthorizer; + } + } + + private class DataAccountRegisterOperationBuilderFilter implements DataAccountRegisterOperationBuilder { + + @Override + public DataAccountRegisterOperation register(BlockchainIdentity accountID) { + DataAccountRegisterOperation op = DATA_ACC_REG_OP_BUILDER.register(accountID); + operationList.add(op); + return op; + } + } + + private class DataAccountKVSetOperationBuilderFilter implements DataAccountKVSetOperationBuilder { + + private DataAccountKVSetOperationBuilder innerBuilder; + + private DataAccountKVSetOperation op; + + public DataAccountKVSetOperationBuilderFilter(Bytes accountAddress) { + innerBuilder = new DataAccountKVSetOperationBuilderImpl(accountAddress); + } + + @Override + public DataAccountKVSetOperation getOperation() { + return innerBuilder.getOperation(); + } + + private void addOperation() { + if (op == null) { + op = innerBuilder.getOperation(); + operationList.add(op); + } + } + + @Override + public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { + innerBuilder.setText(key, value, expVersion); + addOperation(); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { + innerBuilder.setInt64(key, value, expVersion); + addOperation(); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { + innerBuilder.setBytes(key, value, expVersion); + addOperation(); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { + innerBuilder.setBytes(key, value, expVersion); + addOperation(); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { + innerBuilder.setImage(key, value, expVersion); + addOperation(); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { + innerBuilder.setJSON(key, value, expVersion); + addOperation(); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { + innerBuilder.setXML(key, value, expVersion); + addOperation(); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { + innerBuilder.setTimestamp(key, value, expVersion); + addOperation(); + return this; + } + + } + + private class ContractCodeDeployOperationBuilderFilter implements ContractCodeDeployOperationBuilder { + @Override + public ContractCodeDeployOperation deploy(BlockchainIdentity id, byte[] chainCode) { + ContractCodeDeployOperation op = CONTRACT_CODE_DEPLOY_OP_BUILDER.deploy(id, chainCode); + operationList.add(op); + return op; + } + } + + private class ParticipantRegisterOperationBuilderFilter implements ParticipantRegisterOperationBuilder { + @Override + public ParticipantRegisterOperation register(String participantName, BlockchainIdentity participantIdentity, NetworkAddress networkAddress) { + ParticipantRegisterOperation op = PARTICIPANT_REG_OP_BUILDER.register(participantName, participantIdentity, networkAddress); + operationList.add(op); + return op; + } + } + + private class ParticipantStateUpdateOperationBuilderFilter implements ParticipantStateUpdateOperationBuilder { + @Override + public ParticipantStateUpdateOperation update(BlockchainIdentity blockchainIdentity, NetworkAddress networkAddress, ParticipantNodeState participantNodeState) { + ParticipantStateUpdateOperation op = PARTICIPANT_STATE_UPDATE_OP_BUILDER.update(blockchainIdentity, networkAddress, participantNodeState); + operationList.add(op); + return op; + } + } + + private class ContractEventSendOperationBuilderFilter implements ContractEventSendOperationBuilder { + + @Override + public ContractEventSendOperation send(String address, String event, BytesValueList args) { + return send(Bytes.fromBase58(address), event, args); + } + + @Override + public synchronized ContractEventSendOperation send(Bytes address, String event, BytesValueList args) { + ContractEventSendOpTemplate op = new ContractEventSendOpTemplate(address, event, args); + operationList.add(op); + return op; + } + + } + + /** + * 不做任何操作的返回值处理器; + * + * @author huanghaiquan + * + */ + private static class NullOperationReturnValueHandler implements OperationResultHandle { + + private int operationIndex; + + public NullOperationReturnValueHandler(int operationIndex) { + this.operationIndex = operationIndex; + } + + @Override + public int getOperationIndex() { + return operationIndex; + } + + @Override + public Object complete(BytesValue bytesValue) { + return null; + } + + @Override + public void complete(Throwable error) { + } + + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java index f63a7f2a..98694c60 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/BlockchainQueryService.java @@ -1,330 +1,330 @@ -package com.jd.blockchain.transaction; - -import org.springframework.cglib.core.Block; - -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.ContractInfo; -import com.jd.blockchain.ledger.TypedKVEntry; -import com.jd.blockchain.ledger.KVInfoVO; -import com.jd.blockchain.ledger.LedgerAdminInfo; -import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.LedgerInfo; -import com.jd.blockchain.ledger.LedgerMetadata; -import com.jd.blockchain.ledger.LedgerTransaction; -import com.jd.blockchain.ledger.ParticipantNode; -import com.jd.blockchain.ledger.Transaction; -import com.jd.blockchain.ledger.TransactionState; -import com.jd.blockchain.ledger.UserInfo; - -/** - * 区块链查询器; - * - * @author huanghaiquan - * - */ -public interface BlockchainQueryService { - - /** - * 返回所有的账本的 hash 列表;
- * - * 注:账本的 hash 既是该账本的创世区块的 hash; - * - * @return 账本 hash 的集合; - */ - HashDigest[] getLedgerHashs(); - - /** - * 获取账本信息; - * - * @param ledgerHash - * @return 账本对象;如果不存在,则返回 null; - */ - LedgerInfo getLedger(HashDigest ledgerHash); - - /** - * 获取账本信息; - * - * @param ledgerHash - * @return 账本对象;如果不存在,则返回 null; - */ - LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash); - - /** - * 返回当前账本的参与者信息列表 - * - * @param ledgerHash - * @return - */ - ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash); - - /** - * 返回当前账本的元数据 - * - * @param ledgerHash - * @return - */ - LedgerMetadata getLedgerMetadata(HashDigest ledgerHash); - - /** - * 返回指定账本序号的区块; - * - * @param ledgerHash 账本hash; - * @param height 高度; - * @return - */ - LedgerBlock getBlock(HashDigest ledgerHash, long height); - - /** - * 返回指定区块hash的区块; - * - * @param ledgerHash 账本hash; - * @param blockHash 区块hash; - * @return - */ - LedgerBlock getBlock(HashDigest ledgerHash, HashDigest blockHash); - - /** - * 返回指定高度的区块中记录的交易总数; - * - * @param ledgerHash - * @param height - * @return - */ - long getTransactionCount(HashDigest ledgerHash, long height); - - /** - * 返回指定高度的区块中记录的交易总数; - * - * @param ledgerHash - * @param blockHash - * @return - */ - long getTransactionCount(HashDigest ledgerHash, HashDigest blockHash); - - /** - * 返回当前账本的交易总数 - * - * @param ledgerHash - * @return - */ - long getTransactionTotalCount(HashDigest ledgerHash); - - /** - * 返回指定高度的区块中记录的数据账户总数 - * - * @param ledgerHash - * @param height - * @return - */ - long getDataAccountCount(HashDigest ledgerHash, long height); - - /** - * 返回指定的区块中记录的数据账户总数 - * - * @param ledgerHash - * @param blockHash - * @return - */ - long getDataAccountCount(HashDigest ledgerHash, HashDigest blockHash); - - /** - * 返回当前账本的数据账户总数 - * - * @param ledgerHash - * @return - */ - long getDataAccountTotalCount(HashDigest ledgerHash); - - /** - * 返回指定高度区块中的用户总数 - * - * @param ledgerHash - * @param height - * @return - */ - long getUserCount(HashDigest ledgerHash, long height); - - /** - * 返回指定区块中的用户总数 - * - * @param ledgerHash - * @param blockHash - * @return - */ - long getUserCount(HashDigest ledgerHash, HashDigest blockHash); - - /** - * 返回当前账本的用户总数 - * - * @param ledgerHash - * @return - */ - long getUserTotalCount(HashDigest ledgerHash); - - /** - * 返回指定高度区块中的合约总数 - * - * @param ledgerHash - * @param height - * @return - */ - long getContractCount(HashDigest ledgerHash, long height); - - /** - * 返回指定区块中的合约总数 - * - * @param ledgerHash - * @param blockHash - * @return - */ - long getContractCount(HashDigest ledgerHash, HashDigest blockHash); - - /** - * 返回当前账本的合约总数 - * - * @param ledgerHash - * @return - */ - long getContractTotalCount(HashDigest ledgerHash); - - /** - * 分页返回指定账本序号的区块中的交易列表; - * - * @param ledgerHash 账本hash; - * @param height 账本高度; - * @param fromIndex 开始的记录数; - * @param count 本次返回的记录数;
- * 最小为1,最大值受到系统参数的限制;
- * 注:通过 {@link #getBlock(String, long)} 方法获得的区块信息中可以得到区块的总交易数 - * {@link Block#getTxCount()}; - * @return - */ - LedgerTransaction[] getTransactions(HashDigest ledgerHash, long height, int fromIndex, int count); - - /** - * 分页返回指定账本序号的区块中的交易列表; - * - * @param ledgerHash 账本hash; - * @param blockHash 账本高度; - * @param fromIndex 开始的记录数; - * @param count 本次返回的记录数;
- * 如果参数值为 -1,则返回全部的记录;
- * 注:通过 {@link #getBlock(String, String)} - * 方法获得的区块信息中可以得到区块的总交易数 {@link Block#getTxCount()}; - * @return - */ - LedgerTransaction[] getTransactions(HashDigest ledgerHash, HashDigest blockHash, int fromIndex, int count); - - /** - * 根据交易内容的哈希获取对应的交易记录; - * - * @param ledgerHash 账本hash; - * @param contentHash 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值; - * @return - */ - LedgerTransaction getTransactionByContentHash(HashDigest ledgerHash, HashDigest contentHash); - - /** - * 根据交易内容的哈希获取对应的交易状态; - * - * @param ledgerHash 账本hash; - * @param contentHash 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值; - * @return - */ - TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash); - - /** - * 返回用户信息; - * - * @param ledgerHash - * @param address - * @return - */ - UserInfo getUser(HashDigest ledgerHash, String address); - - /** - * 返回数据账户信息; - * - * @param ledgerHash - * @param address - * @return - */ - BlockchainIdentity getDataAccount(HashDigest ledgerHash, String address); - - /** - * 返回数据账户中指定的键的最新值;
- * - * 返回结果的顺序与指定的键的顺序是一致的;
- * - * 如果某个键不存在,则返回版本为 -1 的数据项; - * - * @param ledgerHash - * @param address - * @param keys - * @return - */ - TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys); - - TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO); - - /** - * 返回指定数据账户中KV数据的总数;
- * - * @param ledgerHash - * @param address - * @return - */ - long getDataEntriesTotalCount(HashDigest ledgerHash, String address); - - /** - * 返回数据账户中指定序号的最新值; 返回结果的顺序与指定的序号的顺序是一致的;
- * - * @param ledgerHash 账本hash; - * @param address 数据账户地址; - * @param fromIndex 开始的记录数; - * @param count 本次返回的记录数;
- * 如果参数值为 -1,则返回全部的记录;
- * @return - */ - TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count); - - /** - * 返回合约账户信息; - * - * @param ledgerHash - * @param address - * @return - */ - ContractInfo getContract(HashDigest ledgerHash, String address); - - /** - * get users by ledgerHash and its range; - * - * @param ledgerHash - * @param fromIndex - * @param count - * @return - */ - BlockchainIdentity[] getUsers(HashDigest ledgerHash, int fromIndex, int count); - - /** - * get data accounts by ledgerHash and its range; - * - * @param ledgerHash - * @param fromIndex - * @param count - * @return - */ - BlockchainIdentity[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count); - - /** - * get contract accounts by ledgerHash and its range; - * - * @param ledgerHash - * @param fromIndex - * @param count - * @return - */ - BlockchainIdentity[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count); -} +package com.jd.blockchain.transaction; + +import org.springframework.cglib.core.Block; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.ContractInfo; +import com.jd.blockchain.ledger.TypedKVEntry; +import com.jd.blockchain.ledger.KVInfoVO; +import com.jd.blockchain.ledger.LedgerAdminInfo; +import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerInfo; +import com.jd.blockchain.ledger.LedgerMetadata; +import com.jd.blockchain.ledger.LedgerTransaction; +import com.jd.blockchain.ledger.ParticipantNode; +import com.jd.blockchain.ledger.Transaction; +import com.jd.blockchain.ledger.TransactionState; +import com.jd.blockchain.ledger.UserInfo; + +/** + * 区块链查询器; + * + * @author huanghaiquan + * + */ +public interface BlockchainQueryService { + + /** + * 返回所有的账本的 hash 列表;
+ * + * 注:账本的 hash 既是该账本的创世区块的 hash; + * + * @return 账本 hash 的集合; + */ + HashDigest[] getLedgerHashs(); + + /** + * 获取账本信息; + * + * @param ledgerHash + * @return 账本对象;如果不存在,则返回 null; + */ + LedgerInfo getLedger(HashDigest ledgerHash); + + /** + * 获取账本信息; + * + * @param ledgerHash + * @return 账本对象;如果不存在,则返回 null; + */ + LedgerAdminInfo getLedgerAdminInfo(HashDigest ledgerHash); + + /** + * 返回当前账本的参与者信息列表 + * + * @param ledgerHash + * @return + */ + ParticipantNode[] getConsensusParticipants(HashDigest ledgerHash); + + /** + * 返回当前账本的元数据 + * + * @param ledgerHash + * @return + */ + LedgerMetadata getLedgerMetadata(HashDigest ledgerHash); + + /** + * 返回指定账本序号的区块; + * + * @param ledgerHash 账本hash; + * @param height 高度; + * @return + */ + LedgerBlock getBlock(HashDigest ledgerHash, long height); + + /** + * 返回指定区块hash的区块; + * + * @param ledgerHash 账本hash; + * @param blockHash 区块hash; + * @return + */ + LedgerBlock getBlock(HashDigest ledgerHash, HashDigest blockHash); + + /** + * 返回指定高度的区块中记录的交易总数; + * + * @param ledgerHash + * @param height + * @return + */ + long getTransactionCount(HashDigest ledgerHash, long height); + + /** + * 返回指定高度的区块中记录的交易总数; + * + * @param ledgerHash + * @param blockHash + * @return + */ + long getTransactionCount(HashDigest ledgerHash, HashDigest blockHash); + + /** + * 返回当前账本的交易总数 + * + * @param ledgerHash + * @return + */ + long getTransactionTotalCount(HashDigest ledgerHash); + + /** + * 返回指定高度的区块中记录的数据账户总数 + * + * @param ledgerHash + * @param height + * @return + */ + long getDataAccountCount(HashDigest ledgerHash, long height); + + /** + * 返回指定的区块中记录的数据账户总数 + * + * @param ledgerHash + * @param blockHash + * @return + */ + long getDataAccountCount(HashDigest ledgerHash, HashDigest blockHash); + + /** + * 返回当前账本的数据账户总数 + * + * @param ledgerHash + * @return + */ + long getDataAccountTotalCount(HashDigest ledgerHash); + + /** + * 返回指定高度区块中的用户总数 + * + * @param ledgerHash + * @param height + * @return + */ + long getUserCount(HashDigest ledgerHash, long height); + + /** + * 返回指定区块中的用户总数 + * + * @param ledgerHash + * @param blockHash + * @return + */ + long getUserCount(HashDigest ledgerHash, HashDigest blockHash); + + /** + * 返回当前账本的用户总数 + * + * @param ledgerHash + * @return + */ + long getUserTotalCount(HashDigest ledgerHash); + + /** + * 返回指定高度区块中的合约总数 + * + * @param ledgerHash + * @param height + * @return + */ + long getContractCount(HashDigest ledgerHash, long height); + + /** + * 返回指定区块中的合约总数 + * + * @param ledgerHash + * @param blockHash + * @return + */ + long getContractCount(HashDigest ledgerHash, HashDigest blockHash); + + /** + * 返回当前账本的合约总数 + * + * @param ledgerHash + * @return + */ + long getContractTotalCount(HashDigest ledgerHash); + + /** + * 分页返回指定账本序号的区块中的交易列表; + * + * @param ledgerHash 账本hash; + * @param height 账本高度; + * @param fromIndex 开始的记录数; + * @param count 本次返回的记录数;
+ * 最小为1,最大值受到系统参数的限制;
+ * 注:通过 {@link #getBlock(String, long)} 方法获得的区块信息中可以得到区块的总交易数 + * {@link Block#getTxCount()}; + * @return + */ + LedgerTransaction[] getTransactions(HashDigest ledgerHash, long height, int fromIndex, int count); + + /** + * 分页返回指定账本序号的区块中的交易列表; + * + * @param ledgerHash 账本hash; + * @param blockHash 账本高度; + * @param fromIndex 开始的记录数; + * @param count 本次返回的记录数;
+ * 如果参数值为 -1,则返回全部的记录;
+ * 注:通过 {@link #getBlock(String, String)} + * 方法获得的区块信息中可以得到区块的总交易数 {@link Block#getTxCount()}; + * @return + */ + LedgerTransaction[] getTransactions(HashDigest ledgerHash, HashDigest blockHash, int fromIndex, int count); + + /** + * 根据交易内容的哈希获取对应的交易记录; + * + * @param ledgerHash 账本hash; + * @param contentHash 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值; + * @return + */ + LedgerTransaction getTransactionByContentHash(HashDigest ledgerHash, HashDigest contentHash); + + /** + * 根据交易内容的哈希获取对应的交易状态; + * + * @param ledgerHash 账本hash; + * @param contentHash 交易内容的hash,即交易的 {@link Transaction#getContentHash()} 属性的值; + * @return + */ + TransactionState getTransactionStateByContentHash(HashDigest ledgerHash, HashDigest contentHash); + + /** + * 返回用户信息; + * + * @param ledgerHash + * @param address + * @return + */ + UserInfo getUser(HashDigest ledgerHash, String address); + + /** + * 返回数据账户信息; + * + * @param ledgerHash + * @param address + * @return + */ + BlockchainIdentity getDataAccount(HashDigest ledgerHash, String address); + + /** + * 返回数据账户中指定的键的最新值;
+ * + * 返回结果的顺序与指定的键的顺序是一致的;
+ * + * 如果某个键不存在,则返回版本为 -1 的数据项; + * + * @param ledgerHash + * @param address + * @param keys + * @return + */ + TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, String... keys); + + TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, KVInfoVO kvInfoVO); + + /** + * 返回指定数据账户中KV数据的总数;
+ * + * @param ledgerHash + * @param address + * @return + */ + long getDataEntriesTotalCount(HashDigest ledgerHash, String address); + + /** + * 返回数据账户中指定序号的最新值; 返回结果的顺序与指定的序号的顺序是一致的;
+ * + * @param ledgerHash 账本hash; + * @param address 数据账户地址; + * @param fromIndex 开始的记录数; + * @param count 本次返回的记录数;
+ * 如果参数值为 -1,则返回全部的记录;
+ * @return + */ + TypedKVEntry[] getDataEntries(HashDigest ledgerHash, String address, int fromIndex, int count); + + /** + * 返回合约账户信息; + * + * @param ledgerHash + * @param address + * @return + */ + ContractInfo getContract(HashDigest ledgerHash, String address); + + /** + * get users by ledgerHash and its range; + * + * @param ledgerHash + * @param fromIndex + * @param count + * @return + */ + BlockchainIdentity[] getUsers(HashDigest ledgerHash, int fromIndex, int count); + + /** + * get data accounts by ledgerHash and its range; + * + * @param ledgerHash + * @param fromIndex + * @param count + * @return + */ + BlockchainIdentity[] getDataAccounts(HashDigest ledgerHash, int fromIndex, int count); + + /** + * get contract accounts by ledgerHash and its range; + * + * @param ledgerHash + * @param fromIndex + * @param count + * @return + */ + BlockchainIdentity[] getContractAccounts(HashDigest ledgerHash, int fromIndex, int count); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOpTemplate.java index 4da74638..61ec8cc8 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOpTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOpTemplate.java @@ -1,41 +1,41 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.ContractCodeDeployOperation; -import com.jd.blockchain.ledger.DigitalSignature; - -public class ContractCodeDeployOpTemplate implements ContractCodeDeployOperation { - static { - DataContractRegistry.register(ContractCodeDeployOperation.class); - } - - private BlockchainIdentity contractID; - - private byte[] chainCode; - - public ContractCodeDeployOpTemplate() { - } - - public ContractCodeDeployOpTemplate(BlockchainIdentity contractID, byte[] chainCode) { - this.contractID = contractID; - this.chainCode = chainCode; - } - - @Override - public BlockchainIdentity getContractID() { - return contractID; - } - - @Override - public byte[] getChainCode() { - return chainCode; - } - - @Override - public DigitalSignature getAddressSignature() { - // TODO Auto-generated method stub - return null; - } - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.ContractCodeDeployOperation; +import com.jd.blockchain.ledger.DigitalSignature; + +public class ContractCodeDeployOpTemplate implements ContractCodeDeployOperation { + static { + DataContractRegistry.register(ContractCodeDeployOperation.class); + } + + private BlockchainIdentity contractID; + + private byte[] chainCode; + + public ContractCodeDeployOpTemplate() { + } + + public ContractCodeDeployOpTemplate(BlockchainIdentity contractID, byte[] chainCode) { + this.contractID = contractID; + this.chainCode = chainCode; + } + + @Override + public BlockchainIdentity getContractID() { + return contractID; + } + + @Override + public byte[] getChainCode() { + return chainCode; + } + + @Override + public DigitalSignature getAddressSignature() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOperationBuilder.java index ff2c18fb..a75a34b9 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOperationBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOperationBuilder.java @@ -1,19 +1,19 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.ContractCodeDeployOperation; - -public interface ContractCodeDeployOperationBuilder { - - /** - * 部署合约; - * - * @param id - * 区块链身份; - * @param chainCode - * 合约应用的字节代码; - * @return - */ - ContractCodeDeployOperation deploy(BlockchainIdentity id, byte[] chainCode); - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.ContractCodeDeployOperation; + +public interface ContractCodeDeployOperationBuilder { + + /** + * 部署合约; + * + * @param id + * 区块链身份; + * @param chainCode + * 合约应用的字节代码; + * @return + */ + ContractCodeDeployOperation deploy(BlockchainIdentity id, byte[] chainCode); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOperationBuilderImpl.java index a0c2bba4..fe69879c 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOperationBuilderImpl.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractCodeDeployOperationBuilderImpl.java @@ -1,14 +1,14 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.ContractCodeDeployOperation; - -public class ContractCodeDeployOperationBuilderImpl implements ContractCodeDeployOperationBuilder{ - - @Override - public ContractCodeDeployOperation deploy(BlockchainIdentity id, byte[] chainCode) { - ContractCodeDeployOpTemplate op = new ContractCodeDeployOpTemplate(id, chainCode); - return op; - } - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.ContractCodeDeployOperation; + +public class ContractCodeDeployOperationBuilderImpl implements ContractCodeDeployOperationBuilder{ + + @Override + public ContractCodeDeployOperation deploy(BlockchainIdentity id, byte[] chainCode) { + ContractCodeDeployOpTemplate op = new ContractCodeDeployOpTemplate(id, chainCode); + return op; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilder.java index 675fd8d6..48124243 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilder.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.BytesValueList; -import com.jd.blockchain.ledger.ContractEventSendOperation; -import com.jd.blockchain.utils.Bytes; - -public interface ContractEventSendOperationBuilder { - - /** - * @param address 合约地址; - * @param event 事件名; - * @param args 事件参数; - * @return - */ - ContractEventSendOperation send(String address, String event, BytesValueList args); - - /** - * @param address 合约地址; - * @param event 事件名; - * @param args 事件参数; - * @return - */ - ContractEventSendOperation send(Bytes address, String event, BytesValueList args); -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.BytesValueList; +import com.jd.blockchain.ledger.ContractEventSendOperation; +import com.jd.blockchain.utils.Bytes; + +public interface ContractEventSendOperationBuilder { + + /** + * @param address 合约地址; + * @param event 事件名; + * @param args 事件参数; + * @return + */ + ContractEventSendOperation send(String address, String event, BytesValueList args); + + /** + * @param address 合约地址; + * @param event 事件名; + * @param args 事件参数; + * @return + */ + ContractEventSendOperation send(Bytes address, String event, BytesValueList args); +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilderImpl.java index faae0029..96533720 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilderImpl.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractEventSendOperationBuilderImpl.java @@ -1,21 +1,21 @@ -//package com.jd.blockchain.transaction; -// -//import com.jd.blockchain.ledger.ContractEventSendOperation; -//import com.jd.blockchain.utils.Bytes; -// -//@Deprecated -//class ContractEventSendOperationBuilderImpl implements ContractEventSendOperationBuilder { -// -// @Override -// public ContractEventSendOperation send(String address, String event, byte[] args) { -// ContractEventSendOpTemplate op = new ContractEventSendOpTemplate(Bytes.fromBase58(address), event, args); -// return op; -// } -// -// @Override -// public ContractEventSendOperation send(Bytes address, String event, byte[] args) { -// ContractEventSendOpTemplate op = new ContractEventSendOpTemplate(address, event, args); -// return op; -// } -// -//} +//package com.jd.blockchain.transaction; +// +//import com.jd.blockchain.ledger.ContractEventSendOperation; +//import com.jd.blockchain.utils.Bytes; +// +//@Deprecated +//class ContractEventSendOperationBuilderImpl implements ContractEventSendOperationBuilder { +// +// @Override +// public ContractEventSendOperation send(String address, String event, byte[] args) { +// ContractEventSendOpTemplate op = new ContractEventSendOpTemplate(Bytes.fromBase58(address), event, args); +// return op; +// } +// +// @Override +// public ContractEventSendOperation send(Bytes address, String event, byte[] args) { +// ContractEventSendOpTemplate op = new ContractEventSendOpTemplate(address, event, args); +// return op; +// } +// +//} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java index e5e7b947..a536e5ac 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/ContractInvocationProxyBuilder.java @@ -1,44 +1,44 @@ -package com.jd.blockchain.transaction; - -import java.lang.reflect.Proxy; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import com.jd.blockchain.contract.ContractType; -import com.jd.blockchain.utils.Bytes; - -/** - * 合约调用代理的构建器; - * - * @author huanghaiquan - * - */ -public class ContractInvocationProxyBuilder { - - private Map, ContractType> contractTypes = new ConcurrentHashMap<>(); - - public T create(String address, Class contractIntf, ContractEventSendOperationBuilder contractEventBuilder) { - return create(Bytes.fromBase58(address), contractIntf, contractEventBuilder); - } - - @SuppressWarnings("unchecked") - public T create(Bytes address, Class contractIntf, ContractEventSendOperationBuilder contractEventBuilder) { - ContractType contractType = resolveContractType(contractIntf); - - ContractInvocationHandler proxyHandler = new ContractInvocationHandler(address, contractType, contractEventBuilder); - - T proxy = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), - new Class[] { contractIntf }, proxyHandler); - return proxy; - } - - private ContractType resolveContractType(Class contractIntf) { - ContractType contractType = contractTypes.get(contractIntf); - if (contractType != null) { - return contractType; - } - ContractType ct = ContractType.resolve(contractIntf); - contractTypes.put(contractIntf, ct); - return ct; - } -} +package com.jd.blockchain.transaction; + +import java.lang.reflect.Proxy; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.jd.blockchain.contract.ContractType; +import com.jd.blockchain.utils.Bytes; + +/** + * 合约调用代理的构建器; + * + * @author huanghaiquan + * + */ +public class ContractInvocationProxyBuilder { + + private Map, ContractType> contractTypes = new ConcurrentHashMap<>(); + + public T create(String address, Class contractIntf, ContractEventSendOperationBuilder contractEventBuilder) { + return create(Bytes.fromBase58(address), contractIntf, contractEventBuilder); + } + + @SuppressWarnings("unchecked") + public T create(Bytes address, Class contractIntf, ContractEventSendOperationBuilder contractEventBuilder) { + ContractType contractType = resolveContractType(contractIntf); + + ContractInvocationHandler proxyHandler = new ContractInvocationHandler(address, contractType, contractEventBuilder); + + T proxy = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), + new Class[] { contractIntf }, proxyHandler); + return proxy; + } + + private ContractType resolveContractType(Class contractIntf) { + ContractType contractType = contractTypes.get(contractIntf); + if (contractType != null) { + return contractType; + } + ContractType ct = ContractType.resolve(contractIntf); + contractTypes.put(contractIntf, ct); + return ct; + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOpTemplate.java index a9873c4c..4154761a 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOpTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOpTemplate.java @@ -1,65 +1,65 @@ -package com.jd.blockchain.transaction; - -import java.util.LinkedHashMap; -import java.util.Map; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.utils.Bytes; - -public class DataAccountKVSetOpTemplate implements DataAccountKVSetOperation { - static { - DataContractRegistry.register(DataAccountKVSetOperation.class); - } - - private Bytes accountAddress; - - private Map kvset = new LinkedHashMap<>(); - - public DataAccountKVSetOpTemplate() { - } - - public DataAccountKVSetOpTemplate(Bytes accountAddress) { - this.accountAddress = accountAddress; - } - - public DataAccountKVSetOpTemplate(Bytes accountAddress, Map kvset) { - this.accountAddress = accountAddress; - this.kvset = kvset; - } - - @Override - public Bytes getAccountAddress() { - return accountAddress; - } - - @Override - public KVWriteEntry[] getWriteSet() { - return kvset.values().toArray(new KVWriteEntry[kvset.size()]); - } - - public void setWriteSet(Object[] kvEntries) { - for (Object object : kvEntries) { - KVWriteEntry kvEntry = (KVWriteEntry) object; - set(kvEntry.getKey(), kvEntry.getValue(), kvEntry.getExpectedVersion()); - } - return; - } - - public void set(String key, BytesValue value, long expVersion) { - if (kvset.containsKey(key)) { - throw new IllegalArgumentException("Cann't set the same key repeatedly!"); - } - KVData kvdata = new KVData(key, value, expVersion); - kvset.put(key, kvdata); - } - - public void set(KVData kvData) { - if (kvset.containsKey(kvData.getKey())) { - throw new IllegalArgumentException("Cann't set the same key repeatedly!"); - } - kvset.put(kvData.getKey(), kvData); - } - -} +package com.jd.blockchain.transaction; + +import java.util.LinkedHashMap; +import java.util.Map; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.DataAccountKVSetOperation; +import com.jd.blockchain.utils.Bytes; + +public class DataAccountKVSetOpTemplate implements DataAccountKVSetOperation { + static { + DataContractRegistry.register(DataAccountKVSetOperation.class); + } + + private Bytes accountAddress; + + private Map kvset = new LinkedHashMap<>(); + + public DataAccountKVSetOpTemplate() { + } + + public DataAccountKVSetOpTemplate(Bytes accountAddress) { + this.accountAddress = accountAddress; + } + + public DataAccountKVSetOpTemplate(Bytes accountAddress, Map kvset) { + this.accountAddress = accountAddress; + this.kvset = kvset; + } + + @Override + public Bytes getAccountAddress() { + return accountAddress; + } + + @Override + public KVWriteEntry[] getWriteSet() { + return kvset.values().toArray(new KVWriteEntry[kvset.size()]); + } + + public void setWriteSet(Object[] kvEntries) { + for (Object object : kvEntries) { + KVWriteEntry kvEntry = (KVWriteEntry) object; + set(kvEntry.getKey(), kvEntry.getValue(), kvEntry.getExpectedVersion()); + } + return; + } + + public void set(String key, BytesValue value, long expVersion) { + if (kvset.containsKey(key)) { + throw new IllegalArgumentException("Cann't set the same key repeatedly!"); + } + KVData kvdata = new KVData(key, value, expVersion); + kvset.put(key, kvdata); + } + + public void set(KVData kvData) { + if (kvset.containsKey(kvData.getKey())) { + throw new IllegalArgumentException("Cann't set the same key repeatedly!"); + } + kvset.put(kvData.getKey(), kvData); + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilder.java index f7c9ae8f..5a94e02f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilder.java @@ -1,151 +1,151 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.utils.Bytes; - -/** - * @author huanghaiquan - * - */ -public interface DataAccountKVSetOperationBuilder { - - /** - * 数据账户的KV写入操作; - * - * @return - */ - DataAccountKVSetOperation getOperation(); - -// /** -// * 写入字节数组; -// * -// * @param key -// * 键; -// * @param value -// * 值;byte[]格式 -// * @param expVersion -// * 预期的当前版本;如果版本不匹配,则写入失败; -// * @return -// */ -// @Deprecated -// DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion); - - /** - * 写入字节数组; - * - * @param key - * 键; - * @param value - * 值;byte[]格式 - * @param expVersion - * 预期的当前版本;如果版本不匹配,则写入失败; - * @return - */ - DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion); - - /** - * 写入字节数组; - * - * @param key - * 键; - * @param value - * 值;Bytes格式 - * @param expVersion - * 预期的当前版本;如果版本不匹配,则写入失败; - * @return - */ - DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion); - - /** - * 写入键值; - * - * @param key - * 键; - * @param value - * 值;String格式 - * @param expVersion - * 预期的当前版本;如果版本不匹配,则写入失败; - * @return - */ - DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion); - -// /** -// * 写入文本键值; -// * -// * @param key -// * 键; -// * @param value -// * 值;String格式 -// * @param expVersion -// * 预期的当前版本;如果版本不匹配,则写入失败; -// * @return -// */ -// @Deprecated -// DataAccountKVSetOperationBuilder set(String key, String value, long expVersion); - - /** - * 写入文本键值; - * - * @param key - * 键; - * @param value - * 值;String格式 - * @param expVersion - * 预期的当前版本;如果版本不匹配,则写入失败; - * @return - */ - DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion); - - /** - * 写入JSON键值; - * - * @param key - * 键; - * @param value - * 值;String格式 - * @param expVersion - * 预期的当前版本;如果版本不匹配,则写入失败; - * @return - */ - DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion); - - /** - * 写入XML键值; - * - * @param key - * 键; - * @param value - * 值;String格式 - * @param expVersion - * 预期的当前版本;如果版本不匹配,则写入失败; - * @return - */ - DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion); - - /** - * 写入64位整数; - * - * @param key - * 键; - * @param value - * 值;long格式 - * @param expVersion - * 预期的当前版本;如果版本不匹配,则写入失败; - * @return - */ - DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion); - - /** - * 写入时间戳; - * - * @param key - * 键; - * @param value - * 值;long格式 - * @param expVersion - * 预期的当前版本;如果版本不匹配,则写入失败; - * @return - */ - DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion); - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.DataAccountKVSetOperation; +import com.jd.blockchain.utils.Bytes; + +/** + * @author huanghaiquan + * + */ +public interface DataAccountKVSetOperationBuilder { + + /** + * 数据账户的KV写入操作; + * + * @return + */ + DataAccountKVSetOperation getOperation(); + +// /** +// * 写入字节数组; +// * +// * @param key +// * 键; +// * @param value +// * 值;byte[]格式 +// * @param expVersion +// * 预期的当前版本;如果版本不匹配,则写入失败; +// * @return +// */ +// @Deprecated +// DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion); + + /** + * 写入字节数组; + * + * @param key + * 键; + * @param value + * 值;byte[]格式 + * @param expVersion + * 预期的当前版本;如果版本不匹配,则写入失败; + * @return + */ + DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion); + + /** + * 写入字节数组; + * + * @param key + * 键; + * @param value + * 值;Bytes格式 + * @param expVersion + * 预期的当前版本;如果版本不匹配,则写入失败; + * @return + */ + DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion); + + /** + * 写入键值; + * + * @param key + * 键; + * @param value + * 值;String格式 + * @param expVersion + * 预期的当前版本;如果版本不匹配,则写入失败; + * @return + */ + DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion); + +// /** +// * 写入文本键值; +// * +// * @param key +// * 键; +// * @param value +// * 值;String格式 +// * @param expVersion +// * 预期的当前版本;如果版本不匹配,则写入失败; +// * @return +// */ +// @Deprecated +// DataAccountKVSetOperationBuilder set(String key, String value, long expVersion); + + /** + * 写入文本键值; + * + * @param key + * 键; + * @param value + * 值;String格式 + * @param expVersion + * 预期的当前版本;如果版本不匹配,则写入失败; + * @return + */ + DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion); + + /** + * 写入JSON键值; + * + * @param key + * 键; + * @param value + * 值;String格式 + * @param expVersion + * 预期的当前版本;如果版本不匹配,则写入失败; + * @return + */ + DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion); + + /** + * 写入XML键值; + * + * @param key + * 键; + * @param value + * 值;String格式 + * @param expVersion + * 预期的当前版本;如果版本不匹配,则写入失败; + * @return + */ + DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion); + + /** + * 写入64位整数; + * + * @param key + * 键; + * @param value + * 值;long格式 + * @param expVersion + * 预期的当前版本;如果版本不匹配,则写入失败; + * @return + */ + DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion); + + /** + * 写入时间戳; + * + * @param key + * 键; + * @param value + * 值;long格式 + * @param expVersion + * 预期的当前版本;如果版本不匹配,则写入失败; + * @return + */ + DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java index cec540c9..3992fefb 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountKVSetOperationBuilderImpl.java @@ -1,88 +1,88 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.BytesValue; -import com.jd.blockchain.ledger.TypedValue; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.utils.Bytes; - -public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOperationBuilder { - - private DataAccountKVSetOpTemplate operation; - - public DataAccountKVSetOperationBuilderImpl(Bytes accountAddress) { - operation = new DataAccountKVSetOpTemplate(accountAddress); - } - - @Override - public DataAccountKVSetOperation getOperation() { - return operation; - } - -// @Deprecated -// @Override -// public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) { -// return setBytes(key, value, expVersion); -// } - - @Override - public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { - BytesValue bytesValue = TypedValue.fromBytes(value); - operation.set(key, bytesValue, expVersion); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { - BytesValue bytesValue = TypedValue.fromImage(value); - operation.set(key, bytesValue, expVersion); - return this; - } - -// @Override -// public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) { -// return setText(key, value, expVersion); -// } - - @Override - public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { - BytesValue bytesValue = TypedValue.fromText(value); - operation.set(key, bytesValue, expVersion); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { - BytesValue bytesValue = TypedValue.fromBytes(value); - operation.set(key, bytesValue, expVersion); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { - BytesValue bytesValue = TypedValue.fromInt64(value); - operation.set(key, bytesValue, expVersion); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { - BytesValue bytesValue = TypedValue.fromJSON(value); - operation.set(key, bytesValue, expVersion); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { - BytesValue bytesValue = TypedValue.fromXML(value); - operation.set(key, bytesValue, expVersion); - return this; - } - - @Override - public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { - BytesValue bytesValue = TypedValue.fromTimestamp(value); - operation.set(key, bytesValue, expVersion); - return this; - } - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.BytesValue; +import com.jd.blockchain.ledger.TypedValue; +import com.jd.blockchain.ledger.DataAccountKVSetOperation; +import com.jd.blockchain.utils.Bytes; + +public class DataAccountKVSetOperationBuilderImpl implements DataAccountKVSetOperationBuilder { + + private DataAccountKVSetOpTemplate operation; + + public DataAccountKVSetOperationBuilderImpl(Bytes accountAddress) { + operation = new DataAccountKVSetOpTemplate(accountAddress); + } + + @Override + public DataAccountKVSetOperation getOperation() { + return operation; + } + +// @Deprecated +// @Override +// public DataAccountKVSetOperationBuilder set(String key, byte[] value, long expVersion) { +// return setBytes(key, value, expVersion); +// } + + @Override + public DataAccountKVSetOperationBuilder setBytes(String key, byte[] value, long expVersion) { + BytesValue bytesValue = TypedValue.fromBytes(value); + operation.set(key, bytesValue, expVersion); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setImage(String key, byte[] value, long expVersion) { + BytesValue bytesValue = TypedValue.fromImage(value); + operation.set(key, bytesValue, expVersion); + return this; + } + +// @Override +// public DataAccountKVSetOperationBuilder set(String key, String value, long expVersion) { +// return setText(key, value, expVersion); +// } + + @Override + public DataAccountKVSetOperationBuilder setText(String key, String value, long expVersion) { + BytesValue bytesValue = TypedValue.fromText(value); + operation.set(key, bytesValue, expVersion); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setBytes(String key, Bytes value, long expVersion) { + BytesValue bytesValue = TypedValue.fromBytes(value); + operation.set(key, bytesValue, expVersion); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setInt64(String key, long value, long expVersion) { + BytesValue bytesValue = TypedValue.fromInt64(value); + operation.set(key, bytesValue, expVersion); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setJSON(String key, String value, long expVersion) { + BytesValue bytesValue = TypedValue.fromJSON(value); + operation.set(key, bytesValue, expVersion); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setXML(String key, String value, long expVersion) { + BytesValue bytesValue = TypedValue.fromXML(value); + operation.set(key, bytesValue, expVersion); + return this; + } + + @Override + public DataAccountKVSetOperationBuilder setTimestamp(String key, long value, long expVersion) { + BytesValue bytesValue = TypedValue.fromTimestamp(value); + operation.set(key, bytesValue, expVersion); + return this; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOpTemplate.java index ffcbd455..d6c3591d 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOpTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOpTemplate.java @@ -1,34 +1,34 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.ledger.DataAccountRegisterOperation; -import com.jd.blockchain.ledger.DigitalSignature; - -public class DataAccountRegisterOpTemplate implements DataAccountRegisterOperation { - static { - DataContractRegistry.register(DataAccountKVSetOperation.class); - } - - private BlockchainIdentity accountID; - - public DataAccountRegisterOpTemplate() { - } - - public DataAccountRegisterOpTemplate(BlockchainIdentity accountID) { - this.accountID = accountID; - } - - @Override - public BlockchainIdentity getAccountID() { - return accountID; - } - - @Override - public DigitalSignature getAddressSignature() { - // TODO Auto-generated method stub - return null; - } - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.DataAccountKVSetOperation; +import com.jd.blockchain.ledger.DataAccountRegisterOperation; +import com.jd.blockchain.ledger.DigitalSignature; + +public class DataAccountRegisterOpTemplate implements DataAccountRegisterOperation { + static { + DataContractRegistry.register(DataAccountKVSetOperation.class); + } + + private BlockchainIdentity accountID; + + public DataAccountRegisterOpTemplate() { + } + + public DataAccountRegisterOpTemplate(BlockchainIdentity accountID) { + this.accountID = accountID; + } + + @Override + public BlockchainIdentity getAccountID() { + return accountID; + } + + @Override + public DigitalSignature getAddressSignature() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOperationBuilder.java index ca248fc4..65af0827 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOperationBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOperationBuilder.java @@ -1,14 +1,14 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.DataAccountRegisterOperation; - -public interface DataAccountRegisterOperationBuilder { - - /** - * @param id - * @return - */ - DataAccountRegisterOperation register(BlockchainIdentity id); - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.DataAccountRegisterOperation; + +public interface DataAccountRegisterOperationBuilder { + + /** + * @param id + * @return + */ + DataAccountRegisterOperation register(BlockchainIdentity id); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOperationBuilderImpl.java index eba6b97d..56271e6f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOperationBuilderImpl.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DataAccountRegisterOperationBuilderImpl.java @@ -1,15 +1,15 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.DataAccountRegisterOperation; - -public class DataAccountRegisterOperationBuilderImpl implements DataAccountRegisterOperationBuilder{ - - @Override - public DataAccountRegisterOperation register(BlockchainIdentity userID) { - return new DataAccountRegisterOpTemplate(userID); - } - - - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.DataAccountRegisterOperation; + +public class DataAccountRegisterOperationBuilderImpl implements DataAccountRegisterOperationBuilder{ + + @Override + public DataAccountRegisterOperation register(BlockchainIdentity userID) { + return new DataAccountRegisterOpTemplate(userID); + } + + + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DigitalSignatureBlob.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DigitalSignatureBlob.java index a2125490..ddbbd26f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DigitalSignatureBlob.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/DigitalSignatureBlob.java @@ -1,116 +1,116 @@ -package com.jd.blockchain.transaction; - - -import com.jd.blockchain.crypto.PubKey; -import com.jd.blockchain.crypto.SignatureDigest; -import com.jd.blockchain.ledger.DigitalSignature; -import com.jd.blockchain.ledger.MagicNumber; - -/** - * 数字签名的字节块; - * - *

- * 字节位如下:
- * [第1字节]:标识数据类型为数字签名的魔数常量 ({@link MagicNumber#SIGNATURE});
- * 
- * [第2字节] - [第N字节]: 公钥;
- * 		注:公钥的值是包含了公钥算法标识和公钥内容的字节码编码;
- * 
- * [第N+1字节] - 结束: 摘要;
- * 
- * 
- * - * @author huanghaiquan - * - */ -public class DigitalSignatureBlob implements DigitalSignature { - - private PubKey pubKey; - - private SignatureDigest digest; - - @Override - public PubKey getPubKey() { - return pubKey; - } - - @Override - public SignatureDigest getDigest() { - return digest; - } - - public DigitalSignatureBlob() { - } - - public DigitalSignatureBlob(PubKey pubKey, SignatureDigest digest) { - this.pubKey = pubKey; - this.digest = digest; - } - - -// @Override -// public void resolvFrom(InputStream in) { -// try { -// byte[] buff = new byte[1]; -// int len = in.read(buff); -// if (len < 1) { -// throw new IllegalArgumentException("No enough bytes was read for the magic number [SIGNATURE]!"); -// } -// if (buff[0] != MagicNumber.SIGNATURE) { -// throw new IllegalArgumentException("Magic number [SIGNATURE] dismatch!"); -// } -// PubKey pk = CryptoKeyEncoding.readPubKey(in); -// ByteArray dg = BytesEncoding.readAsByteArray(NumberMask.SHORT, in); -// this.pubKey = pk; -// this.digest = dg; -// } catch (IOException e) { -// throw new RuntimeIOException(e.getMessage(), e); -// } -// } -// -// @Override -// public void writeTo(OutputStream out) { -// try { -// out.write(MagicNumber.SIGNATURE); -// CryptoKeyEncoding.writeKey(pubKey, out); -// BytesEncoding.write(digest, NumberMask.SHORT, out); -// } catch (IOException e) { -// throw new RuntimeIOException(e.getMessage(), e); -// } -// } -// -// @Override -// public boolean equals(Object o) { -// if (this == o) return true; -// if (!(o instanceof DigitalSignatureBlob)) return false; -// DigitalSignatureBlob that = (DigitalSignatureBlob) o; -// return Objects.equals(getPubKey(), that.getPubKey()) && -// Objects.equals(getDigest(), that.getDigest()); -// } -// -// public byte[] toBytes() { -// ByteArrayOutputStream out = new ByteArrayOutputStream(); -// writeTo(out); -// return out.toByteArray(); -// } -// -// @Override -// public String toString() { -// return toBytes().toString(); -// } -// -// @Override -// public void writeExternal(ObjectOutput out) throws IOException { -// byte[] bts = toBytes(); -// out.writeInt(bts.length); -// out.write(bts, 0, bts.length); -// } -// -// @Override -// public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { -// int size = in.readInt(); -// byte[] bs = new byte[size]; -// in.readFully(bs, 0, size); -// resolvFrom(new ByteArrayInputStream(bs)); -// } -} +package com.jd.blockchain.transaction; + + +import com.jd.blockchain.crypto.PubKey; +import com.jd.blockchain.crypto.SignatureDigest; +import com.jd.blockchain.ledger.DigitalSignature; +import com.jd.blockchain.ledger.MagicNumber; + +/** + * 数字签名的字节块; + * + *
+ * 字节位如下:
+ * [第1字节]:标识数据类型为数字签名的魔数常量 ({@link MagicNumber#SIGNATURE});
+ * 
+ * [第2字节] - [第N字节]: 公钥;
+ * 		注:公钥的值是包含了公钥算法标识和公钥内容的字节码编码;
+ * 
+ * [第N+1字节] - 结束: 摘要;
+ * 
+ * 
+ * + * @author huanghaiquan + * + */ +public class DigitalSignatureBlob implements DigitalSignature { + + private PubKey pubKey; + + private SignatureDigest digest; + + @Override + public PubKey getPubKey() { + return pubKey; + } + + @Override + public SignatureDigest getDigest() { + return digest; + } + + public DigitalSignatureBlob() { + } + + public DigitalSignatureBlob(PubKey pubKey, SignatureDigest digest) { + this.pubKey = pubKey; + this.digest = digest; + } + + +// @Override +// public void resolvFrom(InputStream in) { +// try { +// byte[] buff = new byte[1]; +// int len = in.read(buff); +// if (len < 1) { +// throw new IllegalArgumentException("No enough bytes was read for the magic number [SIGNATURE]!"); +// } +// if (buff[0] != MagicNumber.SIGNATURE) { +// throw new IllegalArgumentException("Magic number [SIGNATURE] dismatch!"); +// } +// PubKey pk = CryptoKeyEncoding.readPubKey(in); +// ByteArray dg = BytesEncoding.readAsByteArray(NumberMask.SHORT, in); +// this.pubKey = pk; +// this.digest = dg; +// } catch (IOException e) { +// throw new RuntimeIOException(e.getMessage(), e); +// } +// } +// +// @Override +// public void writeTo(OutputStream out) { +// try { +// out.write(MagicNumber.SIGNATURE); +// CryptoKeyEncoding.writeKey(pubKey, out); +// BytesEncoding.write(digest, NumberMask.SHORT, out); +// } catch (IOException e) { +// throw new RuntimeIOException(e.getMessage(), e); +// } +// } +// +// @Override +// public boolean equals(Object o) { +// if (this == o) return true; +// if (!(o instanceof DigitalSignatureBlob)) return false; +// DigitalSignatureBlob that = (DigitalSignatureBlob) o; +// return Objects.equals(getPubKey(), that.getPubKey()) && +// Objects.equals(getDigest(), that.getDigest()); +// } +// +// public byte[] toBytes() { +// ByteArrayOutputStream out = new ByteArrayOutputStream(); +// writeTo(out); +// return out.toByteArray(); +// } +// +// @Override +// public String toString() { +// return toBytes().toString(); +// } +// +// @Override +// public void writeExternal(ObjectOutput out) throws IOException { +// byte[] bts = toBytes(); +// out.writeInt(bts.length); +// out.write(bts, 0, bts.length); +// } +// +// @Override +// public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { +// int size = in.readInt(); +// byte[] bs = new byte[size]; +// in.readFully(bs, 0, size); +// resolvFrom(new ByteArrayInputStream(bs)); +// } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOpTemplate.java index 4259c98c..48b9e305 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOpTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOpTemplate.java @@ -1,26 +1,26 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.LedgerInitOperation; -import com.jd.blockchain.ledger.LedgerInitSetting; - -public class LedgerInitOpTemplate implements LedgerInitOperation { - static { - DataContractRegistry.register(LedgerInitOperation.class); - } - - private LedgerInitSetting initSetting; - - public LedgerInitOpTemplate() { - } - - public LedgerInitOpTemplate(LedgerInitSetting initSetting) { - this.initSetting = initSetting; - } - - @Override - public LedgerInitSetting getInitSetting() { - return initSetting; - } - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.ledger.LedgerInitOperation; +import com.jd.blockchain.ledger.LedgerInitSetting; + +public class LedgerInitOpTemplate implements LedgerInitOperation { + static { + DataContractRegistry.register(LedgerInitOperation.class); + } + + private LedgerInitSetting initSetting; + + public LedgerInitOpTemplate() { + } + + public LedgerInitOpTemplate(LedgerInitSetting initSetting) { + this.initSetting = initSetting; + } + + @Override + public LedgerInitSetting getInitSetting() { + return initSetting; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOperationBuilder.java index 9416d73d..bada0ff8 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOperationBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOperationBuilder.java @@ -1,17 +1,17 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.LedgerInitOperation; -import com.jd.blockchain.ledger.LedgerInitSetting; - -public interface LedgerInitOperationBuilder { - - /** - * 注册; - * - * @param initSetting - * 账本初始化配置; - * @return LedgerInitOperation - */ - LedgerInitOperation create(LedgerInitSetting initSetting); - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.LedgerInitOperation; +import com.jd.blockchain.ledger.LedgerInitSetting; + +public interface LedgerInitOperationBuilder { + + /** + * 注册; + * + * @param initSetting + * 账本初始化配置; + * @return LedgerInitOperation + */ + LedgerInitOperation create(LedgerInitSetting initSetting); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOperationBuilderImpl.java index 9562ae64..2f39f8d4 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOperationBuilderImpl.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/LedgerInitOperationBuilderImpl.java @@ -1,13 +1,13 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.LedgerInitOperation; -import com.jd.blockchain.ledger.LedgerInitSetting; - -public class LedgerInitOperationBuilderImpl implements LedgerInitOperationBuilder { - - @Override - public LedgerInitOperation create(LedgerInitSetting initSetting) { - return new LedgerInitOpTemplate(initSetting); - } - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.LedgerInitOperation; +import com.jd.blockchain.ledger.LedgerInitSetting; + +public class LedgerInitOperationBuilderImpl implements LedgerInitOperationBuilder { + + @Override + public LedgerInitOperation create(LedgerInitSetting initSetting) { + return new LedgerInitOpTemplate(initSetting); + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/NewLedgerOpBlob.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/NewLedgerOpBlob.java index ee496969..ef9293e7 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/NewLedgerOpBlob.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/NewLedgerOpBlob.java @@ -1,38 +1,38 @@ -package com.jd.blockchain.transaction; -//package com.jd.blockchain.ledger.data; -// -//import com.jd.blockchain.ledger.OperationType; -//import my.utils.io.ByteArray; -// -//public class NewLedgerOpBlob { -// -// private ByteArray genesisKey; -// -// public NewLedgerOpBlob() { -// } -// -// public NewLedgerOpBlob(ByteArray genesisKey) { -// this.genesisKey = genesisKey; -// } -// -// public void resolvFrom(OpBlob opBlob) { -//// if (OperationType.NEW_LEDGER.CODE != opBlob.getCode()) { -//// throw new IllegalArgumentException( -//// "Could not resolve operation info due to NEW_LEDGER operation code mismatch!"); -//// } -//// -//// genesisKey = opBlob.getArg(0); -// } -// -// public OpBlob toBlob() { -// // 写入操作码; -// OpBlob opBlob = new OpBlob(); -// opBlob.setOperation(OperationType.NEW_LEDGER.CODE, genesisKey); -// -// return opBlob; -// } -// -// public ByteArray getGenesisKey() { -// return genesisKey; -// } -//} +package com.jd.blockchain.transaction; +//package com.jd.blockchain.ledger.data; +// +//import com.jd.blockchain.ledger.OperationType; +//import my.utils.io.ByteArray; +// +//public class NewLedgerOpBlob { +// +// private ByteArray genesisKey; +// +// public NewLedgerOpBlob() { +// } +// +// public NewLedgerOpBlob(ByteArray genesisKey) { +// this.genesisKey = genesisKey; +// } +// +// public void resolvFrom(OpBlob opBlob) { +//// if (OperationType.NEW_LEDGER.CODE != opBlob.getCode()) { +//// throw new IllegalArgumentException( +//// "Could not resolve operation info due to NEW_LEDGER operation code mismatch!"); +//// } +//// +//// genesisKey = opBlob.getArg(0); +// } +// +// public OpBlob toBlob() { +// // 写入操作码; +// OpBlob opBlob = new OpBlob(); +// opBlob.setOperation(OperationType.NEW_LEDGER.CODE, genesisKey); +// +// return opBlob; +// } +// +// public ByteArray getGenesisKey() { +// return genesisKey; +// } +//} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PrivilegeSettingOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PrivilegeSettingOperationBuilder.java index f10d77e1..027ae891 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PrivilegeSettingOperationBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PrivilegeSettingOperationBuilder.java @@ -1,25 +1,25 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.PermissionType; - -/** - * 账户权限设置操作; - * - *
- * - * 注:默认情况下,在账户被注册时,账户自身会包含在权限设置表中,具有全部的权限;
- * - * 但这不是必须的,使用者可以根据业务需要,去掉账户自身的权限,并将权限赋予其它的账户,以此实现将区块链账户分别用于表示“角色”和“数据”这两种目的; - * - * @author huanghaiquan - * - */ -public interface PrivilegeSettingOperationBuilder { - - PrivilegeSettingOperationBuilder setThreshhold(PermissionType privilege, long threshhold); - - PrivilegeSettingOperationBuilder enable(PermissionType privilege, String address, int weight); - - PrivilegeSettingOperationBuilder disable(PermissionType privilege, String address); - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.PermissionType; + +/** + * 账户权限设置操作; + * + *
+ * + * 注:默认情况下,在账户被注册时,账户自身会包含在权限设置表中,具有全部的权限;
+ * + * 但这不是必须的,使用者可以根据业务需要,去掉账户自身的权限,并将权限赋予其它的账户,以此实现将区块链账户分别用于表示“角色”和“数据”这两种目的; + * + * @author huanghaiquan + * + */ +public interface PrivilegeSettingOperationBuilder { + + PrivilegeSettingOperationBuilder setThreshhold(PermissionType privilege, long threshhold); + + PrivilegeSettingOperationBuilder enable(PermissionType privilege, String address, int weight); + + PrivilegeSettingOperationBuilder disable(PermissionType privilege, String address); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PubKeyData.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PubKeyData.java index a31864e6..205e66b6 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PubKeyData.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/PubKeyData.java @@ -1,30 +1,30 @@ -package com.jd.blockchain.transaction; -//package com.jd.blockchain.ledger.data; -// -//import com.jd.blockchain.ledger.KeyType; -//import com.jd.blockchain.ledger.PubKey; -// -//import my.utils.io.ByteArray; -// -//public class PubKeyData implements PubKey{ -// -// private KeyType type; -// -// private ByteArray value; -// -// public PubKeyData(KeyType type, ByteArray value) { -// this.type = type; -// this.value = value; -// } -// -// @Override -// public KeyType getType() { -// return type; -// } -// -// @Override -// public ByteArray getValue() { -// return value; -// } -// -//} +package com.jd.blockchain.transaction; +//package com.jd.blockchain.ledger.data; +// +//import com.jd.blockchain.ledger.KeyType; +//import com.jd.blockchain.ledger.PubKey; +// +//import my.utils.io.ByteArray; +// +//public class PubKeyData implements PubKey{ +// +// private KeyType type; +// +// private ByteArray value; +// +// public PubKeyData(KeyType type, ByteArray value) { +// this.type = type; +// this.value = value; +// } +// +// @Override +// public KeyType getType() { +// return type; +// } +// +// @Override +// public ByteArray getValue() { +// return value; +// } +// +//} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java index ba5fc4e5..6d8a4d0e 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/RolesConfigureOpTemplate.java @@ -1,139 +1,139 @@ -package com.jd.blockchain.transaction; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.LedgerPermission; -import com.jd.blockchain.ledger.RolesConfigureOperation; -import com.jd.blockchain.ledger.SecurityUtils; -import com.jd.blockchain.ledger.TransactionPermission; -import com.jd.blockchain.ledger.UserRegisterOperation; -import com.jd.blockchain.utils.ArrayUtils; - -public class RolesConfigureOpTemplate implements RolesConfigurer, RolesConfigureOperation { - - static { - DataContractRegistry.register(UserRegisterOperation.class); - DataContractRegistry.register(RolesConfigureOperation.class); - DataContractRegistry.register(RolePrivilegeEntry.class); - } - - private Map rolesMap = Collections - .synchronizedMap(new LinkedHashMap()); - - public RolesConfigureOpTemplate() { - } - - boolean isEmpty() { - return rolesMap.isEmpty(); - } - - @Override - public RolePrivilegeEntry[] getRoles() { - return rolesMap.values().toArray(new RolePrivilegeEntry[rolesMap.size()]); - } - - @Override - public RolesConfigureOperation getOperation() { - return this; - } - - @Override - public RolePrivilegeConfigurer configure(String roleName) { - roleName = SecurityUtils.formatRoleName(roleName); - - RolePrivilegeConfig roleConfig = rolesMap.get(roleName); - if (roleConfig == null) { - roleConfig = new RolePrivilegeConfig(roleName); - rolesMap.put(roleName, roleConfig); - } - return roleConfig; - } - - private class RolePrivilegeConfig implements RolePrivilegeConfigurer, RolePrivilegeEntry { - - private String roleName; - - private Set enableLedgerPermissions = new LinkedHashSet(); - private Set disableLedgerPermissions = new LinkedHashSet(); - - private Set enableTxPermissions = new LinkedHashSet(); - private Set disableTxPermissions = new LinkedHashSet(); - - private RolePrivilegeConfig(String roleName) { - this.roleName = roleName; - } - - @Override - public String getRoleName() { - return roleName; - } - - @Override - public LedgerPermission[] getEnableLedgerPermissions() { - return ArrayUtils.toArray(enableLedgerPermissions, LedgerPermission.class); - } - - @Override - public LedgerPermission[] getDisableLedgerPermissions() { - return ArrayUtils.toArray(disableLedgerPermissions, LedgerPermission.class); - } - - @Override - public TransactionPermission[] getEnableTransactionPermissions() { - return ArrayUtils.toArray(enableTxPermissions, TransactionPermission.class); - } - - @Override - public TransactionPermission[] getDisableTransactionPermissions() { - return ArrayUtils.toArray(disableTxPermissions, TransactionPermission.class); - } - - @Override - public RolePrivilegeConfigurer enable(LedgerPermission... permissions) { - List permissionList = ArrayUtils.asList(permissions); - enableLedgerPermissions.addAll(permissionList); - disableLedgerPermissions.removeAll(permissionList); - - return this; - } - - @Override - public RolePrivilegeConfigurer disable(LedgerPermission... permissions) { - List permissionList = ArrayUtils.asList(permissions); - disableLedgerPermissions.addAll(permissionList); - enableLedgerPermissions.removeAll(permissionList); - - return this; - } - - @Override - public RolePrivilegeConfigurer enable(TransactionPermission... permissions) { - List permissionList = ArrayUtils.asList(permissions); - enableTxPermissions.addAll(permissionList); - disableTxPermissions.removeAll(permissionList); - - return this; - } - - @Override - public RolePrivilegeConfigurer disable(TransactionPermission... permissions) { - List permissionList = ArrayUtils.asList(permissions); - disableTxPermissions.addAll(permissionList); - enableTxPermissions.removeAll(permissionList); - - return this; - } - - @Override - public RolePrivilegeConfigurer configure(String roleName) { - return RolesConfigureOpTemplate.this.configure(roleName); - } - - } -} +package com.jd.blockchain.transaction; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.ledger.LedgerPermission; +import com.jd.blockchain.ledger.RolesConfigureOperation; +import com.jd.blockchain.ledger.SecurityUtils; +import com.jd.blockchain.ledger.TransactionPermission; +import com.jd.blockchain.ledger.UserRegisterOperation; +import com.jd.blockchain.utils.ArrayUtils; + +public class RolesConfigureOpTemplate implements RolesConfigurer, RolesConfigureOperation { + + static { + DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(RolesConfigureOperation.class); + DataContractRegistry.register(RolePrivilegeEntry.class); + } + + private Map rolesMap = Collections + .synchronizedMap(new LinkedHashMap()); + + public RolesConfigureOpTemplate() { + } + + boolean isEmpty() { + return rolesMap.isEmpty(); + } + + @Override + public RolePrivilegeEntry[] getRoles() { + return rolesMap.values().toArray(new RolePrivilegeEntry[rolesMap.size()]); + } + + @Override + public RolesConfigureOperation getOperation() { + return this; + } + + @Override + public RolePrivilegeConfigurer configure(String roleName) { + roleName = SecurityUtils.formatRoleName(roleName); + + RolePrivilegeConfig roleConfig = rolesMap.get(roleName); + if (roleConfig == null) { + roleConfig = new RolePrivilegeConfig(roleName); + rolesMap.put(roleName, roleConfig); + } + return roleConfig; + } + + private class RolePrivilegeConfig implements RolePrivilegeConfigurer, RolePrivilegeEntry { + + private String roleName; + + private Set enableLedgerPermissions = new LinkedHashSet(); + private Set disableLedgerPermissions = new LinkedHashSet(); + + private Set enableTxPermissions = new LinkedHashSet(); + private Set disableTxPermissions = new LinkedHashSet(); + + private RolePrivilegeConfig(String roleName) { + this.roleName = roleName; + } + + @Override + public String getRoleName() { + return roleName; + } + + @Override + public LedgerPermission[] getEnableLedgerPermissions() { + return ArrayUtils.toArray(enableLedgerPermissions, LedgerPermission.class); + } + + @Override + public LedgerPermission[] getDisableLedgerPermissions() { + return ArrayUtils.toArray(disableLedgerPermissions, LedgerPermission.class); + } + + @Override + public TransactionPermission[] getEnableTransactionPermissions() { + return ArrayUtils.toArray(enableTxPermissions, TransactionPermission.class); + } + + @Override + public TransactionPermission[] getDisableTransactionPermissions() { + return ArrayUtils.toArray(disableTxPermissions, TransactionPermission.class); + } + + @Override + public RolePrivilegeConfigurer enable(LedgerPermission... permissions) { + List permissionList = ArrayUtils.asList(permissions); + enableLedgerPermissions.addAll(permissionList); + disableLedgerPermissions.removeAll(permissionList); + + return this; + } + + @Override + public RolePrivilegeConfigurer disable(LedgerPermission... permissions) { + List permissionList = ArrayUtils.asList(permissions); + disableLedgerPermissions.addAll(permissionList); + enableLedgerPermissions.removeAll(permissionList); + + return this; + } + + @Override + public RolePrivilegeConfigurer enable(TransactionPermission... permissions) { + List permissionList = ArrayUtils.asList(permissions); + enableTxPermissions.addAll(permissionList); + disableTxPermissions.removeAll(permissionList); + + return this; + } + + @Override + public RolePrivilegeConfigurer disable(TransactionPermission... permissions) { + List permissionList = ArrayUtils.asList(permissions); + disableTxPermissions.addAll(permissionList); + enableTxPermissions.removeAll(permissionList); + + return this; + } + + @Override + public RolePrivilegeConfigurer configure(String roleName) { + return RolesConfigureOpTemplate.this.configure(roleName); + } + + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperationBuilder.java index f3b6622c..44051b10 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperationBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SecurityOperationBuilder.java @@ -1,19 +1,19 @@ -package com.jd.blockchain.transaction; - -public interface SecurityOperationBuilder { - - /** - * 配置角色; - * - * @return - */ - RolesConfigurer roles(); - - /** - * 授权用户; - * - * @return - */ - UserAuthorizer authorziations(); - -} +package com.jd.blockchain.transaction; + +public interface SecurityOperationBuilder { + + /** + * 配置角色; + * + * @return + */ + RolesConfigurer roles(); + + /** + * 授权用户; + * + * @return + */ + UserAuthorizer authorziations(); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SignatureEncoding.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SignatureEncoding.java index d28c829e..280a7882 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SignatureEncoding.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/SignatureEncoding.java @@ -1,27 +1,27 @@ -package com.jd.blockchain.transaction; - -import org.springframework.util.Base64Utils; - -import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.ledger.DigitalSignature; - -public class SignatureEncoding { - - public static byte[] encode(DigitalSignature signature) { - return BinaryProtocol.encode(signature, DigitalSignature.class); - } - - public static DigitalSignature decode(byte[] bytesSignature) { - return BinaryProtocol.decode(bytesSignature); - } - - public static DigitalSignature decodeFromBase64(String base64Signature) { - byte[] bytesSignature = Base64Utils.decodeFromUrlSafeString(base64Signature); - return decode(bytesSignature); - } - - public static String encodeToBase64(DigitalSignature signature) { - byte[] bytesSignature = encode(signature); - return Base64Utils.encodeToUrlSafeString(bytesSignature); - } -} +package com.jd.blockchain.transaction; + +import org.springframework.util.Base64Utils; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.ledger.DigitalSignature; + +public class SignatureEncoding { + + public static byte[] encode(DigitalSignature signature) { + return BinaryProtocol.encode(signature, DigitalSignature.class); + } + + public static DigitalSignature decode(byte[] bytesSignature) { + return BinaryProtocol.decode(bytesSignature); + } + + public static DigitalSignature decodeFromBase64(String base64Signature) { + byte[] bytesSignature = Base64Utils.decodeFromUrlSafeString(base64Signature); + return decode(bytesSignature); + } + + public static String encodeToBase64(DigitalSignature signature) { + byte[] bytesSignature = encode(signature); + return Base64Utils.encodeToUrlSafeString(bytesSignature); + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TransactionService.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TransactionService.java index 9d9a9ab8..014e5117 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TransactionService.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TransactionService.java @@ -1,10 +1,10 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.ledger.TransactionResponse; - -public interface TransactionService { - - TransactionResponse process(TransactionRequest txRequest); - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.TransactionRequest; +import com.jd.blockchain.ledger.TransactionResponse; + +public interface TransactionService { + + TransactionResponse process(TransactionRequest txRequest); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestBuilder.java index 68653c0e..3ff1fd4c 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestBuilder.java @@ -1,106 +1,106 @@ -package com.jd.blockchain.transaction; - -import java.util.ArrayList; -import java.util.List; - -import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.crypto.AsymmetricKeypair; -import com.jd.blockchain.crypto.Crypto; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.DigitalSignature; -import com.jd.blockchain.ledger.NodeRequest; -import com.jd.blockchain.ledger.TransactionContent; -import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.ledger.TransactionRequestBuilder; - -public class TxRequestBuilder implements TransactionRequestBuilder { - - private static final String DEFAULT_HASH_ALGORITHM = "SHA256"; - - private TransactionContent txContent; - - private List endpointSignatures = new ArrayList<>(); - - private List nodeSignatures = new ArrayList<>(); - - public TxRequestBuilder(TransactionContent txContent) { - this.txContent = txContent; - } - - @Override - public HashDigest getHash() { - return txContent.getHash(); - } - - @Override - public TransactionContent getTransactionContent() { - return txContent; - } - - @Override - public DigitalSignature signAsEndpoint(AsymmetricKeypair keyPair) { - DigitalSignature signature = SignatureUtils.sign(txContent, keyPair); - addEndpointSignature(signature); - return signature; - } - - @Override - public DigitalSignature signAsNode(AsymmetricKeypair keyPair) { - DigitalSignature signature = SignatureUtils.sign(txContent, keyPair); - addNodeSignature(signature); - return signature; - } - - @Override - public void addNodeSignature(DigitalSignature... signatures) { - if (signatures != null) { - for (DigitalSignature s : signatures) { - nodeSignatures.add(s); - } - } - } - - @Override - public void addEndpointSignature(DigitalSignature... signatures) { - if (signatures != null) { - for (DigitalSignature s : signatures) { - endpointSignatures.add(s); - } - } - } - -// public static DigitalSignature sign(TransactionContent txContent, AsymmetricKeypair keyPair) { -// SignatureDigest signatureDigest = sign(txContent, keyPair.getPrivKey()); -// DigitalSignature signature = new DigitalSignatureBlob(keyPair.getPubKey(), signatureDigest); -// return signature; -// } -// -// public static SignatureDigest sign(TransactionContent txContent, PrivKey privKey) { -// return Crypto.getSignatureFunction(privKey.getAlgorithm()).sign(privKey, txContent.getHash().toBytes()); -// } - -// public static boolean verifySignature(TransactionContent txContent, SignatureDigest signDigest, PubKey pubKey) { -// if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) { -// return false; -// } -// return verifyHashSignature(txContent.getHash(), signDigest, pubKey); -// } -// -// public static boolean verifyHashSignature(HashDigest hash, SignatureDigest signDigest, PubKey pubKey) { -// return Crypto.getSignatureFunction(pubKey.getAlgorithm()).verify(signDigest, pubKey, hash.toBytes()); -// } - - @Override - public TransactionRequest buildRequest() { - TxRequestMessage txMessage = new TxRequestMessage(txContent); - txMessage.addEndpointSignatures(endpointSignatures); - txMessage.addNodeSignatures(nodeSignatures); - - byte[] reqBytes = BinaryProtocol.encode(txMessage, NodeRequest.class); - HashDigest reqHash = Crypto.getHashFunction(DEFAULT_HASH_ALGORITHM).hash(reqBytes); - txMessage.setHash(reqHash); - - return txMessage; - } - -} +package com.jd.blockchain.transaction; + +import java.util.ArrayList; +import java.util.List; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.crypto.AsymmetricKeypair; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.DigitalSignature; +import com.jd.blockchain.ledger.NodeRequest; +import com.jd.blockchain.ledger.TransactionContent; +import com.jd.blockchain.ledger.TransactionRequest; +import com.jd.blockchain.ledger.TransactionRequestBuilder; + +public class TxRequestBuilder implements TransactionRequestBuilder { + + private static final String DEFAULT_HASH_ALGORITHM = "SHA256"; + + private TransactionContent txContent; + + private List endpointSignatures = new ArrayList<>(); + + private List nodeSignatures = new ArrayList<>(); + + public TxRequestBuilder(TransactionContent txContent) { + this.txContent = txContent; + } + + @Override + public HashDigest getHash() { + return txContent.getHash(); + } + + @Override + public TransactionContent getTransactionContent() { + return txContent; + } + + @Override + public DigitalSignature signAsEndpoint(AsymmetricKeypair keyPair) { + DigitalSignature signature = SignatureUtils.sign(txContent, keyPair); + addEndpointSignature(signature); + return signature; + } + + @Override + public DigitalSignature signAsNode(AsymmetricKeypair keyPair) { + DigitalSignature signature = SignatureUtils.sign(txContent, keyPair); + addNodeSignature(signature); + return signature; + } + + @Override + public void addNodeSignature(DigitalSignature... signatures) { + if (signatures != null) { + for (DigitalSignature s : signatures) { + nodeSignatures.add(s); + } + } + } + + @Override + public void addEndpointSignature(DigitalSignature... signatures) { + if (signatures != null) { + for (DigitalSignature s : signatures) { + endpointSignatures.add(s); + } + } + } + +// public static DigitalSignature sign(TransactionContent txContent, AsymmetricKeypair keyPair) { +// SignatureDigest signatureDigest = sign(txContent, keyPair.getPrivKey()); +// DigitalSignature signature = new DigitalSignatureBlob(keyPair.getPubKey(), signatureDigest); +// return signature; +// } +// +// public static SignatureDigest sign(TransactionContent txContent, PrivKey privKey) { +// return Crypto.getSignatureFunction(privKey.getAlgorithm()).sign(privKey, txContent.getHash().toBytes()); +// } + +// public static boolean verifySignature(TransactionContent txContent, SignatureDigest signDigest, PubKey pubKey) { +// if (!TxBuilder.verifyTxContentHash(txContent, txContent.getHash())) { +// return false; +// } +// return verifyHashSignature(txContent.getHash(), signDigest, pubKey); +// } +// +// public static boolean verifyHashSignature(HashDigest hash, SignatureDigest signDigest, PubKey pubKey) { +// return Crypto.getSignatureFunction(pubKey.getAlgorithm()).verify(signDigest, pubKey, hash.toBytes()); +// } + + @Override + public TransactionRequest buildRequest() { + TxRequestMessage txMessage = new TxRequestMessage(txContent); + txMessage.addEndpointSignatures(endpointSignatures); + txMessage.addNodeSignatures(nodeSignatures); + + byte[] reqBytes = BinaryProtocol.encode(txMessage, NodeRequest.class); + HashDigest reqHash = Crypto.getHashFunction(DEFAULT_HASH_ALGORITHM).hash(reqBytes); + txMessage.setHash(reqHash); + + return txMessage; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestMessage.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestMessage.java index 50037ee4..c2cd4df8 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestMessage.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxRequestMessage.java @@ -1,385 +1,385 @@ -package com.jd.blockchain.transaction; - -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.AddressEncoding; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.DigitalSignature; -import com.jd.blockchain.ledger.MagicNumber; -import com.jd.blockchain.ledger.NodeRequest; -import com.jd.blockchain.ledger.TransactionContent; -import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.utils.Bytes; - -/** - * TxRequestMessage 交易消息; - *

- * - * TxRequestMessage 表示参与者提交的交易请求,由3部分组成:交易内容、参与者签名、网关节点签名;
- * - *

- * 字节位如下:
- * [第1字节]:标识数据类型为交易请求的魔数常量 ({@link MagicNumber#TX_REQUEST});
- * 
- * [第2字节] - [第N字节]: 交易内容;
- * 
- * [第N+1字节]: 交易参与者数量(有效值范围 0 - 255);
- *         注:在单个交易中,参与者的数量总是有限的,对于那些需要更多参与者且数量不确定的场景,可以通过合约来实现把参与者分为多次 TX 提交,最终组合完成一次完整的业务进程;
- * [第N+2字节] - [第X字节]: 参与者的签名列表;
- * 
- * [第X+1字节]:对交易请求的哈希算法的代码;
- * [第X+2字节] - [第Y字节]:对交易请求的哈希值;针对交易请求中此段之前的全部内容进行哈希计算,包括:交易请求魔数、交易内容、签名者列表、哈希算法代码;
- * 
- * [第Y+1字节] - 结束: 网关节点针对交易请求的签名;
- * 
- * - * @author huanghaiquan - * - */ -public class TxRequestMessage implements TransactionRequest {// , Externalizable { - - /** - * 交易参与者的个数的最大值; - */ - public static final int MAX_TX_PARTICIPANT_COUNT = 0xFF; - - private HashDigest hash; - - private TransactionContent transactionContent; - - private Map endpointSignatureMap = new LinkedHashMap<>(); - - private Map nodeSignatureMap = new LinkedHashMap<>(); - - // private CryptoAlgorithm defaultHashAlgorithm = CryptoAlgorithm.SHA_256; - - // public TxRequestMessage() { - // } - - static { - DataContractRegistry.register(NodeRequest.class); - } - - public TxRequestMessage(TransactionContent txContent) { - // if (!(txContent instanceof BytesWriter)) { - // throw new IllegalArgumentException("The tx content must be instance of - // BytesWriter!"); - // } - this.transactionContent = txContent; - } - - public TxRequestMessage(TransactionRequest txRequest) { - this.transactionContent = txRequest.getTransactionContent(); - setHash(txRequest.getHash()); - setEndpointSignatures(txRequest.getEndpointSignatures()); - setNodeSignatures(txRequest.getNodeSignatures()); - } - - @Override - public TransactionContent getTransactionContent() { - return this.transactionContent; - } - - @Override - public DigitalSignature[] getEndpointSignatures() { - return endpointSignatureMap.values().toArray(new DigitalSignature[endpointSignatureMap.size()]); - } - - @Override - public DigitalSignature[] getNodeSignatures() { - return nodeSignatureMap.values().toArray(new DigitalSignature[nodeSignatureMap.size()]); - } - - public void setEndpointSignatures(Object[] endpointSignatures) { - if (endpointSignatures != null) { - for (Object object : endpointSignatures) { - DigitalSignature endpointSignature = (DigitalSignature) object; - addEndpointSignatures(endpointSignature); - } - } - return; - } - - public void setNodeSignatures(Object[] nodeSignatures) { - if (nodeSignatures != null) { - for (Object object : nodeSignatures) { - DigitalSignature nodeSignature = (DigitalSignature) object; - addNodeSignatures(nodeSignature); - } - } - return; - } - - private void doAddEndpointSignature(DigitalSignature signature) { - Bytes address = AddressEncoding.generateAddress(signature.getPubKey()); - if (endpointSignatureMap.containsKey(address)) { - throw new IllegalArgumentException( - String.format("Participant signature of Address[%s] already exist!", address)); - } - endpointSignatureMap.put(address, signature); - } - - /** - * 从参与者签名列表中检查是否包含指定的参与者; - * - * @param userBid - * 参与者的身份; - * @return - */ - public boolean containsEndpointSignature(BlockchainIdentity userBid) { - return endpointSignatureMap.containsKey(userBid.getAddress()); - } - - public boolean containsEndpointSignature(Bytes userAddress) { - return endpointSignatureMap.containsKey(userAddress); - } - - public void addEndpointSignatures(DigitalSignature... signature) { - for (DigitalSignature sign : signature) { - doAddEndpointSignature(sign); - } - } - - public void addEndpointSignatures(List signature) { - for (DigitalSignature sign : signature) { - doAddEndpointSignature(sign); - } - } - - /** - * 从节点签名列表中检查是否包含指定的节点; - * - * @param nodeBid - * 节点的身份; - * @return - */ - public boolean containsNodeSignature(BlockchainIdentity nodeBid) { - return nodeSignatureMap.containsKey(nodeBid.getAddress()); - } - - public boolean containsNodeSignature(Bytes nodeAddress) { - return nodeSignatureMap.containsKey(nodeAddress); - } - - private void doAddNodeSignatures(DigitalSignature signature) { - Bytes address = AddressEncoding.generateAddress(signature.getPubKey()); - if (nodeSignatureMap.containsKey(address)) { - throw new IllegalArgumentException(String.format("Node signature of Address[%s] already exist!", address)); - } - nodeSignatureMap.put(address, signature); - } - - public void addNodeSignatures(DigitalSignature... signature) { - for (DigitalSignature sign : signature) { - doAddNodeSignatures(sign); - } - } - - public void addNodeSignatures(List signature) { - for (DigitalSignature sign : signature) { - doAddNodeSignatures(sign); - } - } - - @Override - public HashDigest getHash() { - return hash; - } - - public void setHash(HashDigest hash) { - this.hash = hash; - } - - // public HashDigest updateHash() { - // return computeHash(this.defaultHashAlgorithm); - // } - - // public HashDigest updateHash(CryptoAlgorithm hashAlgorithm) { - // return computeHash(hashAlgorithm); - // } - // - // private HashDigest computeHash(CryptoAlgorithm hashAlgorithm) { - // byte[] reqBody = getRequestBody(); - // this.hash = CryptoUtils.hash(hashAlgorithm).hash(reqBody); - // return this.hash; - // } - - // @Override - // public void resolvFrom(InputStream in) throws IOException { - // // 解析校验交易请求魔数; - // byte[] buff = new byte[1]; - // int len = in.read(buff, 0, 1); - // if (len < 1) { - // throw new IllegalArgumentException("No bytes was read for the magic number - // [TX_REQUEST]!"); - // } - // if (MagicNumber.TX_REQUEST != buff[0]) { - // throw new IllegalArgumentException("Magic number [TX_REQUEST] dismatch!"); - // } - // - // // 解析交易内容; - // TxContentBlob txContentBlob = new TxContentBlob(); - // txContentBlob.resolvFrom(in); - // - // // 解析参与者签名列表; - // int participantCount = NumberMask.TINY.resolveMaskedNumber(in); - // List partiSignList = new ArrayList<>(); - // for (int i = 0; i < participantCount; i++) { - // DigitalSignatureBlob signature = new DigitalSignatureBlob(); - // signature.resolvFrom(in); - // - // partiSignList.add(signature); - // } - // - // // 解析节点签名列表; - // int nodeCount = NumberMask.TINY.resolveMaskedNumber(in); - // List nodeSignList = new ArrayList<>(); - // for (int i = 0; i < nodeCount; i++) { - // DigitalSignatureBlob nodeSign = new DigitalSignatureBlob(); - // nodeSign.resolvFrom(in); - // nodeSignList.add(nodeSign); - // } - // - // // 解析哈希算法标识符; - // HashAlgorithm hashAlgorithm = HashAlgorithm.valueOf((byte) in.read()); - // - // // 解析原始的哈希; - // ByteArray hash = HashEncoding.read(in); - // - // this.txContent = txContentBlob; - // addParticipantSignatures(partiSignList); - // addNodeSignatures(nodeSignList); - // this.hash = hash; - // - // // 校验原始哈希; - // byte[] bodyBytes = getRequestBody(); - // ByteArray rHash = HashEncoding.computeHash(bodyBytes, hashAlgorithm); - // if (!rHash.equals(hash)) { - // throw new IllegalArgumentException("The hash is not match with request - // content!"); - // } - // } - // - // /** - // * 输出交易请求消息; - // * - // * 注:此方法不会自动重新计算hash;如果消息的内容发生改变后,需要调用主动调用 {@link #updateHash()} 方法重新计算 hash; - // */ - // @Override - // public void writeTo(OutputStream out) throws IOException { - // if (this.hash == null) { - // updateHash(); - // } - // - // buildRequestBody(out); - // - // // 写入 hash 值; - // HashEncoding.write(hash, out); - // } - - // /** - // * 生成请求体,包括:交易请求魔数、交易内容、参与者签名者列表、哈希算法代号; - // * - // * @param out - // * @throws IOException - // */ - // private void buildRequestBody(OutputStream out) throws IOException { - // - // buildParticipantRequest(out); - // - // // 写入节点签名列表; - // NumberMask.TINY.writeMask(nodeSignatureMap.size(), out); - // for (DigitalSignature nodeSignatureBlob : nodeSignatureMap.values()) { - // nodeSignatureBlob.writeTo(out); - // } - // - // // 写入 hash 算法代号; - // out.write(hashAlgorithm.getAlgorithm()); - // } - - // /** - // * 生成参与者的请求数据; - // * - // *
- // * 参与者的请求数据仅包含“交易请求模数({@link MagicNumber#TX_REQUEST })” - // * “交易内容({@link #getTransactionContent()})” - // * 和“参与者签名列表({@link #getParticipantSignatures()})”三项属性; - // * - // * @param out - // */ - // public void buildParticipantRequest(OutputStream out) { - // try { - // // 写入魔数; - // out.write(MagicNumber.TX_REQUEST); - // - // // 写入交易内容; - // txContent.writeTo(out); - // - // // 写入 1 个字节的参与者签名数量; - // if (participantSignatureMap.size() > MAX_TX_PARTICIPANT_COUNT) { - // throw new IllegalArgumentException("The number of participant signatures is - // out of the max count[" - // + MAX_TX_PARTICIPANT_COUNT + "]!"); - // } - // - // NumberMask.TINY.writeMask(participantSignatureMap.size(), out); - // // 写入参与者签名列表; - // for (DigitalSignature digitalSignatureBlob : - // participantSignatureMap.values()) { - // digitalSignatureBlob.writeTo(out); - // } - // - // } catch (IOException e) { - // throw new RuntimeIOException(e.getMessage(), e); - // } - // } - // - // @Override - // public void writeExternal(ObjectOutput out) throws IOException { - // ByteArrayOutputStream os = new ByteArrayOutputStream(); - // writeTo(os); - // byte[] bts = os.toByteArray(); - // out.writeInt(bts.length); - // out.write(bts); - // } - // - // @Override - // public void readExternal(ObjectInput in) throws IOException, - // ClassNotFoundException { - // int len = in.readInt(); - // byte[] bts = new byte[len]; - // in.readFully(bts); - // this.resolvFrom(new ByteArrayInputStream(bts)); - // } - - // @Override - // public byte[] toBytes() { - // ByteArrayOutputStream out = new ByteArrayOutputStream(); - // try { - // writeTo(out); - // } catch (IOException e) { - // throw new RuntimeIOException(e.getMessage(), e); - // } - // return out.toByteArray(); - // } - - // @Override - // public ByteArray getHashData() { - // return ByteArray.wrap(getRequestBody()); - // } - - // private byte[] getRequestBody() { - // try { - // ByteArrayOutputStream out = new ByteArrayOutputStream(); - // buildRequestBody(out); - // - // return out.toByteArray(); - // } catch (IOException e) { - // throw new RuntimeIOException(e.getMessage(), e); - // } - // } -} +package com.jd.blockchain.transaction; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.AddressEncoding; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.DigitalSignature; +import com.jd.blockchain.ledger.MagicNumber; +import com.jd.blockchain.ledger.NodeRequest; +import com.jd.blockchain.ledger.TransactionContent; +import com.jd.blockchain.ledger.TransactionRequest; +import com.jd.blockchain.utils.Bytes; + +/** + * TxRequestMessage 交易消息; + *

+ * + * TxRequestMessage 表示参与者提交的交易请求,由3部分组成:交易内容、参与者签名、网关节点签名;
+ * + *

+ * 字节位如下:
+ * [第1字节]:标识数据类型为交易请求的魔数常量 ({@link MagicNumber#TX_REQUEST});
+ * 
+ * [第2字节] - [第N字节]: 交易内容;
+ * 
+ * [第N+1字节]: 交易参与者数量(有效值范围 0 - 255);
+ *         注:在单个交易中,参与者的数量总是有限的,对于那些需要更多参与者且数量不确定的场景,可以通过合约来实现把参与者分为多次 TX 提交,最终组合完成一次完整的业务进程;
+ * [第N+2字节] - [第X字节]: 参与者的签名列表;
+ * 
+ * [第X+1字节]:对交易请求的哈希算法的代码;
+ * [第X+2字节] - [第Y字节]:对交易请求的哈希值;针对交易请求中此段之前的全部内容进行哈希计算,包括:交易请求魔数、交易内容、签名者列表、哈希算法代码;
+ * 
+ * [第Y+1字节] - 结束: 网关节点针对交易请求的签名;
+ * 
+ * + * @author huanghaiquan + * + */ +public class TxRequestMessage implements TransactionRequest {// , Externalizable { + + /** + * 交易参与者的个数的最大值; + */ + public static final int MAX_TX_PARTICIPANT_COUNT = 0xFF; + + private HashDigest hash; + + private TransactionContent transactionContent; + + private Map endpointSignatureMap = new LinkedHashMap<>(); + + private Map nodeSignatureMap = new LinkedHashMap<>(); + + // private CryptoAlgorithm defaultHashAlgorithm = CryptoAlgorithm.SHA_256; + + // public TxRequestMessage() { + // } + + static { + DataContractRegistry.register(NodeRequest.class); + } + + public TxRequestMessage(TransactionContent txContent) { + // if (!(txContent instanceof BytesWriter)) { + // throw new IllegalArgumentException("The tx content must be instance of + // BytesWriter!"); + // } + this.transactionContent = txContent; + } + + public TxRequestMessage(TransactionRequest txRequest) { + this.transactionContent = txRequest.getTransactionContent(); + setHash(txRequest.getHash()); + setEndpointSignatures(txRequest.getEndpointSignatures()); + setNodeSignatures(txRequest.getNodeSignatures()); + } + + @Override + public TransactionContent getTransactionContent() { + return this.transactionContent; + } + + @Override + public DigitalSignature[] getEndpointSignatures() { + return endpointSignatureMap.values().toArray(new DigitalSignature[endpointSignatureMap.size()]); + } + + @Override + public DigitalSignature[] getNodeSignatures() { + return nodeSignatureMap.values().toArray(new DigitalSignature[nodeSignatureMap.size()]); + } + + public void setEndpointSignatures(Object[] endpointSignatures) { + if (endpointSignatures != null) { + for (Object object : endpointSignatures) { + DigitalSignature endpointSignature = (DigitalSignature) object; + addEndpointSignatures(endpointSignature); + } + } + return; + } + + public void setNodeSignatures(Object[] nodeSignatures) { + if (nodeSignatures != null) { + for (Object object : nodeSignatures) { + DigitalSignature nodeSignature = (DigitalSignature) object; + addNodeSignatures(nodeSignature); + } + } + return; + } + + private void doAddEndpointSignature(DigitalSignature signature) { + Bytes address = AddressEncoding.generateAddress(signature.getPubKey()); + if (endpointSignatureMap.containsKey(address)) { + throw new IllegalArgumentException( + String.format("Participant signature of Address[%s] already exist!", address)); + } + endpointSignatureMap.put(address, signature); + } + + /** + * 从参与者签名列表中检查是否包含指定的参与者; + * + * @param userBid + * 参与者的身份; + * @return + */ + public boolean containsEndpointSignature(BlockchainIdentity userBid) { + return endpointSignatureMap.containsKey(userBid.getAddress()); + } + + public boolean containsEndpointSignature(Bytes userAddress) { + return endpointSignatureMap.containsKey(userAddress); + } + + public void addEndpointSignatures(DigitalSignature... signature) { + for (DigitalSignature sign : signature) { + doAddEndpointSignature(sign); + } + } + + public void addEndpointSignatures(List signature) { + for (DigitalSignature sign : signature) { + doAddEndpointSignature(sign); + } + } + + /** + * 从节点签名列表中检查是否包含指定的节点; + * + * @param nodeBid + * 节点的身份; + * @return + */ + public boolean containsNodeSignature(BlockchainIdentity nodeBid) { + return nodeSignatureMap.containsKey(nodeBid.getAddress()); + } + + public boolean containsNodeSignature(Bytes nodeAddress) { + return nodeSignatureMap.containsKey(nodeAddress); + } + + private void doAddNodeSignatures(DigitalSignature signature) { + Bytes address = AddressEncoding.generateAddress(signature.getPubKey()); + if (nodeSignatureMap.containsKey(address)) { + throw new IllegalArgumentException(String.format("Node signature of Address[%s] already exist!", address)); + } + nodeSignatureMap.put(address, signature); + } + + public void addNodeSignatures(DigitalSignature... signature) { + for (DigitalSignature sign : signature) { + doAddNodeSignatures(sign); + } + } + + public void addNodeSignatures(List signature) { + for (DigitalSignature sign : signature) { + doAddNodeSignatures(sign); + } + } + + @Override + public HashDigest getHash() { + return hash; + } + + public void setHash(HashDigest hash) { + this.hash = hash; + } + + // public HashDigest updateHash() { + // return computeHash(this.defaultHashAlgorithm); + // } + + // public HashDigest updateHash(CryptoAlgorithm hashAlgorithm) { + // return computeHash(hashAlgorithm); + // } + // + // private HashDigest computeHash(CryptoAlgorithm hashAlgorithm) { + // byte[] reqBody = getRequestBody(); + // this.hash = CryptoUtils.hash(hashAlgorithm).hash(reqBody); + // return this.hash; + // } + + // @Override + // public void resolvFrom(InputStream in) throws IOException { + // // 解析校验交易请求魔数; + // byte[] buff = new byte[1]; + // int len = in.read(buff, 0, 1); + // if (len < 1) { + // throw new IllegalArgumentException("No bytes was read for the magic number + // [TX_REQUEST]!"); + // } + // if (MagicNumber.TX_REQUEST != buff[0]) { + // throw new IllegalArgumentException("Magic number [TX_REQUEST] dismatch!"); + // } + // + // // 解析交易内容; + // TxContentBlob txContentBlob = new TxContentBlob(); + // txContentBlob.resolvFrom(in); + // + // // 解析参与者签名列表; + // int participantCount = NumberMask.TINY.resolveMaskedNumber(in); + // List partiSignList = new ArrayList<>(); + // for (int i = 0; i < participantCount; i++) { + // DigitalSignatureBlob signature = new DigitalSignatureBlob(); + // signature.resolvFrom(in); + // + // partiSignList.add(signature); + // } + // + // // 解析节点签名列表; + // int nodeCount = NumberMask.TINY.resolveMaskedNumber(in); + // List nodeSignList = new ArrayList<>(); + // for (int i = 0; i < nodeCount; i++) { + // DigitalSignatureBlob nodeSign = new DigitalSignatureBlob(); + // nodeSign.resolvFrom(in); + // nodeSignList.add(nodeSign); + // } + // + // // 解析哈希算法标识符; + // HashAlgorithm hashAlgorithm = HashAlgorithm.valueOf((byte) in.read()); + // + // // 解析原始的哈希; + // ByteArray hash = HashEncoding.read(in); + // + // this.txContent = txContentBlob; + // addParticipantSignatures(partiSignList); + // addNodeSignatures(nodeSignList); + // this.hash = hash; + // + // // 校验原始哈希; + // byte[] bodyBytes = getRequestBody(); + // ByteArray rHash = HashEncoding.computeHash(bodyBytes, hashAlgorithm); + // if (!rHash.equals(hash)) { + // throw new IllegalArgumentException("The hash is not match with request + // content!"); + // } + // } + // + // /** + // * 输出交易请求消息; + // * + // * 注:此方法不会自动重新计算hash;如果消息的内容发生改变后,需要调用主动调用 {@link #updateHash()} 方法重新计算 hash; + // */ + // @Override + // public void writeTo(OutputStream out) throws IOException { + // if (this.hash == null) { + // updateHash(); + // } + // + // buildRequestBody(out); + // + // // 写入 hash 值; + // HashEncoding.write(hash, out); + // } + + // /** + // * 生成请求体,包括:交易请求魔数、交易内容、参与者签名者列表、哈希算法代号; + // * + // * @param out + // * @throws IOException + // */ + // private void buildRequestBody(OutputStream out) throws IOException { + // + // buildParticipantRequest(out); + // + // // 写入节点签名列表; + // NumberMask.TINY.writeMask(nodeSignatureMap.size(), out); + // for (DigitalSignature nodeSignatureBlob : nodeSignatureMap.values()) { + // nodeSignatureBlob.writeTo(out); + // } + // + // // 写入 hash 算法代号; + // out.write(hashAlgorithm.getAlgorithm()); + // } + + // /** + // * 生成参与者的请求数据; + // * + // *
+ // * 参与者的请求数据仅包含“交易请求模数({@link MagicNumber#TX_REQUEST })” + // * “交易内容({@link #getTransactionContent()})” + // * 和“参与者签名列表({@link #getParticipantSignatures()})”三项属性; + // * + // * @param out + // */ + // public void buildParticipantRequest(OutputStream out) { + // try { + // // 写入魔数; + // out.write(MagicNumber.TX_REQUEST); + // + // // 写入交易内容; + // txContent.writeTo(out); + // + // // 写入 1 个字节的参与者签名数量; + // if (participantSignatureMap.size() > MAX_TX_PARTICIPANT_COUNT) { + // throw new IllegalArgumentException("The number of participant signatures is + // out of the max count[" + // + MAX_TX_PARTICIPANT_COUNT + "]!"); + // } + // + // NumberMask.TINY.writeMask(participantSignatureMap.size(), out); + // // 写入参与者签名列表; + // for (DigitalSignature digitalSignatureBlob : + // participantSignatureMap.values()) { + // digitalSignatureBlob.writeTo(out); + // } + // + // } catch (IOException e) { + // throw new RuntimeIOException(e.getMessage(), e); + // } + // } + // + // @Override + // public void writeExternal(ObjectOutput out) throws IOException { + // ByteArrayOutputStream os = new ByteArrayOutputStream(); + // writeTo(os); + // byte[] bts = os.toByteArray(); + // out.writeInt(bts.length); + // out.write(bts); + // } + // + // @Override + // public void readExternal(ObjectInput in) throws IOException, + // ClassNotFoundException { + // int len = in.readInt(); + // byte[] bts = new byte[len]; + // in.readFully(bts); + // this.resolvFrom(new ByteArrayInputStream(bts)); + // } + + // @Override + // public byte[] toBytes() { + // ByteArrayOutputStream out = new ByteArrayOutputStream(); + // try { + // writeTo(out); + // } catch (IOException e) { + // throw new RuntimeIOException(e.getMessage(), e); + // } + // return out.toByteArray(); + // } + + // @Override + // public ByteArray getHashData() { + // return ByteArray.wrap(getRequestBody()); + // } + + // private byte[] getRequestBody() { + // try { + // ByteArrayOutputStream out = new ByteArrayOutputStream(); + // buildRequestBody(out); + // + // return out.toByteArray(); + // } catch (IOException e) { + // throw new RuntimeIOException(e.getMessage(), e); + // } + // } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxResponseMessage.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxResponseMessage.java index 57107ff3..0bed71b5 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxResponseMessage.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxResponseMessage.java @@ -1,86 +1,86 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.TransactionState; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.OperationResult; -import com.jd.blockchain.ledger.TransactionResponse; - -/** - * @author huanghaiquan - * - */ -public class TxResponseMessage implements TransactionResponse { - - private HashDigest contentHash; - - private HashDigest blockHash; - - private long blockHeight; - - private TransactionState executionState; - - private OperationResult[] operationResults; - - public TxResponseMessage() { - } - - // 重新包装operationResults - public TxResponseMessage(TransactionResponse transactionResponse, OperationResult[] operationResults) { - this.contentHash = transactionResponse.getContentHash(); - this.blockHash = transactionResponse.getBlockHash(); - this.blockHeight = transactionResponse.getBlockHeight(); - this.executionState = transactionResponse.getExecutionState(); - this.operationResults = operationResults; - } - - public TxResponseMessage(HashDigest contentHash) { - this.contentHash = contentHash; - } - - @Override - public HashDigest getContentHash() { - return contentHash; - } - - @Override - public TransactionState getExecutionState() { - return executionState; - } - - public void setExecutionState(TransactionState executionState) { - this.executionState = executionState; - } - - @Override - public HashDigest getBlockHash() { - return blockHash; - } - - public void setBlockHash(HashDigest blockHash) { - this.blockHash = blockHash; - } - - @Override - public long getBlockHeight() { - return blockHeight; - } - - public void setBlockHeight(long blockHeight) { - this.blockHeight = blockHeight; - } - - public void setOperationResults(OperationResult[] operationResults) { - this.operationResults = operationResults; - } - - @Override - public boolean isSuccess() { - return blockHash != null & executionState == TransactionState.SUCCESS; - } - - @Override - public OperationResult[] getOperationResults() { - return operationResults; - } - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.TransactionState; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.OperationResult; +import com.jd.blockchain.ledger.TransactionResponse; + +/** + * @author huanghaiquan + * + */ +public class TxResponseMessage implements TransactionResponse { + + private HashDigest contentHash; + + private HashDigest blockHash; + + private long blockHeight; + + private TransactionState executionState; + + private OperationResult[] operationResults; + + public TxResponseMessage() { + } + + // 重新包装operationResults + public TxResponseMessage(TransactionResponse transactionResponse, OperationResult[] operationResults) { + this.contentHash = transactionResponse.getContentHash(); + this.blockHash = transactionResponse.getBlockHash(); + this.blockHeight = transactionResponse.getBlockHeight(); + this.executionState = transactionResponse.getExecutionState(); + this.operationResults = operationResults; + } + + public TxResponseMessage(HashDigest contentHash) { + this.contentHash = contentHash; + } + + @Override + public HashDigest getContentHash() { + return contentHash; + } + + @Override + public TransactionState getExecutionState() { + return executionState; + } + + public void setExecutionState(TransactionState executionState) { + this.executionState = executionState; + } + + @Override + public HashDigest getBlockHash() { + return blockHash; + } + + public void setBlockHash(HashDigest blockHash) { + this.blockHash = blockHash; + } + + @Override + public long getBlockHeight() { + return blockHeight; + } + + public void setBlockHeight(long blockHeight) { + this.blockHeight = blockHeight; + } + + public void setOperationResults(OperationResult[] operationResults) { + this.operationResults = operationResults; + } + + @Override + public boolean isSuccess() { + return blockHash != null & executionState == TransactionState.SUCCESS; + } + + @Override + public OperationResult[] getOperationResults() { + return operationResults; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java index 5f006111..01fb8caf 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/TxTemplate.java @@ -1,111 +1,111 @@ -package com.jd.blockchain.transaction; - -import java.io.IOException; -import java.util.Collection; - -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.PreparedTransaction; -import com.jd.blockchain.ledger.TransactionRequestBuilder; -import com.jd.blockchain.ledger.TransactionTemplate; -import com.jd.blockchain.utils.Bytes; - -public class TxTemplate implements TransactionTemplate { - - private TxBuilder txBuilder; - - private TransactionService txService; - - private TxStateManager stateManager; - - public TxTemplate(HashDigest ledgerHash, TransactionService txService) { - this.stateManager = new TxStateManager(); - this.txBuilder = new TxBuilder(ledgerHash); - this.txService = txService; - } - - @Override - public HashDigest getLedgerHash() { - return txBuilder.getLedgerHash(); - } - - @Override - public PreparedTransaction prepare() { - stateManager.prepare(); - TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); - return new PreparedTx(stateManager, txReqBuilder, txService, txBuilder.getReturnValuehandlers()); - } - - @Override - public SecurityOperationBuilder security() { - stateManager.operate(); - return txBuilder.security(); - } - - @Override - public UserRegisterOperationBuilder users() { - stateManager.operate(); - return txBuilder.users(); - } - - @Override - public DataAccountRegisterOperationBuilder dataAccounts() { - stateManager.operate(); - return txBuilder.dataAccounts(); - } - - @Override - public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) { - stateManager.operate(); - return txBuilder.dataAccount(accountAddress); - } - - @Override - public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) { - stateManager.operate(); - return txBuilder.dataAccount(accountAddress); - } - - @Override - public ContractCodeDeployOperationBuilder contracts() { - stateManager.operate(); - return txBuilder.contracts(); - } - - @Override - public ParticipantRegisterOperationBuilder participants() { - stateManager.operate(); - return txBuilder.participants(); - } - - @Override - public ParticipantStateUpdateOperationBuilder states() { - stateManager.operate(); - return txBuilder.states(); - } - - @Override - public T contract(Bytes address, Class contractIntf) { - stateManager.operate(); - return txBuilder.contract(address, contractIntf); - } - - @Override - public T contract(String address, Class contractIntf) { - stateManager.operate(); - return txBuilder.contract(address, contractIntf); - } - - @Override - public void close() throws IOException { - if (!stateManager.close()) { - Collection handlers = txBuilder.getReturnValuehandlers(); - if (handlers.size() > 0) { - TransactionCancelledExeption error = new TransactionCancelledExeption( - "Transaction template has been cancelled!"); - for (OperationResultHandle handle : handlers) { - handle.complete(error); - } - } - } - } -} +package com.jd.blockchain.transaction; + +import java.io.IOException; +import java.util.Collection; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.PreparedTransaction; +import com.jd.blockchain.ledger.TransactionRequestBuilder; +import com.jd.blockchain.ledger.TransactionTemplate; +import com.jd.blockchain.utils.Bytes; + +public class TxTemplate implements TransactionTemplate { + + private TxBuilder txBuilder; + + private TransactionService txService; + + private TxStateManager stateManager; + + public TxTemplate(HashDigest ledgerHash, TransactionService txService) { + this.stateManager = new TxStateManager(); + this.txBuilder = new TxBuilder(ledgerHash); + this.txService = txService; + } + + @Override + public HashDigest getLedgerHash() { + return txBuilder.getLedgerHash(); + } + + @Override + public PreparedTransaction prepare() { + stateManager.prepare(); + TransactionRequestBuilder txReqBuilder = txBuilder.prepareRequest(); + return new PreparedTx(stateManager, txReqBuilder, txService, txBuilder.getReturnValuehandlers()); + } + + @Override + public SecurityOperationBuilder security() { + stateManager.operate(); + return txBuilder.security(); + } + + @Override + public UserRegisterOperationBuilder users() { + stateManager.operate(); + return txBuilder.users(); + } + + @Override + public DataAccountRegisterOperationBuilder dataAccounts() { + stateManager.operate(); + return txBuilder.dataAccounts(); + } + + @Override + public DataAccountKVSetOperationBuilder dataAccount(String accountAddress) { + stateManager.operate(); + return txBuilder.dataAccount(accountAddress); + } + + @Override + public DataAccountKVSetOperationBuilder dataAccount(Bytes accountAddress) { + stateManager.operate(); + return txBuilder.dataAccount(accountAddress); + } + + @Override + public ContractCodeDeployOperationBuilder contracts() { + stateManager.operate(); + return txBuilder.contracts(); + } + + @Override + public ParticipantRegisterOperationBuilder participants() { + stateManager.operate(); + return txBuilder.participants(); + } + + @Override + public ParticipantStateUpdateOperationBuilder states() { + stateManager.operate(); + return txBuilder.states(); + } + + @Override + public T contract(Bytes address, Class contractIntf) { + stateManager.operate(); + return txBuilder.contract(address, contractIntf); + } + + @Override + public T contract(String address, Class contractIntf) { + stateManager.operate(); + return txBuilder.contract(address, contractIntf); + } + + @Override + public void close() throws IOException { + if (!stateManager.close()) { + Collection handlers = txBuilder.getReturnValuehandlers(); + if (handlers.size() > 0) { + TransactionCancelledExeption error = new TransactionCancelledExeption( + "Transaction template has been cancelled!"); + for (OperationResultHandle handle : handlers) { + handle.complete(error); + } + } + } + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizeOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizeOpTemplate.java index ca66a6d9..d4c06cc0 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizeOpTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserAuthorizeOpTemplate.java @@ -1,130 +1,130 @@ -package com.jd.blockchain.transaction; - -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.RolesPolicy; -import com.jd.blockchain.ledger.SecurityUtils; -import com.jd.blockchain.ledger.UserAuthorizeOperation; -import com.jd.blockchain.ledger.UserRegisterOperation; -import com.jd.blockchain.utils.ArrayUtils; -import com.jd.blockchain.utils.Bytes; - -public class UserAuthorizeOpTemplate implements UserAuthorizer, UserAuthorizeOperation { - - static { - DataContractRegistry.register(UserRegisterOperation.class); - DataContractRegistry.register(UserAuthorizeOperation.class); - DataContractRegistry.register(UserRolesEntry.class); - } - - private Set userAuthMap = Collections - .synchronizedSet(new LinkedHashSet()); - - public UserAuthorizeOpTemplate() { - } - - public UserAuthorizeOpTemplate(BlockchainIdentity userID) { - } - - @Override - public AuthorizationDataEntry[] getUserRolesAuthorizations() { - return ArrayUtils.toArray(userAuthMap, AuthorizationDataEntry.class); - } - - @Override - public UserAuthorizeOperation getOperation() { - return this; - } - - @Override - public UserRolesAuthorizer forUser(Bytes... userAddresses) { - AuthorizationDataEntry userRolesAuth = new AuthorizationDataEntry(userAddresses); - userAuthMap.add(userRolesAuth); - return userRolesAuth; - } - - @Override - public UserRolesAuthorizer forUser(BlockchainIdentity... userIds) { - Bytes[] addresses = Arrays.stream(userIds).map(p -> p.getAddress()).toArray(Bytes[]::new); - return forUser(addresses); - } - - private class AuthorizationDataEntry implements UserRolesAuthorizer, UserRolesEntry { - - private Bytes[] userAddress; - - private RolesPolicy policy = RolesPolicy.UNION; - - private Set authRoles = new LinkedHashSet(); - private Set unauthRoles = new LinkedHashSet(); - - private AuthorizationDataEntry(Bytes[] userAddress) { - this.userAddress = userAddress; - } - - @Override - public Bytes[] getUserAddresses() { - return userAddress; - } - - @Override - public RolesPolicy getPolicy() { - return policy; - } - - @Override - public String[] getAuthorizedRoles() { - return ArrayUtils.toArray(authRoles, String.class); - } - - @Override - public String[] getUnauthorizedRoles() { - return ArrayUtils.toArray(unauthRoles, String.class); - } - - @Override - public UserRolesAuthorizer setPolicy(RolesPolicy policy) { - this.policy = policy; - return this; - } - - @Override - public UserRolesAuthorizer authorize(String... roles) { - String roleName; - for (String r : roles) { - roleName = SecurityUtils.formatRoleName(r); - authRoles.add(roleName); - unauthRoles.remove(roleName); - } - - return this; - } - - @Override - public UserRolesAuthorizer unauthorize(String... roles) { - String roleName; - for (String r : roles) { - roleName = SecurityUtils.formatRoleName(r); - unauthRoles.add(roleName); - authRoles.remove(roleName); - } - - return this; - } - - @Override - public UserRolesAuthorizer forUser(BlockchainIdentity... userIds) { - return UserAuthorizeOpTemplate.this.forUser(userIds); - } - - @Override - public UserRolesAuthorizer forUser(Bytes... userAddresses) { - return UserAuthorizeOpTemplate.this.forUser(userAddresses); - } - } -} +package com.jd.blockchain.transaction; + +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.RolesPolicy; +import com.jd.blockchain.ledger.SecurityUtils; +import com.jd.blockchain.ledger.UserAuthorizeOperation; +import com.jd.blockchain.ledger.UserRegisterOperation; +import com.jd.blockchain.utils.ArrayUtils; +import com.jd.blockchain.utils.Bytes; + +public class UserAuthorizeOpTemplate implements UserAuthorizer, UserAuthorizeOperation { + + static { + DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(UserAuthorizeOperation.class); + DataContractRegistry.register(UserRolesEntry.class); + } + + private Set userAuthMap = Collections + .synchronizedSet(new LinkedHashSet()); + + public UserAuthorizeOpTemplate() { + } + + public UserAuthorizeOpTemplate(BlockchainIdentity userID) { + } + + @Override + public AuthorizationDataEntry[] getUserRolesAuthorizations() { + return ArrayUtils.toArray(userAuthMap, AuthorizationDataEntry.class); + } + + @Override + public UserAuthorizeOperation getOperation() { + return this; + } + + @Override + public UserRolesAuthorizer forUser(Bytes... userAddresses) { + AuthorizationDataEntry userRolesAuth = new AuthorizationDataEntry(userAddresses); + userAuthMap.add(userRolesAuth); + return userRolesAuth; + } + + @Override + public UserRolesAuthorizer forUser(BlockchainIdentity... userIds) { + Bytes[] addresses = Arrays.stream(userIds).map(p -> p.getAddress()).toArray(Bytes[]::new); + return forUser(addresses); + } + + private class AuthorizationDataEntry implements UserRolesAuthorizer, UserRolesEntry { + + private Bytes[] userAddress; + + private RolesPolicy policy = RolesPolicy.UNION; + + private Set authRoles = new LinkedHashSet(); + private Set unauthRoles = new LinkedHashSet(); + + private AuthorizationDataEntry(Bytes[] userAddress) { + this.userAddress = userAddress; + } + + @Override + public Bytes[] getUserAddresses() { + return userAddress; + } + + @Override + public RolesPolicy getPolicy() { + return policy; + } + + @Override + public String[] getAuthorizedRoles() { + return ArrayUtils.toArray(authRoles, String.class); + } + + @Override + public String[] getUnauthorizedRoles() { + return ArrayUtils.toArray(unauthRoles, String.class); + } + + @Override + public UserRolesAuthorizer setPolicy(RolesPolicy policy) { + this.policy = policy; + return this; + } + + @Override + public UserRolesAuthorizer authorize(String... roles) { + String roleName; + for (String r : roles) { + roleName = SecurityUtils.formatRoleName(r); + authRoles.add(roleName); + unauthRoles.remove(roleName); + } + + return this; + } + + @Override + public UserRolesAuthorizer unauthorize(String... roles) { + String roleName; + for (String r : roles) { + roleName = SecurityUtils.formatRoleName(r); + unauthRoles.add(roleName); + authRoles.remove(roleName); + } + + return this; + } + + @Override + public UserRolesAuthorizer forUser(BlockchainIdentity... userIds) { + return UserAuthorizeOpTemplate.this.forUser(userIds); + } + + @Override + public UserRolesAuthorizer forUser(Bytes... userAddresses) { + return UserAuthorizeOpTemplate.this.forUser(userAddresses); + } + } +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOpTemplate.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOpTemplate.java index 91ea541a..38f921df 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOpTemplate.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOpTemplate.java @@ -1,27 +1,27 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.UserRegisterOperation; - -public class UserRegisterOpTemplate implements UserRegisterOperation { - - static { - DataContractRegistry.register(UserRegisterOperation.class); - } - - private BlockchainIdentity userID; - - public UserRegisterOpTemplate() { - } - - public UserRegisterOpTemplate(BlockchainIdentity userID) { - this.userID = userID; - } - - @Override - public BlockchainIdentity getUserID() { - return userID; - } - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.UserRegisterOperation; + +public class UserRegisterOpTemplate implements UserRegisterOperation { + + static { + DataContractRegistry.register(UserRegisterOperation.class); + } + + private BlockchainIdentity userID; + + public UserRegisterOpTemplate() { + } + + public UserRegisterOpTemplate(BlockchainIdentity userID) { + this.userID = userID; + } + + @Override + public BlockchainIdentity getUserID() { + return userID; + } + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOperationBuilder.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOperationBuilder.java index 76f0e956..283f2a9f 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOperationBuilder.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOperationBuilder.java @@ -1,19 +1,19 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.UserRegisterOperation; - -public interface UserRegisterOperationBuilder { - - /** - * 注册; - * - * @param id - * 区块链身份; - * @param stateType - * 负载类型; - * @return - */ - UserRegisterOperation register(BlockchainIdentity userID); - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.UserRegisterOperation; + +public interface UserRegisterOperationBuilder { + + /** + * 注册; + * + * @param id + * 区块链身份; + * @param stateType + * 负载类型; + * @return + */ + UserRegisterOperation register(BlockchainIdentity userID); + +} diff --git a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOperationBuilderImpl.java b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOperationBuilderImpl.java index 39a84725..c33f91cd 100644 --- a/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOperationBuilderImpl.java +++ b/source/ledger/ledger-model/src/main/java/com/jd/blockchain/transaction/UserRegisterOperationBuilderImpl.java @@ -1,15 +1,15 @@ -package com.jd.blockchain.transaction; - -import com.jd.blockchain.ledger.BlockchainIdentity; -import com.jd.blockchain.ledger.UserRegisterOperation; - -public class UserRegisterOperationBuilderImpl implements UserRegisterOperationBuilder{ - - @Override - public UserRegisterOperation register(BlockchainIdentity userID) { - return new UserRegisterOpTemplate(userID); - } - - - -} +package com.jd.blockchain.transaction; + +import com.jd.blockchain.ledger.BlockchainIdentity; +import com.jd.blockchain.ledger.UserRegisterOperation; + +public class UserRegisterOperationBuilderImpl implements UserRegisterOperationBuilder{ + + @Override + public UserRegisterOperation register(BlockchainIdentity userID) { + return new UserRegisterOpTemplate(userID); + } + + + +} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesEncodingTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesEncodingTest.java index 32d48aba..69b244a1 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesEncodingTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/BytesEncodingTest.java @@ -1,84 +1,84 @@ -package test.com.jd.blockchain.ledger; - -import static org.junit.Assert.*; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; - -import org.junit.Test; -import org.mockito.Mockito; - -import com.jd.blockchain.utils.io.BytesEncoding; -import com.jd.blockchain.utils.io.NumberMask; - -public class BytesEncodingTest { - - @Test - public void testReadAndWriteSize() { - assertReadAndWriteSizeOK(0, NumberMask.TINY); - assertReadAndWriteSizeOK(255, NumberMask.TINY); - assertReadAndWriteSizeOK(1, NumberMask.TINY); - assertReadAndWriteSizeOK(128, NumberMask.TINY); - assertReadAndWriteSizeError(256, NumberMask.TINY); - assertReadAndWriteSizeError(Integer.MIN_VALUE, NumberMask.TINY); - assertReadAndWriteSizeError(Integer.MAX_VALUE, NumberMask.TINY); - - assertReadAndWriteSizeOK(0, NumberMask.SHORT); - assertReadAndWriteSizeOK(255, NumberMask.SHORT); - assertReadAndWriteSizeOK(1, NumberMask.SHORT); - assertReadAndWriteSizeOK(128, NumberMask.SHORT); - assertReadAndWriteSizeOK(256, NumberMask.SHORT); - assertReadAndWriteSizeOK(1 << 7, NumberMask.SHORT); - assertReadAndWriteSizeOK((1 << 15) - 1, NumberMask.SHORT); - assertReadAndWriteSizeError((1 << 15) + 1, NumberMask.SHORT); - assertReadAndWriteSizeError(1 << 16, NumberMask.SHORT); - assertReadAndWriteSizeError(Integer.MIN_VALUE, NumberMask.SHORT); - assertReadAndWriteSizeError(Integer.MAX_VALUE, NumberMask.SHORT); - - assertReadAndWriteSizeOK(0, NumberMask.NORMAL); - assertReadAndWriteSizeOK(255, NumberMask.NORMAL); - assertReadAndWriteSizeOK(1, NumberMask.NORMAL); - assertReadAndWriteSizeOK(128, NumberMask.NORMAL); - assertReadAndWriteSizeOK(256, NumberMask.NORMAL); - assertReadAndWriteSizeOK(1 << 7, NumberMask.NORMAL); - assertReadAndWriteSizeOK((1 << 15) - 1, NumberMask.NORMAL); - assertReadAndWriteSizeOK((1 << 15) + 1, NumberMask.NORMAL); - assertReadAndWriteSizeOK(1 << 16, NumberMask.NORMAL); - assertReadAndWriteSizeOK(Short.MAX_VALUE, NumberMask.NORMAL); - assertReadAndWriteSizeOK((1 << 16) - 1, NumberMask.NORMAL); - assertReadAndWriteSizeOK(1 << 24, NumberMask.NORMAL); - assertReadAndWriteSizeOK((1 << 24) - 1, NumberMask.NORMAL); - assertReadAndWriteSizeOK((1 << 30) - 1, NumberMask.NORMAL); - assertReadAndWriteSizeError(1 << 30, NumberMask.NORMAL); - assertReadAndWriteSizeError(Integer.MIN_VALUE, NumberMask.NORMAL); - assertReadAndWriteSizeError(Integer.MAX_VALUE, NumberMask.NORMAL); - } - - private void assertReadAndWriteSizeError(int size, NumberMask mask) { - Exception error = null; - try { - assertReadAndWriteSizeOK(size, mask); - } catch (Exception e) { - error = e; - } - assertNotNull(error); - } - - private void assertReadAndWriteSizeOK(int size, NumberMask mask) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - mask.writeMask(size, out); - - byte[] sizebytes = out.toByteArray(); - - assertTrue(sizebytes.length <= mask.MAX_HEADER_LENGTH); - assertTrue(size <= mask.getBoundarySize(sizebytes.length)); - - ByteArrayInputStream in = new ByteArrayInputStream(sizebytes); - int sizeResolved = mask.resolveMaskedNumber(in); - - assertEquals(size, sizeResolved); - - assertTrue(in.available() == 0); - } - -} +package test.com.jd.blockchain.ledger; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import org.junit.Test; +import org.mockito.Mockito; + +import com.jd.blockchain.utils.io.BytesEncoding; +import com.jd.blockchain.utils.io.NumberMask; + +public class BytesEncodingTest { + + @Test + public void testReadAndWriteSize() { + assertReadAndWriteSizeOK(0, NumberMask.TINY); + assertReadAndWriteSizeOK(255, NumberMask.TINY); + assertReadAndWriteSizeOK(1, NumberMask.TINY); + assertReadAndWriteSizeOK(128, NumberMask.TINY); + assertReadAndWriteSizeError(256, NumberMask.TINY); + assertReadAndWriteSizeError(Integer.MIN_VALUE, NumberMask.TINY); + assertReadAndWriteSizeError(Integer.MAX_VALUE, NumberMask.TINY); + + assertReadAndWriteSizeOK(0, NumberMask.SHORT); + assertReadAndWriteSizeOK(255, NumberMask.SHORT); + assertReadAndWriteSizeOK(1, NumberMask.SHORT); + assertReadAndWriteSizeOK(128, NumberMask.SHORT); + assertReadAndWriteSizeOK(256, NumberMask.SHORT); + assertReadAndWriteSizeOK(1 << 7, NumberMask.SHORT); + assertReadAndWriteSizeOK((1 << 15) - 1, NumberMask.SHORT); + assertReadAndWriteSizeError((1 << 15) + 1, NumberMask.SHORT); + assertReadAndWriteSizeError(1 << 16, NumberMask.SHORT); + assertReadAndWriteSizeError(Integer.MIN_VALUE, NumberMask.SHORT); + assertReadAndWriteSizeError(Integer.MAX_VALUE, NumberMask.SHORT); + + assertReadAndWriteSizeOK(0, NumberMask.NORMAL); + assertReadAndWriteSizeOK(255, NumberMask.NORMAL); + assertReadAndWriteSizeOK(1, NumberMask.NORMAL); + assertReadAndWriteSizeOK(128, NumberMask.NORMAL); + assertReadAndWriteSizeOK(256, NumberMask.NORMAL); + assertReadAndWriteSizeOK(1 << 7, NumberMask.NORMAL); + assertReadAndWriteSizeOK((1 << 15) - 1, NumberMask.NORMAL); + assertReadAndWriteSizeOK((1 << 15) + 1, NumberMask.NORMAL); + assertReadAndWriteSizeOK(1 << 16, NumberMask.NORMAL); + assertReadAndWriteSizeOK(Short.MAX_VALUE, NumberMask.NORMAL); + assertReadAndWriteSizeOK((1 << 16) - 1, NumberMask.NORMAL); + assertReadAndWriteSizeOK(1 << 24, NumberMask.NORMAL); + assertReadAndWriteSizeOK((1 << 24) - 1, NumberMask.NORMAL); + assertReadAndWriteSizeOK((1 << 30) - 1, NumberMask.NORMAL); + assertReadAndWriteSizeError(1 << 30, NumberMask.NORMAL); + assertReadAndWriteSizeError(Integer.MIN_VALUE, NumberMask.NORMAL); + assertReadAndWriteSizeError(Integer.MAX_VALUE, NumberMask.NORMAL); + } + + private void assertReadAndWriteSizeError(int size, NumberMask mask) { + Exception error = null; + try { + assertReadAndWriteSizeOK(size, mask); + } catch (Exception e) { + error = e; + } + assertNotNull(error); + } + + private void assertReadAndWriteSizeOK(int size, NumberMask mask) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + mask.writeMask(size, out); + + byte[] sizebytes = out.toByteArray(); + + assertTrue(sizebytes.length <= mask.MAX_HEADER_LENGTH); + assertTrue(size <= mask.getBoundarySize(sizebytes.length)); + + ByteArrayInputStream in = new ByteArrayInputStream(sizebytes); + int sizeResolved = mask.resolveMaskedNumber(in); + + assertEquals(size, sizeResolved); + + assertTrue(in.available() == 0); + } + +} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/OpBlobTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/OpBlobTest.java index 6ea6da45..365c737b 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/OpBlobTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/OpBlobTest.java @@ -1,83 +1,83 @@ -package test.com.jd.blockchain.ledger; -//package test.com.jd.blockchain.ledger.data; -// -//import static org.junit.Assert.*; -// -//import java.io.IOException; -// -//import org.junit.Test; -// -//import com.jd.blockchain.ledger.StateOpType; -//import com.jd.blockchain.ledger.Operation; -//import com.jd.blockchain.ledger.OperationType; -//import com.jd.blockchain.ledger.data.OpBlob; -// -//import my.utils.io.ByteArray; -//import my.utils.io.BytesUtils; -//import my.utils.security.RandomUtils; -// -//public class OpBlobTest { -// -// /** -// * 验证无子操作的情形; -// * -// * @throws IOException -// */ -// @Test -// public void testSerializeNoSubOP() throws IOException { -// OpBlob op = new OpBlob(); -// byte[] opArg = RandomUtils.generateRandomBytes(16); -// op.setOperation(OperationType.REGISTER_USER.CODE, ByteArray.wrap(opArg)); -// -// byte[] opBytes = BytesUtils.toBytes(op); -// -// assertEquals(OperationType.REGISTER_USER.CODE, opBytes[0]); -// -// OpBlob resolvedOP = new OpBlob(); -// resolvedOP.resolvFrom(ByteArray.wrap(opBytes).asInputStream()); -// -// assertEquals(op.getCode(), resolvedOP.getCode()); -// assertEquals(op.getArgCount(), resolvedOP.getArgCount()); -// assertEquals(0, resolvedOP.getSubOperations().length); -// assertEquals(op.getSubOperations().length, resolvedOP.getSubOperations().length); -// -// } -// -// /** -// * 验证有子操作的情形; -// * -// * @throws IOException -// */ -// @Test -// public void testSerializeWithSubOP() throws IOException { -// OpBlob op = new OpBlob(); -// byte[] opArg = RandomUtils.generateRandomBytes(16); -// op.setOperation(OperationType.REGISTER_USER.CODE, ByteArray.wrap(opArg)); -// -// byte[] subopArg = RandomUtils.generateRandomBytes(16); -// op.addSubOperation(StateOpType.SET, ByteArray.wrap(subopArg)); -// -// byte[] opBytes = BytesUtils.toBytes(op); -// -// assertEquals(OperationType.REGISTER_USER.CODE, opBytes[0]); -// -// OpBlob resolvedOP = new OpBlob(); -// resolvedOP.resolvFrom(ByteArray.wrap(opBytes).asInputStream()); -// -// assertEquals(op.getCode(), resolvedOP.getCode()); -// assertEquals(op.getArgCount(), resolvedOP.getArgCount()); -// -// Operation[] subOps = op.getSubOperations(); -// Operation[] resolvedSubOps = resolvedOP.getSubOperations(); -// assertEquals(1, subOps.length); -// assertEquals(subOps.length, resolvedSubOps.length); -// -// for (int i = 0; i < resolvedSubOps.length; i++) { -// assertEquals(subOps[i].getCode(), resolvedSubOps[i].getCode()); -// assertEquals(1, resolvedSubOps[i].getArgCount()); -// assertEquals(subOps[i].getArgCount(), resolvedSubOps[i].getArgCount()); -// assertEquals(subOps[i].getArg(0), resolvedSubOps[i].getArg(0)); -// } -// } -// -//} +package test.com.jd.blockchain.ledger; +//package test.com.jd.blockchain.ledger.data; +// +//import static org.junit.Assert.*; +// +//import java.io.IOException; +// +//import org.junit.Test; +// +//import com.jd.blockchain.ledger.StateOpType; +//import com.jd.blockchain.ledger.Operation; +//import com.jd.blockchain.ledger.OperationType; +//import com.jd.blockchain.ledger.data.OpBlob; +// +//import my.utils.io.ByteArray; +//import my.utils.io.BytesUtils; +//import my.utils.security.RandomUtils; +// +//public class OpBlobTest { +// +// /** +// * 验证无子操作的情形; +// * +// * @throws IOException +// */ +// @Test +// public void testSerializeNoSubOP() throws IOException { +// OpBlob op = new OpBlob(); +// byte[] opArg = RandomUtils.generateRandomBytes(16); +// op.setOperation(OperationType.REGISTER_USER.CODE, ByteArray.wrap(opArg)); +// +// byte[] opBytes = BytesUtils.toBytes(op); +// +// assertEquals(OperationType.REGISTER_USER.CODE, opBytes[0]); +// +// OpBlob resolvedOP = new OpBlob(); +// resolvedOP.resolvFrom(ByteArray.wrap(opBytes).asInputStream()); +// +// assertEquals(op.getCode(), resolvedOP.getCode()); +// assertEquals(op.getArgCount(), resolvedOP.getArgCount()); +// assertEquals(0, resolvedOP.getSubOperations().length); +// assertEquals(op.getSubOperations().length, resolvedOP.getSubOperations().length); +// +// } +// +// /** +// * 验证有子操作的情形; +// * +// * @throws IOException +// */ +// @Test +// public void testSerializeWithSubOP() throws IOException { +// OpBlob op = new OpBlob(); +// byte[] opArg = RandomUtils.generateRandomBytes(16); +// op.setOperation(OperationType.REGISTER_USER.CODE, ByteArray.wrap(opArg)); +// +// byte[] subopArg = RandomUtils.generateRandomBytes(16); +// op.addSubOperation(StateOpType.SET, ByteArray.wrap(subopArg)); +// +// byte[] opBytes = BytesUtils.toBytes(op); +// +// assertEquals(OperationType.REGISTER_USER.CODE, opBytes[0]); +// +// OpBlob resolvedOP = new OpBlob(); +// resolvedOP.resolvFrom(ByteArray.wrap(opBytes).asInputStream()); +// +// assertEquals(op.getCode(), resolvedOP.getCode()); +// assertEquals(op.getArgCount(), resolvedOP.getArgCount()); +// +// Operation[] subOps = op.getSubOperations(); +// Operation[] resolvedSubOps = resolvedOP.getSubOperations(); +// assertEquals(1, subOps.length); +// assertEquals(subOps.length, resolvedSubOps.length); +// +// for (int i = 0; i < resolvedSubOps.length; i++) { +// assertEquals(subOps[i].getCode(), resolvedSubOps[i].getCode()); +// assertEquals(1, resolvedSubOps[i].getArgCount()); +// assertEquals(subOps[i].getArgCount(), resolvedSubOps[i].getArgCount()); +// assertEquals(subOps[i].getArg(0), resolvedSubOps[i].getArg(0)); +// } +// } +// +//} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SizeHeaderMaskTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SizeHeaderMaskTest.java index b8e7875c..148cf75d 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SizeHeaderMaskTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/SizeHeaderMaskTest.java @@ -1,40 +1,40 @@ -package test.com.jd.blockchain.ledger; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import com.jd.blockchain.utils.io.NumberMask; - - -public class SizeHeaderMaskTest { - - @Test - public void testSizeHeaderMask() { - assertTrue(NumberMask.TINY.MAX_HEADER_LENGTH == 1); - assertEquals(256, NumberMask.TINY.getBoundarySize(1)); - - assertTrue(NumberMask.SHORT.MAX_HEADER_LENGTH == 2); - assertEquals(128, NumberMask.SHORT.getBoundarySize(1)); - assertEquals(32768, NumberMask.SHORT.getBoundarySize(2)); - - assertTrue(NumberMask.NORMAL.MAX_HEADER_LENGTH == 4); - assertEquals(64, NumberMask.NORMAL.getBoundarySize(1)); - assertEquals(16384, NumberMask.NORMAL.getBoundarySize(2)); - assertEquals(4194304, NumberMask.NORMAL.getBoundarySize(3)); - assertEquals(1073741824, NumberMask.NORMAL.getBoundarySize(4)); - - //不考虑 long 的情况; -// assertTrue(SizeHeaderMask.LONG.MAX_HEADER_LENGTH == 8); -// assertEquals(32L, SizeHeaderMask.LONG.getBoundarySize((byte)1)); -// assertEquals(8192L, SizeHeaderMask.LONG.getBoundarySize((byte)2)); -// assertEquals(2097152L, SizeHeaderMask.LONG.getBoundarySize((byte)3)); -// assertEquals(536870912L, SizeHeaderMask.LONG.getBoundarySize((byte)4)); -// assertEquals(137438953472L, SizeHeaderMask.LONG.getBoundarySize((byte)5)); -// assertEquals(35184372088832L, SizeHeaderMask.LONG.getBoundarySize((byte)6)); -// assertEquals(9007199254740992L, SizeHeaderMask.LONG.getBoundarySize((byte)7)); -// assertEquals(2305843009213693952L, SizeHeaderMask.LONG.getBoundarySize((byte)8)); - } - -} +package test.com.jd.blockchain.ledger; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.jd.blockchain.utils.io.NumberMask; + + +public class SizeHeaderMaskTest { + + @Test + public void testSizeHeaderMask() { + assertTrue(NumberMask.TINY.MAX_HEADER_LENGTH == 1); + assertEquals(256, NumberMask.TINY.getBoundarySize(1)); + + assertTrue(NumberMask.SHORT.MAX_HEADER_LENGTH == 2); + assertEquals(128, NumberMask.SHORT.getBoundarySize(1)); + assertEquals(32768, NumberMask.SHORT.getBoundarySize(2)); + + assertTrue(NumberMask.NORMAL.MAX_HEADER_LENGTH == 4); + assertEquals(64, NumberMask.NORMAL.getBoundarySize(1)); + assertEquals(16384, NumberMask.NORMAL.getBoundarySize(2)); + assertEquals(4194304, NumberMask.NORMAL.getBoundarySize(3)); + assertEquals(1073741824, NumberMask.NORMAL.getBoundarySize(4)); + + //不考虑 long 的情况; +// assertTrue(SizeHeaderMask.LONG.MAX_HEADER_LENGTH == 8); +// assertEquals(32L, SizeHeaderMask.LONG.getBoundarySize((byte)1)); +// assertEquals(8192L, SizeHeaderMask.LONG.getBoundarySize((byte)2)); +// assertEquals(2097152L, SizeHeaderMask.LONG.getBoundarySize((byte)3)); +// assertEquals(536870912L, SizeHeaderMask.LONG.getBoundarySize((byte)4)); +// assertEquals(137438953472L, SizeHeaderMask.LONG.getBoundarySize((byte)5)); +// assertEquals(35184372088832L, SizeHeaderMask.LONG.getBoundarySize((byte)6)); +// assertEquals(9007199254740992L, SizeHeaderMask.LONG.getBoundarySize((byte)7)); +// assertEquals(2305843009213693952L, SizeHeaderMask.LONG.getBoundarySize((byte)8)); + } + +} diff --git a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java index c8d8c313..c920db09 100644 --- a/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java +++ b/source/ledger/ledger-model/src/test/java/test/com/jd/blockchain/ledger/TxContentBlobTest.java @@ -1,116 +1,116 @@ -package test.com.jd.blockchain.ledger; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -import java.io.IOException; -import java.util.UUID; - -import org.junit.Before; -import org.junit.Test; - -import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.Crypto; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.BlockchainKeyGenerator; -import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.DataAccountKVSetOperation; -import com.jd.blockchain.ledger.HashObject; -import com.jd.blockchain.ledger.Operation; -import com.jd.blockchain.ledger.TransactionContent; -import com.jd.blockchain.ledger.TransactionContentBody; -import com.jd.blockchain.transaction.BlockchainOperationFactory; -import com.jd.blockchain.transaction.TxContentBlob; - -public class TxContentBlobTest { - - private TxContentBlob contentBlob; - - @Before - public void initTxContentBlob() throws Exception { - DataContractRegistry.register(TransactionContentBody.class); - DataContractRegistry.register(TransactionContent.class); - DataContractRegistry.register(HashObject.class); - - BlockchainKeypair id = BlockchainKeyGenerator.getInstance().generate("ED25519"); - - HashDigest ledgerHash = Crypto.getHashFunction("SHA256") - .hash(UUID.randomUUID().toString().getBytes("UTF-8")); - - BlockchainOperationFactory opFactory = new BlockchainOperationFactory(); - - contentBlob = new TxContentBlob(ledgerHash); - - HashDigest contentHash = Crypto.getHashFunction("SHA256") - .hash("jd.com".getBytes()); - contentBlob.setHash(contentHash); - - DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) - .setText("Name", "AAA", -1).getOperation(); - contentBlob.addOperation(kvsetOP); - } - - @Test - public void testSerialize_TransactionContentBody() - throws IOException, InstantiationException, IllegalAccessException { - - byte[] bytesContent = BinaryProtocol.encode(contentBlob, TransactionContentBody.class); - TransactionContentBody resolvedContentBlob = BinaryProtocol.decode(bytesContent); - - assertEquals(contentBlob.getLedgerHash(), resolvedContentBlob.getLedgerHash()); - // assertEquals(contentBlob.getSubjectAccount(), - // resolvedContentBlob.getSubjectAccount()); - // assertEquals(contentBlob.getSequenceNumber(), - // resolvedContentBlob.getSequenceNumber()); - assertEquals(contentBlob.getOperations().length, resolvedContentBlob.getOperations().length); - - assertEquals(contentBlob.getOperations().length, resolvedContentBlob.getOperations().length); - Operation[] resolvedOperations = resolvedContentBlob.getOperations(); - Operation[] dataOperations = contentBlob.getOperations(); - for (int i = 0; i < dataOperations.length; i++) { - DataAccountKVSetOperation resolvedOperation = (DataAccountKVSetOperation) resolvedOperations[i]; - DataAccountKVSetOperation dataOperation = (DataAccountKVSetOperation) dataOperations[i]; - assertEquals(dataOperation.getAccountAddress(), resolvedOperation.getAccountAddress()); - DataAccountKVSetOperation.KVWriteEntry[] dataKv = dataOperation.getWriteSet(); - DataAccountKVSetOperation.KVWriteEntry[] resolvedKv = resolvedOperation.getWriteSet(); - for (int j = 0; j < dataKv.length; j++) { - assertEquals(dataKv[i].getKey(), resolvedKv[i].getKey()); - assertEquals(dataKv[i].getExpectedVersion(), resolvedKv[i].getExpectedVersion()); - assertArrayEquals(dataKv[i].getValue().getBytes().toBytes(), - resolvedKv[i].getValue().getBytes().toBytes()); - } - } - } - - @Test - public void testSerialize_TransactionContent() throws IOException, InstantiationException, IllegalAccessException { - - byte[] bytesContent = BinaryProtocol.encode(contentBlob, TransactionContent.class); - TransactionContentBody resolvedContentBlob = BinaryProtocol.decode(bytesContent); - - assertEquals(contentBlob.getLedgerHash(), resolvedContentBlob.getLedgerHash()); - // assertEquals(contentBlob.getSubjectAccount(), - // resolvedContentBlob.getSubjectAccount()); - // assertEquals(contentBlob.getSequenceNumber(), - // resolvedContentBlob.getSequenceNumber()); - assertEquals(contentBlob.getOperations().length, resolvedContentBlob.getOperations().length); - - assertEquals(contentBlob.getOperations().length, resolvedContentBlob.getOperations().length); - Operation[] resolvedOperations = resolvedContentBlob.getOperations(); - Operation[] dataOperations = contentBlob.getOperations(); - for (int i = 0; i < dataOperations.length; i++) { - DataAccountKVSetOperation resolvedOperation = (DataAccountKVSetOperation) resolvedOperations[i]; - DataAccountKVSetOperation dataOperation = (DataAccountKVSetOperation) dataOperations[i]; - assertEquals(dataOperation.getAccountAddress(), resolvedOperation.getAccountAddress()); - DataAccountKVSetOperation.KVWriteEntry[] dataKv = dataOperation.getWriteSet(); - DataAccountKVSetOperation.KVWriteEntry[] resolvedKv = resolvedOperation.getWriteSet(); - for (int j = 0; j < dataKv.length; j++) { - assertEquals(dataKv[i].getKey(), resolvedKv[i].getKey()); - assertEquals(dataKv[i].getExpectedVersion(), resolvedKv[i].getExpectedVersion()); - assertArrayEquals(dataKv[i].getValue().getBytes().toBytes(), - resolvedKv[i].getValue().getBytes().toBytes()); - } - } - } -} +package test.com.jd.blockchain.ledger; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.UUID; + +import org.junit.Before; +import org.junit.Test; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.BlockchainKeyGenerator; +import com.jd.blockchain.ledger.BlockchainKeypair; +import com.jd.blockchain.ledger.DataAccountKVSetOperation; +import com.jd.blockchain.ledger.HashObject; +import com.jd.blockchain.ledger.Operation; +import com.jd.blockchain.ledger.TransactionContent; +import com.jd.blockchain.ledger.TransactionContentBody; +import com.jd.blockchain.transaction.BlockchainOperationFactory; +import com.jd.blockchain.transaction.TxContentBlob; + +public class TxContentBlobTest { + + private TxContentBlob contentBlob; + + @Before + public void initTxContentBlob() throws Exception { + DataContractRegistry.register(TransactionContentBody.class); + DataContractRegistry.register(TransactionContent.class); + DataContractRegistry.register(HashObject.class); + + BlockchainKeypair id = BlockchainKeyGenerator.getInstance().generate("ED25519"); + + HashDigest ledgerHash = Crypto.getHashFunction("SHA256") + .hash(UUID.randomUUID().toString().getBytes("UTF-8")); + + BlockchainOperationFactory opFactory = new BlockchainOperationFactory(); + + contentBlob = new TxContentBlob(ledgerHash); + + HashDigest contentHash = Crypto.getHashFunction("SHA256") + .hash("jd.com".getBytes()); + contentBlob.setHash(contentHash); + + DataAccountKVSetOperation kvsetOP = opFactory.dataAccount(id.getAddress()) + .setText("Name", "AAA", -1).getOperation(); + contentBlob.addOperation(kvsetOP); + } + + @Test + public void testSerialize_TransactionContentBody() + throws IOException, InstantiationException, IllegalAccessException { + + byte[] bytesContent = BinaryProtocol.encode(contentBlob, TransactionContentBody.class); + TransactionContentBody resolvedContentBlob = BinaryProtocol.decode(bytesContent); + + assertEquals(contentBlob.getLedgerHash(), resolvedContentBlob.getLedgerHash()); + // assertEquals(contentBlob.getSubjectAccount(), + // resolvedContentBlob.getSubjectAccount()); + // assertEquals(contentBlob.getSequenceNumber(), + // resolvedContentBlob.getSequenceNumber()); + assertEquals(contentBlob.getOperations().length, resolvedContentBlob.getOperations().length); + + assertEquals(contentBlob.getOperations().length, resolvedContentBlob.getOperations().length); + Operation[] resolvedOperations = resolvedContentBlob.getOperations(); + Operation[] dataOperations = contentBlob.getOperations(); + for (int i = 0; i < dataOperations.length; i++) { + DataAccountKVSetOperation resolvedOperation = (DataAccountKVSetOperation) resolvedOperations[i]; + DataAccountKVSetOperation dataOperation = (DataAccountKVSetOperation) dataOperations[i]; + assertEquals(dataOperation.getAccountAddress(), resolvedOperation.getAccountAddress()); + DataAccountKVSetOperation.KVWriteEntry[] dataKv = dataOperation.getWriteSet(); + DataAccountKVSetOperation.KVWriteEntry[] resolvedKv = resolvedOperation.getWriteSet(); + for (int j = 0; j < dataKv.length; j++) { + assertEquals(dataKv[i].getKey(), resolvedKv[i].getKey()); + assertEquals(dataKv[i].getExpectedVersion(), resolvedKv[i].getExpectedVersion()); + assertArrayEquals(dataKv[i].getValue().getBytes().toBytes(), + resolvedKv[i].getValue().getBytes().toBytes()); + } + } + } + + @Test + public void testSerialize_TransactionContent() throws IOException, InstantiationException, IllegalAccessException { + + byte[] bytesContent = BinaryProtocol.encode(contentBlob, TransactionContent.class); + TransactionContentBody resolvedContentBlob = BinaryProtocol.decode(bytesContent); + + assertEquals(contentBlob.getLedgerHash(), resolvedContentBlob.getLedgerHash()); + // assertEquals(contentBlob.getSubjectAccount(), + // resolvedContentBlob.getSubjectAccount()); + // assertEquals(contentBlob.getSequenceNumber(), + // resolvedContentBlob.getSequenceNumber()); + assertEquals(contentBlob.getOperations().length, resolvedContentBlob.getOperations().length); + + assertEquals(contentBlob.getOperations().length, resolvedContentBlob.getOperations().length); + Operation[] resolvedOperations = resolvedContentBlob.getOperations(); + Operation[] dataOperations = contentBlob.getOperations(); + for (int i = 0; i < dataOperations.length; i++) { + DataAccountKVSetOperation resolvedOperation = (DataAccountKVSetOperation) resolvedOperations[i]; + DataAccountKVSetOperation dataOperation = (DataAccountKVSetOperation) dataOperations[i]; + assertEquals(dataOperation.getAccountAddress(), resolvedOperation.getAccountAddress()); + DataAccountKVSetOperation.KVWriteEntry[] dataKv = dataOperation.getWriteSet(); + DataAccountKVSetOperation.KVWriteEntry[] resolvedKv = resolvedOperation.getWriteSet(); + for (int j = 0; j < dataKv.length; j++) { + assertEquals(dataKv[i].getKey(), resolvedKv[i].getKey()); + assertEquals(dataKv[i].getExpectedVersion(), resolvedKv[i].getExpectedVersion()); + assertArrayEquals(dataKv[i].getValue().getBytes().toBytes(), + resolvedKv[i].getValue().getBytes().toBytes()); + } + } + } +} diff --git a/source/peer/config/hosts.config b/source/peer/config/hosts.config index 8d5fdf76..d1775d3a 100644 --- a/source/peer/config/hosts.config +++ b/source/peer/config/hosts.config @@ -1,36 +1,36 @@ -# Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This file defines the replicas ids, IPs and ports. -# It is used by the replicas and clients to find connection info -# to the initial replicas. -# The ports defined here are the ports used by clients to communicate -# with the replicas. Additional connections are opened by replicas to -# communicate with each other. This additional connection is opened in the -# next port defined here. For an example, consider the line "0 127.0.0.1 11000". -# That means that clients will open a communication channel to replica 0 in -# IP 127.0.0.1 and port 11000. On startup, replicas with id different than 0 -# will open a communication channel to replica 0 in port 11001. -# The same holds for replicas 1, 2, 3 ... N. - -#server id, address and port (the ids from 0 to n-1 are the service replicas) -0 127.0.0.1 11000 -1 127.0.0.1 11010 -2 127.0.0.1 11020 -3 127.0.0.1 11030 -#4 192.168.151.33 11040 -#5 192.168.151.38 11050 -#6 127.0.0.1 11060 -#7 127.0.0.1 11070 -7001 127.0.0.1 11100 +# Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file defines the replicas ids, IPs and ports. +# It is used by the replicas and clients to find connection info +# to the initial replicas. +# The ports defined here are the ports used by clients to communicate +# with the replicas. Additional connections are opened by replicas to +# communicate with each other. This additional connection is opened in the +# next port defined here. For an example, consider the line "0 127.0.0.1 11000". +# That means that clients will open a communication channel to replica 0 in +# IP 127.0.0.1 and port 11000. On startup, replicas with id different than 0 +# will open a communication channel to replica 0 in port 11001. +# The same holds for replicas 1, 2, 3 ... N. + +#server id, address and port (the ids from 0 to n-1 are the service replicas) +0 127.0.0.1 11000 +1 127.0.0.1 11010 +2 127.0.0.1 11020 +3 127.0.0.1 11030 +#4 192.168.151.33 11040 +#5 192.168.151.38 11050 +#6 127.0.0.1 11060 +#7 127.0.0.1 11070 +7001 127.0.0.1 11100 diff --git a/source/peer/config/system.config b/source/peer/config/system.config index c5bb2fa4..3da6e093 100644 --- a/source/peer/config/system.config +++ b/source/peer/config/system.config @@ -1,121 +1,121 @@ -# Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -############################################ -####### Communication Configurations ####### -############################################ - -#HMAC algorithm used to authenticate messages between processes (HmacMD5 is the default value) -#This parameter is not currently being used being used -#system.authentication.hmacAlgorithm = HmacSHA1 - -#Specify if the communication system should use a thread to send data (true or false) -system.communication.useSenderThread = true - -#Force all processes to use the same public/private keys pair and secret key. This is useful when deploying experiments -#and benchmarks, but must not be used in production systems. -system.communication.defaultkeys = true - -############################################ -### Replication Algorithm Configurations ### -############################################ - -#Number of servers in the group -system.servers.num = 4 - -#Maximum number of faulty replicas -system.servers.f = 1 - -#Timeout to asking for a client request -system.totalordermulticast.timeout = 2000 - - -#Maximum batch size (in number of messages) -system.totalordermulticast.maxbatchsize = 400 - -#Number of nonces (for non-determinism actions) generated -system.totalordermulticast.nonces = 10 - -#if verification of leader-generated timestamps are increasing -#it can only be used on systems in which the network clocks -#are synchronized -system.totalordermulticast.verifyTimestamps = false - -#Quantity of messages that can be stored in the receive queue of the communication system -system.communication.inQueueSize = 500000 - -# Quantity of messages that can be stored in the send queue of each replica -system.communication.outQueueSize = 500000 - -#Set to 1 if SMaRt should use signatures, set to 0 if otherwise -system.communication.useSignatures = 0 - -#Set to 1 if SMaRt should use MAC's, set to 0 if otherwise -system.communication.useMACs = 1 - -#Set to 1 if SMaRt should use the standard output to display debug messages, set to 0 if otherwise -system.debug = 0 - -#Print information about the replica when it is shutdown -system.shutdownhook = true - -############################################ -###### State Transfer Configurations ####### -############################################ - -#Activate the state transfer protocol ('true' to activate, 'false' to de-activate) -system.totalordermulticast.state_transfer = true - -#Maximum ahead-of-time message not discarded -system.totalordermulticast.highMark = 10000 - -#Maximum ahead-of-time message not discarded when the replica is still on EID 0 (after which the state transfer is triggered) -system.totalordermulticast.revival_highMark = 10 - -#Number of ahead-of-time messages necessary to trigger the state transfer after a request timeout occurs -system.totalordermulticast.timeout_highMark = 200 - -############################################ -###### Log and Checkpoint Configurations ### -############################################ - -system.totalordermulticast.log = true -system.totalordermulticast.log_parallel = false -system.totalordermulticast.log_to_disk = false -system.totalordermulticast.sync_log = false - -#Period at which BFT-SMaRt requests the state to the application (for the state transfer state protocol) -system.totalordermulticast.checkpoint_period = 1000 -system.totalordermulticast.global_checkpoint_period = 120000 - -system.totalordermulticast.checkpoint_to_disk = false -system.totalordermulticast.sync_ckp = false - - -############################################ -###### Reconfiguration Configurations ###### -############################################ - -#Replicas ID for the initial view, separated by a comma. -# The number of replicas in this parameter should be equal to that specified in 'system.servers.num' -system.initial.view = 0,1,2,3 - -#The ID of the trust third party (TTP) -system.ttp.id = 7002 - -#This sets if the system will function in Byzantine or crash-only mode. Set to "true" to support Byzantine faults -system.bft = true - -#Custom View Storage; -#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage +# Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################################ +####### Communication Configurations ####### +############################################ + +#HMAC algorithm used to authenticate messages between processes (HmacMD5 is the default value) +#This parameter is not currently being used being used +#system.authentication.hmacAlgorithm = HmacSHA1 + +#Specify if the communication system should use a thread to send data (true or false) +system.communication.useSenderThread = true + +#Force all processes to use the same public/private keys pair and secret key. This is useful when deploying experiments +#and benchmarks, but must not be used in production systems. +system.communication.defaultkeys = true + +############################################ +### Replication Algorithm Configurations ### +############################################ + +#Number of servers in the group +system.servers.num = 4 + +#Maximum number of faulty replicas +system.servers.f = 1 + +#Timeout to asking for a client request +system.totalordermulticast.timeout = 2000 + + +#Maximum batch size (in number of messages) +system.totalordermulticast.maxbatchsize = 400 + +#Number of nonces (for non-determinism actions) generated +system.totalordermulticast.nonces = 10 + +#if verification of leader-generated timestamps are increasing +#it can only be used on systems in which the network clocks +#are synchronized +system.totalordermulticast.verifyTimestamps = false + +#Quantity of messages that can be stored in the receive queue of the communication system +system.communication.inQueueSize = 500000 + +# Quantity of messages that can be stored in the send queue of each replica +system.communication.outQueueSize = 500000 + +#Set to 1 if SMaRt should use signatures, set to 0 if otherwise +system.communication.useSignatures = 0 + +#Set to 1 if SMaRt should use MAC's, set to 0 if otherwise +system.communication.useMACs = 1 + +#Set to 1 if SMaRt should use the standard output to display debug messages, set to 0 if otherwise +system.debug = 0 + +#Print information about the replica when it is shutdown +system.shutdownhook = true + +############################################ +###### State Transfer Configurations ####### +############################################ + +#Activate the state transfer protocol ('true' to activate, 'false' to de-activate) +system.totalordermulticast.state_transfer = true + +#Maximum ahead-of-time message not discarded +system.totalordermulticast.highMark = 10000 + +#Maximum ahead-of-time message not discarded when the replica is still on EID 0 (after which the state transfer is triggered) +system.totalordermulticast.revival_highMark = 10 + +#Number of ahead-of-time messages necessary to trigger the state transfer after a request timeout occurs +system.totalordermulticast.timeout_highMark = 200 + +############################################ +###### Log and Checkpoint Configurations ### +############################################ + +system.totalordermulticast.log = true +system.totalordermulticast.log_parallel = false +system.totalordermulticast.log_to_disk = false +system.totalordermulticast.sync_log = false + +#Period at which BFT-SMaRt requests the state to the application (for the state transfer state protocol) +system.totalordermulticast.checkpoint_period = 1000 +system.totalordermulticast.global_checkpoint_period = 120000 + +system.totalordermulticast.checkpoint_to_disk = false +system.totalordermulticast.sync_ckp = false + + +############################################ +###### Reconfiguration Configurations ###### +############################################ + +#Replicas ID for the initial view, separated by a comma. +# The number of replicas in this parameter should be equal to that specified in 'system.servers.num' +system.initial.view = 0,1,2,3 + +#The ID of the trust third party (TTP) +system.ttp.id = 7002 + +#This sets if the system will function in Byzantine or crash-only mode. Set to "true" to support Byzantine faults +system.bft = true + +#Custom View Storage; +#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage diff --git a/source/peer/pom.xml b/source/peer/pom.xml index 23a08185..bc0fcfb3 100644 --- a/source/peer/pom.xml +++ b/source/peer/pom.xml @@ -1,98 +1,98 @@ - - 4.0.0 - - com.jd.blockchain - jdchain-root - 1.1.2.RELEASE - - peer - - - 2.10.0 - 1.7.25 - - - - - com.jd.blockchain - consensus-framework - ${project.version} - - - com.jd.blockchain - ledger-rpc - ${project.version} - - - com.jd.blockchain - consensus-mq - ${project.version} - - - com.jd.blockchain - consensus-bftsmart - ${project.version} - - - com.jd.blockchain - ledger-core - ${project.version} - - - com.jd.blockchain - tools-initializer - ${project.version} - - - com.jd.blockchain - utils-web - ${project.version} - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-logging - - - - - - org.springframework.boot - spring-boot-starter-log4j2 - - - - org.springframework.boot - spring-boot-starter-security - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - true - - - - - + + 4.0.0 + + com.jd.blockchain + jdchain-root + 1.1.2.RELEASE + + peer + + + 2.10.0 + 1.7.25 + + + + + com.jd.blockchain + consensus-framework + ${project.version} + + + com.jd.blockchain + ledger-rpc + ${project.version} + + + com.jd.blockchain + consensus-mq + ${project.version} + + + com.jd.blockchain + consensus-bftsmart + ${project.version} + + + com.jd.blockchain + ledger-core + ${project.version} + + + com.jd.blockchain + tools-initializer + ${project.version} + + + com.jd.blockchain + utils-web + ${project.version} + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + org.springframework.boot + spring-boot-starter-security + + + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + + \ No newline at end of file diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/PeerConfiguration.java b/source/peer/src/main/java/com/jd/blockchain/peer/PeerConfiguration.java index 86b169a4..b7dc9f2e 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/PeerConfiguration.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/PeerConfiguration.java @@ -1,15 +1,15 @@ -package com.jd.blockchain.peer; - -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.ComponentScan; - -@SpringBootApplication -@EnableAutoConfiguration -@EnableConfigurationProperties -@ComponentScan -public class PeerConfiguration { - -} - +package com.jd.blockchain.peer; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@EnableAutoConfiguration +@EnableConfigurationProperties +@ComponentScan +public class PeerConfiguration { + +} + diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/consensus/BlockchainConsensusServiceImpl.java b/source/peer/src/main/java/com/jd/blockchain/peer/consensus/BlockchainConsensusServiceImpl.java index 5f62888f..593a90f4 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/consensus/BlockchainConsensusServiceImpl.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/consensus/BlockchainConsensusServiceImpl.java @@ -1,213 +1,213 @@ -//package com.jd.blockchain.peer.consensus; -// -//import com.jd.blockchain.binaryproto.BinaryEncodingUtils; -//import com.jd.blockchain.consensus.BatchConsensusListener; -//import com.jd.blockchain.consensus.action.ActionRequest; -//import com.jd.blockchain.consensus.action.ActionRequestData; -//import com.jd.blockchain.consensus.bft.*; -//import com.jd.blockchain.crypto.CryptoAlgorithm; -//import com.jd.blockchain.crypto.CryptoUtils; -//import com.jd.blockchain.ledger.*; -//import com.jd.blockchain.ledger.data.TxContentBlob; -//import com.jd.blockchain.ledger.data.TxRequestMessage; -//import my.utils.io.BytesEncoding; -//import my.utils.io.NumberMask; -//import org.slf4j.Logger; -//import org.slf4j.LoggerFactory; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.stereotype.Service; -// -//import com.jd.blockchain.crypto.hash.HashDigest; -//import com.jd.blockchain.ledger.core.TransactionBatchProcess; -//import com.jd.blockchain.ledger.core.TransactionBatchResultHandle; -//import com.jd.blockchain.ledger.core.TransactionEngine; -//import com.jd.blockchain.sdk.bftsmart.ConsensusTransactionService; -// -//import java.io.ByteArrayOutputStream; -//import java.util.concurrent.*; -//import java.util.concurrent.atomic.AtomicBoolean; -//import java.util.concurrent.atomic.AtomicLong; -// -///** -// * @author huanghaiquan -// * -// */ -//@Service -//public class BlockchainConsensusServiceImpl implements ConsensusTransactionService, BatchConsensusListener { -// -// private static final Logger LOGGER = LoggerFactory.getLogger(BlockchainConsensusServiceImpl.class); -// -// private final ExecutorService sendExecutorService = Executors.newFixedThreadPool(10); -// -// private final ScheduledExecutorService timerEexecutorService = new ScheduledThreadPoolExecutor(1); -// //结块之前接收的消息数 -// private int receiveCounts = 0; -// //区块提交之后,后续第一个交易到达的时间 -// private long initTimeStamp = 0; -// //达到一定的交易数后发送结块共识消息 -// private int TransactionCount = 100; -// //两秒内没有收到新的共识消息,发送结块共识消息,把不足TransactionCount的消息结块入帐本,单位毫秒 -// private long TimeOut = 2000; -// -// private final AtomicLong blockIndex = new AtomicLong(); -// -// private long currBlockIndex = 0L; -// -// private final AtomicBoolean blockFlag = new AtomicBoolean(false); -// -// -// @Autowired -// private TransactionEngine txEngine; -// -// //0.5 version implement -//// @Override -//// public void beforeBatch(byte[] groupId) { -//// // 以“账本哈希”为共识分组ID; -//// HashDigest ledgerHash = new HashDigest(groupId); -//// txEngine.createNextBatch(ledgerHash); -//// -//// LOGGER.info("Create new block to process transaction batch! --[LedgerHash=" + ledgerHash.toBase58() + "]"); -//// } -// -// //0.6 version implement, not used -// @Override -// public void beforeBatch(byte[] groupId) { -//// // 以“账本哈希”为共识分组ID; -//// HashDigest ledgerHash = new HashDigest(groupId); -//// txEngine.createNextBatch(ledgerHash); -//// -//// LOGGER.info("Create new block to process transaction batch! --[LedgerHash=" + ledgerHash.toBase58() + "]"); -// } -// -// /** -// * 处理收到的交易消息,并返回结果; -// */ -// //0.5 version implement -//// @Override -//// public TransactionResponse process(TransactionRequest txRequest) { -//// TransactionBatchProcess txBatchProcess = txEngine.getBatch(txRequest.getTransactionContent().getLedgerHash()); -//// return txBatchProcess.schedule(txRequest); -//// } -// -// //由Leader Peer发送结块通知消息,需要PEER对此消息进行共识,达到共识结点结块的一致性 -// public void notifyCommit(final long currBlockIndex, HashDigest ledgerHash, BftsmartConsensusSetting bftsmartConsensusSetting, BftsmartTopology bftsmartTopology) { -// //if peer is leader, send commit block consensus request -// System.out.println(Thread.currentThread().getId() + " leader run notifyCommit = " + receiveCounts + " TransactionCount = " + TransactionCount); -// if (receiveCounts >= TransactionCount) { -// System.out.println(Thread.currentThread().getId() + "this.blockIndex = " + this.blockIndex.get() + ", currBlockIndex=" + currBlockIndex); -// boolean isAdd = this.blockIndex.compareAndSet(currBlockIndex, currBlockIndex + 1); -// System.out.println(Thread.currentThread().getId() + " leader run isadd = " + isAdd); -// if (isAdd) { -// sendExecutorService.execute(sendBlockMessage(ledgerHash, bftsmartConsensusSetting, bftsmartTopology)); -// } -// } -// } -// -// private Runnable sendBlockMessage(HashDigest ledgerHash, BftsmartConsensusSetting bftsmartConsensusSetting, BftsmartTopology bftsmartTopology) { -// Runnable runnable = () -> sendCommitBlockMessage(ledgerHash, bftsmartConsensusSetting, bftsmartTopology); -// return runnable; -// } -// //发送结块通知消息 -// private void sendCommitBlockMessage(HashDigest ledgerHash, BftsmartConsensusSetting bftsmartConsensusSetting, BftsmartTopology bftsmartTopology) { -// -//// ActionRequestData request = new ActionRequestData(); -//// request.setGroupId(ledgerHash.toBytes()); -//// request.setHandleType("com.jd.blockchain.sdk.bftsmart.ConsensusTransactionService"); -//// request.setHandleMethod("public abstract com.jd.blockchain.ledger.TransactionResponse com.jd.blockchain.sdk.bftsmart.ConsensusTransactionService.process(com.jd.blockchain.ledger.TransactionRequest)"); -//// request.setTransactionType("COMMITBLOCK"); -//// -//// BlockchainKeyPair userKeyPeer = BlockchainKeyGenerator.getInstance().generate(); -//// -//// TxContentBlob txContentBlob = new TxContentBlob(ledgerHash); -//// -//// byte[] reqBytes = BinaryEncodingUtils.encode(txContentBlob, TransactionContent.class); -//// HashDigest reqHash = CryptoUtils.hash(CryptoAlgorithm.SHA256).hash(reqBytes); -//// txContentBlob.setHash(reqHash); -//// -//// TxRequestMessage transactionRequest = new TxRequestMessage(txContentBlob); -//// -//// byte[] encodeBytes = BinaryEncodingUtils.encode(transactionRequest, TransactionRequest.class); -//// -//// ByteArrayOutputStream out = new ByteArrayOutputStream(); -//// BytesEncoding.write(encodeBytes, NumberMask.NORMAL, out); -//// -//// request.setMessageBody(out.toByteArray()); -//// byte[] commandReq = BinaryEncodingUtils.encode(request, ActionRequest.class); -//// -//// BftsmartConsensusClient bftsmartConsensusClient = new BftsmartConsensusClient(0, bftsmartConsensusSetting, bftsmartTopology); -//// bftsmartConsensusClient.invokeOrdered(commandReq); -//// -//// LOGGER.info(String.format("Send notify commit block msg success!")); -// } -// -// //0.6 version implement -// @Override -// public TransactionResponse process(TransactionRequest txRequest) { -//// System.out.println("peer process thread = " + Thread.currentThread().getId()); -//// System.out.println("peer process object = " + this); -// HashDigest ledgerHash = txRequest.getTransactionContent().getLedgerHash(); -// TransactionBatchProcess txBatchProcess = txEngine.getBatch(ledgerHash); -// -// boolean isLeader = BftsmartConsensusUtils.getLeader(); -// BftsmartConsensusSetting bftsmartConsensusSetting =BftsmartConsensusUtils.getSetting(); -// BftsmartTopology bftsmartTopology = BftsmartConsensusUtils.getTopology(); -// -// if (txBatchProcess == null) { -// txBatchProcess = txEngine.createNextBatch(ledgerHash); -// currBlockIndex = txBatchProcess.blockHeight(); -// this.blockIndex.set(currBlockIndex); -// receiveCounts = 0; -// -// if (isLeader) { -// long timerStart = System.currentTimeMillis(); -// System.out.println("first message time = "+timerStart); -// timerEexecutorService.schedule(timeTask(currBlockIndex, ledgerHash, bftsmartConsensusSetting, bftsmartTopology), 500L, TimeUnit.MILLISECONDS); -// } -// } -// receiveCounts++; -// if (isLeader) { -// notifyCommit(currBlockIndex, ledgerHash, bftsmartConsensusSetting, bftsmartTopology); -// } -// return txBatchProcess.schedule(txRequest); -// } -// -// @Override -// public void afterBatch(byte[] groupId, Exception error) { -// HashDigest ledgerHash = new HashDigest(groupId); -// TransactionBatchProcess txBatchProcess = txEngine.getBatch(ledgerHash); -// -// if (error != null) { -// txBatchProcess.cancel(TransactionState.SYSTEM_ERROR); -// LOGGER.error("Error occurred on executing batch transactions, so the new block is canceled! --" + error.getMessage(), error); -// return; -// } -// -// //生成区块; -// TransactionBatchResultHandle batchResultHandle = txBatchProcess.prepare(); -// -// LedgerBlock newBlock = batchResultHandle.getBlock(); -// // TODO: 对新区块进行最后的共识; -// HashDigest blockHash = newBlock.getHash(); -// -// LOGGER.info(String.format( -// "Create new block success! --[LedgerHash=%s][BlockHash=%s][BlockHeigth=%s]", -// ledgerHash.toBase58(), blockHash.toBase58(), newBlock.getHeight())); -// -// // 提交新区块; -// batchResultHandle.commit(); -// -// } -// -// private Runnable timeTask(final long currBlockIndex, HashDigest ledgerHash, BftsmartConsensusSetting bftsmartConsensusSetting, BftsmartTopology bftsmartTopology) { -// Runnable task = () -> { -// // todo -// boolean isAdd = this.blockIndex.compareAndSet(currBlockIndex, currBlockIndex + 1); -// if (isAdd) { -// System.out.println(Thread.currentThread().getId() + " leader run isadd = " + isAdd + " timer send commitblock message ! curren time = " + System.currentTimeMillis()); -// sendCommitBlockMessage(ledgerHash, bftsmartConsensusSetting, bftsmartTopology); -// } -// }; -// return task; -// } -// -// } +//package com.jd.blockchain.peer.consensus; +// +//import com.jd.blockchain.binaryproto.BinaryEncodingUtils; +//import com.jd.blockchain.consensus.BatchConsensusListener; +//import com.jd.blockchain.consensus.action.ActionRequest; +//import com.jd.blockchain.consensus.action.ActionRequestData; +//import com.jd.blockchain.consensus.bft.*; +//import com.jd.blockchain.crypto.CryptoAlgorithm; +//import com.jd.blockchain.crypto.CryptoUtils; +//import com.jd.blockchain.ledger.*; +//import com.jd.blockchain.ledger.data.TxContentBlob; +//import com.jd.blockchain.ledger.data.TxRequestMessage; +//import my.utils.io.BytesEncoding; +//import my.utils.io.NumberMask; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Service; +// +//import com.jd.blockchain.crypto.hash.HashDigest; +//import com.jd.blockchain.ledger.core.TransactionBatchProcess; +//import com.jd.blockchain.ledger.core.TransactionBatchResultHandle; +//import com.jd.blockchain.ledger.core.TransactionEngine; +//import com.jd.blockchain.sdk.bftsmart.ConsensusTransactionService; +// +//import java.io.ByteArrayOutputStream; +//import java.util.concurrent.*; +//import java.util.concurrent.atomic.AtomicBoolean; +//import java.util.concurrent.atomic.AtomicLong; +// +///** +// * @author huanghaiquan +// * +// */ +//@Service +//public class BlockchainConsensusServiceImpl implements ConsensusTransactionService, BatchConsensusListener { +// +// private static final Logger LOGGER = LoggerFactory.getLogger(BlockchainConsensusServiceImpl.class); +// +// private final ExecutorService sendExecutorService = Executors.newFixedThreadPool(10); +// +// private final ScheduledExecutorService timerEexecutorService = new ScheduledThreadPoolExecutor(1); +// //结块之前接收的消息数 +// private int receiveCounts = 0; +// //区块提交之后,后续第一个交易到达的时间 +// private long initTimeStamp = 0; +// //达到一定的交易数后发送结块共识消息 +// private int TransactionCount = 100; +// //两秒内没有收到新的共识消息,发送结块共识消息,把不足TransactionCount的消息结块入帐本,单位毫秒 +// private long TimeOut = 2000; +// +// private final AtomicLong blockIndex = new AtomicLong(); +// +// private long currBlockIndex = 0L; +// +// private final AtomicBoolean blockFlag = new AtomicBoolean(false); +// +// +// @Autowired +// private TransactionEngine txEngine; +// +// //0.5 version implement +//// @Override +//// public void beforeBatch(byte[] groupId) { +//// // 以“账本哈希”为共识分组ID; +//// HashDigest ledgerHash = new HashDigest(groupId); +//// txEngine.createNextBatch(ledgerHash); +//// +//// LOGGER.info("Create new block to process transaction batch! --[LedgerHash=" + ledgerHash.toBase58() + "]"); +//// } +// +// //0.6 version implement, not used +// @Override +// public void beforeBatch(byte[] groupId) { +//// // 以“账本哈希”为共识分组ID; +//// HashDigest ledgerHash = new HashDigest(groupId); +//// txEngine.createNextBatch(ledgerHash); +//// +//// LOGGER.info("Create new block to process transaction batch! --[LedgerHash=" + ledgerHash.toBase58() + "]"); +// } +// +// /** +// * 处理收到的交易消息,并返回结果; +// */ +// //0.5 version implement +//// @Override +//// public TransactionResponse process(TransactionRequest txRequest) { +//// TransactionBatchProcess txBatchProcess = txEngine.getBatch(txRequest.getTransactionContent().getLedgerHash()); +//// return txBatchProcess.schedule(txRequest); +//// } +// +// //由Leader Peer发送结块通知消息,需要PEER对此消息进行共识,达到共识结点结块的一致性 +// public void notifyCommit(final long currBlockIndex, HashDigest ledgerHash, BftsmartConsensusSetting bftsmartConsensusSetting, BftsmartTopology bftsmartTopology) { +// //if peer is leader, send commit block consensus request +// System.out.println(Thread.currentThread().getId() + " leader run notifyCommit = " + receiveCounts + " TransactionCount = " + TransactionCount); +// if (receiveCounts >= TransactionCount) { +// System.out.println(Thread.currentThread().getId() + "this.blockIndex = " + this.blockIndex.get() + ", currBlockIndex=" + currBlockIndex); +// boolean isAdd = this.blockIndex.compareAndSet(currBlockIndex, currBlockIndex + 1); +// System.out.println(Thread.currentThread().getId() + " leader run isadd = " + isAdd); +// if (isAdd) { +// sendExecutorService.execute(sendBlockMessage(ledgerHash, bftsmartConsensusSetting, bftsmartTopology)); +// } +// } +// } +// +// private Runnable sendBlockMessage(HashDigest ledgerHash, BftsmartConsensusSetting bftsmartConsensusSetting, BftsmartTopology bftsmartTopology) { +// Runnable runnable = () -> sendCommitBlockMessage(ledgerHash, bftsmartConsensusSetting, bftsmartTopology); +// return runnable; +// } +// //发送结块通知消息 +// private void sendCommitBlockMessage(HashDigest ledgerHash, BftsmartConsensusSetting bftsmartConsensusSetting, BftsmartTopology bftsmartTopology) { +// +//// ActionRequestData request = new ActionRequestData(); +//// request.setGroupId(ledgerHash.toBytes()); +//// request.setHandleType("com.jd.blockchain.sdk.bftsmart.ConsensusTransactionService"); +//// request.setHandleMethod("public abstract com.jd.blockchain.ledger.TransactionResponse com.jd.blockchain.sdk.bftsmart.ConsensusTransactionService.process(com.jd.blockchain.ledger.TransactionRequest)"); +//// request.setTransactionType("COMMITBLOCK"); +//// +//// BlockchainKeyPair userKeyPeer = BlockchainKeyGenerator.getInstance().generate(); +//// +//// TxContentBlob txContentBlob = new TxContentBlob(ledgerHash); +//// +//// byte[] reqBytes = BinaryEncodingUtils.encode(txContentBlob, TransactionContent.class); +//// HashDigest reqHash = CryptoUtils.hash(CryptoAlgorithm.SHA256).hash(reqBytes); +//// txContentBlob.setHash(reqHash); +//// +//// TxRequestMessage transactionRequest = new TxRequestMessage(txContentBlob); +//// +//// byte[] encodeBytes = BinaryEncodingUtils.encode(transactionRequest, TransactionRequest.class); +//// +//// ByteArrayOutputStream out = new ByteArrayOutputStream(); +//// BytesEncoding.write(encodeBytes, NumberMask.NORMAL, out); +//// +//// request.setMessageBody(out.toByteArray()); +//// byte[] commandReq = BinaryEncodingUtils.encode(request, ActionRequest.class); +//// +//// BftsmartConsensusClient bftsmartConsensusClient = new BftsmartConsensusClient(0, bftsmartConsensusSetting, bftsmartTopology); +//// bftsmartConsensusClient.invokeOrdered(commandReq); +//// +//// LOGGER.info(String.format("Send notify commit block msg success!")); +// } +// +// //0.6 version implement +// @Override +// public TransactionResponse process(TransactionRequest txRequest) { +//// System.out.println("peer process thread = " + Thread.currentThread().getId()); +//// System.out.println("peer process object = " + this); +// HashDigest ledgerHash = txRequest.getTransactionContent().getLedgerHash(); +// TransactionBatchProcess txBatchProcess = txEngine.getBatch(ledgerHash); +// +// boolean isLeader = BftsmartConsensusUtils.getLeader(); +// BftsmartConsensusSetting bftsmartConsensusSetting =BftsmartConsensusUtils.getSetting(); +// BftsmartTopology bftsmartTopology = BftsmartConsensusUtils.getTopology(); +// +// if (txBatchProcess == null) { +// txBatchProcess = txEngine.createNextBatch(ledgerHash); +// currBlockIndex = txBatchProcess.blockHeight(); +// this.blockIndex.set(currBlockIndex); +// receiveCounts = 0; +// +// if (isLeader) { +// long timerStart = System.currentTimeMillis(); +// System.out.println("first message time = "+timerStart); +// timerEexecutorService.schedule(timeTask(currBlockIndex, ledgerHash, bftsmartConsensusSetting, bftsmartTopology), 500L, TimeUnit.MILLISECONDS); +// } +// } +// receiveCounts++; +// if (isLeader) { +// notifyCommit(currBlockIndex, ledgerHash, bftsmartConsensusSetting, bftsmartTopology); +// } +// return txBatchProcess.schedule(txRequest); +// } +// +// @Override +// public void afterBatch(byte[] groupId, Exception error) { +// HashDigest ledgerHash = new HashDigest(groupId); +// TransactionBatchProcess txBatchProcess = txEngine.getBatch(ledgerHash); +// +// if (error != null) { +// txBatchProcess.cancel(TransactionState.SYSTEM_ERROR); +// LOGGER.error("Error occurred on executing batch transactions, so the new block is canceled! --" + error.getMessage(), error); +// return; +// } +// +// //生成区块; +// TransactionBatchResultHandle batchResultHandle = txBatchProcess.prepare(); +// +// LedgerBlock newBlock = batchResultHandle.getBlock(); +// // TODO: 对新区块进行最后的共识; +// HashDigest blockHash = newBlock.getHash(); +// +// LOGGER.info(String.format( +// "Create new block success! --[LedgerHash=%s][BlockHash=%s][BlockHeigth=%s]", +// ledgerHash.toBase58(), blockHash.toBase58(), newBlock.getHeight())); +// +// // 提交新区块; +// batchResultHandle.commit(); +// +// } +// +// private Runnable timeTask(final long currBlockIndex, HashDigest ledgerHash, BftsmartConsensusSetting bftsmartConsensusSetting, BftsmartTopology bftsmartTopology) { +// Runnable task = () -> { +// // todo +// boolean isAdd = this.blockIndex.compareAndSet(currBlockIndex, currBlockIndex + 1); +// if (isAdd) { +// System.out.println(Thread.currentThread().getId() + " leader run isadd = " + isAdd + " timer send commitblock message ! curren time = " + System.currentTimeMillis()); +// sendCommitBlockMessage(ledgerHash, bftsmartConsensusSetting, bftsmartTopology); +// } +// }; +// return task; +// } +// +// } diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusViewDefinition.java b/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusViewDefinition.java index a56e5ed4..d19a93af 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusViewDefinition.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/consensus/ConsensusViewDefinition.java @@ -1,93 +1,93 @@ -package com.jd.blockchain.peer.consensus; - -import java.io.Serializable; -import java.util.ArrayList; - -import com.jd.blockchain.utils.net.NetworkAddress; - -public class ConsensusViewDefinition implements Serializable { - - private static final long serialVersionUID = -201642288565436003L; - - private static int[] EMPTY_IDS = {}; - - private ArrayList nodes = new ArrayList<>(); - - public int getF() { - return (int) ((getNodeCount() - 1) / 3); - } - - /** - * 法定的数量; - * - * @return - */ - public int getN() { - return 3 * getF() + 1; - } - - /** - * 实际的节点数量; - * - * @return - */ - public int getNodeCount() { - return nodes.size(); - } - - /** - * 返回法定数量的初始节点的 ID 列表; - * - * @return - */ - public int[] getQuorumIDs() { - if (getNodeCount() == 0) { - return EMPTY_IDS; - } - int[] ids = new int[getN()]; - for (int i = 0; i < ids.length; i++) { - ids[i] = nodes.get(i).getId(); - } - return ids; - } - - /** - * 加入节点信息; - * - * @param networkAddress - * @return 返回分配给新节点的 ID (ID >= 0);如果节点数量以达到 (3f+1) 的数量; - */ - public synchronized int addNode(NetworkAddress networkAddress) { - for (NodeInfo ninf : nodes) { - if (ninf.getNetworkAddress().equals(networkAddress)) { - throw new IllegalArgumentException("Add node[" + networkAddress.toString() + "] reaptly!"); - } - } - NodeInfo nodeInfo = new NodeInfo(nodes.size(), networkAddress); - nodes.add(nodeInfo); - return nodeInfo.getId(); - } - - public static class NodeInfo implements Serializable { - - private static final long serialVersionUID = -9178639061945239622L; - - private int id; - - private NetworkAddress networkAddress; - - public NodeInfo(int id, NetworkAddress networkAddress) { - this.id = id; - this.networkAddress = networkAddress; - } - - public int getId() { - return id; - } - - public NetworkAddress getNetworkAddress() { - return networkAddress; - } - } - -} +package com.jd.blockchain.peer.consensus; + +import java.io.Serializable; +import java.util.ArrayList; + +import com.jd.blockchain.utils.net.NetworkAddress; + +public class ConsensusViewDefinition implements Serializable { + + private static final long serialVersionUID = -201642288565436003L; + + private static int[] EMPTY_IDS = {}; + + private ArrayList nodes = new ArrayList<>(); + + public int getF() { + return (int) ((getNodeCount() - 1) / 3); + } + + /** + * 法定的数量; + * + * @return + */ + public int getN() { + return 3 * getF() + 1; + } + + /** + * 实际的节点数量; + * + * @return + */ + public int getNodeCount() { + return nodes.size(); + } + + /** + * 返回法定数量的初始节点的 ID 列表; + * + * @return + */ + public int[] getQuorumIDs() { + if (getNodeCount() == 0) { + return EMPTY_IDS; + } + int[] ids = new int[getN()]; + for (int i = 0; i < ids.length; i++) { + ids[i] = nodes.get(i).getId(); + } + return ids; + } + + /** + * 加入节点信息; + * + * @param networkAddress + * @return 返回分配给新节点的 ID (ID >= 0);如果节点数量以达到 (3f+1) 的数量; + */ + public synchronized int addNode(NetworkAddress networkAddress) { + for (NodeInfo ninf : nodes) { + if (ninf.getNetworkAddress().equals(networkAddress)) { + throw new IllegalArgumentException("Add node[" + networkAddress.toString() + "] reaptly!"); + } + } + NodeInfo nodeInfo = new NodeInfo(nodes.size(), networkAddress); + nodes.add(nodeInfo); + return nodeInfo.getId(); + } + + public static class NodeInfo implements Serializable { + + private static final long serialVersionUID = -9178639061945239622L; + + private int id; + + private NetworkAddress networkAddress; + + public NodeInfo(int id, NetworkAddress networkAddress) { + this.id = id; + this.networkAddress = networkAddress; + } + + public int getId() { + return id; + } + + public NetworkAddress getNetworkAddress() { + return networkAddress; + } + } + +} diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebSecurityConfiguration.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebSecurityConfiguration.java index 1b285b0a..3cccf09f 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebSecurityConfiguration.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebSecurityConfiguration.java @@ -1,20 +1,20 @@ -package com.jd.blockchain.peer.web; - -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; - -@Configuration -@EnableWebSecurity -public class PeerWebSecurityConfiguration extends WebSecurityConfigurerAdapter { - - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests().anyRequest().permitAll(); - http.csrf().disable(); - } - -} +package com.jd.blockchain.peer.web; + +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class PeerWebSecurityConfiguration extends WebSecurityConfigurerAdapter { + + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().permitAll(); + http.csrf().disable(); + } + +} diff --git a/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebServerConfigurer.java b/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebServerConfigurer.java index f0d52ac5..71f0ac83 100644 --- a/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebServerConfigurer.java +++ b/source/peer/src/main/java/com/jd/blockchain/peer/web/PeerWebServerConfigurer.java @@ -1,51 +1,51 @@ -package com.jd.blockchain.peer.web; - -import java.util.List; - -import com.jd.blockchain.web.converters.BinaryMessageConverter; -import com.jd.blockchain.web.converters.HashDigestInputConverter; - -import com.jd.blockchain.web.serializes.ByteArrayObjectUtil; -import org.springframework.context.annotation.Configuration; -import org.springframework.format.FormatterRegistry; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -import com.jd.blockchain.utils.io.ByteArray; -import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; -import com.jd.blockchain.utils.web.model.JsonWebResponseMessageConverter; - -@Configuration -public class PeerWebServerConfigurer implements WebMvcConfigurer { - - static { - JSONSerializeUtils.disableCircularReferenceDetect(); - JSONSerializeUtils.configStringSerializer(ByteArray.class); - } - - @Override - public void extendMessageConverters(List> converters) { - int index = converters.size(); - for (int i = 0; i < converters.size(); i++) { - if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) { - index = i; - break; - } - } - converters.add(index, new JsonWebResponseMessageConverter()); - - converters.add(0, new BinaryMessageConverter()); - - initByteArrayJsonSerialize(); - } - - @Override - public void addFormatters(FormatterRegistry registry) { - registry.addConverter(new HashDigestInputConverter()); - } - - private void initByteArrayJsonSerialize() { - ByteArrayObjectUtil.init(); - } -} +package com.jd.blockchain.peer.web; + +import java.util.List; + +import com.jd.blockchain.web.converters.BinaryMessageConverter; +import com.jd.blockchain.web.converters.HashDigestInputConverter; + +import com.jd.blockchain.web.serializes.ByteArrayObjectUtil; +import org.springframework.context.annotation.Configuration; +import org.springframework.format.FormatterRegistry; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import com.jd.blockchain.utils.io.ByteArray; +import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; +import com.jd.blockchain.utils.web.model.JsonWebResponseMessageConverter; + +@Configuration +public class PeerWebServerConfigurer implements WebMvcConfigurer { + + static { + JSONSerializeUtils.disableCircularReferenceDetect(); + JSONSerializeUtils.configStringSerializer(ByteArray.class); + } + + @Override + public void extendMessageConverters(List> converters) { + int index = converters.size(); + for (int i = 0; i < converters.size(); i++) { + if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) { + index = i; + break; + } + } + converters.add(index, new JsonWebResponseMessageConverter()); + + converters.add(0, new BinaryMessageConverter()); + + initByteArrayJsonSerialize(); + } + + @Override + public void addFormatters(FormatterRegistry registry) { + registry.addConverter(new HashDigestInputConverter()); + } + + private void initByteArrayJsonSerialize() { + ByteArrayObjectUtil.init(); + } +} diff --git a/source/peer/src/test/java/test/com/jd/blockchain/peer/service/ConsensusViewDefinitionTest.java b/source/peer/src/test/java/test/com/jd/blockchain/peer/service/ConsensusViewDefinitionTest.java index 545a0223..451a6f32 100644 --- a/source/peer/src/test/java/test/com/jd/blockchain/peer/service/ConsensusViewDefinitionTest.java +++ b/source/peer/src/test/java/test/com/jd/blockchain/peer/service/ConsensusViewDefinitionTest.java @@ -1,47 +1,47 @@ -package test.com.jd.blockchain.peer.service; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.jd.blockchain.peer.consensus.ConsensusViewDefinition; -import com.jd.blockchain.utils.net.NetworkAddress; - -public class ConsensusViewDefinitionTest { - - @Test - public void test() { - ConsensusViewDefinition viewDef = new ConsensusViewDefinition(); - - assertEquals(0, viewDef.getNodeCount()); - assertEquals(1, viewDef.getN()); - assertEquals(0, viewDef.getF()); - - viewDef.addNode(new NetworkAddress("localhost", 10001)); - assertEquals(1, viewDef.getNodeCount()); - assertEquals(1, viewDef.getN()); - assertEquals(0, viewDef.getF()); - - viewDef.addNode(new NetworkAddress("localhost", 10002)); - assertEquals(2, viewDef.getNodeCount()); - assertEquals(1, viewDef.getN()); - assertEquals(0, viewDef.getF()); - - viewDef.addNode(new NetworkAddress("localhost", 10003)); - assertEquals(3, viewDef.getNodeCount()); - assertEquals(1, viewDef.getN()); - assertEquals(0, viewDef.getF()); - - viewDef.addNode(new NetworkAddress("localhost", 10004)); - assertEquals(4, viewDef.getNodeCount()); - assertEquals(4, viewDef.getN()); - assertEquals(1, viewDef.getF()); - - viewDef.addNode(new NetworkAddress("localhost", 10005)); - assertEquals(5, viewDef.getNodeCount()); - assertEquals(4, viewDef.getN()); - assertEquals(1, viewDef.getF()); - - } - -} +package test.com.jd.blockchain.peer.service; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.jd.blockchain.peer.consensus.ConsensusViewDefinition; +import com.jd.blockchain.utils.net.NetworkAddress; + +public class ConsensusViewDefinitionTest { + + @Test + public void test() { + ConsensusViewDefinition viewDef = new ConsensusViewDefinition(); + + assertEquals(0, viewDef.getNodeCount()); + assertEquals(1, viewDef.getN()); + assertEquals(0, viewDef.getF()); + + viewDef.addNode(new NetworkAddress("localhost", 10001)); + assertEquals(1, viewDef.getNodeCount()); + assertEquals(1, viewDef.getN()); + assertEquals(0, viewDef.getF()); + + viewDef.addNode(new NetworkAddress("localhost", 10002)); + assertEquals(2, viewDef.getNodeCount()); + assertEquals(1, viewDef.getN()); + assertEquals(0, viewDef.getF()); + + viewDef.addNode(new NetworkAddress("localhost", 10003)); + assertEquals(3, viewDef.getNodeCount()); + assertEquals(1, viewDef.getN()); + assertEquals(0, viewDef.getF()); + + viewDef.addNode(new NetworkAddress("localhost", 10004)); + assertEquals(4, viewDef.getNodeCount()); + assertEquals(4, viewDef.getN()); + assertEquals(1, viewDef.getF()); + + viewDef.addNode(new NetworkAddress("localhost", 10005)); + assertEquals(5, viewDef.getNodeCount()); + assertEquals(4, viewDef.getN()); + assertEquals(1, viewDef.getF()); + + } + +} diff --git a/source/peer/src/test/java/test/com/jd/blockchain/peer/service/LedgerInitCordinatorTest.java b/source/peer/src/test/java/test/com/jd/blockchain/peer/service/LedgerInitCordinatorTest.java index e45b661b..30534b52 100644 --- a/source/peer/src/test/java/test/com/jd/blockchain/peer/service/LedgerInitCordinatorTest.java +++ b/source/peer/src/test/java/test/com/jd/blockchain/peer/service/LedgerInitCordinatorTest.java @@ -1,151 +1,151 @@ -//package test.com.jd.blockchain.peer.service; -// -//import com.jd.blockchain.ledger.*; -//import com.jd.blockchain.ledger.service.LedgerService; -//import com.jd.blockchain.ledger.service.impl.LedgerServiceImpl; -//import com.jd.blockchain.peer.service.LedgerInitCordinator; -//import com.jd.blockchain.storage.service.KeyValueStorageService; -//import com.jd.blockchain.storage.service.impl.hashmap.HashMapStorageService; -//import my.utils.net.NetworkAddress; -//import org.junit.After; -//import org.junit.Before; -//import org.junit.Test; -// -//import java.util.ArrayList; -//import java.util.Arrays; -//import java.util.Collections; -//import java.util.List; -// -//import static org.junit.Assert.*; -// -//public class LedgerInitCordinatorTest { -// -// private LedgerService ledgerService; -// private NetworkAddress localpeer = new NetworkAddress("127.0.0.1", 9000); -// -// @Before -// public void setup() { -// KeyValueStorageService storageService = new HashMapStorageService(); -// ledgerService = new LedgerServiceImpl(storageService); -// } -// -// @After -// public void teardown() { -// ledgerService = null; -// } -// -// @Test -// public void testStart() { -// BlockchainKeyPair genesisAccount = BlockchainKeyGenerator.getInstance().generate(); -// LedgerInitCordinator cordinator = new LedgerInitCordinator(ledgerService, localpeer, genesisAccount.getIdentity()); -// cordinator.start(); -// -// assertEquals(cordinator.getLedgerBuilder().getGenesisSeed(), cordinator.getLedgerDefinition().getGenesisKey()); -// assertEquals(cordinator.getLedgerDefinition().isConfigReady(), false); -// assertEquals(cordinator.getLedgerDefinition().genesisAccountNum(), 1); -// assertEquals(cordinator.getLedgerDefinition().getInitializingOperations().length, 0); -// } -// -// @Test -// public void testJoinLedger() { -// BlockchainKeyPair genesisAccount = BlockchainKeyGenerator.getInstance().generate(); -// LedgerInitCordinator cordinator = new LedgerInitCordinator(ledgerService, localpeer, genesisAccount.getIdentity()); -// cordinator.start(); -// -// NetworkAddress remotepeer1 = new NetworkAddress("127.0.0.1", 9001); -// BlockchainKeyPair remoteAccount1 = BlockchainKeyGenerator.getInstance().generate(); -// BlockchainIdentity[] remoteIdentities1 = new BlockchainIdentity[1]; -// remoteIdentities1[0] = remoteAccount1.getIdentity(); -// -// NetworkAddress remotepeer2 = new NetworkAddress("127.0.0.1", 9002); -// BlockchainKeyPair remoteAccount2 = BlockchainKeyGenerator.getInstance().generate(); -// BlockchainIdentity[] remoteIdentities2 = new BlockchainIdentity[1]; -// remoteIdentities2[0] = remoteAccount2.getIdentity(); -// -// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer1, remoteIdentities1, new BlockchainOperation[0]); -// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer2, remoteIdentities2, new BlockchainOperation[0]); -// -// assertEquals(cordinator.getLedgerDefinition().genesisAccountNum(), 3); -// assertEquals(cordinator.getLedgerDefinition().getInitializingOperations().length, 0); -// } -// -// @Test -// public void testPrepare() { -// BlockchainKeyPair genesisAccount = BlockchainKeyGenerator.getInstance().generate(); -// LedgerInitCordinator cordinator = new LedgerInitCordinator(ledgerService, localpeer, genesisAccount.getIdentity()); -// cordinator.start(); -// TransactionContent content = cordinator.prepare(cordinator.getLedgerDefinition().getDefinitionId()); -// -// assertEquals(cordinator.getLedgerDefinition().isConfigReady(), true); -// assertEquals(content.getOperations().length, 1); -// } -// -// @Test -// public void testSign() { -// BlockchainKeyPair genesisAccount = BlockchainKeyGenerator.getInstance().generate(); -// LedgerInitCordinator cordinator = new LedgerInitCordinator(ledgerService, localpeer, genesisAccount.getIdentity()); -// cordinator.start(); -// -// NetworkAddress remotepeer1 = new NetworkAddress("127.0.0.1", 9001); -// BlockchainKeyPair remoteAccount1 = BlockchainKeyGenerator.getInstance().generate(); -// BlockchainIdentity[] remoteIdentities1 = new BlockchainIdentity[1]; -// remoteIdentities1[0] = remoteAccount1.getIdentity(); -// -// NetworkAddress remotepeer2 = new NetworkAddress("127.0.0.1", 9002); -// BlockchainKeyPair remoteAccount2 = BlockchainKeyGenerator.getInstance().generate(); -// BlockchainIdentity[] remoteIdentities2 = new BlockchainIdentity[1]; -// remoteIdentities2[0] = remoteAccount2.getIdentity(); -// -// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer1, remoteIdentities1, new BlockchainOperation[0]); -// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer2, remoteIdentities2, new BlockchainOperation[0]); -// -// TransactionContent content = cordinator.prepare(cordinator.getLedgerDefinition().getDefinitionId()); -// -// DigitalSignature genesisSign = cordinator.sign(genesisAccount); -// DigitalSignature remoteSign1 = cordinator.sign(remoteAccount1); -// DigitalSignature remoteSign2 = cordinator.sign(remoteAccount2); -// -// List signatures = Arrays.asList(cordinator.getLedgerDefinition().genesisSignatures()); -// -// assertEquals(cordinator.getLedgerDefinition().genesisSignatures().length, 3); -// assertEquals(signatures.contains(genesisSign), true); -// assertEquals(signatures.contains(remoteSign1), true); -// assertEquals(signatures.contains(remoteSign2), true); -// assertEquals(cordinator.getLedgerDefinition().isSignatureReady(), true); -// } -// -// @Test -// public void testConsistent() { -// BlockchainKeyPair genesisAccount = BlockchainKeyGenerator.getInstance().generate(); -// LedgerInitCordinator cordinator = new LedgerInitCordinator(ledgerService, localpeer, genesisAccount.getIdentity()); -// cordinator.start(); -// -// NetworkAddress remotepeer1 = new NetworkAddress("127.0.0.1", 9001); -// BlockchainKeyPair remoteAccount1 = BlockchainKeyGenerator.getInstance().generate(); -// BlockchainIdentity[] remoteIdentities1 = new BlockchainIdentity[1]; -// remoteIdentities1[0] = remoteAccount1.getIdentity(); -// -// NetworkAddress remotepeer2 = new NetworkAddress("127.0.0.1", 9002); -// BlockchainKeyPair remoteAccount2 = BlockchainKeyGenerator.getInstance().generate(); -// BlockchainIdentity[] remoteIdentities2 = new BlockchainIdentity[1]; -// remoteIdentities2[0] = remoteAccount2.getIdentity(); -// -// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer1, remoteIdentities1, new BlockchainOperation[0]); -// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer2, remoteIdentities2, new BlockchainOperation[0]); -// -// TransactionContent content = cordinator.prepare(cordinator.getLedgerDefinition().getDefinitionId()); -// -// cordinator.sign(genesisAccount); -// cordinator.sign(remoteAccount1); -// cordinator.sign(remoteAccount2); -// cordinator.preGenerateLedger(); -// -// cordinator.addConsensusLedgerHash(cordinator.getLedgerDefinition().getDefinitionId(), genesisAccount.getAddress(), cordinator.getLedgerBuilder().getLedger().getBlockHash()); -// -// cordinator.addConsensusLedgerHash(cordinator.getLedgerDefinition().getDefinitionId(), remoteAccount1.getAddress(), cordinator.getLedgerBuilder().getLedger().getBlockHash()); -// -// cordinator.addConsensusLedgerHash(cordinator.getLedgerDefinition().getDefinitionId(), remoteAccount2.getAddress(), cordinator.getLedgerBuilder().getLedger().getBlockHash()); -// -// assertEquals(cordinator.isLedgerConsistent(), true); -// } +//package test.com.jd.blockchain.peer.service; +// +//import com.jd.blockchain.ledger.*; +//import com.jd.blockchain.ledger.service.LedgerService; +//import com.jd.blockchain.ledger.service.impl.LedgerServiceImpl; +//import com.jd.blockchain.peer.service.LedgerInitCordinator; +//import com.jd.blockchain.storage.service.KeyValueStorageService; +//import com.jd.blockchain.storage.service.impl.hashmap.HashMapStorageService; +//import my.utils.net.NetworkAddress; +//import org.junit.After; +//import org.junit.Before; +//import org.junit.Test; +// +//import java.util.ArrayList; +//import java.util.Arrays; +//import java.util.Collections; +//import java.util.List; +// +//import static org.junit.Assert.*; +// +//public class LedgerInitCordinatorTest { +// +// private LedgerService ledgerService; +// private NetworkAddress localpeer = new NetworkAddress("127.0.0.1", 9000); +// +// @Before +// public void setup() { +// KeyValueStorageService storageService = new HashMapStorageService(); +// ledgerService = new LedgerServiceImpl(storageService); +// } +// +// @After +// public void teardown() { +// ledgerService = null; +// } +// +// @Test +// public void testStart() { +// BlockchainKeyPair genesisAccount = BlockchainKeyGenerator.getInstance().generate(); +// LedgerInitCordinator cordinator = new LedgerInitCordinator(ledgerService, localpeer, genesisAccount.getIdentity()); +// cordinator.start(); +// +// assertEquals(cordinator.getLedgerBuilder().getGenesisSeed(), cordinator.getLedgerDefinition().getGenesisKey()); +// assertEquals(cordinator.getLedgerDefinition().isConfigReady(), false); +// assertEquals(cordinator.getLedgerDefinition().genesisAccountNum(), 1); +// assertEquals(cordinator.getLedgerDefinition().getInitializingOperations().length, 0); +// } +// +// @Test +// public void testJoinLedger() { +// BlockchainKeyPair genesisAccount = BlockchainKeyGenerator.getInstance().generate(); +// LedgerInitCordinator cordinator = new LedgerInitCordinator(ledgerService, localpeer, genesisAccount.getIdentity()); +// cordinator.start(); +// +// NetworkAddress remotepeer1 = new NetworkAddress("127.0.0.1", 9001); +// BlockchainKeyPair remoteAccount1 = BlockchainKeyGenerator.getInstance().generate(); +// BlockchainIdentity[] remoteIdentities1 = new BlockchainIdentity[1]; +// remoteIdentities1[0] = remoteAccount1.getIdentity(); +// +// NetworkAddress remotepeer2 = new NetworkAddress("127.0.0.1", 9002); +// BlockchainKeyPair remoteAccount2 = BlockchainKeyGenerator.getInstance().generate(); +// BlockchainIdentity[] remoteIdentities2 = new BlockchainIdentity[1]; +// remoteIdentities2[0] = remoteAccount2.getIdentity(); +// +// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer1, remoteIdentities1, new BlockchainOperation[0]); +// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer2, remoteIdentities2, new BlockchainOperation[0]); +// +// assertEquals(cordinator.getLedgerDefinition().genesisAccountNum(), 3); +// assertEquals(cordinator.getLedgerDefinition().getInitializingOperations().length, 0); +// } +// +// @Test +// public void testPrepare() { +// BlockchainKeyPair genesisAccount = BlockchainKeyGenerator.getInstance().generate(); +// LedgerInitCordinator cordinator = new LedgerInitCordinator(ledgerService, localpeer, genesisAccount.getIdentity()); +// cordinator.start(); +// TransactionContent content = cordinator.prepare(cordinator.getLedgerDefinition().getDefinitionId()); +// +// assertEquals(cordinator.getLedgerDefinition().isConfigReady(), true); +// assertEquals(content.getOperations().length, 1); +// } +// +// @Test +// public void testSign() { +// BlockchainKeyPair genesisAccount = BlockchainKeyGenerator.getInstance().generate(); +// LedgerInitCordinator cordinator = new LedgerInitCordinator(ledgerService, localpeer, genesisAccount.getIdentity()); +// cordinator.start(); +// +// NetworkAddress remotepeer1 = new NetworkAddress("127.0.0.1", 9001); +// BlockchainKeyPair remoteAccount1 = BlockchainKeyGenerator.getInstance().generate(); +// BlockchainIdentity[] remoteIdentities1 = new BlockchainIdentity[1]; +// remoteIdentities1[0] = remoteAccount1.getIdentity(); +// +// NetworkAddress remotepeer2 = new NetworkAddress("127.0.0.1", 9002); +// BlockchainKeyPair remoteAccount2 = BlockchainKeyGenerator.getInstance().generate(); +// BlockchainIdentity[] remoteIdentities2 = new BlockchainIdentity[1]; +// remoteIdentities2[0] = remoteAccount2.getIdentity(); +// +// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer1, remoteIdentities1, new BlockchainOperation[0]); +// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer2, remoteIdentities2, new BlockchainOperation[0]); +// +// TransactionContent content = cordinator.prepare(cordinator.getLedgerDefinition().getDefinitionId()); +// +// DigitalSignature genesisSign = cordinator.sign(genesisAccount); +// DigitalSignature remoteSign1 = cordinator.sign(remoteAccount1); +// DigitalSignature remoteSign2 = cordinator.sign(remoteAccount2); +// +// List signatures = Arrays.asList(cordinator.getLedgerDefinition().genesisSignatures()); +// +// assertEquals(cordinator.getLedgerDefinition().genesisSignatures().length, 3); +// assertEquals(signatures.contains(genesisSign), true); +// assertEquals(signatures.contains(remoteSign1), true); +// assertEquals(signatures.contains(remoteSign2), true); +// assertEquals(cordinator.getLedgerDefinition().isSignatureReady(), true); +// } +// +// @Test +// public void testConsistent() { +// BlockchainKeyPair genesisAccount = BlockchainKeyGenerator.getInstance().generate(); +// LedgerInitCordinator cordinator = new LedgerInitCordinator(ledgerService, localpeer, genesisAccount.getIdentity()); +// cordinator.start(); +// +// NetworkAddress remotepeer1 = new NetworkAddress("127.0.0.1", 9001); +// BlockchainKeyPair remoteAccount1 = BlockchainKeyGenerator.getInstance().generate(); +// BlockchainIdentity[] remoteIdentities1 = new BlockchainIdentity[1]; +// remoteIdentities1[0] = remoteAccount1.getIdentity(); +// +// NetworkAddress remotepeer2 = new NetworkAddress("127.0.0.1", 9002); +// BlockchainKeyPair remoteAccount2 = BlockchainKeyGenerator.getInstance().generate(); +// BlockchainIdentity[] remoteIdentities2 = new BlockchainIdentity[1]; +// remoteIdentities2[0] = remoteAccount2.getIdentity(); +// +// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer1, remoteIdentities1, new BlockchainOperation[0]); +// cordinator.joinLedger(cordinator.getLedgerDefinition().getDefinitionId(), remotepeer2, remoteIdentities2, new BlockchainOperation[0]); +// +// TransactionContent content = cordinator.prepare(cordinator.getLedgerDefinition().getDefinitionId()); +// +// cordinator.sign(genesisAccount); +// cordinator.sign(remoteAccount1); +// cordinator.sign(remoteAccount2); +// cordinator.preGenerateLedger(); +// +// cordinator.addConsensusLedgerHash(cordinator.getLedgerDefinition().getDefinitionId(), genesisAccount.getAddress(), cordinator.getLedgerBuilder().getLedger().getBlockHash()); +// +// cordinator.addConsensusLedgerHash(cordinator.getLedgerDefinition().getDefinitionId(), remoteAccount1.getAddress(), cordinator.getLedgerBuilder().getLedger().getBlockHash()); +// +// cordinator.addConsensusLedgerHash(cordinator.getLedgerDefinition().getDefinitionId(), remoteAccount2.getAddress(), cordinator.getLedgerBuilder().getLedger().getBlockHash()); +// +// assertEquals(cordinator.isLedgerConsistent(), true); +// } //} \ No newline at end of file diff --git a/source/peer/src/test/java/test/com/jd/blockchain/peer/web/ControllerTestConfiguration.java b/source/peer/src/test/java/test/com/jd/blockchain/peer/web/ControllerTestConfiguration.java index 46dad9bc..12fb0710 100644 --- a/source/peer/src/test/java/test/com/jd/blockchain/peer/web/ControllerTestConfiguration.java +++ b/source/peer/src/test/java/test/com/jd/blockchain/peer/web/ControllerTestConfiguration.java @@ -1,37 +1,37 @@ -//package test.com.jd.blockchain.peer.web; -// -//import org.springframework.boot.test.mocker.mockito.MockBean; -//import org.springframework.context.annotation.Bean; -//import org.springframework.context.annotation.Configuration; -// -//import com.jd.blockchain.peer.PeerSettings; -//import com.jd.blockchain.peer.service.MessageBroadcaster; -//import com.jd.blockchain.peer.service.PeerKeyStorageService; -// -//@Configuration -//public class ControllerTestConfiguration { -// -// @Bean -// public PeerKeyStorageService peerKeyStorageService() { -// return new PeerKeyStorageServiceImpl(); -// } -// -//// @MockBean -//// private LedgerService ledgerService; -// -// @MockBean -// private MessageBroadcaster msgBroadcaster; // 用于向客户端进行消息通知; -// -// -// @Bean -// public PeerSettings peerSettring() { -// PeerSettings setting = new PeerSettings(); -// PeerSettings.ConsensusSetting consensusSetting = new PeerSettings.ConsensusSetting(); -// consensusSetting.setIp("127.0.0.1"); -// consensusSetting.setPort(9000); -// setting.setConsensus(consensusSetting); -// -// return setting; -// } -// -//} +//package test.com.jd.blockchain.peer.web; +// +//import org.springframework.boot.test.mocker.mockito.MockBean; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +// +//import com.jd.blockchain.peer.PeerSettings; +//import com.jd.blockchain.peer.service.MessageBroadcaster; +//import com.jd.blockchain.peer.service.PeerKeyStorageService; +// +//@Configuration +//public class ControllerTestConfiguration { +// +// @Bean +// public PeerKeyStorageService peerKeyStorageService() { +// return new PeerKeyStorageServiceImpl(); +// } +// +//// @MockBean +//// private LedgerService ledgerService; +// +// @MockBean +// private MessageBroadcaster msgBroadcaster; // 用于向客户端进行消息通知; +// +// +// @Bean +// public PeerSettings peerSettring() { +// PeerSettings setting = new PeerSettings(); +// PeerSettings.ConsensusSetting consensusSetting = new PeerSettings.ConsensusSetting(); +// consensusSetting.setIp("127.0.0.1"); +// consensusSetting.setPort(9000); +// setting.setConsensus(consensusSetting); +// +// return setting; +// } +// +//} diff --git a/source/peer/src/test/java/test/com/jd/blockchain/peer/web/LedgerInitializingControllerTest.java b/source/peer/src/test/java/test/com/jd/blockchain/peer/web/LedgerInitializingControllerTest.java index c1736b31..d48952da 100644 --- a/source/peer/src/test/java/test/com/jd/blockchain/peer/web/LedgerInitializingControllerTest.java +++ b/source/peer/src/test/java/test/com/jd/blockchain/peer/web/LedgerInitializingControllerTest.java @@ -1,245 +1,245 @@ -//package test.com.jd.blockchain.peer.web; -// -//import static org.junit.Assert.assertEquals; -//import static org.mockito.Matchers.any; -// -//import java.util.Arrays; -//import java.util.List; -// -//import com.jd.blockchain.ledger.service.impl.LedgerServiceImpl; -//import org.junit.*; -//import org.junit.runner.RunWith; -//import org.junit.runners.MethodSorters; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.boot.test.context.SpringBootTest; -//import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -//import org.springframework.util.Base64Utils; -// -//import com.jd.blockchain.binaryproto.BinaryEncodingUtils; -//import com.jd.blockchain.ledger.AccountRegisterOperation; -//import com.jd.blockchain.ledger.AccountStateOperation; -//import com.jd.blockchain.ledger.AccountStateType; -//import com.jd.blockchain.ledger.BlockchainIdentity; -//import com.jd.blockchain.ledger.BlockchainKeyGenerator; -//import com.jd.blockchain.ledger.BlockchainKeyPair; -//import com.jd.blockchain.ledger.BlockchainOperation; -//import com.jd.blockchain.ledger.DigitalSignature; -//import com.jd.blockchain.ledger.Ledger; -//import com.jd.blockchain.ledger.TransactionContent; -//import com.jd.blockchain.ledger.data.BlockchainOperationFactory; -//import com.jd.blockchain.ledger.data.SignatureEncoding; -//import com.jd.blockchain.ledger.service.LedgerBuilder; -//import com.jd.blockchain.ledger.service.LedgerService; -//import com.jd.blockchain.peer.PeerSettings; -//import com.jd.blockchain.peer.service.LedgerDefinition; -//import com.jd.blockchain.peer.service.MessageBroadcaster; -//import com.jd.blockchain.peer.service.PeerKeyStorageService; -//import com.jd.blockchain.peer.web.JoinLedgerParameter; -//import com.jd.blockchain.peer.web.LedgerInitializationContext; -//import com.jd.blockchain.peer.web.LedgerInitializingController; -//import com.jd.blockchain.storage.service.impl.hashmap.HashMapStorageService; -// -//import my.utils.io.ByteArray; -//import my.utils.net.NetworkAddress; -//import my.utils.serialize.binary.BinarySerializeUtils; -//import my.utils.serialize.json.JSONSerializeUtils; -// -//@Ignore -//@RunWith(SpringJUnit4ClassRunner.class) -//@SpringBootTest(classes = {ControllerTestConfiguration.class}) -//@FixMethodOrder(MethodSorters.NAME_ASCENDING) -//public class LedgerInitializingControllerTest { -// -// @Autowired -// private PeerKeyStorageService keystoreService; -// -// @Autowired -// private LedgerService ledgerService; -// -// @Autowired -// private PeerSettings peerSettings; -// -// @Autowired -// private MessageBroadcaster msgBroadcaster; // 用于向客户端进行消息通知; -// -// private LedgerInitializingController controller; -// -// @BeforeClass -// public static void setUpBeforeClass() throws Exception { -// } -// -// @AfterClass -// public static void tearDownAfterClass() throws Exception { -// } -// -// private BlockchainKeyPair keyOfP1 = BlockchainKeyGenerator.getInstance().generate(); -// -// @Before -// public void setup() { -// ledgerService = new LedgerServiceImpl(new HashMapStorageService()); -// controller = new LedgerInitializingController(peerSettings, keystoreService, ledgerService, msgBroadcaster); -// -// //when(ledgerService.newLedger()).thenReturn(new LedgerBuilderImpl(ByteArray.wrap("genesisKey".getBytes()), ledgerService)); -// //when(ledgerService.newLedger(ByteArray.wrap("genesisKey".getBytes()))).thenReturn(new LedgerBuilderImpl(ByteArray.wrap("genesisKey".getBytes()), ledgerService)); -// } -// -// @After -// public void after() { -// controller = null; -// } -// -// @Test -// public void testStartNewLedger() { -// LedgerInitializationContext context = controller.startNewLedger("TestParticipantName", PeerKeyStorageServiceImpl.keyOfP1.getAddress()); -// -// assertEquals(context.getLocalAccount(), keystoreService.getBlockchainKey(PeerKeyStorageServiceImpl.keyOfP1.getAddress()).getIdentity()); -// assertEquals(context.getLocalConsensusAddress(), new NetworkAddress(peerSettings.getConsensus().getIp(), peerSettings.getConsensus().getPort())); -// assertEquals(context.getLedgerDefinition().genesisAccountNum(), 1); -// assertEquals(context.getLedgerDefinition().isConfigReady(), false); -// assertEquals(context.getLedgerDefinition().getInitializingOperations().length, 2); -// -// JSONSerializeUtils.disableCircularReferenceDetect(); -// JSONSerializeUtils.configStringSerializer(ByteArray.class); -// System.out.println(JSONSerializeUtils.serializeToJSON(context)); -// } -// -// @Test -// public void testStartJoiningLedger() { -// LedgerInitializationContext context = controller.startNewLedger("TestParticipantName", PeerKeyStorageServiceImpl.keyOfP1.getAddress()); -// -// JoinLedgerParameter parameter = new JoinLedgerParameter(); -// BlockchainKeyPair identity = BlockchainKeyGenerator.getInstance().generate(); -// parameter.setGenesisAccounts(new BlockchainIdentity[]{identity.getIdentity()}); -// -// AccountRegisterOperation regGenesisAccountOP = BlockchainOperationFactory.getInstance().register(identity.getIdentity(), -// AccountStateType.MAP); -// AccountStateOperation initGenesisAccountInfoOP = BlockchainOperationFactory.getInstance() -// .updateState(identity.getAddress()); -// initGenesisAccountInfoOP.putString("NAME", "joinLedger"); -// initGenesisAccountInfoOP.putString("DESCRIPTION", ""); -// -// parameter.setOperations(new BlockchainOperation[]{regGenesisAccountOP, initGenesisAccountInfoOP}); -// parameter.setNetworkAddress(new NetworkAddress("127.0.0.1", 9001)); -// -// LedgerDefinition definition = decodeObject(controller.joinLedger(context.getLedgerDefinition().getDefinitionId(), encodeObject(parameter)), LedgerDefinition.class); -// -// assertEquals(definition.genesisAccountNum(), 2); -// assertEquals(definition.getInitializingOperations().length, 4); -// assertEquals(definition.isConfigReady(), false); -// } -// -// @Test -// public void testPrepare() { -// LedgerInitializationContext context = controller.startNewLedger("TestParticipantName",PeerKeyStorageServiceImpl.keyOfP1.getAddress()); -// -// JoinLedgerParameter parameter = new JoinLedgerParameter(); -// BlockchainIdentity identity = keystoreService.generateNewKey("identity").getIdentity(); -// -// parameter.setGenesisAccounts(new BlockchainIdentity[]{identity}); -// -// AccountRegisterOperation regGenesisAccountOP = BlockchainOperationFactory.getInstance().register(identity, AccountStateType.MAP); -// AccountStateOperation initGenesisAccountInfoOP = BlockchainOperationFactory.getInstance() -// .updateState(identity.getAddress()); -// initGenesisAccountInfoOP.putString("NAME", "joinLedger"); -// initGenesisAccountInfoOP.putString("DESCRIPTION", ""); -// -// parameter.setOperations(new BlockchainOperation[]{regGenesisAccountOP, initGenesisAccountInfoOP}); -// parameter.setNetworkAddress(new NetworkAddress("127.0.0.1", 9001)); -// -// controller.joinLedger(context.getLedgerDefinition().getDefinitionId(), encodeObject(parameter)); -// context = controller.prepareAndSign(); -// -// assertEquals(context.getLedgerDefinition().isConfigReady(), true); -// } -// -// @Test -// public void testAttachSignature() { -// LedgerInitializationContext context = controller.startNewLedger("TestParticipantName", PeerKeyStorageServiceImpl.keyOfP1.getAddress()); -// JoinLedgerParameter parameter = new JoinLedgerParameter(); -// BlockchainIdentity identity = keystoreService.generateNewKey("identity").getIdentity(); -// -// parameter.setGenesisAccounts(new BlockchainIdentity[]{identity}); -// parameter.setOperations(new BlockchainOperation[]{}); -// parameter.setNetworkAddress(new NetworkAddress("127.0.0.1", 9001)); -// -// controller.joinLedger(context.getLedgerDefinition().getDefinitionId(), encodeObject(parameter)); -// context = controller.prepareAndSign(); -// -// LedgerBuilder ledgerBuilder = ledgerService.newLedger(context.getLedgerDefinition().getGenesisKey()); -// ledgerBuilder.addLedgerKeys(context.getLedgerDefinition().genesisIdentites()); -// ledgerBuilder.addInitializeOperations(context.getLedgerDefinition().getInitializingOperations()); -// -// TransactionContent txContent = ledgerBuilder.prepare(); -// context.setTransaction(txContent); -// -// byte[] txContentBytes = BinaryEncodingUtils.encode(txContent, TransactionContent.class); -// DigitalSignature signature = keystoreService.sign(txContentBytes, identity.getAddress()); -// ledgerBuilder.attachSignature(signature); -// -// String base64Signature = SignatureEncoding.encodeToBase64(signature); -// controller.attachSignature(context.getLedgerDefinition().getDefinitionId(), base64Signature); -// -// List signatures = Arrays.asList(context.getLedgerDefinition().genesisSignatures()); -// -// assertEquals(context.getLedgerDefinition().genesisSignatures().length, 2); -// assertEquals(signatures.contains(signature), true); -// assertEquals(context.getLedgerDefinition().isSignatureReady(), true); -// } -// -// @Test -// public void testconsensusLedger() { -// LedgerInitializationContext context = controller.startNewLedger("TestParticipantName", PeerKeyStorageServiceImpl.keyOfP1.getAddress()); -// -// BlockchainIdentity identity = PeerKeyStorageServiceImpl.keyOfP2.getIdentity(); -// JoinLedgerParameter parameter = new JoinLedgerParameter(); -// parameter.setGenesisAccounts(new BlockchainIdentity[]{identity}); -// parameter.setOperations(new BlockchainOperation[]{}); -// parameter.setNetworkAddress(new NetworkAddress("127.0.0.1", 9001)); -// -// controller.joinLedger(context.getLedgerDefinition().getDefinitionId(), encodeObject(parameter)); -// context = controller.prepareAndSign(); -// -// // other peer -// LedgerBuilder builder = ledgerService.newLedger(context.getLedgerDefinition().getGenesisKey()); -// builder.addLedgerKeys(context.getLedgerDefinition().genesisIdentites()); -// builder.addInitializeOperations(context.getLedgerDefinition().getInitializingOperations()); -// -// builder.prepare(); -// String base64Signature = SignatureEncoding.encodeToBase64(builder.sign(PeerKeyStorageServiceImpl.keyOfP2)); -// controller.attachSignature(context.getLedgerDefinition().getDefinitionId(), base64Signature); -// -// // 附加全部的签名列表到本地,生成创世区块,建立账本,并提交账本hash到协调节点进行共识; -// context = controller.getLedgerInitContext(); -// for (DigitalSignature signature1 : context.getLedgerDefinition().genesisSignatures()) { -// builder.attachSignature(signature1); -// } -// -// builder.preCommit(); -// Ledger ledger = builder.getLedger(); -// -// // 向协调节点发送账本hash进行共识; -// controller.consensusLedger(context.getLedgerDefinition().getDefinitionId(), identity.getAddress(), ledger.getLedgerHash().toBase64()); -// -// assertEquals(true, controller.getLedgerInitContext().isConsistent()); -// } -// -// private String encodeObject(Object obj) { -// byte[] bts = BinarySerializeUtils.serialize(obj); -// return Base64Utils.encodeToString(bts); -// } -// -// @SuppressWarnings("unchecked") -// private T decodeObject(String base64Str, Class clazz) { -// byte[] bts = Base64Utils.decodeFromString(base64Str); -// // if (BytesReader.class.isAssignableFrom(clazz)) { -// // BytesReader instance = (BytesReader) BeanUtils.instantiate(clazz); -// // try { -// // instance.resolvFrom(new ByteArrayInputStream(bts)); -// // } catch (IOException e) { -// // throw new IORuntimeException(e.getMessage(), e); -// // } -// // return (T) instance; -// // } -// return (T) BinarySerializeUtils.deserialize(bts); -// } -//} +//package test.com.jd.blockchain.peer.web; +// +//import static org.junit.Assert.assertEquals; +//import static org.mockito.Matchers.any; +// +//import java.util.Arrays; +//import java.util.List; +// +//import com.jd.blockchain.ledger.service.impl.LedgerServiceImpl; +//import org.junit.*; +//import org.junit.runner.RunWith; +//import org.junit.runners.MethodSorters; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +//import org.springframework.util.Base64Utils; +// +//import com.jd.blockchain.binaryproto.BinaryEncodingUtils; +//import com.jd.blockchain.ledger.AccountRegisterOperation; +//import com.jd.blockchain.ledger.AccountStateOperation; +//import com.jd.blockchain.ledger.AccountStateType; +//import com.jd.blockchain.ledger.BlockchainIdentity; +//import com.jd.blockchain.ledger.BlockchainKeyGenerator; +//import com.jd.blockchain.ledger.BlockchainKeyPair; +//import com.jd.blockchain.ledger.BlockchainOperation; +//import com.jd.blockchain.ledger.DigitalSignature; +//import com.jd.blockchain.ledger.Ledger; +//import com.jd.blockchain.ledger.TransactionContent; +//import com.jd.blockchain.ledger.data.BlockchainOperationFactory; +//import com.jd.blockchain.ledger.data.SignatureEncoding; +//import com.jd.blockchain.ledger.service.LedgerBuilder; +//import com.jd.blockchain.ledger.service.LedgerService; +//import com.jd.blockchain.peer.PeerSettings; +//import com.jd.blockchain.peer.service.LedgerDefinition; +//import com.jd.blockchain.peer.service.MessageBroadcaster; +//import com.jd.blockchain.peer.service.PeerKeyStorageService; +//import com.jd.blockchain.peer.web.JoinLedgerParameter; +//import com.jd.blockchain.peer.web.LedgerInitializationContext; +//import com.jd.blockchain.peer.web.LedgerInitializingController; +//import com.jd.blockchain.storage.service.impl.hashmap.HashMapStorageService; +// +//import my.utils.io.ByteArray; +//import my.utils.net.NetworkAddress; +//import my.utils.serialize.binary.BinarySerializeUtils; +//import my.utils.serialize.json.JSONSerializeUtils; +// +//@Ignore +//@RunWith(SpringJUnit4ClassRunner.class) +//@SpringBootTest(classes = {ControllerTestConfiguration.class}) +//@FixMethodOrder(MethodSorters.NAME_ASCENDING) +//public class LedgerInitializingControllerTest { +// +// @Autowired +// private PeerKeyStorageService keystoreService; +// +// @Autowired +// private LedgerService ledgerService; +// +// @Autowired +// private PeerSettings peerSettings; +// +// @Autowired +// private MessageBroadcaster msgBroadcaster; // 用于向客户端进行消息通知; +// +// private LedgerInitializingController controller; +// +// @BeforeClass +// public static void setUpBeforeClass() throws Exception { +// } +// +// @AfterClass +// public static void tearDownAfterClass() throws Exception { +// } +// +// private BlockchainKeyPair keyOfP1 = BlockchainKeyGenerator.getInstance().generate(); +// +// @Before +// public void setup() { +// ledgerService = new LedgerServiceImpl(new HashMapStorageService()); +// controller = new LedgerInitializingController(peerSettings, keystoreService, ledgerService, msgBroadcaster); +// +// //when(ledgerService.newLedger()).thenReturn(new LedgerBuilderImpl(ByteArray.wrap("genesisKey".getBytes()), ledgerService)); +// //when(ledgerService.newLedger(ByteArray.wrap("genesisKey".getBytes()))).thenReturn(new LedgerBuilderImpl(ByteArray.wrap("genesisKey".getBytes()), ledgerService)); +// } +// +// @After +// public void after() { +// controller = null; +// } +// +// @Test +// public void testStartNewLedger() { +// LedgerInitializationContext context = controller.startNewLedger("TestParticipantName", PeerKeyStorageServiceImpl.keyOfP1.getAddress()); +// +// assertEquals(context.getLocalAccount(), keystoreService.getBlockchainKey(PeerKeyStorageServiceImpl.keyOfP1.getAddress()).getIdentity()); +// assertEquals(context.getLocalConsensusAddress(), new NetworkAddress(peerSettings.getConsensus().getIp(), peerSettings.getConsensus().getPort())); +// assertEquals(context.getLedgerDefinition().genesisAccountNum(), 1); +// assertEquals(context.getLedgerDefinition().isConfigReady(), false); +// assertEquals(context.getLedgerDefinition().getInitializingOperations().length, 2); +// +// JSONSerializeUtils.disableCircularReferenceDetect(); +// JSONSerializeUtils.configStringSerializer(ByteArray.class); +// System.out.println(JSONSerializeUtils.serializeToJSON(context)); +// } +// +// @Test +// public void testStartJoiningLedger() { +// LedgerInitializationContext context = controller.startNewLedger("TestParticipantName", PeerKeyStorageServiceImpl.keyOfP1.getAddress()); +// +// JoinLedgerParameter parameter = new JoinLedgerParameter(); +// BlockchainKeyPair identity = BlockchainKeyGenerator.getInstance().generate(); +// parameter.setGenesisAccounts(new BlockchainIdentity[]{identity.getIdentity()}); +// +// AccountRegisterOperation regGenesisAccountOP = BlockchainOperationFactory.getInstance().register(identity.getIdentity(), +// AccountStateType.MAP); +// AccountStateOperation initGenesisAccountInfoOP = BlockchainOperationFactory.getInstance() +// .updateState(identity.getAddress()); +// initGenesisAccountInfoOP.putString("NAME", "joinLedger"); +// initGenesisAccountInfoOP.putString("DESCRIPTION", ""); +// +// parameter.setOperations(new BlockchainOperation[]{regGenesisAccountOP, initGenesisAccountInfoOP}); +// parameter.setNetworkAddress(new NetworkAddress("127.0.0.1", 9001)); +// +// LedgerDefinition definition = decodeObject(controller.joinLedger(context.getLedgerDefinition().getDefinitionId(), encodeObject(parameter)), LedgerDefinition.class); +// +// assertEquals(definition.genesisAccountNum(), 2); +// assertEquals(definition.getInitializingOperations().length, 4); +// assertEquals(definition.isConfigReady(), false); +// } +// +// @Test +// public void testPrepare() { +// LedgerInitializationContext context = controller.startNewLedger("TestParticipantName",PeerKeyStorageServiceImpl.keyOfP1.getAddress()); +// +// JoinLedgerParameter parameter = new JoinLedgerParameter(); +// BlockchainIdentity identity = keystoreService.generateNewKey("identity").getIdentity(); +// +// parameter.setGenesisAccounts(new BlockchainIdentity[]{identity}); +// +// AccountRegisterOperation regGenesisAccountOP = BlockchainOperationFactory.getInstance().register(identity, AccountStateType.MAP); +// AccountStateOperation initGenesisAccountInfoOP = BlockchainOperationFactory.getInstance() +// .updateState(identity.getAddress()); +// initGenesisAccountInfoOP.putString("NAME", "joinLedger"); +// initGenesisAccountInfoOP.putString("DESCRIPTION", ""); +// +// parameter.setOperations(new BlockchainOperation[]{regGenesisAccountOP, initGenesisAccountInfoOP}); +// parameter.setNetworkAddress(new NetworkAddress("127.0.0.1", 9001)); +// +// controller.joinLedger(context.getLedgerDefinition().getDefinitionId(), encodeObject(parameter)); +// context = controller.prepareAndSign(); +// +// assertEquals(context.getLedgerDefinition().isConfigReady(), true); +// } +// +// @Test +// public void testAttachSignature() { +// LedgerInitializationContext context = controller.startNewLedger("TestParticipantName", PeerKeyStorageServiceImpl.keyOfP1.getAddress()); +// JoinLedgerParameter parameter = new JoinLedgerParameter(); +// BlockchainIdentity identity = keystoreService.generateNewKey("identity").getIdentity(); +// +// parameter.setGenesisAccounts(new BlockchainIdentity[]{identity}); +// parameter.setOperations(new BlockchainOperation[]{}); +// parameter.setNetworkAddress(new NetworkAddress("127.0.0.1", 9001)); +// +// controller.joinLedger(context.getLedgerDefinition().getDefinitionId(), encodeObject(parameter)); +// context = controller.prepareAndSign(); +// +// LedgerBuilder ledgerBuilder = ledgerService.newLedger(context.getLedgerDefinition().getGenesisKey()); +// ledgerBuilder.addLedgerKeys(context.getLedgerDefinition().genesisIdentites()); +// ledgerBuilder.addInitializeOperations(context.getLedgerDefinition().getInitializingOperations()); +// +// TransactionContent txContent = ledgerBuilder.prepare(); +// context.setTransaction(txContent); +// +// byte[] txContentBytes = BinaryEncodingUtils.encode(txContent, TransactionContent.class); +// DigitalSignature signature = keystoreService.sign(txContentBytes, identity.getAddress()); +// ledgerBuilder.attachSignature(signature); +// +// String base64Signature = SignatureEncoding.encodeToBase64(signature); +// controller.attachSignature(context.getLedgerDefinition().getDefinitionId(), base64Signature); +// +// List signatures = Arrays.asList(context.getLedgerDefinition().genesisSignatures()); +// +// assertEquals(context.getLedgerDefinition().genesisSignatures().length, 2); +// assertEquals(signatures.contains(signature), true); +// assertEquals(context.getLedgerDefinition().isSignatureReady(), true); +// } +// +// @Test +// public void testconsensusLedger() { +// LedgerInitializationContext context = controller.startNewLedger("TestParticipantName", PeerKeyStorageServiceImpl.keyOfP1.getAddress()); +// +// BlockchainIdentity identity = PeerKeyStorageServiceImpl.keyOfP2.getIdentity(); +// JoinLedgerParameter parameter = new JoinLedgerParameter(); +// parameter.setGenesisAccounts(new BlockchainIdentity[]{identity}); +// parameter.setOperations(new BlockchainOperation[]{}); +// parameter.setNetworkAddress(new NetworkAddress("127.0.0.1", 9001)); +// +// controller.joinLedger(context.getLedgerDefinition().getDefinitionId(), encodeObject(parameter)); +// context = controller.prepareAndSign(); +// +// // other peer +// LedgerBuilder builder = ledgerService.newLedger(context.getLedgerDefinition().getGenesisKey()); +// builder.addLedgerKeys(context.getLedgerDefinition().genesisIdentites()); +// builder.addInitializeOperations(context.getLedgerDefinition().getInitializingOperations()); +// +// builder.prepare(); +// String base64Signature = SignatureEncoding.encodeToBase64(builder.sign(PeerKeyStorageServiceImpl.keyOfP2)); +// controller.attachSignature(context.getLedgerDefinition().getDefinitionId(), base64Signature); +// +// // 附加全部的签名列表到本地,生成创世区块,建立账本,并提交账本hash到协调节点进行共识; +// context = controller.getLedgerInitContext(); +// for (DigitalSignature signature1 : context.getLedgerDefinition().genesisSignatures()) { +// builder.attachSignature(signature1); +// } +// +// builder.preCommit(); +// Ledger ledger = builder.getLedger(); +// +// // 向协调节点发送账本hash进行共识; +// controller.consensusLedger(context.getLedgerDefinition().getDefinitionId(), identity.getAddress(), ledger.getLedgerHash().toBase64()); +// +// assertEquals(true, controller.getLedgerInitContext().isConsistent()); +// } +// +// private String encodeObject(Object obj) { +// byte[] bts = BinarySerializeUtils.serialize(obj); +// return Base64Utils.encodeToString(bts); +// } +// +// @SuppressWarnings("unchecked") +// private T decodeObject(String base64Str, Class clazz) { +// byte[] bts = Base64Utils.decodeFromString(base64Str); +// // if (BytesReader.class.isAssignableFrom(clazz)) { +// // BytesReader instance = (BytesReader) BeanUtils.instantiate(clazz); +// // try { +// // instance.resolvFrom(new ByteArrayInputStream(bts)); +// // } catch (IOException e) { +// // throw new IORuntimeException(e.getMessage(), e); +// // } +// // return (T) instance; +// // } +// return (T) BinarySerializeUtils.deserialize(bts); +// } +//} diff --git a/source/peer/src/test/java/test/com/jd/blockchain/peer/web/LedgerInitializingTest.java b/source/peer/src/test/java/test/com/jd/blockchain/peer/web/LedgerInitializingTest.java index 0595ced1..68550bd7 100644 --- a/source/peer/src/test/java/test/com/jd/blockchain/peer/web/LedgerInitializingTest.java +++ b/source/peer/src/test/java/test/com/jd/blockchain/peer/web/LedgerInitializingTest.java @@ -1,252 +1,252 @@ -//package test.com.jd.blockchain.peer.web; -// -//import static org.mockito.Matchers.any; -//import static org.mockito.Matchers.anyInt; -//import static org.mockito.Mockito.mocker; -//import static org.mockito.Mockito.spy; -//import static org.mockito.Mockito.when; -// -//import org.junit.After; -//import org.junit.AfterClass; -//import org.junit.Before; -//import org.junit.BeforeClass; -//import org.junit.FixMethodOrder; -//import org.junit.Ignore; -//import org.junit.Test; -//import org.junit.runner.RunWith; -//import org.junit.runners.MethodSorters; -//import org.mockito.invocation.InvocationOnMock; -//import org.mockito.stubbing.Answer; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.boot.test.context.SpringBootTest; -//import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -// -//import com.jd.blockchain.ledger.BlockchainIdentity; -//import com.jd.blockchain.ledger.BlockchainKeyPair; -//import com.jd.blockchain.ledger.DigitalSignature; -//import com.jd.blockchain.ledger.data.SignatureUtils; -//import com.jd.blockchain.ledger.service.LedgerService; -//import com.jd.blockchain.ledger.service.impl.LedgerServiceImpl; -//import com.jd.blockchain.peer.PeerSettings; -//import com.jd.blockchain.peer.service.BlockchainKeyInfo; -//import com.jd.blockchain.peer.service.MessageBroadcaster; -//import com.jd.blockchain.peer.service.PeerKeyStorageService; -//import com.jd.blockchain.peer.web.LedgerInitializationContext; -//import com.jd.blockchain.peer.web.LedgerInitializingController; -//import com.jd.blockchain.peer.web.LedgerInitializingHttpService; -//import com.jd.blockchain.storage.service.impl.redis.RedisStorageService; -// -//import my.utils.io.ByteArray; -//import redis.clients.jedis.Jedis; -// -//@Ignore -//@RunWith(SpringJUnit4ClassRunner.class) -//@SpringBootTest(classes = { ControllerTestConfiguration.class}) -//@FixMethodOrder(MethodSorters.NAME_ASCENDING) -//public class LedgerInitializingTest { -// -// @Autowired -// private PeerKeyStorageService keyStorageService; -// -// @BeforeClass -// public static void setUpBeforeClass() throws Exception { -// } -// -// @AfterClass -// public static void tearDownAfterClass() throws Exception { -// } -// -// @Before -// public void setup() { -// } -// -// @After -// public void after() { -// } -// -// @Test -// public void testStartNewLedger() { -// // 准备上下文; -// ServerContext cordinator = new ServerContext("cordinator", 0, 9000, keyStorageService); -// -// ServerContext participant1 = new ServerContext("participant1", 1, 9001, keyStorageService); -// participant1.setLedgerInitHttpServiceProxy(cordinator.getController()); -// -// ServerContext participant2 = new ServerContext("participant2", 2, 9002, keyStorageService); -// participant2.setLedgerInitHttpServiceProxy(cordinator.getController()); -// -// ServerContext participant3 = new ServerContext("participant3", 3, 9003, keyStorageService); -// participant3.setLedgerInitHttpServiceProxy(cordinator.getController()); -// -// // 协调节点开始新建账本; -// LedgerInitializationContext ctx = cordinator.controller.startNewLedger(cordinator.keyInfo.getName(), -// cordinator.keyInfo.getIdentity().getAddress()); -// String defId = ctx.getLedgerDefinition().getDefinitionId(); -// -// // 参与者加入账本; -// participant1.controller.startJoiningLedger(defId, "localhost", 9000, participant1.keyInfo.getName(), -// participant1.keyInfo.getIdentity().getAddress()); -// participant2.controller.startJoiningLedger(defId, "localhost", 9000, participant2.keyInfo.getName(), -// participant2.keyInfo.getIdentity().getAddress()); -// participant3.controller.startJoiningLedger(defId, "localhost", 9000, participant3.keyInfo.getName(), -// participant3.keyInfo.getIdentity().getAddress()); -// -// // TODO:断言协调节点已经收到了参与者的请求; -// -// -// // 协调节点签署账本; -// cordinator.controller.prepareAndSign(); -// -// // 等待各个参与节点完成签署和生成块; -// try { -// Thread.sleep(5000); -// } catch (InterruptedException e) { -// // Swallow InterruptedException; -// } -// -// LedgerInitializationContext cordCtx = cordinator.controller.getLedgerInitContext(); -// LedgerInitializationContext part1Ctx = participant1.controller.getLedgerInitContext(); -// LedgerInitializationContext part2Ctx = participant2.controller.getLedgerInitContext(); -// LedgerInitializationContext part3Ctx = participant3.controller.getLedgerInitContext(); -// -// // 断言各个参与节点都达到了块一致的状态; -// //ssertTrue(cordCtx.isConsistent()); -// -// // 等待各个参与节点完成签署和生成块; -// try { -// Thread.sleep(5000); -// } catch (InterruptedException e) { -// // Swallow InterruptedException; -// } -// //assertTrue(part1Ctx.isConsistent()); -// //assertTrue(part2Ctx.isConsistent()); -// //assertTrue(part3Ctx.isConsistent()); -// -// // 断言各个参与节点的块都是真正地一致; -// //assertEquals(cordCtx.getLedger().getLedgerHash(), part1Ctx.getLedger().getLedgerHash()); -// //assertEquals(cordCtx.getLedger().getLedgerHash(), part2Ctx.getLedger().getLedgerHash()); -// //assertEquals(cordCtx.getLedger().getLedgerHash(), part3Ctx.getLedger().getLedgerHash()); -// -// // 协调节点提交; -// cordinator.controller.commitLedger(); -// -// // 等待各个参与节点完成提交; -// try { -// Thread.sleep(5000); -// } catch (InterruptedException e) { -// // Swallow InterruptedException; -// } -// -// // 断言各个参与节点的状态都被重置了; -// cordCtx = cordinator.controller.getLedgerInitContext(); -// part1Ctx = participant1.controller.getLedgerInitContext(); -// part2Ctx = participant2.controller.getLedgerInitContext(); -// part3Ctx = participant3.controller.getLedgerInitContext(); -// -// //assertFalse(cordCtx.isJoined()); -// //assertFalse(part1Ctx.isJoined()); -// //assertFalse(part2Ctx.isJoined()); -// //assertFalse(part3Ctx.isJoined()); -// -// //assertNull(cordCtx.getLedgerDefinition()); -// //assertNull(part1Ctx.getLedgerDefinition()); -// //assertNull(part2Ctx.getLedgerDefinition()); -// //assertNull(part3Ctx.getLedgerDefinition()); -// } -// -// public static class ServerContext { -// -// private PeerKeyStorageService keystoreService; -// -// private LedgerService ledgerService; -// -// private PeerSettings peerSettings; -// -// private MessageBroadcaster msgBroadcaster; // 用于向客户端进行消息通知; -// -// private LedgerInitializingController controller; -// -// //private final BlockchainKeyPair key; -// -// private final BlockchainIdentity identity; -// -// private final BlockchainKeyInfo keyInfo; -// -// private LedgerInitializingHttpService ledgerInitHttpServiceProxy; -// -// public ServerContext(String name, int idx, int port, PeerKeyStorageService keystoreService) { -// Jedis jedis = new Jedis("192.168.151.33", 6379); -// jedis.select(idx); -// jedis.connect(); -// -// this.ledgerService = new LedgerServiceImpl(new RedisStorageService(jedis)); -// this.peerSettings = peerSetting(port); -// this.keystoreService = keystoreService; -// -// this.keyInfo = this.keystoreService.generateNewKey(name); -// this.identity = this.keyInfo.getIdentity(); -// -// //this.key = BlockchainKeyGenerator.getInstance().generate(KeyType.ED25519); -// //this.keyInfo = new BlockchainKeyInfo(); -// //this.keyInfo.setName(name); -// //this.keyInfo.setIdentity(key.getIdentity()); -// -// initTestContext(); -// } -// -// -// private PeerSettings peerSetting(int port) { -// PeerSettings setting = new PeerSettings(); -// PeerSettings.ConsensusSetting consensusSetting = new PeerSettings.ConsensusSetting(); -// consensusSetting.setIp("127.0.0.1"); -// consensusSetting.setPort(port); -// setting.setConsensus(consensusSetting); -// -// return setting; -// } -// -// -// private void initTestContext() { -// //keystoreService = spy(PeerKeyStorageServiceImpl.class); -// //when(keystoreService.getBlockchainKey(key.getAddress())).thenReturn(keyInfo); -// //when(keystoreService.sign(any(), key.getAddress())).then(answerSignature(key)); -// -// msgBroadcaster = mocker(MessageBroadcaster.class); -// -// LedgerInitializingController ctrl = new LedgerInitializingController(peerSettings, keystoreService, -// ledgerService, msgBroadcaster); -// this.controller = spy(ctrl); -// -// when(controller.getLedgerInitHttpService(any(), anyInt())).then(new Answer() { -// @Override -// public LedgerInitializingHttpService answer(InvocationOnMock invocationOnMock) throws Throwable { -// return ledgerInitHttpServiceProxy; -// } -// }); -// } -// -// private Answer answerSignature(BlockchainKeyPair keyPair) { -// return new Answer() { -// @Override -// public DigitalSignature answer(InvocationOnMock invocation) throws Throwable { -// Object[] args = invocation.getArguments(); -// ByteArray data = (ByteArray) args[0]; -// return SignatureUtils.sign(data, keyPair); -// } -// }; -// } -// -// public LedgerInitializingController getController() { -// return controller; -// } -// -// public LedgerInitializingHttpService getLedgerInitHttpServiceProxy() { -// return ledgerInitHttpServiceProxy; -// } -// -// public void setLedgerInitHttpServiceProxy(LedgerInitializingHttpService ledgerInitHttpServiceProxy) { -// this.ledgerInitHttpServiceProxy = ledgerInitHttpServiceProxy; -// } -// -// } -//} +//package test.com.jd.blockchain.peer.web; +// +//import static org.mockito.Matchers.any; +//import static org.mockito.Matchers.anyInt; +//import static org.mockito.Mockito.mocker; +//import static org.mockito.Mockito.spy; +//import static org.mockito.Mockito.when; +// +//import org.junit.After; +//import org.junit.AfterClass; +//import org.junit.Before; +//import org.junit.BeforeClass; +//import org.junit.FixMethodOrder; +//import org.junit.Ignore; +//import org.junit.Test; +//import org.junit.runner.RunWith; +//import org.junit.runners.MethodSorters; +//import org.mockito.invocation.InvocationOnMock; +//import org.mockito.stubbing.Answer; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.boot.test.context.SpringBootTest; +//import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +// +//import com.jd.blockchain.ledger.BlockchainIdentity; +//import com.jd.blockchain.ledger.BlockchainKeyPair; +//import com.jd.blockchain.ledger.DigitalSignature; +//import com.jd.blockchain.ledger.data.SignatureUtils; +//import com.jd.blockchain.ledger.service.LedgerService; +//import com.jd.blockchain.ledger.service.impl.LedgerServiceImpl; +//import com.jd.blockchain.peer.PeerSettings; +//import com.jd.blockchain.peer.service.BlockchainKeyInfo; +//import com.jd.blockchain.peer.service.MessageBroadcaster; +//import com.jd.blockchain.peer.service.PeerKeyStorageService; +//import com.jd.blockchain.peer.web.LedgerInitializationContext; +//import com.jd.blockchain.peer.web.LedgerInitializingController; +//import com.jd.blockchain.peer.web.LedgerInitializingHttpService; +//import com.jd.blockchain.storage.service.impl.redis.RedisStorageService; +// +//import my.utils.io.ByteArray; +//import redis.clients.jedis.Jedis; +// +//@Ignore +//@RunWith(SpringJUnit4ClassRunner.class) +//@SpringBootTest(classes = { ControllerTestConfiguration.class}) +//@FixMethodOrder(MethodSorters.NAME_ASCENDING) +//public class LedgerInitializingTest { +// +// @Autowired +// private PeerKeyStorageService keyStorageService; +// +// @BeforeClass +// public static void setUpBeforeClass() throws Exception { +// } +// +// @AfterClass +// public static void tearDownAfterClass() throws Exception { +// } +// +// @Before +// public void setup() { +// } +// +// @After +// public void after() { +// } +// +// @Test +// public void testStartNewLedger() { +// // 准备上下文; +// ServerContext cordinator = new ServerContext("cordinator", 0, 9000, keyStorageService); +// +// ServerContext participant1 = new ServerContext("participant1", 1, 9001, keyStorageService); +// participant1.setLedgerInitHttpServiceProxy(cordinator.getController()); +// +// ServerContext participant2 = new ServerContext("participant2", 2, 9002, keyStorageService); +// participant2.setLedgerInitHttpServiceProxy(cordinator.getController()); +// +// ServerContext participant3 = new ServerContext("participant3", 3, 9003, keyStorageService); +// participant3.setLedgerInitHttpServiceProxy(cordinator.getController()); +// +// // 协调节点开始新建账本; +// LedgerInitializationContext ctx = cordinator.controller.startNewLedger(cordinator.keyInfo.getName(), +// cordinator.keyInfo.getIdentity().getAddress()); +// String defId = ctx.getLedgerDefinition().getDefinitionId(); +// +// // 参与者加入账本; +// participant1.controller.startJoiningLedger(defId, "localhost", 9000, participant1.keyInfo.getName(), +// participant1.keyInfo.getIdentity().getAddress()); +// participant2.controller.startJoiningLedger(defId, "localhost", 9000, participant2.keyInfo.getName(), +// participant2.keyInfo.getIdentity().getAddress()); +// participant3.controller.startJoiningLedger(defId, "localhost", 9000, participant3.keyInfo.getName(), +// participant3.keyInfo.getIdentity().getAddress()); +// +// // TODO:断言协调节点已经收到了参与者的请求; +// +// +// // 协调节点签署账本; +// cordinator.controller.prepareAndSign(); +// +// // 等待各个参与节点完成签署和生成块; +// try { +// Thread.sleep(5000); +// } catch (InterruptedException e) { +// // Swallow InterruptedException; +// } +// +// LedgerInitializationContext cordCtx = cordinator.controller.getLedgerInitContext(); +// LedgerInitializationContext part1Ctx = participant1.controller.getLedgerInitContext(); +// LedgerInitializationContext part2Ctx = participant2.controller.getLedgerInitContext(); +// LedgerInitializationContext part3Ctx = participant3.controller.getLedgerInitContext(); +// +// // 断言各个参与节点都达到了块一致的状态; +// //ssertTrue(cordCtx.isConsistent()); +// +// // 等待各个参与节点完成签署和生成块; +// try { +// Thread.sleep(5000); +// } catch (InterruptedException e) { +// // Swallow InterruptedException; +// } +// //assertTrue(part1Ctx.isConsistent()); +// //assertTrue(part2Ctx.isConsistent()); +// //assertTrue(part3Ctx.isConsistent()); +// +// // 断言各个参与节点的块都是真正地一致; +// //assertEquals(cordCtx.getLedger().getLedgerHash(), part1Ctx.getLedger().getLedgerHash()); +// //assertEquals(cordCtx.getLedger().getLedgerHash(), part2Ctx.getLedger().getLedgerHash()); +// //assertEquals(cordCtx.getLedger().getLedgerHash(), part3Ctx.getLedger().getLedgerHash()); +// +// // 协调节点提交; +// cordinator.controller.commitLedger(); +// +// // 等待各个参与节点完成提交; +// try { +// Thread.sleep(5000); +// } catch (InterruptedException e) { +// // Swallow InterruptedException; +// } +// +// // 断言各个参与节点的状态都被重置了; +// cordCtx = cordinator.controller.getLedgerInitContext(); +// part1Ctx = participant1.controller.getLedgerInitContext(); +// part2Ctx = participant2.controller.getLedgerInitContext(); +// part3Ctx = participant3.controller.getLedgerInitContext(); +// +// //assertFalse(cordCtx.isJoined()); +// //assertFalse(part1Ctx.isJoined()); +// //assertFalse(part2Ctx.isJoined()); +// //assertFalse(part3Ctx.isJoined()); +// +// //assertNull(cordCtx.getLedgerDefinition()); +// //assertNull(part1Ctx.getLedgerDefinition()); +// //assertNull(part2Ctx.getLedgerDefinition()); +// //assertNull(part3Ctx.getLedgerDefinition()); +// } +// +// public static class ServerContext { +// +// private PeerKeyStorageService keystoreService; +// +// private LedgerService ledgerService; +// +// private PeerSettings peerSettings; +// +// private MessageBroadcaster msgBroadcaster; // 用于向客户端进行消息通知; +// +// private LedgerInitializingController controller; +// +// //private final BlockchainKeyPair key; +// +// private final BlockchainIdentity identity; +// +// private final BlockchainKeyInfo keyInfo; +// +// private LedgerInitializingHttpService ledgerInitHttpServiceProxy; +// +// public ServerContext(String name, int idx, int port, PeerKeyStorageService keystoreService) { +// Jedis jedis = new Jedis("192.168.151.33", 6379); +// jedis.select(idx); +// jedis.connect(); +// +// this.ledgerService = new LedgerServiceImpl(new RedisStorageService(jedis)); +// this.peerSettings = peerSetting(port); +// this.keystoreService = keystoreService; +// +// this.keyInfo = this.keystoreService.generateNewKey(name); +// this.identity = this.keyInfo.getIdentity(); +// +// //this.key = BlockchainKeyGenerator.getInstance().generate(KeyType.ED25519); +// //this.keyInfo = new BlockchainKeyInfo(); +// //this.keyInfo.setName(name); +// //this.keyInfo.setIdentity(key.getIdentity()); +// +// initTestContext(); +// } +// +// +// private PeerSettings peerSetting(int port) { +// PeerSettings setting = new PeerSettings(); +// PeerSettings.ConsensusSetting consensusSetting = new PeerSettings.ConsensusSetting(); +// consensusSetting.setIp("127.0.0.1"); +// consensusSetting.setPort(port); +// setting.setConsensus(consensusSetting); +// +// return setting; +// } +// +// +// private void initTestContext() { +// //keystoreService = spy(PeerKeyStorageServiceImpl.class); +// //when(keystoreService.getBlockchainKey(key.getAddress())).thenReturn(keyInfo); +// //when(keystoreService.sign(any(), key.getAddress())).then(answerSignature(key)); +// +// msgBroadcaster = mocker(MessageBroadcaster.class); +// +// LedgerInitializingController ctrl = new LedgerInitializingController(peerSettings, keystoreService, +// ledgerService, msgBroadcaster); +// this.controller = spy(ctrl); +// +// when(controller.getLedgerInitHttpService(any(), anyInt())).then(new Answer() { +// @Override +// public LedgerInitializingHttpService answer(InvocationOnMock invocationOnMock) throws Throwable { +// return ledgerInitHttpServiceProxy; +// } +// }); +// } +// +// private Answer answerSignature(BlockchainKeyPair keyPair) { +// return new Answer() { +// @Override +// public DigitalSignature answer(InvocationOnMock invocation) throws Throwable { +// Object[] args = invocation.getArguments(); +// ByteArray data = (ByteArray) args[0]; +// return SignatureUtils.sign(data, keyPair); +// } +// }; +// } +// +// public LedgerInitializingController getController() { +// return controller; +// } +// +// public LedgerInitializingHttpService getLedgerInitHttpServiceProxy() { +// return ledgerInitHttpServiceProxy; +// } +// +// public void setLedgerInitHttpServiceProxy(LedgerInitializingHttpService ledgerInitHttpServiceProxy) { +// this.ledgerInitHttpServiceProxy = ledgerInitHttpServiceProxy; +// } +// +// } +//} diff --git a/source/peer/src/test/java/test/com/jd/blockchain/peer/web/PeerKeyStorageServiceImpl.java b/source/peer/src/test/java/test/com/jd/blockchain/peer/web/PeerKeyStorageServiceImpl.java index 5491b2f5..02c54d8a 100644 --- a/source/peer/src/test/java/test/com/jd/blockchain/peer/web/PeerKeyStorageServiceImpl.java +++ b/source/peer/src/test/java/test/com/jd/blockchain/peer/web/PeerKeyStorageServiceImpl.java @@ -1,140 +1,140 @@ -//package test.com.jd.blockchain.peer.web; -// -//import java.util.Arrays; -//import java.util.Comparator; -//import java.util.Map; -//import java.util.concurrent.ConcurrentHashMap; -// -//import javax.annotation.PostConstruct; -// -//import com.jd.blockchain.crypto.CryptoAlgorithm; -//import com.jd.blockchain.crypto.asymmetric.PrivKey; -//import com.jd.blockchain.crypto.asymmetric.PubKey; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.stereotype.Service; -// -//import com.jd.blockchain.ledger.BlockchainIdentity; -//import com.jd.blockchain.ledger.BlockchainKeyGenerator; -//import com.jd.blockchain.ledger.BlockchainKeyPair; -//import com.jd.blockchain.ledger.DigitalSignature; -//import com.jd.blockchain.ledger.data.CryptoKeyEncoding; -//import com.jd.blockchain.ledger.data.SignatureUtils; -//import com.jd.blockchain.peer.PeerSettings; -//import com.jd.blockchain.peer.service.BlockchainKeyInfo; -//import com.jd.blockchain.peer.service.PeerKeyStorageService; -// -//import my.utils.io.ByteArray; -// -//@Service -//public class PeerKeyStorageServiceImpl implements PeerKeyStorageService { -// -// @Autowired -// private PeerSettings settings; -// -// public static BlockchainKeyPair keyOfP1 = BlockchainKeyGenerator.getInstance().generate(); -// public static BlockchainKeyPair keyOfP2 = BlockchainKeyGenerator.getInstance().generate(); -// -// private Map keyStores = new ConcurrentHashMap<>(); -// -// private static String[] encodeToStringLines(BlockchainKeyStore keyStore) { -// return new String[] { keyStore.getKeyInfo().getName(), keyStore.getKeyPair().getAddress(), -// keyStore.getKeyPair().getPubKey().toString(), keyStore.getKeyPair().getPrivKey().toString() }; -// } -// -// private static BlockchainKeyStore decodeFromStringLines(String[] lines) { -// String name = lines[0]; -// String address = lines[1]; -// PubKey pubKey = (PubKey) CryptoKeyEncoding.fromBase58(lines[2]); -// PrivKey privKey = (PrivKey) CryptoKeyEncoding.fromBase58(lines[3]); -// return new BlockchainKeyStore(name, address, pubKey, privKey); -// } -// -// @PostConstruct -// private void init() { -// keyStores.put(keyOfP1.getAddress(), new BlockchainKeyStore("a", keyOfP1)); -// keyStores.put(keyOfP1.getAddress(), new BlockchainKeyStore("b", keyOfP1)); -// } -// -// @Override -// public BlockchainKeyInfo generateNewKey(String name) { -// BlockchainKeyPair keypair = BlockchainKeyGenerator.getInstance().generate(CryptoAlgorithm.ED25519); -// BlockchainKeyStore keystore = new BlockchainKeyStore(name, keypair); -// -// keyStores.put(keypair.getAddress(), keystore); -// return keystore.getKeyInfo(); -// } -// -// @Override -// public DigitalSignature sign(ByteArray data, String address) { -// BlockchainKeyStore keystore = keyStores.get(address); -// if (keystore == null) { -// throw new IllegalArgumentException("Key not exist!"); -// } -// return SignatureUtils.sign(data, keystore.getKeyPair()); -// } -// -// @Override -// public DigitalSignature sign(byte[] data, String address) { -// BlockchainKeyStore keystore = keyStores.get(address); -// if (keystore == null) { -// throw new IllegalArgumentException("Key not exist!"); -// } -// return SignatureUtils.sign(data, keystore.getKeyPair()); -// } -// -// @Override -// public BlockchainKeyInfo getBlockchainKey(String address) { -// BlockchainKeyStore keystore = keyStores.get(address); -// if (keystore == null) { -// throw new IllegalArgumentException("Key not exist!"); -// } -// return keystore.getKeyInfo(); -// } -// -// @Override -// public BlockchainKeyInfo[] getBlockchainKeys() { -// BlockchainKeyInfo[] keys = new BlockchainKeyInfo[keyStores.size()]; -// int i = 0; -// for (BlockchainKeyStore keystore : keyStores.values()) { -// keys[i] = keystore.getKeyInfo(); -// i++; -// } -// Arrays.sort(keys, new Comparator() { -// @Override -// public int compare(BlockchainKeyInfo o1, BlockchainKeyInfo o2) { -// return o1.getName().compareTo(o2.getName()); -// } -// }); -// return keys; -// } -// -// private static class BlockchainKeyStore { -// private BlockchainKeyInfo keyInfo; -// -// private BlockchainKeyPair keyPair; -// -// public BlockchainKeyStore(String name, String address, PubKey pubKey, PrivKey privKey) { -// keyInfo = new BlockchainKeyInfo(); -// keyInfo.setName(name); -// keyInfo.setIdentity(new BlockchainIdentity(address, pubKey)); -// keyPair = new BlockchainKeyPair(address, pubKey, privKey); -// } -// -// public BlockchainKeyStore(String name, BlockchainKeyPair keypair) { -// keyInfo = new BlockchainKeyInfo(); -// keyInfo.setName(name); -// keyInfo.setIdentity(keypair.getIdentity()); -// this.keyPair = keypair; -// } -// -// public BlockchainKeyInfo getKeyInfo() { -// return keyInfo; -// } -// -// public BlockchainKeyPair getKeyPair() { -// return keyPair; -// } -// -// } -// -//} +//package test.com.jd.blockchain.peer.web; +// +//import java.util.Arrays; +//import java.util.Comparator; +//import java.util.Map; +//import java.util.concurrent.ConcurrentHashMap; +// +//import javax.annotation.PostConstruct; +// +//import com.jd.blockchain.crypto.CryptoAlgorithm; +//import com.jd.blockchain.crypto.asymmetric.PrivKey; +//import com.jd.blockchain.crypto.asymmetric.PubKey; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Service; +// +//import com.jd.blockchain.ledger.BlockchainIdentity; +//import com.jd.blockchain.ledger.BlockchainKeyGenerator; +//import com.jd.blockchain.ledger.BlockchainKeyPair; +//import com.jd.blockchain.ledger.DigitalSignature; +//import com.jd.blockchain.ledger.data.CryptoKeyEncoding; +//import com.jd.blockchain.ledger.data.SignatureUtils; +//import com.jd.blockchain.peer.PeerSettings; +//import com.jd.blockchain.peer.service.BlockchainKeyInfo; +//import com.jd.blockchain.peer.service.PeerKeyStorageService; +// +//import my.utils.io.ByteArray; +// +//@Service +//public class PeerKeyStorageServiceImpl implements PeerKeyStorageService { +// +// @Autowired +// private PeerSettings settings; +// +// public static BlockchainKeyPair keyOfP1 = BlockchainKeyGenerator.getInstance().generate(); +// public static BlockchainKeyPair keyOfP2 = BlockchainKeyGenerator.getInstance().generate(); +// +// private Map keyStores = new ConcurrentHashMap<>(); +// +// private static String[] encodeToStringLines(BlockchainKeyStore keyStore) { +// return new String[] { keyStore.getKeyInfo().getName(), keyStore.getKeyPair().getAddress(), +// keyStore.getKeyPair().getPubKey().toString(), keyStore.getKeyPair().getPrivKey().toString() }; +// } +// +// private static BlockchainKeyStore decodeFromStringLines(String[] lines) { +// String name = lines[0]; +// String address = lines[1]; +// PubKey pubKey = (PubKey) CryptoKeyEncoding.fromBase58(lines[2]); +// PrivKey privKey = (PrivKey) CryptoKeyEncoding.fromBase58(lines[3]); +// return new BlockchainKeyStore(name, address, pubKey, privKey); +// } +// +// @PostConstruct +// private void init() { +// keyStores.put(keyOfP1.getAddress(), new BlockchainKeyStore("a", keyOfP1)); +// keyStores.put(keyOfP1.getAddress(), new BlockchainKeyStore("b", keyOfP1)); +// } +// +// @Override +// public BlockchainKeyInfo generateNewKey(String name) { +// BlockchainKeyPair keypair = BlockchainKeyGenerator.getInstance().generate(CryptoAlgorithm.ED25519); +// BlockchainKeyStore keystore = new BlockchainKeyStore(name, keypair); +// +// keyStores.put(keypair.getAddress(), keystore); +// return keystore.getKeyInfo(); +// } +// +// @Override +// public DigitalSignature sign(ByteArray data, String address) { +// BlockchainKeyStore keystore = keyStores.get(address); +// if (keystore == null) { +// throw new IllegalArgumentException("Key not exist!"); +// } +// return SignatureUtils.sign(data, keystore.getKeyPair()); +// } +// +// @Override +// public DigitalSignature sign(byte[] data, String address) { +// BlockchainKeyStore keystore = keyStores.get(address); +// if (keystore == null) { +// throw new IllegalArgumentException("Key not exist!"); +// } +// return SignatureUtils.sign(data, keystore.getKeyPair()); +// } +// +// @Override +// public BlockchainKeyInfo getBlockchainKey(String address) { +// BlockchainKeyStore keystore = keyStores.get(address); +// if (keystore == null) { +// throw new IllegalArgumentException("Key not exist!"); +// } +// return keystore.getKeyInfo(); +// } +// +// @Override +// public BlockchainKeyInfo[] getBlockchainKeys() { +// BlockchainKeyInfo[] keys = new BlockchainKeyInfo[keyStores.size()]; +// int i = 0; +// for (BlockchainKeyStore keystore : keyStores.values()) { +// keys[i] = keystore.getKeyInfo(); +// i++; +// } +// Arrays.sort(keys, new Comparator() { +// @Override +// public int compare(BlockchainKeyInfo o1, BlockchainKeyInfo o2) { +// return o1.getName().compareTo(o2.getName()); +// } +// }); +// return keys; +// } +// +// private static class BlockchainKeyStore { +// private BlockchainKeyInfo keyInfo; +// +// private BlockchainKeyPair keyPair; +// +// public BlockchainKeyStore(String name, String address, PubKey pubKey, PrivKey privKey) { +// keyInfo = new BlockchainKeyInfo(); +// keyInfo.setName(name); +// keyInfo.setIdentity(new BlockchainIdentity(address, pubKey)); +// keyPair = new BlockchainKeyPair(address, pubKey, privKey); +// } +// +// public BlockchainKeyStore(String name, BlockchainKeyPair keypair) { +// keyInfo = new BlockchainKeyInfo(); +// keyInfo.setName(name); +// keyInfo.setIdentity(keypair.getIdentity()); +// this.keyPair = keypair; +// } +// +// public BlockchainKeyInfo getKeyInfo() { +// return keyInfo; +// } +// +// public BlockchainKeyPair getKeyPair() { +// return keyPair; +// } +// +// } +// +//} diff --git a/source/sdk/pom.xml b/source/sdk/pom.xml index c4037224..fb570108 100644 --- a/source/sdk/pom.xml +++ b/source/sdk/pom.xml @@ -1,20 +1,20 @@ - - 4.0.0 - - com.jd.blockchain - jdchain-root - 1.1.2.RELEASE - - sdk - pom - - - sdk-base - - sdk-client - sdk-samples - - - + + 4.0.0 + + com.jd.blockchain + jdchain-root + 1.1.2.RELEASE + + sdk + pom + + + sdk-base + + sdk-client + sdk-samples + + + \ No newline at end of file diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/AbstractBlockchainServiceFactory.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/AbstractBlockchainServiceFactory.java index e7293cc6..37125469 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/AbstractBlockchainServiceFactory.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/AbstractBlockchainServiceFactory.java @@ -1,51 +1,51 @@ -//package com.jd.blockchain.sdk; -// -//import java.io.Closeable; -// -//import com.jd.blockchain.ledger.CryptoSetting; -//import com.jd.blockchain.ledger.data.TransactionService; -//import com.jd.blockchain.sdk.proxy.BlockchainServiceProxy; -// -///** -// * -// * @author huanghaiquan -// * -// */ -//public abstract class AbstractBlockchainServiceFactory implements Closeable { -// -// private final Object mutex = new Object(); -// -// private volatile BlockchainService blockchainService; -// -//// protected ServiceSetting setting; -// -// private CryptoSetting cryptoSetting; -// -// public AbstractBlockchainServiceFactory() { -// } -// -// public BlockchainService getBlockchainService() { -// if (blockchainService == null) { -// synchronized (mutex) { -// if (blockchainService == null) { -// BlockchainQueryService queryService = getQueryService(setting); -// TransactionService consensusService = getConsensusService(setting); -// blockchainService = createBlockchainService(setting, consensusService, queryService); -// } -// } -// } -// return blockchainService; -// } -// -// protected BlockchainService createBlockchainService(ServiceSetting setting, TransactionService consensusService, BlockchainQueryService queryService) { -// return new BlockchainServiceProxy(consensusService, queryService); -// } -// -// protected abstract BlockchainQueryService getQueryService(ServiceSetting setting); -// -// protected abstract TransactionService getConsensusService(ServiceSetting setting); -// -// @Override -// public abstract void close(); -// -//} +//package com.jd.blockchain.sdk; +// +//import java.io.Closeable; +// +//import com.jd.blockchain.ledger.CryptoSetting; +//import com.jd.blockchain.ledger.data.TransactionService; +//import com.jd.blockchain.sdk.proxy.BlockchainServiceProxy; +// +///** +// * +// * @author huanghaiquan +// * +// */ +//public abstract class AbstractBlockchainServiceFactory implements Closeable { +// +// private final Object mutex = new Object(); +// +// private volatile BlockchainService blockchainService; +// +//// protected ServiceSetting setting; +// +// private CryptoSetting cryptoSetting; +// +// public AbstractBlockchainServiceFactory() { +// } +// +// public BlockchainService getBlockchainService() { +// if (blockchainService == null) { +// synchronized (mutex) { +// if (blockchainService == null) { +// BlockchainQueryService queryService = getQueryService(setting); +// TransactionService consensusService = getConsensusService(setting); +// blockchainService = createBlockchainService(setting, consensusService, queryService); +// } +// } +// } +// return blockchainService; +// } +// +// protected BlockchainService createBlockchainService(ServiceSetting setting, TransactionService consensusService, BlockchainQueryService queryService) { +// return new BlockchainServiceProxy(consensusService, queryService); +// } +// +// protected abstract BlockchainQueryService getQueryService(ServiceSetting setting); +// +// protected abstract TransactionService getConsensusService(ServiceSetting setting); +// +// @Override +// public abstract void close(); +// +//} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventHandle.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventHandle.java index 383a72c4..e1af4b42 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventHandle.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventHandle.java @@ -1,45 +1,45 @@ -package com.jd.blockchain.sdk; - -/** - * BlockchainEventHandle 维护了一个具体的事件监听实例的状态,提供了在不需要继续监听时进行取消的方法 - * {@link #cancel()}; - * - * @author huanghaiquan - * - */ -public interface BlockchainEventHandle { - - /** - * 要监听的事件类型; - * - * @return - */ - int getFilteredEventTypes(); - - /** - * 要监听的交易;如果为 null,则不进行交易过滤; - * - * @return - */ - String getFilteredTxHash(); - - /** - * 要监听的账户地址;如果为 null,这不进行账户地址过滤; - * - * @return - */ - String getFilteredAccountAddress(); - - /** - * 监听器实例; - * - * @return - */ - BlockchainEventListener getListener(); - - /** - * 取消监听; - */ - void cancel(); - -} +package com.jd.blockchain.sdk; + +/** + * BlockchainEventHandle 维护了一个具体的事件监听实例的状态,提供了在不需要继续监听时进行取消的方法 + * {@link #cancel()}; + * + * @author huanghaiquan + * + */ +public interface BlockchainEventHandle { + + /** + * 要监听的事件类型; + * + * @return + */ + int getFilteredEventTypes(); + + /** + * 要监听的交易;如果为 null,则不进行交易过滤; + * + * @return + */ + String getFilteredTxHash(); + + /** + * 要监听的账户地址;如果为 null,这不进行账户地址过滤; + * + * @return + */ + String getFilteredAccountAddress(); + + /** + * 监听器实例; + * + * @return + */ + BlockchainEventListener getListener(); + + /** + * 取消监听; + */ + void cancel(); + +} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventListener.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventListener.java index 6b87a9cf..9afe806c 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventListener.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventListener.java @@ -1,7 +1,7 @@ -package com.jd.blockchain.sdk; - -public interface BlockchainEventListener { - - public void onEvent(BlockchainEventMessage eventMessage, BlockchainEventHandle eventHandle); - -} +package com.jd.blockchain.sdk; + +public interface BlockchainEventListener { + + public void onEvent(BlockchainEventMessage eventMessage, BlockchainEventHandle eventHandle); + +} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventMessage.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventMessage.java index 8a1a442d..ec2067ec 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventMessage.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventMessage.java @@ -1,45 +1,45 @@ -package com.jd.blockchain.sdk; - -import java.util.BitSet; - -import com.jd.blockchain.ledger.BlockchainEventType; - -public interface BlockchainEventMessage { - - /** - * 事件代码;
- * - * 事件代码是本次事件的所有类型事件码的按位或的结果;

- * - * 可以按以下方法检查是否包含某个特定事件:
- * - * - * ({@link BlockchainEventType#PAYLOAD_UPDATED} & {@link #getEventCode()}) == {@link BlockchainEventType#PAYLOAD_UPDATED} - * - * - * @return - */ - int getEventCode(); - - /** - * 区块高度; - * - * @return - */ - long getLedgerNumber(); - - /** - * 包含本次事件中的所有成功交易的布隆过滤器(BloomFilter)的值; - * - * @return - */ - BitSet getBloomFilterOfTxs(); - - /** - * 包含本次事件中的所有变更账户的布隆过滤器(BloomFilter)的值; - * - * @return - */ - BitSet getBloomFilterOfAccounts(); - -} +package com.jd.blockchain.sdk; + +import java.util.BitSet; + +import com.jd.blockchain.ledger.BlockchainEventType; + +public interface BlockchainEventMessage { + + /** + * 事件代码;
+ * + * 事件代码是本次事件的所有类型事件码的按位或的结果;

+ * + * 可以按以下方法检查是否包含某个特定事件:
+ * + * + * ({@link BlockchainEventType#PAYLOAD_UPDATED} & {@link #getEventCode()}) == {@link BlockchainEventType#PAYLOAD_UPDATED} + * + * + * @return + */ + int getEventCode(); + + /** + * 区块高度; + * + * @return + */ + long getLedgerNumber(); + + /** + * 包含本次事件中的所有成功交易的布隆过滤器(BloomFilter)的值; + * + * @return + */ + BitSet getBloomFilterOfTxs(); + + /** + * 包含本次事件中的所有变更账户的布隆过滤器(BloomFilter)的值; + * + * @return + */ + BitSet getBloomFilterOfAccounts(); + +} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventService.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventService.java index 34f47d38..04341813 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventService.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainEventService.java @@ -1,20 +1,20 @@ -package com.jd.blockchain.sdk; - -public interface BlockchainEventService { - - /** - * 注册区块链事件监听器; - * - * @param filteredEventTypes - * 要监听的事件类型; - * @param filteredTxHash - * 要监听的交易;如果为 null,则不进行交易过滤; - * @param filteredAccountAddress - * 要监听的账户地址;如果为 null,这不进行账户地址过滤; - * @param listener - * 监听器实例; - */ - BlockchainEventHandle addBlockchainEventListener(int filteredEventTypes, String filteredTxHash, - String filteredAccountAddress, BlockchainEventListener listener); - +package com.jd.blockchain.sdk; + +public interface BlockchainEventService { + + /** + * 注册区块链事件监听器; + * + * @param filteredEventTypes + * 要监听的事件类型; + * @param filteredTxHash + * 要监听的交易;如果为 null,则不进行交易过滤; + * @param filteredAccountAddress + * 要监听的账户地址;如果为 null,这不进行账户地址过滤; + * @param listener + * 监听器实例; + */ + BlockchainEventHandle addBlockchainEventListener(int filteredEventTypes, String filteredTxHash, + String filteredAccountAddress, BlockchainEventListener listener); + } \ No newline at end of file diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainService.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainService.java index e24f8a80..d9d57cfd 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainService.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainService.java @@ -1,16 +1,16 @@ -package com.jd.blockchain.sdk; - -import com.jd.blockchain.transaction.BlockchainQueryService; - -/** - * 区块链服务; - * - *
- * 这是一个门面服务(facade); - * - * @author huanghaiquan - * - */ -public interface BlockchainService extends BlockchainQueryService, BlockchainTransactionService, BlockchainEventService { - -} +package com.jd.blockchain.sdk; + +import com.jd.blockchain.transaction.BlockchainQueryService; + +/** + * 区块链服务; + * + *
+ * 这是一个门面服务(facade); + * + * @author huanghaiquan + * + */ +public interface BlockchainService extends BlockchainQueryService, BlockchainTransactionService, BlockchainEventService { + +} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainTransactionService.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainTransactionService.java index f30dee7c..eff792a3 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainTransactionService.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/BlockchainTransactionService.java @@ -1,26 +1,26 @@ -package com.jd.blockchain.sdk; - -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.TransactionTemplate; - -public interface BlockchainTransactionService { - - /** - * 发起新交易; - * - * @return - */ - TransactionTemplate newTransaction(HashDigest ledgerHash); - -// /** -// * 以指定的科目和流水号发起新交易; -// * -// * @param subjectAccount -// * 交易的科目账户地址; -// * @param sequenceNumber -// * 交易的流水号; -// * @return -// */ -// TransactionTemplate newTransaction(ByteArray ledgerHash, String subjectAccount, long sequenceNumber); - +package com.jd.blockchain.sdk; + +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.TransactionTemplate; + +public interface BlockchainTransactionService { + + /** + * 发起新交易; + * + * @return + */ + TransactionTemplate newTransaction(HashDigest ledgerHash); + +// /** +// * 以指定的科目和流水号发起新交易; +// * +// * @param subjectAccount +// * 交易的科目账户地址; +// * @param sequenceNumber +// * 交易的流水号; +// * @return +// */ +// TransactionTemplate newTransaction(ByteArray ledgerHash, String subjectAccount, long sequenceNumber); + } \ No newline at end of file diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/ManagementHttpService.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/ManagementHttpService.java index f4bd68be..a2e12891 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/ManagementHttpService.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/ManagementHttpService.java @@ -1,20 +1,20 @@ -package com.jd.blockchain.sdk; - -import com.jd.blockchain.consensus.ClientIdentifications; -import com.jd.blockchain.sdk.converters.BinarySerializeRequestConverter; -import com.jd.blockchain.sdk.converters.BinarySerializeResponseConverter; -import com.jd.blockchain.setting.GatewayIncomingSetting; -import com.jd.blockchain.utils.http.HttpAction; -import com.jd.blockchain.utils.http.HttpMethod; -import com.jd.blockchain.utils.http.HttpService; -import com.jd.blockchain.utils.http.RequestBody; -import com.jd.blockchain.utils.web.client.WebResponseConverterFactory; - - -@HttpService(path="/management", defaultRequestBodyConverter = BinarySerializeRequestConverter.class, responseConverterFactory=WebResponseConverterFactory.class) -public interface ManagementHttpService { - - @HttpAction(method=HttpMethod.POST, path="/gateway/auth", contentType = BinarySerializeRequestConverter.CONTENT_TYPE_VALUE) - public GatewayIncomingSetting authenticateGateway(@RequestBody ClientIdentifications clientIdentifications) ; - -} +package com.jd.blockchain.sdk; + +import com.jd.blockchain.consensus.ClientIdentifications; +import com.jd.blockchain.sdk.converters.BinarySerializeRequestConverter; +import com.jd.blockchain.sdk.converters.BinarySerializeResponseConverter; +import com.jd.blockchain.setting.GatewayIncomingSetting; +import com.jd.blockchain.utils.http.HttpAction; +import com.jd.blockchain.utils.http.HttpMethod; +import com.jd.blockchain.utils.http.HttpService; +import com.jd.blockchain.utils.http.RequestBody; +import com.jd.blockchain.utils.web.client.WebResponseConverterFactory; + + +@HttpService(path="/management", defaultRequestBodyConverter = BinarySerializeRequestConverter.class, responseConverterFactory=WebResponseConverterFactory.class) +public interface ManagementHttpService { + + @HttpAction(method=HttpMethod.POST, path="/gateway/auth", contentType = BinarySerializeRequestConverter.CONTENT_TYPE_VALUE) + public GatewayIncomingSetting authenticateGateway(@RequestBody ClientIdentifications clientIdentifications) ; + +} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/PrivilegeSetting.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/PrivilegeSetting.java index deafc113..a1f1f05f 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/PrivilegeSetting.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/PrivilegeSetting.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.sdk; - -import com.jd.blockchain.ledger.PermissionType; - -/** - * 权限设置;
- * - * - * - * @author huanghaiquan - * - */ -public interface PrivilegeSetting { - - String[] getSigners(); - - long getMask(String address); - - boolean isEnable(String address, PermissionType privilege); - -} +package com.jd.blockchain.sdk; + +import com.jd.blockchain.ledger.PermissionType; + +/** + * 权限设置;
+ * + * + * + * @author huanghaiquan + * + */ +public interface PrivilegeSetting { + + String[] getSigners(); + + long getMask(String address); + + boolean isEnable(String address, PermissionType privilege); + +} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/TxCommiter.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/TxCommiter.java index 94963e19..09d2de7b 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/TxCommiter.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/TxCommiter.java @@ -1,11 +1,11 @@ -//package com.jd.blockchain.sdk; -// -//import com.jd.blockchain.ledger.DigitalSignature; -//import com.jd.blockchain.ledger.TransactionContent; -//import com.jd.blockchain.ledger.TransactionResponse; -// -//public interface TxCommiter { -// -// public TransactionResponse commitTx(TransactionContent txContent, DigitalSignature[] signatures); -// -//} +//package com.jd.blockchain.sdk; +// +//import com.jd.blockchain.ledger.DigitalSignature; +//import com.jd.blockchain.ledger.TransactionContent; +//import com.jd.blockchain.ledger.TransactionResponse; +// +//public interface TxCommiter { +// +// public TransactionResponse commitTx(TransactionContent txContent, DigitalSignature[] signatures); +// +//} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/CodeDeployOperationBuilder.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/CodeDeployOperationBuilder.java index 7a524131..6e73b08b 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/CodeDeployOperationBuilder.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/CodeDeployOperationBuilder.java @@ -1,74 +1,74 @@ -//package com.jd.blockchain.sdk.proxy; -// -//import com.jd.blockchain.ledger.*; -//import com.jd.blockchain.ledger.data.BlockchainOperationFactory; -//import com.jd.blockchain.ledger.data.OpBlob; -//import com.jd.blockchain.ledger.data.PrivilegeSettingOperationBuilder; -//import my.utils.io.ByteArray; -// -//public class CodeDeployOperationBuilder implements CodeDeployOperation { -// -// private TxTemplate txTemp; -// -// public CodeDeployOperationBuilder(TxTemplate txTemp) { -// this.txTemp = txTemp; -// } -// -// /** -// * 修改脚本; -// * -// * @param id -// * @param code 合约代码; -// * @param codeVersion -// */ -// @Override -// public void set(BlockchainIdentity id, String code, long codeVersion) { -// ContractDeployingOperation codeOperation = BlockchainOperationFactory.getInstance().deploy(id, ByteArray.wrap(code.getBytes())); -// -// txTemp.addOperation((OpBlob) codeOperation.getOperation()); -// } -// -// /** -// * 配置特权操作; -// * -// * @param accountAddress 账户地址; -// * @return -// */ -// @Override -// public PrivilegeSettingOperationBuilder configPrivilege(String accountAddress) { -// return null; -// } -// -// /** -// * 执行针对负载类型 {@link AccountStateType}为 {@link AccountStateType#MAP} 的账户操作; -// * -// * @param accountAddress 要操作的账户地址; -// * @return -// */ -// @Override -// public MapStateOperationBuilder updateState(String accountAddress) { -// return null; -// } -// -// /** -// * 执行定义账户的合约脚本的操作; -// * -// * @param accountAddress 要操作的账户地址; -// * @return -// */ -// @Override -// public CodeDeployOperation defineScript(String accountAddress) { -// return null; -// } -// -// /** -// * 执行调用账户的合约脚本的方法的操作; -// * -// * @param accountAddress 要操作的账户地址; -// * @return -// */ -// @Override -// public ScriptInvokingOperation executeScript(String accountAddress) { -// return null; -// } -//} +//package com.jd.blockchain.sdk.proxy; +// +//import com.jd.blockchain.ledger.*; +//import com.jd.blockchain.ledger.data.BlockchainOperationFactory; +//import com.jd.blockchain.ledger.data.OpBlob; +//import com.jd.blockchain.ledger.data.PrivilegeSettingOperationBuilder; +//import my.utils.io.ByteArray; +// +//public class CodeDeployOperationBuilder implements CodeDeployOperation { +// +// private TxTemplate txTemp; +// +// public CodeDeployOperationBuilder(TxTemplate txTemp) { +// this.txTemp = txTemp; +// } +// +// /** +// * 修改脚本; +// * +// * @param id +// * @param code 合约代码; +// * @param codeVersion +// */ +// @Override +// public void set(BlockchainIdentity id, String code, long codeVersion) { +// ContractDeployingOperation codeOperation = BlockchainOperationFactory.getInstance().deploy(id, ByteArray.wrap(code.getBytes())); +// +// txTemp.addOperation((OpBlob) codeOperation.getOperation()); +// } +// +// /** +// * 配置特权操作; +// * +// * @param accountAddress 账户地址; +// * @return +// */ +// @Override +// public PrivilegeSettingOperationBuilder configPrivilege(String accountAddress) { +// return null; +// } +// +// /** +// * 执行针对负载类型 {@link AccountStateType}为 {@link AccountStateType#MAP} 的账户操作; +// * +// * @param accountAddress 要操作的账户地址; +// * @return +// */ +// @Override +// public MapStateOperationBuilder updateState(String accountAddress) { +// return null; +// } +// +// /** +// * 执行定义账户的合约脚本的操作; +// * +// * @param accountAddress 要操作的账户地址; +// * @return +// */ +// @Override +// public CodeDeployOperation defineScript(String accountAddress) { +// return null; +// } +// +// /** +// * 执行调用账户的合约脚本的方法的操作; +// * +// * @param accountAddress 要操作的账户地址; +// * @return +// */ +// @Override +// public ScriptInvokingOperation executeScript(String accountAddress) { +// return null; +// } +//} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/CodeInvokeOperationBuilder.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/CodeInvokeOperationBuilder.java index 8e5958c7..a925fc15 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/CodeInvokeOperationBuilder.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/CodeInvokeOperationBuilder.java @@ -1,73 +1,73 @@ -//package com.jd.blockchain.sdk.proxy; -// -//import com.jd.blockchain.ledger.CodeDeployOperation; -//import com.jd.blockchain.ledger.ContractEventOperation; -//import com.jd.blockchain.ledger.MapStateOperationBuilder; -//import com.jd.blockchain.ledger.ScriptInvokingOperation; -//import com.jd.blockchain.ledger.data.BlockchainOperationFactory; -//import com.jd.blockchain.ledger.data.OpBlob; -//import com.jd.blockchain.ledger.data.PrivilegeSettingOperationBuilder; -// -//import my.utils.io.ByteArray; -// -//public class CodeInvokeOperationBuilder implements ScriptInvokingOperation { -// private TxTemplate txTemp; -// -// public CodeInvokeOperationBuilder(TxTemplate txTemp) { -// this.txTemp = txTemp; -// } -// -// @Override -// public void invoke(String address, String[] args) { -// ContractEventOperation operation = BlockchainOperationFactory.getInstance().event(address, new ByteArray[] {}); -// -// txTemp.addOperation((OpBlob) operation.getOperation()); -// } -// -// /** -// * 配置特权操作; -// * -// * @param accountAddress -// * 账户地址; -// * @return -// */ -// @Override -// public PrivilegeSettingOperationBuilder configPrivilege(String accountAddress) { -// return null; -// } -// -// /** -// * -// * @param accountAddress -// * 要操作的账户地址; -// * @return -// */ -// @Override -// public MapStateOperationBuilder updateState(String accountAddress) { -// return null; -// } -// -// /** -// * 执行定义账户的合约脚本的操作; -// * -// * @param accountAddress -// * 要操作的账户地址; -// * @return -// */ -// @Override -// public CodeDeployOperation defineScript(String accountAddress) { -// return null; -// } -// -// /** -// * 执行调用账户的合约脚本的方法的操作; -// * -// * @param accountAddress -// * 要操作的账户地址; -// * @return -// */ -// @Override -// public ScriptInvokingOperation executeScript(String accountAddress) { -// return null; -// } -//} +//package com.jd.blockchain.sdk.proxy; +// +//import com.jd.blockchain.ledger.CodeDeployOperation; +//import com.jd.blockchain.ledger.ContractEventOperation; +//import com.jd.blockchain.ledger.MapStateOperationBuilder; +//import com.jd.blockchain.ledger.ScriptInvokingOperation; +//import com.jd.blockchain.ledger.data.BlockchainOperationFactory; +//import com.jd.blockchain.ledger.data.OpBlob; +//import com.jd.blockchain.ledger.data.PrivilegeSettingOperationBuilder; +// +//import my.utils.io.ByteArray; +// +//public class CodeInvokeOperationBuilder implements ScriptInvokingOperation { +// private TxTemplate txTemp; +// +// public CodeInvokeOperationBuilder(TxTemplate txTemp) { +// this.txTemp = txTemp; +// } +// +// @Override +// public void invoke(String address, String[] args) { +// ContractEventOperation operation = BlockchainOperationFactory.getInstance().event(address, new ByteArray[] {}); +// +// txTemp.addOperation((OpBlob) operation.getOperation()); +// } +// +// /** +// * 配置特权操作; +// * +// * @param accountAddress +// * 账户地址; +// * @return +// */ +// @Override +// public PrivilegeSettingOperationBuilder configPrivilege(String accountAddress) { +// return null; +// } +// +// /** +// * +// * @param accountAddress +// * 要操作的账户地址; +// * @return +// */ +// @Override +// public MapStateOperationBuilder updateState(String accountAddress) { +// return null; +// } +// +// /** +// * 执行定义账户的合约脚本的操作; +// * +// * @param accountAddress +// * 要操作的账户地址; +// * @return +// */ +// @Override +// public CodeDeployOperation defineScript(String accountAddress) { +// return null; +// } +// +// /** +// * 执行调用账户的合约脚本的方法的操作; +// * +// * @param accountAddress +// * 要操作的账户地址; +// * @return +// */ +// @Override +// public ScriptInvokingOperation executeScript(String accountAddress) { +// return null; +// } +//} diff --git a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpQueryServiceAdapter.java b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpQueryServiceAdapter.java index cb44c64f..0fccc12b 100644 --- a/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpQueryServiceAdapter.java +++ b/source/sdk/sdk-base/src/main/java/com/jd/blockchain/sdk/proxy/HttpQueryServiceAdapter.java @@ -1,136 +1,136 @@ -//package com.jd.blockchain.sdk.proxy; -// -//import java.util.Map; -//import java.util.Set; -// -//import org.springframework.util.Base64Utils; -// -//import com.jd.blockchain.ledger.Block; -//import com.jd.blockchain.ledger.BlockchainAccount; -//import com.jd.blockchain.ledger.Ledger; -//import com.jd.blockchain.ledger.StateMap; -//import com.jd.blockchain.ledger.Transaction; -//import com.jd.blockchain.sdk.BlockchainQueryService; -//import com.jd.blockchain.service.LedgerQueryHttpService; -// -//import my.utils.http.agent.HttpServiceAgent; -//import my.utils.http.agent.ServiceEndpoint; -//import my.utils.net.NetworkAddress; -//import my.utils.serialize.binary.BinarySerializeUtils; -// -//public class HttpQueryServiceAdapter implements BlockchainQueryService { -// -// private LedgerQueryHttpService queryHttpService; -// -// public HttpQueryServiceAdapter(NetworkAddress serviceAddress) { -// ServiceEndpoint endpoint = new ServiceEndpoint(serviceAddress); -// this.queryHttpService = HttpServiceAgent.createService(LedgerQueryHttpService.class, endpoint); -// } -// -// @Override -// public String[] getAllLedgerHashs() { -// // TODO Auto-generated method stub -// return null; -// } -// -// @Override -// public Ledger getLedger(String ledgerHash) { -// return decodeObject(queryHttpService.getLedger(ledgerHash), Ledger.class); -// } -// -// @Override -// public Block getBlock(String ledgerHash, long height) { -// return decodeObject(queryHttpService.getBlock(ledgerHash, height), Block.class); -// } -// -// /** -// * 返回指定账本序号的区块; -// * -// * @param ledgerHash -// * 账本hash; -// * @param blockHash -// * @return -// */ -// @Override -// public Block getBlock(String ledgerHash, String blockHash) { -// return decodeObject(queryHttpService.getBlock(ledgerHash, blockHash), Block.class); -// } -// -// @Override -// public Transaction[] getTransactions(String ledgerHash, long height, int fromIndex, int count) { -// return decodeObject(queryHttpService.getBlockTransactions(height), Transaction[].class); -// } -// -// /** -// * 分页返回指定账本序号的区块中的交易列表; -// * -// * @param ledgerHash -// * 账本hash; -// * @param blockHash -// * 账本高度; -// * @param fromIndex -// * 开始的记录数; -// * @param count -// * 本次返回的记录数;
-// * 如果参数值为 -1,则返回全部的记录;
-// * 注:通过 {@link #getBlock(String, String)} 方法获得的区块信息中可以得到区块的总交易数 -// * {@link Block#getTxCount()}; -// * @return -// */ -// @Override -// public Transaction[] getTransactions(String ledgerHash, String blockHash, int fromIndex, int count) { -// return decodeObject(queryHttpService.getBlockTransactions(ledgerHash, blockHash, fromIndex, count), -// Transaction[].class); -// } -// -// @Override -// public Transaction getTransactionByTxHash(String ledgerHash, String txHash) { -// return decodeObject(queryHttpService.getBlockTransactionByTxHash(ledgerHash, txHash), Transaction.class); -// } -// -// @Override -// public Transaction getTransactionByContentHash(String ledgerHash, String contentHash) { -// return decodeObject(queryHttpService.getBlockTransactionByContentHash(ledgerHash, contentHash), -// Transaction.class); -// } -// -// @Override -// public BlockchainAccount getAccount(String ledgerHash, String address) { -// return decodeObject(queryHttpService.getAccount(ledgerHash, address), BlockchainAccount.class); -// } -// -// @Override -// public StateMap getStates(String ledgerHash, String address, Set keys) { -// // TODO Auto-generated method stub -// return null; -// } -// -// public StateMap getState(String ledgerHash, String address, String keys) { -// return decodeObject(queryHttpService.getAccountState(ledgerHash,address, keys), StateMap.class); -// } -// -// @Override -// public StateMap queryObject(String ledgerHash, String address, String condition) { -// // TODO Auto-generated method stub -// return null; -// } -// -// @Override -// public Map queryObject(String ledgerHash, String condition) { -// // TODO Auto-generated method stub -// return null; -// } -// -// @Override -// public boolean containState(String ledgerHash, String address, String key) { -// // TODO Auto-generated method stub -// return false; -// } -// -// @SuppressWarnings("unchecked") -// private T decodeObject(String base64Str, Class clazz) { -// byte[] bts = Base64Utils.decodeFromString(base64Str); -// return (T) BinarySerializeUtils.deserialize(bts); -// } -// -//} +//package com.jd.blockchain.sdk.proxy; +// +//import java.util.Map; +//import java.util.Set; +// +//import org.springframework.util.Base64Utils; +// +//import com.jd.blockchain.ledger.Block; +//import com.jd.blockchain.ledger.BlockchainAccount; +//import com.jd.blockchain.ledger.Ledger; +//import com.jd.blockchain.ledger.StateMap; +//import com.jd.blockchain.ledger.Transaction; +//import com.jd.blockchain.sdk.BlockchainQueryService; +//import com.jd.blockchain.service.LedgerQueryHttpService; +// +//import my.utils.http.agent.HttpServiceAgent; +//import my.utils.http.agent.ServiceEndpoint; +//import my.utils.net.NetworkAddress; +//import my.utils.serialize.binary.BinarySerializeUtils; +// +//public class HttpQueryServiceAdapter implements BlockchainQueryService { +// +// private LedgerQueryHttpService queryHttpService; +// +// public HttpQueryServiceAdapter(NetworkAddress serviceAddress) { +// ServiceEndpoint endpoint = new ServiceEndpoint(serviceAddress); +// this.queryHttpService = HttpServiceAgent.createService(LedgerQueryHttpService.class, endpoint); +// } +// +// @Override +// public String[] getAllLedgerHashs() { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public Ledger getLedger(String ledgerHash) { +// return decodeObject(queryHttpService.getLedger(ledgerHash), Ledger.class); +// } +// +// @Override +// public Block getBlock(String ledgerHash, long height) { +// return decodeObject(queryHttpService.getBlock(ledgerHash, height), Block.class); +// } +// +// /** +// * 返回指定账本序号的区块; +// * +// * @param ledgerHash +// * 账本hash; +// * @param blockHash +// * @return +// */ +// @Override +// public Block getBlock(String ledgerHash, String blockHash) { +// return decodeObject(queryHttpService.getBlock(ledgerHash, blockHash), Block.class); +// } +// +// @Override +// public Transaction[] getTransactions(String ledgerHash, long height, int fromIndex, int count) { +// return decodeObject(queryHttpService.getBlockTransactions(height), Transaction[].class); +// } +// +// /** +// * 分页返回指定账本序号的区块中的交易列表; +// * +// * @param ledgerHash +// * 账本hash; +// * @param blockHash +// * 账本高度; +// * @param fromIndex +// * 开始的记录数; +// * @param count +// * 本次返回的记录数;
+// * 如果参数值为 -1,则返回全部的记录;
+// * 注:通过 {@link #getBlock(String, String)} 方法获得的区块信息中可以得到区块的总交易数 +// * {@link Block#getTxCount()}; +// * @return +// */ +// @Override +// public Transaction[] getTransactions(String ledgerHash, String blockHash, int fromIndex, int count) { +// return decodeObject(queryHttpService.getBlockTransactions(ledgerHash, blockHash, fromIndex, count), +// Transaction[].class); +// } +// +// @Override +// public Transaction getTransactionByTxHash(String ledgerHash, String txHash) { +// return decodeObject(queryHttpService.getBlockTransactionByTxHash(ledgerHash, txHash), Transaction.class); +// } +// +// @Override +// public Transaction getTransactionByContentHash(String ledgerHash, String contentHash) { +// return decodeObject(queryHttpService.getBlockTransactionByContentHash(ledgerHash, contentHash), +// Transaction.class); +// } +// +// @Override +// public BlockchainAccount getAccount(String ledgerHash, String address) { +// return decodeObject(queryHttpService.getAccount(ledgerHash, address), BlockchainAccount.class); +// } +// +// @Override +// public StateMap getStates(String ledgerHash, String address, Set keys) { +// // TODO Auto-generated method stub +// return null; +// } +// +// public StateMap getState(String ledgerHash, String address, String keys) { +// return decodeObject(queryHttpService.getAccountState(ledgerHash,address, keys), StateMap.class); +// } +// +// @Override +// public StateMap queryObject(String ledgerHash, String address, String condition) { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public Map queryObject(String ledgerHash, String condition) { +// // TODO Auto-generated method stub +// return null; +// } +// +// @Override +// public boolean containState(String ledgerHash, String address, String key) { +// // TODO Auto-generated method stub +// return false; +// } +// +// @SuppressWarnings("unchecked") +// private T decodeObject(String base64Str, Class clazz) { +// byte[] bts = Base64Utils.decodeFromString(base64Str); +// return (T) BinarySerializeUtils.deserialize(bts); +// } +// +//} diff --git a/source/sdk/sdk-base/src/test/java/test/com/jd/blockchain/sdk/proxy/TxMessageTest.java b/source/sdk/sdk-base/src/test/java/test/com/jd/blockchain/sdk/proxy/TxMessageTest.java index 650b6fd2..794f437b 100644 --- a/source/sdk/sdk-base/src/test/java/test/com/jd/blockchain/sdk/proxy/TxMessageTest.java +++ b/source/sdk/sdk-base/src/test/java/test/com/jd/blockchain/sdk/proxy/TxMessageTest.java @@ -1,64 +1,64 @@ -package test.com.jd.blockchain.sdk.proxy; - -//public class TxMessageTest { -// -// @Test -// public void testSerialize() throws IOException { -// BlockchainKeyPair id = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); -// BlockchainKeyPair id1 = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); -// BlockchainKeyPair id2 = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); -// -// TxContentBlob contentBlob = new TxContentBlob(); -// -// contentBlob.setSubjectAccount(id.getAddress()); -// contentBlob.setSequenceNumber(1); -// -// OpBlob op1 = new OpBlob(); -// op1.setOperation(OperationType.REGISTER_USER.CODE, ByteArray.parseString("AAA", "UTF-8")); -// contentBlob.addOperation(op1); -// -// TxRequestMessage txMsg = new TxRequestMessage(contentBlob); -// -// ByteArray mockedDigest = ByteArray.wrap(RandomUtils.generateRandomBytes(32)); -// DigitalSignatureBlob signature = new DigitalSignatureBlob(id.getPubKey(), mockedDigest); -// txMsg.addEndpointSignatures(signature); -// -// ByteArray mockedDigest1 = ByteArray.wrap(RandomUtils.generateRandomBytes(32)); -// DigitalSignatureBlob signature1 = new DigitalSignatureBlob(id1.getPubKey(), mockedDigest1); -// txMsg.addEndpointSignatures(signature1); -// -// ByteArray mockedDigest2 = ByteArray.wrap(RandomUtils.generateRandomBytes(32)); -// DigitalSignatureBlob signature2 = new DigitalSignatureBlob(id2.getPubKey(), mockedDigest2); -// txMsg.addNodeSignatures(signature2); -// -// // 输出; -// byte[] msgBytes = BinaryEncodingUtils.encode(txMsg, TransactionRequest.class); -// -// assertEquals(MagicNumber.TX_REQUEST, msgBytes[0]); -// -//// TxRequestMessage resolvedTxMsg = new TxRequestMessage(); -//// resolvedTxMsg.resolvFrom(ByteArray.wrap(msgBytes).asInputStream()); -// TxRequestMessage resolvedTxMsg = BinaryEncodingUtils.decode(msgBytes, null, TxRequestMessage.class); -// -// assertEquals(txMsg.getTransactionContent().getSubjectAccount(), -// resolvedTxMsg.getTransactionContent().getSubjectAccount()); -// assertEquals(txMsg.getTransactionContent().getHash(), resolvedTxMsg.getTransactionContent().getHash()); -// assertEquals(txMsg.getHash(), resolvedTxMsg.getHash()); -// -// DigitalSignature[] pSignatures = txMsg.getEndpointSignatures(); -// DigitalSignature[] resolvedPSignatures = txMsg.getEndpointSignatures(); -// assertEquals(pSignatures.length, resolvedPSignatures.length); -// for (int i = 0; i < resolvedPSignatures.length; i++) { -// assertEquals(pSignatures[i].getPubKey().getType(), resolvedPSignatures[i].getPubKey().getType()); -// assertEquals(pSignatures[i].getPubKey().getValue(), resolvedPSignatures[i].getPubKey().getValue()); -// assertEquals(pSignatures[i].getDigest(), resolvedPSignatures[i].getDigest()); -// } -// -// assertEquals(txMsg.getNodeSignatures()[0].getPubKey().getType(), -// resolvedTxMsg.getNodeSignatures()[0].getPubKey().getType()); -// assertEquals(txMsg.getNodeSignatures()[0].getPubKey().getValue(), -// resolvedTxMsg.getNodeSignatures()[0].getPubKey().getValue()); -// assertEquals(txMsg.getNodeSignatures()[0].getDigest(), resolvedTxMsg.getNodeSignatures()[0].getDigest()); -// } -// -//} +package test.com.jd.blockchain.sdk.proxy; + +//public class TxMessageTest { +// +// @Test +// public void testSerialize() throws IOException { +// BlockchainKeyPair id = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); +// BlockchainKeyPair id1 = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); +// BlockchainKeyPair id2 = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); +// +// TxContentBlob contentBlob = new TxContentBlob(); +// +// contentBlob.setSubjectAccount(id.getAddress()); +// contentBlob.setSequenceNumber(1); +// +// OpBlob op1 = new OpBlob(); +// op1.setOperation(OperationType.REGISTER_USER.CODE, ByteArray.parseString("AAA", "UTF-8")); +// contentBlob.addOperation(op1); +// +// TxRequestMessage txMsg = new TxRequestMessage(contentBlob); +// +// ByteArray mockedDigest = ByteArray.wrap(RandomUtils.generateRandomBytes(32)); +// DigitalSignatureBlob signature = new DigitalSignatureBlob(id.getPubKey(), mockedDigest); +// txMsg.addEndpointSignatures(signature); +// +// ByteArray mockedDigest1 = ByteArray.wrap(RandomUtils.generateRandomBytes(32)); +// DigitalSignatureBlob signature1 = new DigitalSignatureBlob(id1.getPubKey(), mockedDigest1); +// txMsg.addEndpointSignatures(signature1); +// +// ByteArray mockedDigest2 = ByteArray.wrap(RandomUtils.generateRandomBytes(32)); +// DigitalSignatureBlob signature2 = new DigitalSignatureBlob(id2.getPubKey(), mockedDigest2); +// txMsg.addNodeSignatures(signature2); +// +// // 输出; +// byte[] msgBytes = BinaryEncodingUtils.encode(txMsg, TransactionRequest.class); +// +// assertEquals(MagicNumber.TX_REQUEST, msgBytes[0]); +// +//// TxRequestMessage resolvedTxMsg = new TxRequestMessage(); +//// resolvedTxMsg.resolvFrom(ByteArray.wrap(msgBytes).asInputStream()); +// TxRequestMessage resolvedTxMsg = BinaryEncodingUtils.decode(msgBytes, null, TxRequestMessage.class); +// +// assertEquals(txMsg.getTransactionContent().getSubjectAccount(), +// resolvedTxMsg.getTransactionContent().getSubjectAccount()); +// assertEquals(txMsg.getTransactionContent().getHash(), resolvedTxMsg.getTransactionContent().getHash()); +// assertEquals(txMsg.getHash(), resolvedTxMsg.getHash()); +// +// DigitalSignature[] pSignatures = txMsg.getEndpointSignatures(); +// DigitalSignature[] resolvedPSignatures = txMsg.getEndpointSignatures(); +// assertEquals(pSignatures.length, resolvedPSignatures.length); +// for (int i = 0; i < resolvedPSignatures.length; i++) { +// assertEquals(pSignatures[i].getPubKey().getType(), resolvedPSignatures[i].getPubKey().getType()); +// assertEquals(pSignatures[i].getPubKey().getValue(), resolvedPSignatures[i].getPubKey().getValue()); +// assertEquals(pSignatures[i].getDigest(), resolvedPSignatures[i].getDigest()); +// } +// +// assertEquals(txMsg.getNodeSignatures()[0].getPubKey().getType(), +// resolvedTxMsg.getNodeSignatures()[0].getPubKey().getType()); +// assertEquals(txMsg.getNodeSignatures()[0].getPubKey().getValue(), +// resolvedTxMsg.getNodeSignatures()[0].getPubKey().getValue()); +// assertEquals(txMsg.getNodeSignatures()[0].getDigest(), resolvedTxMsg.getNodeSignatures()[0].getDigest()); +// } +// +//} diff --git a/source/sdk/sdk-client/pom.xml b/source/sdk/sdk-client/pom.xml index e2e995f4..22b2c53b 100644 --- a/source/sdk/sdk-client/pom.xml +++ b/source/sdk/sdk-client/pom.xml @@ -1,24 +1,24 @@ - - 4.0.0 - - com.jd.blockchain - sdk - 1.1.2.RELEASE - - sdk-client - - - - com.jd.blockchain - sdk-base - ${project.version} - - - - com.jd.blockchain - ledger-rpc - ${project.version} - - + + 4.0.0 + + com.jd.blockchain + sdk + 1.1.2.RELEASE + + sdk-client + + + + com.jd.blockchain + sdk-base + ${project.version} + + + + com.jd.blockchain + ledger-rpc + ${project.version} + + \ No newline at end of file diff --git a/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayIncomingInfo.java b/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayIncomingInfo.java index c59d314a..9af45ef7 100644 --- a/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayIncomingInfo.java +++ b/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayIncomingInfo.java @@ -1,37 +1,37 @@ -package com.jd.blockchain.sdk.client; - -import java.io.Serializable; - -import com.jd.blockchain.utils.net.NetworkAddress; - -/** - * 网关接入信息; - * - * @author huanghaiquan - * - */ -public class GatewayIncomingInfo implements Serializable { - - private static final long serialVersionUID = 981081410237759756L; - - private String sessionId; - - private NetworkAddress queryServiceAddress; - - public String getSessionId() { - return sessionId; - } - - public void setSessionId(String sessionId) { - this.sessionId = sessionId; - } - - public NetworkAddress getQueryServiceAddress() { - return queryServiceAddress; - } - - public void setQueryServiceAddress(NetworkAddress queryServiceAddress) { - this.queryServiceAddress = queryServiceAddress; - } - -} +package com.jd.blockchain.sdk.client; + +import java.io.Serializable; + +import com.jd.blockchain.utils.net.NetworkAddress; + +/** + * 网关接入信息; + * + * @author huanghaiquan + * + */ +public class GatewayIncomingInfo implements Serializable { + + private static final long serialVersionUID = 981081410237759756L; + + private String sessionId; + + private NetworkAddress queryServiceAddress; + + public String getSessionId() { + return sessionId; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public NetworkAddress getQueryServiceAddress() { + return queryServiceAddress; + } + + public void setQueryServiceAddress(NetworkAddress queryServiceAddress) { + this.queryServiceAddress = queryServiceAddress; + } + +} diff --git a/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java b/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java index 1d50d1d7..b13b941f 100644 --- a/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java +++ b/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/GatewayServiceFactory.java @@ -1,225 +1,225 @@ -package com.jd.blockchain.sdk.client; - -import java.io.Closeable; - -import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.consensus.ClientIdentification; -import com.jd.blockchain.consensus.ClientIdentifications; -import com.jd.blockchain.consensus.action.ActionRequest; -import com.jd.blockchain.consensus.action.ActionResponse; -import com.jd.blockchain.crypto.Crypto; -import com.jd.blockchain.crypto.PrivKey; -import com.jd.blockchain.crypto.SignatureDigest; -import com.jd.blockchain.crypto.SignatureFunction; -import com.jd.blockchain.ledger.*; -import com.jd.blockchain.sdk.BlockchainService; -import com.jd.blockchain.sdk.BlockchainServiceFactory; -import com.jd.blockchain.sdk.proxy.HttpBlockchainQueryService; -import com.jd.blockchain.transaction.*; -import com.jd.blockchain.utils.http.agent.HttpServiceAgent; -import com.jd.blockchain.utils.http.agent.ServiceConnection; -import com.jd.blockchain.utils.http.agent.ServiceConnectionManager; -import com.jd.blockchain.utils.http.agent.ServiceEndpoint; -import com.jd.blockchain.utils.net.NetworkAddress; -import com.jd.blockchain.web.serializes.ByteArrayObjectUtil; - -public class GatewayServiceFactory implements BlockchainServiceFactory, Closeable { - - private ServiceConnectionManager httpConnectionManager; - - private BlockchainKeypair userKey; - - private BlockchainService blockchainService; - - static { - DataContractRegistry.register(TransactionContent.class); - DataContractRegistry.register(TransactionContentBody.class); - DataContractRegistry.register(TransactionRequest.class); - DataContractRegistry.register(NodeRequest.class); - DataContractRegistry.register(EndpointRequest.class); - DataContractRegistry.register(TransactionResponse.class); - DataContractRegistry.register(DataAccountKVSetOperation.class); - DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); - - DataContractRegistry.register(Operation.class); - DataContractRegistry.register(ContractCodeDeployOperation.class); - DataContractRegistry.register(ContractEventSendOperation.class); - DataContractRegistry.register(DataAccountRegisterOperation.class); - DataContractRegistry.register(UserRegisterOperation.class); - DataContractRegistry.register(ParticipantRegisterOperation.class); - DataContractRegistry.register(ParticipantStateUpdateOperation.class); - - DataContractRegistry.register(ActionRequest.class); - DataContractRegistry.register(ActionResponse.class); - DataContractRegistry.register(ClientIdentifications.class); - DataContractRegistry.register(ClientIdentification.class); - DataContractRegistry.register(BytesValueList.class); - - // 注册角色/权限相关接口 - DataContractRegistry.register(RolesConfigureOperation.class); - DataContractRegistry.register(RolesConfigureOperation.RolePrivilegeEntry.class); - DataContractRegistry.register(UserAuthorizeOperation.class); - DataContractRegistry.register(UserAuthorizeOperation.UserRolesEntry.class); - DataContractRegistry.register(PrivilegeSet.class); - DataContractRegistry.register(RoleSet.class); - DataContractRegistry.register(SecurityInitSettings.class); - DataContractRegistry.register(RoleInitSettings.class); - DataContractRegistry.register(UserAuthInitSettings.class); - DataContractRegistry.register(LedgerMetadata_V2.class); - - ByteArrayObjectUtil.init(); - } - - protected GatewayServiceFactory(ServiceEndpoint gatewayEndpoint, BlockchainKeypair userKey) { - httpConnectionManager = new ServiceConnectionManager(); - this.userKey = userKey; - - BlockchainQueryService queryService = createQueryService(gatewayEndpoint); - TransactionService txProcSrv = createConsensusService(gatewayEndpoint); - this.blockchainService = new GatewayBlockchainServiceProxy(txProcSrv, queryService); - } - - @Override - public BlockchainService getBlockchainService() { - return blockchainService; - } - - // TODO:暂未实现基于“口令”的认证方式; - /** - * 基于“口令”连接; - * - * @param gatewayHost - * @param gatewayPort - * @param secure - * @param userName - * @param password - * @return - */ - // public static BlockchainServiceFactory connect(String gatewayHost, int - // gatewayPort, boolean secure, String userName, - // String password) { - // ServiceEndpoint gatewayEndpoint = new ServiceEndpoint(gatewayHost, - // gatewayPort, secure); - // BlockchainServiceFactory factory = new - // BlockchainServiceFactory(gatewayEndpoint); - // factory.setMaxConnections(100); - // return factory; - // } - - /** - * 连接网关节点; - * - * @param gatewayAddress 网关节点的网络地址; - * @return 网关服务工厂的实例; - */ - public static GatewayServiceFactory connect(NetworkAddress gatewayAddress) { - return connect(gatewayAddress.getHost(), gatewayAddress.getPort(), gatewayAddress.isSecure(), null); - } - - /** - * 网关服务工厂的实例; - * - * @param gatewayAddress 网关节点的网络地址; - * @param userKey 自动交易签名的用户密钥;可选参数,如果不为 null,则在提交交易时,自动以参数指定的密钥签署交易; - * @return 网关服务工厂的实例; - */ - public static GatewayServiceFactory connect(NetworkAddress gatewayAddress, BlockchainKeypair userKey) { - return connect(gatewayAddress.getHost(), gatewayAddress.getPort(), gatewayAddress.isSecure(), userKey); - } - - /** - * 连接网关节点; - * - * @param gatewayHost 网关节点的地址; - * @param gatewayPort 网关节点的端口; - * @param secure 是否采用安全的通讯协议(HTTPS); - * @return 网关服务工厂的实例; - */ - public static GatewayServiceFactory connect(String gatewayHost, int gatewayPort, boolean secure) { - return connect(gatewayHost, gatewayPort, secure, null); - } - - /** - * 连接网关节点; - * - * @param gatewayHost 网关节点的地址; - * @param gatewayPort 网关节点的端口; - * @param secure 是否采用安全的通讯协议(HTTPS); - * @param userKey 自动交易签名的用户密钥;可选参数,如果不为 null,则在提交交易时,自动以参数指定的密钥签署交易; - * @return 网关服务工厂的实例; - */ - public static GatewayServiceFactory connect(String gatewayHost, int gatewayPort, boolean secure, - BlockchainKeypair userKey) { -// if (userKey == null) { -// throw new IllegalArgumentException("User key is null!"); -// } - ServiceEndpoint gatewayEndpoint = new ServiceEndpoint(gatewayHost, gatewayPort, secure); - GatewayServiceFactory factory = new GatewayServiceFactory(gatewayEndpoint, userKey); - factory.setMaxConnections(100); - // TODO: 未实现网关对用户的认证; - // TODO: 未实现加载不同账本的密码算法配置; - return factory; - } - - public void setMaxConnections(int maxCount) { - httpConnectionManager.setMaxTotal(maxCount).setDefaultMaxPerRoute(maxCount); - } - - private TransactionService createConsensusService(ServiceEndpoint gatewayEndpoint) { - ServiceConnection connection = httpConnectionManager.create(gatewayEndpoint); - TransactionService gatewayConsensusService = HttpServiceAgent.createService(HttpConsensusService.class, - connection, null); - if (userKey != null) { - gatewayConsensusService = new EndpointAutoSigner(gatewayConsensusService, userKey); - } - return gatewayConsensusService; - } - - private BlockchainQueryService createQueryService(ServiceEndpoint gatewayEndpoint) { - ServiceConnection conn = httpConnectionManager.create(gatewayEndpoint); - return HttpServiceAgent.createService(HttpBlockchainQueryService.class, conn, null); - } - - @Override - public void close() { - httpConnectionManager.close(); - } - - private static class EndpointAutoSigner implements TransactionService { - - private TransactionService innerService; - - private BlockchainKeypair userKey; - - public EndpointAutoSigner(TransactionService innerService, BlockchainKeypair userKey) { - this.innerService = innerService; - this.userKey = userKey; - } - - @Override - public TransactionResponse process(TransactionRequest txRequest) { - TxRequestMessage reqMsg = (TxRequestMessage) txRequest; - // TODO: 未实现按不同的账本的密码参数配置,采用不同的哈希算法和签名算法; - if (!reqMsg.containsEndpointSignature(userKey.getAddress())) { - // TODO: 优化上下文对此 TransactionContent 的多次序列化带来的额外性能开销; - DigitalSignature signature = SignatureUtils.sign(txRequest.getTransactionContent(), userKey); - reqMsg.addEndpointSignatures(signature); -// -// -// -// byte[] txContentBytes = BinaryProtocol.encode(txRequest.getTransactionContent(), -// TransactionContent.class); -// PrivKey userPrivKey = userKey.getPrivKey(); -// SignatureFunction signatureFunction = Crypto.getSignatureFunction(userKey.getAlgorithm()); -// if (signatureFunction != null) { -// SignatureDigest signatureDigest = signatureFunction.sign(userPrivKey, txContentBytes); -// DigitalSignature signature = new DigitalSignatureBlob(userKey.getPubKey(), signatureDigest); -// reqMsg.addEndpointSignatures(signature); -// } - } - return innerService.process(txRequest); - } - } - -} +package com.jd.blockchain.sdk.client; + +import java.io.Closeable; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.consensus.ClientIdentification; +import com.jd.blockchain.consensus.ClientIdentifications; +import com.jd.blockchain.consensus.action.ActionRequest; +import com.jd.blockchain.consensus.action.ActionResponse; +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.PrivKey; +import com.jd.blockchain.crypto.SignatureDigest; +import com.jd.blockchain.crypto.SignatureFunction; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.sdk.BlockchainService; +import com.jd.blockchain.sdk.BlockchainServiceFactory; +import com.jd.blockchain.sdk.proxy.HttpBlockchainQueryService; +import com.jd.blockchain.transaction.*; +import com.jd.blockchain.utils.http.agent.HttpServiceAgent; +import com.jd.blockchain.utils.http.agent.ServiceConnection; +import com.jd.blockchain.utils.http.agent.ServiceConnectionManager; +import com.jd.blockchain.utils.http.agent.ServiceEndpoint; +import com.jd.blockchain.utils.net.NetworkAddress; +import com.jd.blockchain.web.serializes.ByteArrayObjectUtil; + +public class GatewayServiceFactory implements BlockchainServiceFactory, Closeable { + + private ServiceConnectionManager httpConnectionManager; + + private BlockchainKeypair userKey; + + private BlockchainService blockchainService; + + static { + DataContractRegistry.register(TransactionContent.class); + DataContractRegistry.register(TransactionContentBody.class); + DataContractRegistry.register(TransactionRequest.class); + DataContractRegistry.register(NodeRequest.class); + DataContractRegistry.register(EndpointRequest.class); + DataContractRegistry.register(TransactionResponse.class); + DataContractRegistry.register(DataAccountKVSetOperation.class); + DataContractRegistry.register(DataAccountKVSetOperation.KVWriteEntry.class); + + DataContractRegistry.register(Operation.class); + DataContractRegistry.register(ContractCodeDeployOperation.class); + DataContractRegistry.register(ContractEventSendOperation.class); + DataContractRegistry.register(DataAccountRegisterOperation.class); + DataContractRegistry.register(UserRegisterOperation.class); + DataContractRegistry.register(ParticipantRegisterOperation.class); + DataContractRegistry.register(ParticipantStateUpdateOperation.class); + + DataContractRegistry.register(ActionRequest.class); + DataContractRegistry.register(ActionResponse.class); + DataContractRegistry.register(ClientIdentifications.class); + DataContractRegistry.register(ClientIdentification.class); + DataContractRegistry.register(BytesValueList.class); + + // 注册角色/权限相关接口 + DataContractRegistry.register(RolesConfigureOperation.class); + DataContractRegistry.register(RolesConfigureOperation.RolePrivilegeEntry.class); + DataContractRegistry.register(UserAuthorizeOperation.class); + DataContractRegistry.register(UserAuthorizeOperation.UserRolesEntry.class); + DataContractRegistry.register(PrivilegeSet.class); + DataContractRegistry.register(RoleSet.class); + DataContractRegistry.register(SecurityInitSettings.class); + DataContractRegistry.register(RoleInitSettings.class); + DataContractRegistry.register(UserAuthInitSettings.class); + DataContractRegistry.register(LedgerMetadata_V2.class); + + ByteArrayObjectUtil.init(); + } + + protected GatewayServiceFactory(ServiceEndpoint gatewayEndpoint, BlockchainKeypair userKey) { + httpConnectionManager = new ServiceConnectionManager(); + this.userKey = userKey; + + BlockchainQueryService queryService = createQueryService(gatewayEndpoint); + TransactionService txProcSrv = createConsensusService(gatewayEndpoint); + this.blockchainService = new GatewayBlockchainServiceProxy(txProcSrv, queryService); + } + + @Override + public BlockchainService getBlockchainService() { + return blockchainService; + } + + // TODO:暂未实现基于“口令”的认证方式; + /** + * 基于“口令”连接; + * + * @param gatewayHost + * @param gatewayPort + * @param secure + * @param userName + * @param password + * @return + */ + // public static BlockchainServiceFactory connect(String gatewayHost, int + // gatewayPort, boolean secure, String userName, + // String password) { + // ServiceEndpoint gatewayEndpoint = new ServiceEndpoint(gatewayHost, + // gatewayPort, secure); + // BlockchainServiceFactory factory = new + // BlockchainServiceFactory(gatewayEndpoint); + // factory.setMaxConnections(100); + // return factory; + // } + + /** + * 连接网关节点; + * + * @param gatewayAddress 网关节点的网络地址; + * @return 网关服务工厂的实例; + */ + public static GatewayServiceFactory connect(NetworkAddress gatewayAddress) { + return connect(gatewayAddress.getHost(), gatewayAddress.getPort(), gatewayAddress.isSecure(), null); + } + + /** + * 网关服务工厂的实例; + * + * @param gatewayAddress 网关节点的网络地址; + * @param userKey 自动交易签名的用户密钥;可选参数,如果不为 null,则在提交交易时,自动以参数指定的密钥签署交易; + * @return 网关服务工厂的实例; + */ + public static GatewayServiceFactory connect(NetworkAddress gatewayAddress, BlockchainKeypair userKey) { + return connect(gatewayAddress.getHost(), gatewayAddress.getPort(), gatewayAddress.isSecure(), userKey); + } + + /** + * 连接网关节点; + * + * @param gatewayHost 网关节点的地址; + * @param gatewayPort 网关节点的端口; + * @param secure 是否采用安全的通讯协议(HTTPS); + * @return 网关服务工厂的实例; + */ + public static GatewayServiceFactory connect(String gatewayHost, int gatewayPort, boolean secure) { + return connect(gatewayHost, gatewayPort, secure, null); + } + + /** + * 连接网关节点; + * + * @param gatewayHost 网关节点的地址; + * @param gatewayPort 网关节点的端口; + * @param secure 是否采用安全的通讯协议(HTTPS); + * @param userKey 自动交易签名的用户密钥;可选参数,如果不为 null,则在提交交易时,自动以参数指定的密钥签署交易; + * @return 网关服务工厂的实例; + */ + public static GatewayServiceFactory connect(String gatewayHost, int gatewayPort, boolean secure, + BlockchainKeypair userKey) { +// if (userKey == null) { +// throw new IllegalArgumentException("User key is null!"); +// } + ServiceEndpoint gatewayEndpoint = new ServiceEndpoint(gatewayHost, gatewayPort, secure); + GatewayServiceFactory factory = new GatewayServiceFactory(gatewayEndpoint, userKey); + factory.setMaxConnections(100); + // TODO: 未实现网关对用户的认证; + // TODO: 未实现加载不同账本的密码算法配置; + return factory; + } + + public void setMaxConnections(int maxCount) { + httpConnectionManager.setMaxTotal(maxCount).setDefaultMaxPerRoute(maxCount); + } + + private TransactionService createConsensusService(ServiceEndpoint gatewayEndpoint) { + ServiceConnection connection = httpConnectionManager.create(gatewayEndpoint); + TransactionService gatewayConsensusService = HttpServiceAgent.createService(HttpConsensusService.class, + connection, null); + if (userKey != null) { + gatewayConsensusService = new EndpointAutoSigner(gatewayConsensusService, userKey); + } + return gatewayConsensusService; + } + + private BlockchainQueryService createQueryService(ServiceEndpoint gatewayEndpoint) { + ServiceConnection conn = httpConnectionManager.create(gatewayEndpoint); + return HttpServiceAgent.createService(HttpBlockchainQueryService.class, conn, null); + } + + @Override + public void close() { + httpConnectionManager.close(); + } + + private static class EndpointAutoSigner implements TransactionService { + + private TransactionService innerService; + + private BlockchainKeypair userKey; + + public EndpointAutoSigner(TransactionService innerService, BlockchainKeypair userKey) { + this.innerService = innerService; + this.userKey = userKey; + } + + @Override + public TransactionResponse process(TransactionRequest txRequest) { + TxRequestMessage reqMsg = (TxRequestMessage) txRequest; + // TODO: 未实现按不同的账本的密码参数配置,采用不同的哈希算法和签名算法; + if (!reqMsg.containsEndpointSignature(userKey.getAddress())) { + // TODO: 优化上下文对此 TransactionContent 的多次序列化带来的额外性能开销; + DigitalSignature signature = SignatureUtils.sign(txRequest.getTransactionContent(), userKey); + reqMsg.addEndpointSignatures(signature); +// +// +// +// byte[] txContentBytes = BinaryProtocol.encode(txRequest.getTransactionContent(), +// TransactionContent.class); +// PrivKey userPrivKey = userKey.getPrivKey(); +// SignatureFunction signatureFunction = Crypto.getSignatureFunction(userKey.getAlgorithm()); +// if (signatureFunction != null) { +// SignatureDigest signatureDigest = signatureFunction.sign(userPrivKey, txContentBytes); +// DigitalSignature signature = new DigitalSignatureBlob(userKey.getPubKey(), signatureDigest); +// reqMsg.addEndpointSignatures(signature); +// } + } + return innerService.process(txRequest); + } + } + +} diff --git a/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/HttpConsensusService.java b/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/HttpConsensusService.java index 9485436f..16e23e8e 100644 --- a/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/HttpConsensusService.java +++ b/source/sdk/sdk-client/src/main/java/com/jd/blockchain/sdk/client/HttpConsensusService.java @@ -1,19 +1,19 @@ -package com.jd.blockchain.sdk.client; - -import com.jd.blockchain.ledger.TransactionRequest; -import com.jd.blockchain.ledger.TransactionResponse; -import com.jd.blockchain.sdk.converters.BinarySerializeRequestConverter; -import com.jd.blockchain.sdk.converters.BinarySerializeResponseConverter; -import com.jd.blockchain.transaction.TransactionService; -import com.jd.blockchain.utils.http.HttpAction; -import com.jd.blockchain.utils.http.HttpMethod; -import com.jd.blockchain.utils.http.HttpService; -import com.jd.blockchain.utils.http.RequestBody; - -@HttpService(defaultRequestBodyConverter = BinarySerializeRequestConverter.class, defaultResponseConverter = BinarySerializeResponseConverter.class) -public interface HttpConsensusService extends TransactionService { - - @HttpAction(method = HttpMethod.POST, path = "rpc/tx", contentType = BinarySerializeRequestConverter.CONTENT_TYPE_VALUE) - @Override - TransactionResponse process(@RequestBody TransactionRequest txRequest); -} +package com.jd.blockchain.sdk.client; + +import com.jd.blockchain.ledger.TransactionRequest; +import com.jd.blockchain.ledger.TransactionResponse; +import com.jd.blockchain.sdk.converters.BinarySerializeRequestConverter; +import com.jd.blockchain.sdk.converters.BinarySerializeResponseConverter; +import com.jd.blockchain.transaction.TransactionService; +import com.jd.blockchain.utils.http.HttpAction; +import com.jd.blockchain.utils.http.HttpMethod; +import com.jd.blockchain.utils.http.HttpService; +import com.jd.blockchain.utils.http.RequestBody; + +@HttpService(defaultRequestBodyConverter = BinarySerializeRequestConverter.class, defaultResponseConverter = BinarySerializeResponseConverter.class) +public interface HttpConsensusService extends TransactionService { + + @HttpAction(method = HttpMethod.POST, path = "rpc/tx", contentType = BinarySerializeRequestConverter.CONTENT_TYPE_VALUE) + @Override + TransactionResponse process(@RequestBody TransactionRequest txRequest); +} diff --git a/source/sdk/sdk-samples/pom.xml b/source/sdk/sdk-samples/pom.xml index ece0c958..83caf6f7 100644 --- a/source/sdk/sdk-samples/pom.xml +++ b/source/sdk/sdk-samples/pom.xml @@ -1,53 +1,53 @@ - - 4.0.0 - - com.jd.blockchain - sdk - 1.1.2.RELEASE - - sdk-samples - - - - com.jd.blockchain - sdk-client - ${project.version} - - - com.jd.blockchain - ledger-model - ${project.version} - - - com.jd.blockchain - tools-initializer - ${project.version} - - - com.jd.blockchain - contract-samples - ${project.version} - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - - - - - - - - + + 4.0.0 + + com.jd.blockchain + sdk + 1.1.2.RELEASE + + sdk-samples + + + + com.jd.blockchain + sdk-client + ${project.version} + + + com.jd.blockchain + ledger-model + ${project.version} + + + com.jd.blockchain + tools-initializer + ${project.version} + + + com.jd.blockchain + contract-samples + ${project.version} + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + + + + + + + \ No newline at end of file diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_EventListener.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_EventListener.java index 935431ec..c4cb2642 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_EventListener.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_EventListener.java @@ -1,74 +1,74 @@ -//package com.jd.blockchain.sdk.samples; -// -//import com.jd.blockchain.ledger.BlockchainEventType; -//import com.jd.blockchain.ledger.BlockchainKeyGenerator; -//import com.jd.blockchain.ledger.BlockchainKeyPair; -//import com.jd.blockchain.ledger.CryptoKeyType; -//import com.jd.blockchain.ledger.StateMap; -//import com.jd.blockchain.sdk.BlockchainEventHandle; -//import com.jd.blockchain.sdk.BlockchainEventListener; -//import com.jd.blockchain.sdk.BlockchainEventMessage; -//import com.jd.blockchain.sdk.BlockchainService; -//import com.jd.blockchain.sdk.client.BlockchainServiceFactory; -// -//import my.utils.net.NetworkAddress; -// -///** -// * 演示监听区块链事件的过程; -// * -// * @author huanghaiquan -// * -// */ -//public class SDKDemo_EventListener { -// -// public static BlockchainKeyPair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); -// -// /** -// * 演示合约执行的过程; -// */ -// public static void demoContract() { -// // 区块链共识域; -// String realm = "SUPPLY_CHAIN_ALLIANCE"; -// // 节点地址列表; -// NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), -// new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), -// new NetworkAddress("192.168.10.13", 8080) }; -// -// // 网关客户端编号; -// int gatewayId = 1001; -// // 账本地址; -// String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; -// // 客户端的认证账户; -// String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; -// String privKey = "safefsd32q34vdsvs"; -// // 创建服务代理; -// final String GATEWAY_IP = "127.0.0.1"; -// final int GATEWAY_PORT = 80; -// final boolean SECURE = false; -// BlockchainServiceFactory serviceFactory = BlockchainServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, -// CLIENT_CERT); -// BlockchainService service = serviceFactory.getBlockchainService(); -// -// // 监听账户变动; -// String walletAccount = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; -// service.addBlockchainEventListener(BlockchainEventType.PAYLOAD_UPDATED.CODE, null, walletAccount, -// new BlockchainEventListener() { -// @Override -// public void onEvent(BlockchainEventMessage eventMessage, BlockchainEventHandle eventHandle) { -// // 钱包余额; -// StateMap balancePayload = service.getState(walletAccount, "RMB-ASSET","name"); -// Long balance = (Long) balancePayload.get("RMB-ASSET").longValue(); -// if (balance != null) { -// // notify balance change; -// } else { -// // wallet is empty and isn't listened any more; -// eventHandle.cancel(); -// } -// } -// }); -// -// // 销毁服务代理; -// serviceFactory.close(); -// } -// -//} +//package com.jd.blockchain.sdk.samples; +// +//import com.jd.blockchain.ledger.BlockchainEventType; +//import com.jd.blockchain.ledger.BlockchainKeyGenerator; +//import com.jd.blockchain.ledger.BlockchainKeyPair; +//import com.jd.blockchain.ledger.CryptoKeyType; +//import com.jd.blockchain.ledger.StateMap; +//import com.jd.blockchain.sdk.BlockchainEventHandle; +//import com.jd.blockchain.sdk.BlockchainEventListener; +//import com.jd.blockchain.sdk.BlockchainEventMessage; +//import com.jd.blockchain.sdk.BlockchainService; +//import com.jd.blockchain.sdk.client.BlockchainServiceFactory; +// +//import my.utils.net.NetworkAddress; +// +///** +// * 演示监听区块链事件的过程; +// * +// * @author huanghaiquan +// * +// */ +//public class SDKDemo_EventListener { +// +// public static BlockchainKeyPair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); +// +// /** +// * 演示合约执行的过程; +// */ +// public static void demoContract() { +// // 区块链共识域; +// String realm = "SUPPLY_CHAIN_ALLIANCE"; +// // 节点地址列表; +// NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), +// new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), +// new NetworkAddress("192.168.10.13", 8080) }; +// +// // 网关客户端编号; +// int gatewayId = 1001; +// // 账本地址; +// String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; +// // 客户端的认证账户; +// String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; +// String privKey = "safefsd32q34vdsvs"; +// // 创建服务代理; +// final String GATEWAY_IP = "127.0.0.1"; +// final int GATEWAY_PORT = 80; +// final boolean SECURE = false; +// BlockchainServiceFactory serviceFactory = BlockchainServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, +// CLIENT_CERT); +// BlockchainService service = serviceFactory.getBlockchainService(); +// +// // 监听账户变动; +// String walletAccount = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; +// service.addBlockchainEventListener(BlockchainEventType.PAYLOAD_UPDATED.CODE, null, walletAccount, +// new BlockchainEventListener() { +// @Override +// public void onEvent(BlockchainEventMessage eventMessage, BlockchainEventHandle eventHandle) { +// // 钱包余额; +// StateMap balancePayload = service.getState(walletAccount, "RMB-ASSET","name"); +// Long balance = (Long) balancePayload.get("RMB-ASSET").longValue(); +// if (balance != null) { +// // notify balance change; +// } else { +// // wallet is empty and isn't listened any more; +// eventHandle.cancel(); +// } +// } +// }); +// +// // 销毁服务代理; +// serviceFactory.close(); +// } +// +//} diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_PrivilegeSetting.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_PrivilegeSetting.java index ea85a11e..bdf819d2 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_PrivilegeSetting.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_PrivilegeSetting.java @@ -1,75 +1,75 @@ -package com.jd.blockchain.sdk.samples; - -public class SDKDemo_PrivilegeSetting { - -// public static BlockchainKeyPair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); -// -// /** -// * 生成一个区块链账户,并注册到区块链; -// */ -// public static void registerAccount() { -// // 区块链共识域; -// String realm = "SUPPLY_CHAIN_ALLIANCE"; -// // 节点地址列表; -// NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), -// new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), -// new NetworkAddress("192.168.10.13", 8080) }; -// -// // 网关客户端编号; -// int gatewayId = 1001; -// // 账本地址; -// String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; -// // 客户端的认证账户; -// String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; -// String privKey = "safefsd32q34vdsvs"; -// // 创建服务代理; -// final String GATEWAY_IP = "127.0.0.1"; -// final int GATEWAY_PORT = 80; -// final boolean SECURE = false; -// BlockchainServiceFactory serviceFactory = BlockchainServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, -// CLIENT_CERT); -// BlockchainTransactionService service = serviceFactory.getBlockchainService(); -// -// HashDigest ledgerHash = getLedgerHash(); -// // 在本地定义注册账号的 TX; -// TransactionTemplate txTemp = service.newTransaction(ledgerHash); -// -// // -------------------------------------- -// // 配置账户的权限; -// String walletAccount = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; -// String user1 = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; -// String user2 = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; -// // 配置: -// // “状态数据的写入权限”的阈值为 100; -// // 需要 user1、user2 两个账户的联合签名才能写入; -// // 当前账户仅用于表示一个业务钱包,禁止自身的写入权限,只能由业务角色的账户才能操作; -// -// -// -// txTemp.configPrivilege(walletAccount).setThreshhold(PrivilegeType.STATE_WRITE, 100) -// .enable(PrivilegeType.STATE_WRITE, user1, 50).enable(PrivilegeType.STATE_WRITE, user2, 50) -// .disable(PrivilegeType.STATE_WRITE, walletAccount); -// // -------------------------------------- -// -// // TX 准备就绪; -// PreparedTransaction prepTx = txTemp.prepare(); -// -// // 使用私钥进行签名; -// BlockchainKeyPair sponsorKey = getSponsorKey(); -// prepTx.sign(sponsorKey); -// -// // 提交交易; -// prepTx.commit(); -// } -// -// private static HashDigest getLedgerHash() { -// // TODO Init ledger hash; -// return null; -// } -// -// private static BlockchainKeyPair getSponsorKey() { -// // TODO Auto-generated method stub -// return null; -// } - -} +package com.jd.blockchain.sdk.samples; + +public class SDKDemo_PrivilegeSetting { + +// public static BlockchainKeyPair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate(CryptoKeyType.ED25519); +// +// /** +// * 生成一个区块链账户,并注册到区块链; +// */ +// public static void registerAccount() { +// // 区块链共识域; +// String realm = "SUPPLY_CHAIN_ALLIANCE"; +// // 节点地址列表; +// NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), +// new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), +// new NetworkAddress("192.168.10.13", 8080) }; +// +// // 网关客户端编号; +// int gatewayId = 1001; +// // 账本地址; +// String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; +// // 客户端的认证账户; +// String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; +// String privKey = "safefsd32q34vdsvs"; +// // 创建服务代理; +// final String GATEWAY_IP = "127.0.0.1"; +// final int GATEWAY_PORT = 80; +// final boolean SECURE = false; +// BlockchainServiceFactory serviceFactory = BlockchainServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, +// CLIENT_CERT); +// BlockchainTransactionService service = serviceFactory.getBlockchainService(); +// +// HashDigest ledgerHash = getLedgerHash(); +// // 在本地定义注册账号的 TX; +// TransactionTemplate txTemp = service.newTransaction(ledgerHash); +// +// // -------------------------------------- +// // 配置账户的权限; +// String walletAccount = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; +// String user1 = "MMMEy902jkjjJJDkshreGeasdfassdfajjf=="; +// String user2 = "Kjfe8832hfa9jjjJJDkshrFjksjdlkfj93F=="; +// // 配置: +// // “状态数据的写入权限”的阈值为 100; +// // 需要 user1、user2 两个账户的联合签名才能写入; +// // 当前账户仅用于表示一个业务钱包,禁止自身的写入权限,只能由业务角色的账户才能操作; +// +// +// +// txTemp.configPrivilege(walletAccount).setThreshhold(PrivilegeType.STATE_WRITE, 100) +// .enable(PrivilegeType.STATE_WRITE, user1, 50).enable(PrivilegeType.STATE_WRITE, user2, 50) +// .disable(PrivilegeType.STATE_WRITE, walletAccount); +// // -------------------------------------- +// +// // TX 准备就绪; +// PreparedTransaction prepTx = txTemp.prepare(); +// +// // 使用私钥进行签名; +// BlockchainKeyPair sponsorKey = getSponsorKey(); +// prepTx.sign(sponsorKey); +// +// // 提交交易; +// prepTx.commit(); +// } +// +// private static HashDigest getLedgerHash() { +// // TODO Init ledger hash; +// return null; +// } +// +// private static BlockchainKeyPair getSponsorKey() { +// // TODO Auto-generated method stub +// return null; +// } + +} diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java index a3e44d95..6d81393d 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_Query.java @@ -1,86 +1,86 @@ -package com.jd.blockchain.sdk.samples; - -import com.jd.blockchain.crypto.Crypto; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.BlockchainKeyGenerator; -import com.jd.blockchain.ledger.BlockchainKeypair; -import com.jd.blockchain.ledger.TypedKVEntry; -import com.jd.blockchain.ledger.LedgerBlock; -import com.jd.blockchain.ledger.LedgerTransaction; -import com.jd.blockchain.ledger.Transaction; -import com.jd.blockchain.sdk.BlockchainService; -import com.jd.blockchain.sdk.client.GatewayServiceFactory; -import com.jd.blockchain.utils.net.NetworkAddress; - -/** - * 演示区块链信息查询的过程; - * - * @author huanghaiquan - * - */ -public class SDKDemo_Query { - - public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); - - public static final HashDigest LEDGER_HASH = Crypto.getHashFunction("SHA256") - .hash("xkxjcioewfqwe".getBytes()); - - /** - * 演示合约执行的过程; - */ - public static void demoContract() { - // 区块链共识域; - String realm = "SUPPLY_CHAIN_ALLIANCE"; - // 节点地址列表; - NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), - new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), - new NetworkAddress("192.168.10.13", 8080) }; - - // 网关客户端编号; - int gatewayId = 1001; // 客户端的认证账户; - // 账本地址; - String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; - String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; - String privKey = "safefsd32q34vdsvs"; - // 创建服务代理; - final String GATEWAY_IP = "127.0.0.1"; - final int GATEWAY_PORT = 80; - final boolean SECURE = false; - GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, - CLIENT_CERT); - BlockchainService service = serviceFactory.getBlockchainService(); - - // 查询区块信息; - // 区块高度; - long ledgerNumber = service.getLedger(LEDGER_HASH).getLatestBlockHeight(); - // 最新区块; - LedgerBlock latestBlock = service.getBlock(LEDGER_HASH, ledgerNumber); - // 区块中的交易的数量; - long txCount = service.getTransactionCount(LEDGER_HASH, latestBlock.getHash()); - // 获取交易列表; - LedgerTransaction[] txList = service.getTransactions(LEDGER_HASH, ledgerNumber, 0, 100); - - // 根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash; - HashDigest txHash = txList[0].getTransactionContent().getHash(); - Transaction tx = service.getTransactionByContentHash(LEDGER_HASH, txHash); - - // 获取数据; - String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; - String[] objKeys = new String[] { "x001", "x002" }; - TypedKVEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys); - - long payloadVersion = kvData[0].getVersion(); - -// boolean exist = service.containState(LEDGER_HASH, commerceAccount, "x003"); - - // 按条件查询; - // 1、从保存会员信息的账户地址查询; -// String condition = "female = true AND age > 18 AND address.city = 'beijing'"; -// String memberInfoAccountAddress = "kkf2io39823jfIjfiIRWKQj30203fx=="; -// StateMap memberInfo = service.queryObject(LEDGER_HASH, memberInfoAccountAddress, condition); -// -// // 2、从保存会员信息的账户地址查询; -// Map memberInfoWithAccounts = service.queryObject(LEDGER_HASH, condition); - } - -} +package com.jd.blockchain.sdk.samples; + +import com.jd.blockchain.crypto.Crypto; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.BlockchainKeyGenerator; +import com.jd.blockchain.ledger.BlockchainKeypair; +import com.jd.blockchain.ledger.TypedKVEntry; +import com.jd.blockchain.ledger.LedgerBlock; +import com.jd.blockchain.ledger.LedgerTransaction; +import com.jd.blockchain.ledger.Transaction; +import com.jd.blockchain.sdk.BlockchainService; +import com.jd.blockchain.sdk.client.GatewayServiceFactory; +import com.jd.blockchain.utils.net.NetworkAddress; + +/** + * 演示区块链信息查询的过程; + * + * @author huanghaiquan + * + */ +public class SDKDemo_Query { + + public static BlockchainKeypair CLIENT_CERT = BlockchainKeyGenerator.getInstance().generate("ED25519"); + + public static final HashDigest LEDGER_HASH = Crypto.getHashFunction("SHA256") + .hash("xkxjcioewfqwe".getBytes()); + + /** + * 演示合约执行的过程; + */ + public static void demoContract() { + // 区块链共识域; + String realm = "SUPPLY_CHAIN_ALLIANCE"; + // 节点地址列表; + NetworkAddress[] peerAddrs = { new NetworkAddress("192.168.10.10", 8080), + new NetworkAddress("192.168.10.11", 8080), new NetworkAddress("192.168.10.12", 8080), + new NetworkAddress("192.168.10.13", 8080) }; + + // 网关客户端编号; + int gatewayId = 1001; // 客户端的认证账户; + // 账本地址; + String ledgerAddress = "ffkjhkeqwiuhivnsh3298josijdocaijsda=="; + String clientAddress = "kkjsafieweqEkadsfaslkdslkae998232jojf=="; + String privKey = "safefsd32q34vdsvs"; + // 创建服务代理; + final String GATEWAY_IP = "127.0.0.1"; + final int GATEWAY_PORT = 80; + final boolean SECURE = false; + GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IP, GATEWAY_PORT, SECURE, + CLIENT_CERT); + BlockchainService service = serviceFactory.getBlockchainService(); + + // 查询区块信息; + // 区块高度; + long ledgerNumber = service.getLedger(LEDGER_HASH).getLatestBlockHeight(); + // 最新区块; + LedgerBlock latestBlock = service.getBlock(LEDGER_HASH, ledgerNumber); + // 区块中的交易的数量; + long txCount = service.getTransactionCount(LEDGER_HASH, latestBlock.getHash()); + // 获取交易列表; + LedgerTransaction[] txList = service.getTransactions(LEDGER_HASH, ledgerNumber, 0, 100); + + // 根据交易的 hash 获得交易;注:客户端生成 PrepareTransaction 时得到交易hash; + HashDigest txHash = txList[0].getTransactionContent().getHash(); + Transaction tx = service.getTransactionByContentHash(LEDGER_HASH, txHash); + + // 获取数据; + String commerceAccount = "GGhhreGeasdfasfUUfehf9932lkae99ds66jf=="; + String[] objKeys = new String[] { "x001", "x002" }; + TypedKVEntry[] kvData = service.getDataEntries(LEDGER_HASH, commerceAccount, objKeys); + + long payloadVersion = kvData[0].getVersion(); + +// boolean exist = service.containState(LEDGER_HASH, commerceAccount, "x003"); + + // 按条件查询; + // 1、从保存会员信息的账户地址查询; +// String condition = "female = true AND age > 18 AND address.city = 'beijing'"; +// String memberInfoAccountAddress = "kkf2io39823jfIjfiIRWKQj30203fx=="; +// StateMap memberInfo = service.queryObject(LEDGER_HASH, memberInfoAccountAddress, condition); +// +// // 2、从保存会员信息的账户地址查询; +// Map memberInfoWithAccounts = service.queryObject(LEDGER_HASH, condition); + } + +} diff --git a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_RegisterAccount.java b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_RegisterAccount.java index 30de0042..07b84984 100644 --- a/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_RegisterAccount.java +++ b/source/sdk/sdk-samples/src/main/java/com/jd/blockchain/sdk/samples/SDKDemo_RegisterAccount.java @@ -1,57 +1,57 @@ -package com.jd.blockchain.sdk.samples; - -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.AsymmetricKeypair; -import com.jd.blockchain.crypto.HashDigest; -import com.jd.blockchain.ledger.*; -import com.jd.blockchain.sdk.BlockchainService; -import com.jd.blockchain.sdk.client.GatewayServiceFactory; -import com.jd.blockchain.utils.ConsoleUtils; - -public class SDKDemo_RegisterAccount { - - public static void main(String[] args) { - - String GATEWAY_IPADDR = "127.0.0.1"; - int GATEWAY_PORT = 8081; - if (args != null && args.length == 2) { - GATEWAY_IPADDR = args[0]; - GATEWAY_PORT = Integer.parseInt(args[1]); - } - - DataContractRegistry.register(TransactionContent.class); - DataContractRegistry.register(TransactionContentBody.class); - DataContractRegistry.register(TransactionRequest.class); - DataContractRegistry.register(NodeRequest.class); - DataContractRegistry.register(EndpointRequest.class); - DataContractRegistry.register(TransactionResponse.class); - - BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); - boolean SECURE = false; - GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, - CLIENT_CERT); - BlockchainService service = serviceFactory.getBlockchainService(); - - HashDigest[] ledgerHashs = service.getLedgerHashs(); - // 在本地定义注册账号的 TX; - TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); - - //existed signer - AsymmetricKeypair keyPair = new BlockchainKeypair(SDKDemo_Params.pubKey1, SDKDemo_Params.privkey1); - - BlockchainKeypair dataAcount = BlockchainKeyGenerator.getInstance().generate(); - - // 注册 - txTemp.dataAccounts().register(dataAcount.getIdentity()); - - // TX 准备就绪; - PreparedTransaction prepTx = txTemp.prepare(); - - prepTx.sign(keyPair); - - // 提交交易; - TransactionResponse transactionResponse = prepTx.commit(); - - ConsoleUtils.info("register dataaccount complete, result is [%s]", transactionResponse.isSuccess()); - } -} +package com.jd.blockchain.sdk.samples; + +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.AsymmetricKeypair; +import com.jd.blockchain.crypto.HashDigest; +import com.jd.blockchain.ledger.*; +import com.jd.blockchain.sdk.BlockchainService; +import com.jd.blockchain.sdk.client.GatewayServiceFactory; +import com.jd.blockchain.utils.ConsoleUtils; + +public class SDKDemo_RegisterAccount { + + public static void main(String[] args) { + + String GATEWAY_IPADDR = "127.0.0.1"; + int GATEWAY_PORT = 8081; + if (args != null && args.length == 2) { + GATEWAY_IPADDR = args[0]; + GATEWAY_PORT = Integer.parseInt(args[1]); + } + + DataContractRegistry.register(TransactionContent.class); + DataContractRegistry.register(TransactionContentBody.class); + DataContractRegistry.register(TransactionRequest.class); + DataContractRegistry.register(NodeRequest.class); + DataContractRegistry.register(EndpointRequest.class); + DataContractRegistry.register(TransactionResponse.class); + + BlockchainKeypair CLIENT_CERT = new BlockchainKeypair(SDKDemo_Params.pubKey0, SDKDemo_Params.privkey0); + boolean SECURE = false; + GatewayServiceFactory serviceFactory = GatewayServiceFactory.connect(GATEWAY_IPADDR, GATEWAY_PORT, SECURE, + CLIENT_CERT); + BlockchainService service = serviceFactory.getBlockchainService(); + + HashDigest[] ledgerHashs = service.getLedgerHashs(); + // 在本地定义注册账号的 TX; + TransactionTemplate txTemp = service.newTransaction(ledgerHashs[0]); + + //existed signer + AsymmetricKeypair keyPair = new BlockchainKeypair(SDKDemo_Params.pubKey1, SDKDemo_Params.privkey1); + + BlockchainKeypair dataAcount = BlockchainKeyGenerator.getInstance().generate(); + + // 注册 + txTemp.dataAccounts().register(dataAcount.getIdentity()); + + // TX 准备就绪; + PreparedTransaction prepTx = txTemp.prepare(); + + prepTx.sign(keyPair); + + // 提交交易; + TransactionResponse transactionResponse = prepTx.commit(); + + ConsoleUtils.info("register dataaccount complete, result is [%s]", transactionResponse.isSuccess()); + } +} diff --git a/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/JedisProperties.java b/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/JedisProperties.java index 8536df26..8a60f079 100644 --- a/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/JedisProperties.java +++ b/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/JedisProperties.java @@ -1,35 +1,35 @@ -package com.jd.blockchain.storage.service.impl.redis; - -public class JedisProperties { - - private String host; - - private int port = 6379; - - private int db = 0; - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public int getDb() { - return db; - } - - public void setDb(int db) { - this.db = db; - } - -} +package com.jd.blockchain.storage.service.impl.redis; + +public class JedisProperties { + + private String host; + + private int port = 6379; + + private int db = 0; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public int getDb() { + return db; + } + + public void setDb(int db) { + this.db = db; + } + +} diff --git a/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/RedisStorageService.java b/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/RedisStorageService.java index 787b77c5..06cef779 100644 --- a/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/RedisStorageService.java +++ b/source/storage/storage-redis/src/main/java/com/jd/blockchain/storage/service/impl/redis/RedisStorageService.java @@ -1,39 +1,39 @@ -package com.jd.blockchain.storage.service.impl.redis; - -import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.KVStorageService; -import com.jd.blockchain.storage.service.VersioningKVStorage; - -import redis.clients.jedis.Jedis; -import redis.clients.jedis.JedisPool; - -public class RedisStorageService implements KVStorageService { - - private RedisExPolicyStorage exStorage; - - private RedisVerioningStorage verStorage; - - private JedisPool jedisPool; - - public RedisStorageService(JedisPool jedisPool) { - this.jedisPool = jedisPool; - this.exStorage = new RedisExPolicyStorage(jedisPool); - this.verStorage = new RedisVerioningStorage(jedisPool); - } - - @Override - public ExPolicyKVStorage getExPolicyKVStorage() { - return exStorage; - } - - @Override - public VersioningKVStorage getVersioningKVStorage() { - return verStorage; - } - - public void clearDB() { - try (Jedis jedis = jedisPool.getResource()) { - jedis.flushDB(); - } - } -} +package com.jd.blockchain.storage.service.impl.redis; + +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.KVStorageService; +import com.jd.blockchain.storage.service.VersioningKVStorage; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; + +public class RedisStorageService implements KVStorageService { + + private RedisExPolicyStorage exStorage; + + private RedisVerioningStorage verStorage; + + private JedisPool jedisPool; + + public RedisStorageService(JedisPool jedisPool) { + this.jedisPool = jedisPool; + this.exStorage = new RedisExPolicyStorage(jedisPool); + this.verStorage = new RedisVerioningStorage(jedisPool); + } + + @Override + public ExPolicyKVStorage getExPolicyKVStorage() { + return exStorage; + } + + @Override + public VersioningKVStorage getVersioningKVStorage() { + return verStorage; + } + + public void clearDB() { + try (Jedis jedis = jedisPool.getResource()) { + jedis.flushDB(); + } + } +} diff --git a/source/storage/storage-redis/src/main/resources/META-INF/spring.factories b/source/storage/storage-redis/src/main/resources/META-INF/spring.factories index c5a24b7e..58aec406 100644 --- a/source/storage/storage-redis/src/main/resources/META-INF/spring.factories +++ b/source/storage/storage-redis/src/main/resources/META-INF/spring.factories @@ -1,2 +1,2 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.jd.blockchain.storage.service.impl.redis.RedisStorageConfiguration \ No newline at end of file diff --git a/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBStorageService.java b/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBStorageService.java index db7b673c..e1fc5d17 100644 --- a/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBStorageService.java +++ b/source/storage/storage-rocksdb/src/main/java/com/jd/blockchain/storage/service/impl/rocksdb/RocksDBStorageService.java @@ -1,30 +1,30 @@ -package com.jd.blockchain.storage.service.impl.rocksdb; - -import org.rocksdb.RocksDB; - -import com.jd.blockchain.storage.service.ExPolicyKVStorage; -import com.jd.blockchain.storage.service.KVStorageService; -import com.jd.blockchain.storage.service.VersioningKVStorage; - -public class RocksDBStorageService implements KVStorageService { - - private ExPolicyKVStorage exStorage; - - private VersioningKVStorage verStorage; - - public RocksDBStorageService(RocksDB db) { - this.verStorage = new RocksDBVersioningStorage(db); - this.exStorage = new RocksDBExPolicyStorage(new RocksDBVersioningStorage(db)); - } - - @Override - public ExPolicyKVStorage getExPolicyKVStorage() { - return exStorage; - } - - @Override - public VersioningKVStorage getVersioningKVStorage() { - return verStorage; - } - -} +package com.jd.blockchain.storage.service.impl.rocksdb; + +import org.rocksdb.RocksDB; + +import com.jd.blockchain.storage.service.ExPolicyKVStorage; +import com.jd.blockchain.storage.service.KVStorageService; +import com.jd.blockchain.storage.service.VersioningKVStorage; + +public class RocksDBStorageService implements KVStorageService { + + private ExPolicyKVStorage exStorage; + + private VersioningKVStorage verStorage; + + public RocksDBStorageService(RocksDB db) { + this.verStorage = new RocksDBVersioningStorage(db); + this.exStorage = new RocksDBExPolicyStorage(new RocksDBVersioningStorage(db)); + } + + @Override + public ExPolicyKVStorage getExPolicyKVStorage() { + return exStorage; + } + + @Override + public VersioningKVStorage getVersioningKVStorage() { + return verStorage; + } + +} diff --git a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java index 980cc32c..b1f6a9a3 100644 --- a/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java +++ b/source/storage/storage-service/src/main/java/com/jd/blockchain/storage/service/VersioningKVStorage.java @@ -1,81 +1,81 @@ -package com.jd.blockchain.storage.service; - -import com.jd.blockchain.utils.Bytes; -import com.jd.blockchain.utils.DataEntry; - -/** - * Versioning Key-Value Storage - *

- * - * One key in this storage has a version attribute, which starts from zero and - * increased by 1 on it's value being updated. - * - *
- * The writing of a key must be specified a explict integer of it's latest - * version at the executing moment. - * - * - * @author huanghaiquan - * - */ -public interface VersioningKVStorage extends BatchStorageService { - - /** - * Return the latest version entry associated the specified key; - * - * If the key doesn't exist, then return -1; - * - * @param key - * @return - */ - long getVersion(Bytes key); - - /** - * Return the specified verson's entry;
- * - * It will return the latest one if the version is -1;
- * - * It will return null if the key or version not exist. - * - * @param key - * @param version - * @return - */ - DataEntry getEntry(Bytes key, long version); - - /** - * Return the specified verson's value;
- * - * If the specified version of key doesn't exist, then return null;
- * - * If the version is specified to -1, then return the latest version's - * value;
- * - * @param key - * @param version - * @return - */ - byte[] get(Bytes key, long version); - - /** - * Update the value of the key;
- * - * If key exist, and the specified version equals to it's latest version, then the value will be - * updated and version will be increased by 1;
- * If key not exist, and the specified version is -1, then the value will be - * created and initialized it's version by 0;
- * - * @param key - * the key; - * @param value - * the new value to update if expected version match the actual - * version; - * @param version - * the latest version expected; - * @return The latest version entry after setting.
- * If the version checking fail, or concurrent confliction occur, then - * return -1 as indication.
- */ - long set(Bytes key, byte[] value, long version); - +package com.jd.blockchain.storage.service; + +import com.jd.blockchain.utils.Bytes; +import com.jd.blockchain.utils.DataEntry; + +/** + * Versioning Key-Value Storage + *

+ * + * One key in this storage has a version attribute, which starts from zero and + * increased by 1 on it's value being updated. + * + *
+ * The writing of a key must be specified a explict integer of it's latest + * version at the executing moment. + * + * + * @author huanghaiquan + * + */ +public interface VersioningKVStorage extends BatchStorageService { + + /** + * Return the latest version entry associated the specified key; + * + * If the key doesn't exist, then return -1; + * + * @param key + * @return + */ + long getVersion(Bytes key); + + /** + * Return the specified verson's entry;
+ * + * It will return the latest one if the version is -1;
+ * + * It will return null if the key or version not exist. + * + * @param key + * @param version + * @return + */ + DataEntry getEntry(Bytes key, long version); + + /** + * Return the specified verson's value;
+ * + * If the specified version of key doesn't exist, then return null;
+ * + * If the version is specified to -1, then return the latest version's + * value;
+ * + * @param key + * @param version + * @return + */ + byte[] get(Bytes key, long version); + + /** + * Update the value of the key;
+ * + * If key exist, and the specified version equals to it's latest version, then the value will be + * updated and version will be increased by 1;
+ * If key not exist, and the specified version is -1, then the value will be + * created and initialized it's version by 0;
+ * + * @param key + * the key; + * @param value + * the new value to update if expected version match the actual + * version; + * @param version + * the latest version expected; + * @return The latest version entry after setting.
+ * If the version checking fail, or concurrent confliction occur, then + * return -1 as indication.
+ */ + long set(Bytes key, byte[] value, long version); + } \ No newline at end of file diff --git a/source/test/pom.xml b/source/test/pom.xml index 5219328f..d7854070 100644 --- a/source/test/pom.xml +++ b/source/test/pom.xml @@ -1,32 +1,32 @@ - - 4.0.0 - - com.jd.blockchain - jdchain-root - 1.1.2.RELEASE - - test - pom - - - test-consensus-client - test-consensus-node - test-ledger - test-integration - - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - true - - - - + + 4.0.0 + + com.jd.blockchain + jdchain-root + 1.1.2.RELEASE + + test + pom + + + test-consensus-client + test-consensus-node + test-ledger + test-integration + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + \ No newline at end of file diff --git a/source/test/test-consensus-client/src/main/java/test/perf/com/jd/blockchain/consensus/client/Settings.java b/source/test/test-consensus-client/src/main/java/test/perf/com/jd/blockchain/consensus/client/Settings.java index a296249c..af0bceb8 100644 --- a/source/test/test-consensus-client/src/main/java/test/perf/com/jd/blockchain/consensus/client/Settings.java +++ b/source/test/test-consensus-client/src/main/java/test/perf/com/jd/blockchain/consensus/client/Settings.java @@ -1,142 +1,142 @@ -package test.perf.com.jd.blockchain.consensus.client; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -import com.jd.blockchain.utils.io.ByteArray; - -/** - * @author huanghaiquan - * - */ -@Configuration -@ConfigurationProperties(prefix = "client") -public class Settings { - - private String name; - - private ConsensusSetting consensus; - - public ByteArray getLedgerHash() { - return ledgerHash; - } - - public void setLedgerHash(ByteArray ledgerHash) { - this.ledgerHash = ledgerHash; - } - - private ByteArray ledgerHash; - - public ConsensusSetting getConsensus() { - return consensus; - } - - public void setConsensus(ConsensusSetting consensus) { - this.consensus = consensus; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - // =================================================================================================== - /** - * 共识相关的参数设置; - * - * @author huanghaiquan - * - */ - public static class ConsensusSetting { - - /** - * 本机用于共识的IP地址; - */ - private String ip; - - /** - * 本机用于共识的端口; - */ - private int port; - - public ConsensusSetting() { - } - - public ConsensusSetting(String ip, int port) { - this.ip = ip; - this.port = port; - } - - private BftsmartSetting bftsmartConfig = new BftsmartSetting("config/system.config", "config/hosts.config"); - - public String getIp() { - return ip; - } - - public void setIp(String ip) { - this.ip = ip; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public BftsmartSetting getBftsmartConfig() { - return bftsmartConfig; - } - - public void setBftsmartConfig(BftsmartSetting bftsmartConfig) { - this.bftsmartConfig = bftsmartConfig; - } - - } - - public static class BftsmartSetting { - - private String hosts; - - private String system; - - private String home; - - public BftsmartSetting() { - } - - public BftsmartSetting(String systemConfig, String hostsConfig) { - this.system = systemConfig; - this.hosts = hostsConfig; - } - - public String getHosts() { - return hosts; - } - - public void setHosts(String hosts) { - this.hosts = hosts; - } - - public String getSystem() { - return system; - } - - public void setSystem(String system) { - this.system = system; - } - - public String getHome() { - return home; - } - - public void setHome(String home) { - this.home = home; - } - - } -} +package test.perf.com.jd.blockchain.consensus.client; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import com.jd.blockchain.utils.io.ByteArray; + +/** + * @author huanghaiquan + * + */ +@Configuration +@ConfigurationProperties(prefix = "client") +public class Settings { + + private String name; + + private ConsensusSetting consensus; + + public ByteArray getLedgerHash() { + return ledgerHash; + } + + public void setLedgerHash(ByteArray ledgerHash) { + this.ledgerHash = ledgerHash; + } + + private ByteArray ledgerHash; + + public ConsensusSetting getConsensus() { + return consensus; + } + + public void setConsensus(ConsensusSetting consensus) { + this.consensus = consensus; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + // =================================================================================================== + /** + * 共识相关的参数设置; + * + * @author huanghaiquan + * + */ + public static class ConsensusSetting { + + /** + * 本机用于共识的IP地址; + */ + private String ip; + + /** + * 本机用于共识的端口; + */ + private int port; + + public ConsensusSetting() { + } + + public ConsensusSetting(String ip, int port) { + this.ip = ip; + this.port = port; + } + + private BftsmartSetting bftsmartConfig = new BftsmartSetting("config/system.config", "config/hosts.config"); + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public BftsmartSetting getBftsmartConfig() { + return bftsmartConfig; + } + + public void setBftsmartConfig(BftsmartSetting bftsmartConfig) { + this.bftsmartConfig = bftsmartConfig; + } + + } + + public static class BftsmartSetting { + + private String hosts; + + private String system; + + private String home; + + public BftsmartSetting() { + } + + public BftsmartSetting(String systemConfig, String hostsConfig) { + this.system = systemConfig; + this.hosts = hostsConfig; + } + + public String getHosts() { + return hosts; + } + + public void setHosts(String hosts) { + this.hosts = hosts; + } + + public String getSystem() { + return system; + } + + public void setSystem(String system) { + this.system = system; + } + + public String getHome() { + return home; + } + + public void setHome(String home) { + this.home = home; + } + + } +} diff --git a/source/test/test-consensus-client/src/main/java/test/perf/com/jd/blockchain/consensus/client/WebConfiguration.java b/source/test/test-consensus-client/src/main/java/test/perf/com/jd/blockchain/consensus/client/WebConfiguration.java index b43acb34..b99c161b 100644 --- a/source/test/test-consensus-client/src/main/java/test/perf/com/jd/blockchain/consensus/client/WebConfiguration.java +++ b/source/test/test-consensus-client/src/main/java/test/perf/com/jd/blockchain/consensus/client/WebConfiguration.java @@ -1,11 +1,11 @@ -package test.perf.com.jd.blockchain.consensus.client; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ComponentScan -public class WebConfiguration { - -} - +package test.perf.com.jd.blockchain.consensus.client; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan +public class WebConfiguration { + +} + diff --git a/source/test/test-consensus-client/src/main/resources/application.properties b/source/test/test-consensus-client/src/main/resources/application.properties index 6fdb220e..63feb453 100644 --- a/source/test/test-consensus-client/src/main/resources/application.properties +++ b/source/test/test-consensus-client/src/main/resources/application.properties @@ -1,28 +1,28 @@ -server.port=10010 - -#server.ssl.key-store=classpath:mykeys.jks -#server.ssl.key-store-password=abc123 -#server.ssl.key-password=abc123 - -server.tomcat.accesslog.enabled=false - -debug=false - -#logging.file=logs/peer.log -logging.level.com.jd.blockchain.peer=DEBUG -logging.level.org.org.springframework=DEBUG - -spring.mvc.favicon.enabled=false - - - -client.name=peer[0] - -client.consensus.ip=127.0.0.1 -client.consensus.port=10000 - -client.consensus.bftsmart-config.home=config -client.consensus.bftsmart-config.system=config/system.config -client.consensus.bftsmart-config.hosts=config/hosts.config - - +server.port=10010 + +#server.ssl.key-store=classpath:mykeys.jks +#server.ssl.key-store-password=abc123 +#server.ssl.key-password=abc123 + +server.tomcat.accesslog.enabled=false + +debug=false + +#logging.file=logs/peer.log +logging.level.com.jd.blockchain.peer=DEBUG +logging.level.org.org.springframework=DEBUG + +spring.mvc.favicon.enabled=false + + + +client.name=peer[0] + +client.consensus.ip=127.0.0.1 +client.consensus.port=10000 + +client.consensus.bftsmart-config.home=config +client.consensus.bftsmart-config.system=config/system.config +client.consensus.bftsmart-config.hosts=config/hosts.config + + diff --git a/source/test/test-consensus-node/config/bft-system.config b/source/test/test-consensus-node/config/bft-system.config index ddf28b45..ada42b49 100644 --- a/source/test/test-consensus-node/config/bft-system.config +++ b/source/test/test-consensus-node/config/bft-system.config @@ -1,121 +1,121 @@ -# Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -############################################ -####### Communication Configurations ####### -############################################ - -#HMAC algorithm used to authenticate messages between processes (HmacMD5 is the default value) -#This parameter is not currently being used being used -#system.authentication.hmacAlgorithm = HmacSHA1 - -#Specify if the communication system should use a thread to send data (true or false) -system.communication.useSenderThread = true - -#Force all processes to use the same public/private keys pair and secret key. This is useful when deploying experiments -#and benchmarks, but must not be used in production systems. -system.communication.defaultkeys = true - -############################################ -### Replication Algorithm Configurations ### -############################################ - -#Number of servers in the group -system.servers.num = 4 - -#Maximum number of faulty replicas -system.servers.f = 1 - -#Timeout to asking for a client request -system.totalordermulticast.timeout = 2000 - - -#Maximum batch size (in number of messages) -system.totalordermulticast.maxbatchsize = 400 - -#Number of nonces (for non-determinism actions) generated -system.totalordermulticast.nonces = 10 - -#if verification of leader-generated timestamps are increasing -#it can only be used on systems in which the network clocks -#are synchronized -system.totalordermulticast.verifyTimestamps = false - -#Quantity of messages that can be stored in the receive queue of the communication system -system.communication.inQueueSize = 500000 - -# Quantity of messages that can be stored in the send queue of each replica -system.communication.outQueueSize = 500000 - -#Set to 1 if SMaRt should use signatures, set to 0 if otherwise -system.communication.useSignatures = 0 - -#Set to 1 if SMaRt should use MAC's, set to 0 if otherwise -system.communication.useMACs = 1 - -#Set to 1 if SMaRt should use the standard output to display debug messages, set to 0 if otherwise -system.debug = 0 - -#Print information about the replica when it is shutdown -system.shutdownhook = true - -############################################ -###### State Transfer Configurations ####### -############################################ - -#Activate the state transfer protocol ('true' to activate, 'false' to de-activate) -system.totalordermulticast.state_transfer = true - -#Maximum ahead-of-time message not discarded -system.totalordermulticast.highMark = 10000 - -#Maximum ahead-of-time message not discarded when the replica is still on EID 0 (after which the state transfer is triggered) -system.totalordermulticast.revival_highMark = 10 - -#Number of ahead-of-time messages necessary to trigger the state transfer after a request timeout occurs -system.totalordermulticast.timeout_highMark = 200 - -############################################ -###### Log and Checkpoint Configurations ### -############################################ - -system.totalordermulticast.log = true -system.totalordermulticast.log_parallel = false -system.totalordermulticast.log_to_disk = false -system.totalordermulticast.sync_log = false - -#Period at which BFT-SMaRt requests the state to the application (for the state transfer state protocol) -system.totalordermulticast.checkpoint_period = 1000 -system.totalordermulticast.global_checkpoint_period = 120000 - -system.totalordermulticast.checkpoint_to_disk = false -system.totalordermulticast.sync_ckp = false - - -############################################ -###### Reconfiguration Configurations ###### -############################################ - -#Replicas ID for the initial view, separated by a comma. -# The number of replicas in this parameter should be equal to that specified in 'system.servers.num' -system.initial.view = 0,1,2,3 - -#The ID of the trust third party (TTP) -system.ttp.id = 7002 - -#This sets if the system will function in Byzantine or crash-only mode. Set to "true" to support Byzantine faults -system.bft = true - -#Custom View Storage; -#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage +# Copyright (c) 2007-2013 Alysson Bessani, Eduardo Alchieri, Paulo Sousa, and the authors indicated in the @author tags +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################################ +####### Communication Configurations ####### +############################################ + +#HMAC algorithm used to authenticate messages between processes (HmacMD5 is the default value) +#This parameter is not currently being used being used +#system.authentication.hmacAlgorithm = HmacSHA1 + +#Specify if the communication system should use a thread to send data (true or false) +system.communication.useSenderThread = true + +#Force all processes to use the same public/private keys pair and secret key. This is useful when deploying experiments +#and benchmarks, but must not be used in production systems. +system.communication.defaultkeys = true + +############################################ +### Replication Algorithm Configurations ### +############################################ + +#Number of servers in the group +system.servers.num = 4 + +#Maximum number of faulty replicas +system.servers.f = 1 + +#Timeout to asking for a client request +system.totalordermulticast.timeout = 2000 + + +#Maximum batch size (in number of messages) +system.totalordermulticast.maxbatchsize = 400 + +#Number of nonces (for non-determinism actions) generated +system.totalordermulticast.nonces = 10 + +#if verification of leader-generated timestamps are increasing +#it can only be used on systems in which the network clocks +#are synchronized +system.totalordermulticast.verifyTimestamps = false + +#Quantity of messages that can be stored in the receive queue of the communication system +system.communication.inQueueSize = 500000 + +# Quantity of messages that can be stored in the send queue of each replica +system.communication.outQueueSize = 500000 + +#Set to 1 if SMaRt should use signatures, set to 0 if otherwise +system.communication.useSignatures = 0 + +#Set to 1 if SMaRt should use MAC's, set to 0 if otherwise +system.communication.useMACs = 1 + +#Set to 1 if SMaRt should use the standard output to display debug messages, set to 0 if otherwise +system.debug = 0 + +#Print information about the replica when it is shutdown +system.shutdownhook = true + +############################################ +###### State Transfer Configurations ####### +############################################ + +#Activate the state transfer protocol ('true' to activate, 'false' to de-activate) +system.totalordermulticast.state_transfer = true + +#Maximum ahead-of-time message not discarded +system.totalordermulticast.highMark = 10000 + +#Maximum ahead-of-time message not discarded when the replica is still on EID 0 (after which the state transfer is triggered) +system.totalordermulticast.revival_highMark = 10 + +#Number of ahead-of-time messages necessary to trigger the state transfer after a request timeout occurs +system.totalordermulticast.timeout_highMark = 200 + +############################################ +###### Log and Checkpoint Configurations ### +############################################ + +system.totalordermulticast.log = true +system.totalordermulticast.log_parallel = false +system.totalordermulticast.log_to_disk = false +system.totalordermulticast.sync_log = false + +#Period at which BFT-SMaRt requests the state to the application (for the state transfer state protocol) +system.totalordermulticast.checkpoint_period = 1000 +system.totalordermulticast.global_checkpoint_period = 120000 + +system.totalordermulticast.checkpoint_to_disk = false +system.totalordermulticast.sync_ckp = false + + +############################################ +###### Reconfiguration Configurations ###### +############################################ + +#Replicas ID for the initial view, separated by a comma. +# The number of replicas in this parameter should be equal to that specified in 'system.servers.num' +system.initial.view = 0,1,2,3 + +#The ID of the trust third party (TTP) +system.ttp.id = 7002 + +#This sets if the system will function in Byzantine or crash-only mode. Set to "true" to support Byzantine faults +system.bft = true + +#Custom View Storage; +#view.storage.handler=bftsmart.reconfiguration.views.DefaultViewStorage diff --git a/source/test/test-consensus-node/src/main/java/test/perf/com/jd/blockchain/consensus/node/Settings.java b/source/test/test-consensus-node/src/main/java/test/perf/com/jd/blockchain/consensus/node/Settings.java index c7f75903..1847308d 100644 --- a/source/test/test-consensus-node/src/main/java/test/perf/com/jd/blockchain/consensus/node/Settings.java +++ b/source/test/test-consensus-node/src/main/java/test/perf/com/jd/blockchain/consensus/node/Settings.java @@ -1,57 +1,57 @@ -package test.perf.com.jd.blockchain.consensus.node; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -/** - * @author huanghaiquan - * - */ -@Configuration -@ConfigurationProperties(prefix = "bft") -public class Settings { - - private String name; - - private String systemConfig = "config/system.config"; - - private String nodesConfig = "config/hosts.config"; - -// private String runtimeHome = "./runtime"; - - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - // =================================================================================================== - - public String getSystemConfig() { - return systemConfig; - } - - public void setSystemConfig(String systemConfig) { - this.systemConfig = systemConfig; - } - - public String getNodesConfig() { - return nodesConfig; - } - - public void setNodesConfig(String nodesConfig) { - this.nodesConfig = nodesConfig; - } - -// public String getRuntimeHome() { -// return runtimeHome; -// } -// -// public void setRuntimeHome(String runtimeHome) { -// this.runtimeHome = runtimeHome; -// } - -} +package test.perf.com.jd.blockchain.consensus.node; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * @author huanghaiquan + * + */ +@Configuration +@ConfigurationProperties(prefix = "bft") +public class Settings { + + private String name; + + private String systemConfig = "config/system.config"; + + private String nodesConfig = "config/hosts.config"; + +// private String runtimeHome = "./runtime"; + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + // =================================================================================================== + + public String getSystemConfig() { + return systemConfig; + } + + public void setSystemConfig(String systemConfig) { + this.systemConfig = systemConfig; + } + + public String getNodesConfig() { + return nodesConfig; + } + + public void setNodesConfig(String nodesConfig) { + this.nodesConfig = nodesConfig; + } + +// public String getRuntimeHome() { +// return runtimeHome; +// } +// +// public void setRuntimeHome(String runtimeHome) { +// this.runtimeHome = runtimeHome; +// } + +} diff --git a/source/test/test-consensus-node/src/main/java/test/perf/com/jd/blockchain/consensus/node/WebConfiguration.java b/source/test/test-consensus-node/src/main/java/test/perf/com/jd/blockchain/consensus/node/WebConfiguration.java index 34a4843a..1abe783b 100644 --- a/source/test/test-consensus-node/src/main/java/test/perf/com/jd/blockchain/consensus/node/WebConfiguration.java +++ b/source/test/test-consensus-node/src/main/java/test/perf/com/jd/blockchain/consensus/node/WebConfiguration.java @@ -1,11 +1,11 @@ -package test.perf.com.jd.blockchain.consensus.node; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ComponentScan -public class WebConfiguration { - -} - +package test.perf.com.jd.blockchain.consensus.node; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan +public class WebConfiguration { + +} + diff --git a/source/test/test-consensus-node/src/main/resources/application.properties b/source/test/test-consensus-node/src/main/resources/application.properties index bbe35d4d..626dd740 100644 --- a/source/test/test-consensus-node/src/main/resources/application.properties +++ b/source/test/test-consensus-node/src/main/resources/application.properties @@ -1,19 +1,19 @@ -server.port=9000 -#server.ssl.key-store=classpath:mykeys.jks -#server.ssl.key-store-password=abc123 -#server.ssl.key-password=abc123 - -server.tomcat.accesslog.enabled=false - -debug=false - -#logging.file=logs/peer.log -logging.level.com.jd.blockchain.peer=DEBUG -logging.level.org.org.springframework=DEBUG - -spring.mvc.favicon.enabled=false - -bft.name=node-0 -bft.nodes-config=config/hosts.config -bft.system-config=config/system.config +server.port=9000 +#server.ssl.key-store=classpath:mykeys.jks +#server.ssl.key-store-password=abc123 +#server.ssl.key-password=abc123 + +server.tomcat.accesslog.enabled=false + +debug=false + +#logging.file=logs/peer.log +logging.level.com.jd.blockchain.peer=DEBUG +logging.level.org.org.springframework=DEBUG + +spring.mvc.favicon.enabled=false + +bft.name=node-0 +bft.nodes-config=config/hosts.config +bft.system-config=config/system.config bft.runtime-home=config \ No newline at end of file diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionRequestBodyConverter.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionRequestBodyConverter.java index 5c7c72e2..e4483c15 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionRequestBodyConverter.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionRequestBodyConverter.java @@ -1,20 +1,20 @@ -package com.jd.blockchain.tools.initializer.web; - -import java.io.IOException; -import java.io.OutputStream; - -import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.utils.http.RequestBodyConverter; - -public class DecisionRequestBodyConverter implements RequestBodyConverter { - - @Override - public void write(Object param, OutputStream out) throws IOException { - if (param instanceof LedgerInitDecision) { - BinaryProtocol.encode(param, LedgerInitDecision.class, out); - return; - } - } - +package com.jd.blockchain.tools.initializer.web; + +import java.io.IOException; +import java.io.OutputStream; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.ledger.core.LedgerInitDecision; +import com.jd.blockchain.utils.http.RequestBodyConverter; + +public class DecisionRequestBodyConverter implements RequestBodyConverter { + + @Override + public void write(Object param, OutputStream out) throws IOException { + if (param instanceof LedgerInitDecision) { + BinaryProtocol.encode(param, LedgerInitDecision.class, out); + return; + } + } + } \ No newline at end of file diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionResponseConverter.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionResponseConverter.java index e9d3017d..862ff491 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionResponseConverter.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/DecisionResponseConverter.java @@ -1,23 +1,23 @@ -package com.jd.blockchain.tools.initializer.web; - -import java.io.InputStream; - -import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.ledger.LedgerInitException; -import com.jd.blockchain.utils.http.HttpServiceContext; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.agent.ServiceRequest; - -public class DecisionResponseConverter implements ResponseConverter { - - @Override - public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) - throws Exception { - LedgerInitResponse resp = LedgerInitResponse.resolve(responseStream); - if (resp.isError()) { - throw new LedgerInitException("Error occurred at remote participant! --" + resp.getErrorMessage()); - } - return BinaryProtocol.decode(resp.getData()); - } - -} +package com.jd.blockchain.tools.initializer.web; + +import java.io.InputStream; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.ledger.LedgerInitException; +import com.jd.blockchain.utils.http.HttpServiceContext; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.agent.ServiceRequest; + +public class DecisionResponseConverter implements ResponseConverter { + + @Override + public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) + throws Exception { + LedgerInitResponse resp = LedgerInitResponse.resolve(responseStream); + if (resp.isError()) { + throw new LedgerInitException("Error occurred at remote participant! --" + resp.getErrorMessage()); + } + return BinaryProtocol.decode(resp.getData()); + } + +} diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitServiceExceptionHandler.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitServiceExceptionHandler.java index 3a7d295f..753d3d33 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitServiceExceptionHandler.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitServiceExceptionHandler.java @@ -1,26 +1,26 @@ -package com.jd.blockchain.tools.initializer.web; - -import javax.servlet.http.HttpServletRequest; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -/** - * 全局异常处理类 - */ -@RestControllerAdvice -public class InitServiceExceptionHandler { - protected final Logger logger = LoggerFactory.getLogger(getClass()); - - @ExceptionHandler(value = Exception.class) - @ResponseBody - public LedgerInitResponse json(HttpServletRequest req, Exception ex) { -// logger.error("Error of web controllers! --" + ex.getMessage(), ex); - System.out.println("[InitServiceExceptionHandler] Error of web controllers! --" + ex.getMessage()); - return LedgerInitResponse.error(ex.getMessage()); - } - +package com.jd.blockchain.tools.initializer.web; + +import javax.servlet.http.HttpServletRequest; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * 全局异常处理类 + */ +@RestControllerAdvice +public class InitServiceExceptionHandler { + protected final Logger logger = LoggerFactory.getLogger(getClass()); + + @ExceptionHandler(value = Exception.class) + @ResponseBody + public LedgerInitResponse json(HttpServletRequest req, Exception ex) { +// logger.error("Error of web controllers! --" + ex.getMessage(), ex); + System.out.println("[InitServiceExceptionHandler] Error of web controllers! --" + ex.getMessage()); + return LedgerInitResponse.error(ex.getMessage()); + } + } \ No newline at end of file diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebSecurityConfiguration.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebSecurityConfiguration.java index cef38324..f997679a 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebSecurityConfiguration.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebSecurityConfiguration.java @@ -1,19 +1,19 @@ -package com.jd.blockchain.tools.initializer.web; - -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; - -@Configuration -@EnableWebSecurity -public class InitWebSecurityConfiguration extends WebSecurityConfigurerAdapter { - - - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests().anyRequest().permitAll(); - http.csrf().disable(); - } - -} +package com.jd.blockchain.tools.initializer.web; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableWebSecurity +public class InitWebSecurityConfiguration extends WebSecurityConfigurerAdapter { + + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().anyRequest().permitAll(); + http.csrf().disable(); + } + +} diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebServerConfiguration.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebServerConfiguration.java index 69195dad..a4fed1f2 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebServerConfiguration.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/InitWebServerConfiguration.java @@ -1,38 +1,38 @@ -package com.jd.blockchain.tools.initializer.web; - -import java.util.List; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; - -import com.jd.blockchain.ledger.core.LedgerManager; -import com.jd.blockchain.utils.io.ByteArray; -import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; - -@Configuration -@ComponentScan -public class InitWebServerConfiguration extends WebMvcConfigurerAdapter { - static { - JSONSerializeUtils.disableCircularReferenceDetect(); - JSONSerializeUtils.configStringSerializer(ByteArray.class); - } - - @Override - public void extendMessageConverters(List> converters) { - converters.add(0, new LedgerInitMessageConverter()); - } - - @Bean - public InitConsensusServiceFactory initCsServiceFactory() { - return new HttpInitConsensServiceFactory(); - } - - @Bean - public LedgerManager getLedgerManager() { - return new LedgerManager(); - } - -} +package com.jd.blockchain.tools.initializer.web; + +import java.util.List; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +import com.jd.blockchain.ledger.core.LedgerManager; +import com.jd.blockchain.utils.io.ByteArray; +import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; + +@Configuration +@ComponentScan +public class InitWebServerConfiguration extends WebMvcConfigurerAdapter { + static { + JSONSerializeUtils.disableCircularReferenceDetect(); + JSONSerializeUtils.configStringSerializer(ByteArray.class); + } + + @Override + public void extendMessageConverters(List> converters) { + converters.add(0, new LedgerInitMessageConverter()); + } + + @Bean + public InitConsensusServiceFactory initCsServiceFactory() { + return new HttpInitConsensServiceFactory(); + } + + @Bean + public LedgerManager getLedgerManager() { + return new LedgerManager(); + } + +} diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitMessageConverter.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitMessageConverter.java index 6361d6a1..d43d581f 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitMessageConverter.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/LedgerInitMessageConverter.java @@ -1,113 +1,113 @@ -package com.jd.blockchain.tools.initializer.web; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.springframework.http.HttpInputMessage; -import org.springframework.http.HttpOutputMessage; -import org.springframework.http.MediaType; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.http.converter.HttpMessageNotWritableException; - -import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.binaryproto.DataContractRegistry; -import com.jd.blockchain.crypto.SignatureDigest; -import com.jd.blockchain.ledger.core.LedgerInitDecision; -import com.jd.blockchain.ledger.core.LedgerInitProposal; -import com.jd.blockchain.ledger.core.LedgerInitProposalData; -import com.jd.blockchain.utils.io.BytesUtils; - -/** - * 针对二进制对象的序列化和反序列化的 HTTP 消息转换器; - * - * @author huanghaiquan - * - */ -public class LedgerInitMessageConverter implements HttpMessageConverter { - - public static final String CONTENT_TYPE_VALUE = "application/bin-obj"; - - public static final MediaType CONTENT_TYPE = MediaType.valueOf(CONTENT_TYPE_VALUE); - - private static final List SUPPORTED_MEDIA_TYPES = Collections.singletonList(CONTENT_TYPE); - - private static final Map, Class> SUPPORTED_CONTRACT_TYPES = new HashMap<>(); - - static { - DataContractRegistry.register(LedgerInitProposal.class); - DataContractRegistry.register(LedgerInitDecision.class); - - SUPPORTED_CONTRACT_TYPES.put(LedgerInitProposal.class, LedgerInitProposalData.class); - SUPPORTED_CONTRACT_TYPES.put(LedgerInitDecision.class, LedgerInitDecisionData.class); - - // SUPPORTED_CONTRACT_TYPES.add(LedgerInitResponse.class); - // DataContractRegistry.register(LedgerInitResponse.class); - } - - private boolean isSupported(Class clazz) { - return getContractType(clazz) != null; - } - - private Class getContractType(Class clazz) { - for (Class itf : SUPPORTED_CONTRACT_TYPES.keySet()) { - if (itf.isAssignableFrom(clazz)) { - return itf; - } - } - return null; - } - - @Override - public boolean canRead(Class clazz, MediaType mediaType) { - return CONTENT_TYPE.includes(mediaType) - && (clazz.isPrimitive() || SignatureDigest.class == clazz || isSupported(clazz)); - } - - @Override - public boolean canWrite(Class clazz, MediaType mediaType) { - return CONTENT_TYPE.includes(mediaType) && (clazz.isPrimitive() || LedgerInitResponse.class.isAssignableFrom(clazz) || isSupported(clazz)); - } - - @Override - public List getSupportedMediaTypes() { - return SUPPORTED_MEDIA_TYPES; - } - - @Override - public Object read(Class clazz, HttpInputMessage inputMessage) - throws IOException, HttpMessageNotReadableException { - if (SignatureDigest.class == clazz) { - byte[] signDigestBytes = BytesUtils.copyToBytes(inputMessage.getBody()); - return new SignatureDigest(signDigestBytes); - } - - Class contractType = getContractType(clazz); - Class implType = SUPPORTED_CONTRACT_TYPES.get(contractType); - return BinaryProtocol.decode(inputMessage.getBody()); - } - - @Override - public void write(Object t, MediaType contentType, HttpOutputMessage outputMessage) - throws IOException, HttpMessageNotWritableException { - LedgerInitResponse resp; - if (t == null) { - resp = LedgerInitResponse.success(null); - } else if (t instanceof LedgerInitResponse) { - resp = (LedgerInitResponse) t; - outputMessage.getBody().write(resp.toBytes()); - } else { - Class contractType = getContractType(t.getClass()); - if (contractType == null) { - throw new IllegalStateException("Unsupported type[" + t.getClass().getName() + "]!"); - } - byte[] data = BinaryProtocol.encode(t, contractType); - resp = LedgerInitResponse.success(data); - outputMessage.getBody().write(resp.toBytes()); - } - } - -} +package com.jd.blockchain.tools.initializer.web; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.binaryproto.DataContractRegistry; +import com.jd.blockchain.crypto.SignatureDigest; +import com.jd.blockchain.ledger.core.LedgerInitDecision; +import com.jd.blockchain.ledger.core.LedgerInitProposal; +import com.jd.blockchain.ledger.core.LedgerInitProposalData; +import com.jd.blockchain.utils.io.BytesUtils; + +/** + * 针对二进制对象的序列化和反序列化的 HTTP 消息转换器; + * + * @author huanghaiquan + * + */ +public class LedgerInitMessageConverter implements HttpMessageConverter { + + public static final String CONTENT_TYPE_VALUE = "application/bin-obj"; + + public static final MediaType CONTENT_TYPE = MediaType.valueOf(CONTENT_TYPE_VALUE); + + private static final List SUPPORTED_MEDIA_TYPES = Collections.singletonList(CONTENT_TYPE); + + private static final Map, Class> SUPPORTED_CONTRACT_TYPES = new HashMap<>(); + + static { + DataContractRegistry.register(LedgerInitProposal.class); + DataContractRegistry.register(LedgerInitDecision.class); + + SUPPORTED_CONTRACT_TYPES.put(LedgerInitProposal.class, LedgerInitProposalData.class); + SUPPORTED_CONTRACT_TYPES.put(LedgerInitDecision.class, LedgerInitDecisionData.class); + + // SUPPORTED_CONTRACT_TYPES.add(LedgerInitResponse.class); + // DataContractRegistry.register(LedgerInitResponse.class); + } + + private boolean isSupported(Class clazz) { + return getContractType(clazz) != null; + } + + private Class getContractType(Class clazz) { + for (Class itf : SUPPORTED_CONTRACT_TYPES.keySet()) { + if (itf.isAssignableFrom(clazz)) { + return itf; + } + } + return null; + } + + @Override + public boolean canRead(Class clazz, MediaType mediaType) { + return CONTENT_TYPE.includes(mediaType) + && (clazz.isPrimitive() || SignatureDigest.class == clazz || isSupported(clazz)); + } + + @Override + public boolean canWrite(Class clazz, MediaType mediaType) { + return CONTENT_TYPE.includes(mediaType) && (clazz.isPrimitive() || LedgerInitResponse.class.isAssignableFrom(clazz) || isSupported(clazz)); + } + + @Override + public List getSupportedMediaTypes() { + return SUPPORTED_MEDIA_TYPES; + } + + @Override + public Object read(Class clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + if (SignatureDigest.class == clazz) { + byte[] signDigestBytes = BytesUtils.copyToBytes(inputMessage.getBody()); + return new SignatureDigest(signDigestBytes); + } + + Class contractType = getContractType(clazz); + Class implType = SUPPORTED_CONTRACT_TYPES.get(contractType); + return BinaryProtocol.decode(inputMessage.getBody()); + } + + @Override + public void write(Object t, MediaType contentType, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + LedgerInitResponse resp; + if (t == null) { + resp = LedgerInitResponse.success(null); + } else if (t instanceof LedgerInitResponse) { + resp = (LedgerInitResponse) t; + outputMessage.getBody().write(resp.toBytes()); + } else { + Class contractType = getContractType(t.getClass()); + if (contractType == null) { + throw new IllegalStateException("Unsupported type[" + t.getClass().getName() + "]!"); + } + byte[] data = BinaryProtocol.encode(t, contractType); + resp = LedgerInitResponse.success(data); + outputMessage.getBody().write(resp.toBytes()); + } + } + +} diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/PermissionResponseConverter.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/PermissionResponseConverter.java index f291d6c9..685af45d 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/PermissionResponseConverter.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/PermissionResponseConverter.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.tools.initializer.web; - -import java.io.InputStream; - -import com.jd.blockchain.binaryproto.BinaryProtocol; -import com.jd.blockchain.ledger.LedgerInitException; -import com.jd.blockchain.ledger.core.LedgerInitProposalData; -import com.jd.blockchain.utils.http.HttpServiceContext; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.agent.ServiceRequest; - -public class PermissionResponseConverter implements ResponseConverter { - - @Override - public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) - throws Exception { - LedgerInitResponse resp = LedgerInitResponse.resolve(responseStream); - if (resp.isError()) { - throw new LedgerInitException("Error occurred at remote participant! --" + resp.getErrorMessage()); - } - return BinaryProtocol.decode(resp.getData()); - } - -} +package com.jd.blockchain.tools.initializer.web; + +import java.io.InputStream; + +import com.jd.blockchain.binaryproto.BinaryProtocol; +import com.jd.blockchain.ledger.LedgerInitException; +import com.jd.blockchain.ledger.core.LedgerInitProposalData; +import com.jd.blockchain.utils.http.HttpServiceContext; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.agent.ServiceRequest; + +public class PermissionResponseConverter implements ResponseConverter { + + @Override + public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) + throws Exception { + LedgerInitResponse resp = LedgerInitResponse.resolve(responseStream); + if (resp.isError()) { + throw new LedgerInitException("Error occurred at remote participant! --" + resp.getErrorMessage()); + } + return BinaryProtocol.decode(resp.getData()); + } + +} diff --git a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/SignatureDigestRequestBodyConverter.java b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/SignatureDigestRequestBodyConverter.java index ec6fc7c0..79abf7d5 100644 --- a/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/SignatureDigestRequestBodyConverter.java +++ b/source/tools/tools-initializer/src/main/java/com/jd/blockchain/tools/initializer/web/SignatureDigestRequestBodyConverter.java @@ -1,19 +1,19 @@ -package com.jd.blockchain.tools.initializer.web; - -import java.io.IOException; -import java.io.OutputStream; - -import com.jd.blockchain.crypto.SignatureDigest; -import com.jd.blockchain.utils.http.RequestBodyConverter; - -public class SignatureDigestRequestBodyConverter implements RequestBodyConverter { - - @Override - public void write(Object param, OutputStream out) throws IOException { - if (param instanceof SignatureDigest) { - out.write(((SignatureDigest)param).toBytes()); - return; - } - } - +package com.jd.blockchain.tools.initializer.web; + +import java.io.IOException; +import java.io.OutputStream; + +import com.jd.blockchain.crypto.SignatureDigest; +import com.jd.blockchain.utils.http.RequestBodyConverter; + +public class SignatureDigestRequestBodyConverter implements RequestBodyConverter { + + @Override + public void write(Object param, OutputStream out) throws IOException { + if (param instanceof SignatureDigest) { + out.write(((SignatureDigest)param).toBytes()); + return; + } + } + } \ No newline at end of file diff --git a/source/tools/tools-initializer/src/main/resources/META-INF/spring.factories b/source/tools/tools-initializer/src/main/resources/META-INF/spring.factories index 854f0848..459b87c8 100644 --- a/source/tools/tools-initializer/src/main/resources/META-INF/spring.factories +++ b/source/tools/tools-initializer/src/main/resources/META-INF/spring.factories @@ -1,2 +1,2 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.jd.blockchain.tools.initializer.InitializerConfiguration \ No newline at end of file diff --git a/source/tools/tools-initializer/src/main/resources/application.properties b/source/tools/tools-initializer/src/main/resources/application.properties index 16cdc6bf..892ff79d 100644 --- a/source/tools/tools-initializer/src/main/resources/application.properties +++ b/source/tools/tools-initializer/src/main/resources/application.properties @@ -1,13 +1,13 @@ -server.address=127.0.0.1 -server.port=8900 - -server.tomcat.accesslog.enabled=true - -debug=false - -logging.config=classpath:log4j2-init.xml -#logging.file=logs/peer.log -logging.level.com.jd.blockchain=DEBUG -logging.level.org.org.springframework=DEBUG - +server.address=127.0.0.1 +server.port=8900 + +server.tomcat.accesslog.enabled=true + +debug=false + +logging.config=classpath:log4j2-init.xml +#logging.file=logs/peer.log +logging.level.com.jd.blockchain=DEBUG +logging.level.org.org.springframework=DEBUG + spring.mvc.favicon.enabled=false \ No newline at end of file diff --git a/source/utils/.gitignore b/source/utils/.gitignore index bb88c990..49a77c09 100644 --- a/source/utils/.gitignore +++ b/source/utils/.gitignore @@ -1,23 +1,23 @@ -**.classpath -**.project -**/bin/ -**.class - -target/ - -*.bak -bin/ -*.iml -*.ipr -*.iws -.idea -.classpath -.project -.settings/ -.DS_Store -.springBeans -.externalToolBuilders/ - - -*.versionsBackup -.factorypath +**.classpath +**.project +**/bin/ +**.class + +target/ + +*.bak +bin/ +*.iml +*.ipr +*.iws +.idea +.classpath +.project +.settings/ +.DS_Store +.springBeans +.externalToolBuilders/ + + +*.versionsBackup +.factorypath diff --git a/source/utils/pom.xml b/source/utils/pom.xml index a9233b6d..4e50253c 100644 --- a/source/utils/pom.xml +++ b/source/utils/pom.xml @@ -1,59 +1,59 @@ - - 4.0.0 - - com.jd.blockchain - jdchain-root - 1.1.2.RELEASE - - utils - pom - - - utils-serialize - utils-web - utils-web-server - utils-common - utils-http - utils-test - - - - - junit - junit - test - - - org.mockito - mockito-core - test - - - - - - - net.i2p.crypto - eddsa - 0.1.0 - - - - - - + + 4.0.0 + + com.jd.blockchain + jdchain-root + 1.1.2.RELEASE + + utils + pom + + + utils-serialize + utils-web + utils-web-server + utils-common + utils-http + utils-test + + + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + + + + net.i2p.crypto + eddsa + 0.1.0 + + + + + + \ No newline at end of file diff --git a/source/utils/utils-common/.gitignore b/source/utils/utils-common/.gitignore index 24d64373..b83d2226 100644 --- a/source/utils/utils-common/.gitignore +++ b/source/utils/utils-common/.gitignore @@ -1 +1 @@ -/target/ +/target/ diff --git a/source/utils/utils-common/pom.xml b/source/utils/utils-common/pom.xml index 04fec308..60f71abf 100644 --- a/source/utils/utils-common/pom.xml +++ b/source/utils/utils-common/pom.xml @@ -1,103 +1,103 @@ - - 4.0.0 - - com.jd.blockchain - utils - 1.1.2.RELEASE - - utils-common - - - - - org.slf4j - slf4j-api - - - - commons-codec - commons-codec - - - - commons-io - commons-io - 2.4 - - - - net.i2p.crypto - eddsa - - - org.bouncycastle - bcprov-jdk15on - - - org.springframework - spring-beans - - - - org.bitbucket.mstrobel - procyon-core - - - org.bitbucket.mstrobel - procyon-expressions - - - org.bitbucket.mstrobel - procyon-reflection - - - org.bitbucket.mstrobel - procyon-compilertools - - - - - - - org.slf4j - slf4j-log4j12 - test - - - org.apache.logging.log4j - log4j-api - test - - - org.apache.logging.log4j - log4j-core - test - - - - - + + 4.0.0 + + com.jd.blockchain + utils + 1.1.2.RELEASE + + utils-common + + + + + org.slf4j + slf4j-api + + + + commons-codec + commons-codec + + + + commons-io + commons-io + 2.4 + + + + net.i2p.crypto + eddsa + + + org.bouncycastle + bcprov-jdk15on + + + org.springframework + spring-beans + + + + org.bitbucket.mstrobel + procyon-core + + + org.bitbucket.mstrobel + procyon-expressions + + + org.bitbucket.mstrobel + procyon-reflection + + + org.bitbucket.mstrobel + procyon-compilertools + + + + + + + org.slf4j + slf4j-log4j12 + test + + + org.apache.logging.log4j + log4j-api + test + + + org.apache.logging.log4j + log4j-core + test + + + + + \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java index cea92cbc..399aba80 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ArrayUtils.java @@ -1,122 +1,122 @@ -package com.jd.blockchain.utils; - -import java.lang.reflect.Array; -import java.util.*; - -/** - * @author haiq - * - */ -public abstract class ArrayUtils { - private ArrayUtils() { - - } - - public static R[] castTo(T[] objs, Class clazz, CastFunction cf) { - if (objs == null) { - return null; - } - @SuppressWarnings("unchecked") - R[] array = (R[]) Array.newInstance(clazz, objs.length); - for (int i = 0; i < objs.length; i++) { - array[i] = cf.cast(objs[i]); - } - return array; - } - - public static T[] singleton(T obj, Class clazz) { - @SuppressWarnings("unchecked") - T[] array = (T[]) Array.newInstance(clazz, 1); - array[0] = obj; - return array; - } - - public static T[] toArray(Iterator itr, Class clazz) { - List lst = new LinkedList(); - while (itr.hasNext()) { - T t = (T) itr.next(); - lst.add(t); - } - @SuppressWarnings("unchecked") - T[] array = (T[]) Array.newInstance(clazz, lst.size()); - lst.toArray(array); - return array; - } - - public static T[] toArray(Collection collection, Class clazz) { - @SuppressWarnings("unchecked") - T[] array = (T[]) Array.newInstance(clazz, collection.size()); - collection.toArray(array); - return array; - } - - public static List asList(T[] array) { - return asList(array, 0, array.length); - } - - public static Set asSet(T[] array) { - if (array == null || array.length == 0) { - return Collections.emptySet(); - } - HashSet set = new HashSet(); - for (T t : array) { - set.add(t); - } - return set; - } - - public static SortedSet asSortedSet(T[] array) { - if (array == null || array.length == 0) { - return Collections.emptySortedSet(); - } - TreeSet set = new TreeSet(); - for (T t : array) { - set.add(t); - } - return set; - } - - public static List asList(T[] array, int fromIndex) { - return asList(array, fromIndex, array.length); - } - - public static List asList(T[] array, int fromIndex, int toIndex) { - if (toIndex < fromIndex) { - throw new IllegalArgumentException("The toIndex less than fromIndex!"); - } - if (fromIndex < 0) { - throw new IllegalArgumentException("The fromIndex is negative!"); - } - if (toIndex > array.length) { - throw new IllegalArgumentException("The toIndex great than the length of array!"); - } - - if (fromIndex == toIndex) { - return Collections.emptyList(); - } - return new ReadonlyArrayListWrapper(array, fromIndex, toIndex); - } - - public static interface CastFunction { - public R cast(T data); - } - - /** - * Reverse all elements of the specified array;
- * - * @param - * @param array - */ - public static void reverse(T[] array) { - if (array == null || array.length < 2) { - return; - } - - T t; - for (int i = 0, j = array.length - 1; i < j; i++, j--) { - t = array[i]; - array[i] = array[j]; - array[j] = t; - } - } -} +package com.jd.blockchain.utils; + +import java.lang.reflect.Array; +import java.util.*; + +/** + * @author haiq + * + */ +public abstract class ArrayUtils { + private ArrayUtils() { + + } + + public static R[] castTo(T[] objs, Class clazz, CastFunction cf) { + if (objs == null) { + return null; + } + @SuppressWarnings("unchecked") + R[] array = (R[]) Array.newInstance(clazz, objs.length); + for (int i = 0; i < objs.length; i++) { + array[i] = cf.cast(objs[i]); + } + return array; + } + + public static T[] singleton(T obj, Class clazz) { + @SuppressWarnings("unchecked") + T[] array = (T[]) Array.newInstance(clazz, 1); + array[0] = obj; + return array; + } + + public static T[] toArray(Iterator itr, Class clazz) { + List lst = new LinkedList(); + while (itr.hasNext()) { + T t = (T) itr.next(); + lst.add(t); + } + @SuppressWarnings("unchecked") + T[] array = (T[]) Array.newInstance(clazz, lst.size()); + lst.toArray(array); + return array; + } + + public static T[] toArray(Collection collection, Class clazz) { + @SuppressWarnings("unchecked") + T[] array = (T[]) Array.newInstance(clazz, collection.size()); + collection.toArray(array); + return array; + } + + public static List asList(T[] array) { + return asList(array, 0, array.length); + } + + public static Set asSet(T[] array) { + if (array == null || array.length == 0) { + return Collections.emptySet(); + } + HashSet set = new HashSet(); + for (T t : array) { + set.add(t); + } + return set; + } + + public static SortedSet asSortedSet(T[] array) { + if (array == null || array.length == 0) { + return Collections.emptySortedSet(); + } + TreeSet set = new TreeSet(); + for (T t : array) { + set.add(t); + } + return set; + } + + public static List asList(T[] array, int fromIndex) { + return asList(array, fromIndex, array.length); + } + + public static List asList(T[] array, int fromIndex, int toIndex) { + if (toIndex < fromIndex) { + throw new IllegalArgumentException("The toIndex less than fromIndex!"); + } + if (fromIndex < 0) { + throw new IllegalArgumentException("The fromIndex is negative!"); + } + if (toIndex > array.length) { + throw new IllegalArgumentException("The toIndex great than the length of array!"); + } + + if (fromIndex == toIndex) { + return Collections.emptyList(); + } + return new ReadonlyArrayListWrapper(array, fromIndex, toIndex); + } + + public static interface CastFunction { + public R cast(T data); + } + + /** + * Reverse all elements of the specified array;
+ * + * @param + * @param array + */ + public static void reverse(T[] array) { + if (array == null || array.length < 2) { + return; + } + + T t; + for (int i = 0, j = array.length - 1; i < j; i++, j--) { + t = array[i]; + array[i] = array[j]; + array[j] = t; + } + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/AttributeMap.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/AttributeMap.java index 5722c50f..7bb98182 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/AttributeMap.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/AttributeMap.java @@ -1,35 +1,35 @@ -package com.jd.blockchain.utils; - -import java.util.Set; - -/** - * AttributeMap 定义字符串 key-value 属性表的通用访问接口; - * - * @author haiq - * - */ -public interface AttributeMap { - - /** - * 属性名称列表; - * - * @return String's set - */ - public Set getAttributeNames(); - - /** - * 是否包含指定名称的属性; - * @param name name; - * @return boolean - */ - public boolean containAttribute(String name); - - /** - * 返回指定名称的属性值; - * - * @param name name - * @return String - */ - public String getAttribute(String name); - -} +package com.jd.blockchain.utils; + +import java.util.Set; + +/** + * AttributeMap 定义字符串 key-value 属性表的通用访问接口; + * + * @author haiq + * + */ +public interface AttributeMap { + + /** + * 属性名称列表; + * + * @return String's set + */ + public Set getAttributeNames(); + + /** + * 是否包含指定名称的属性; + * @param name name; + * @return boolean + */ + public boolean containAttribute(String name); + + /** + * 返回指定名称的属性值; + * + * @param name name + * @return String + */ + public String getAttribute(String name); + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Attributes.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Attributes.java index 82e19fcc..1daf28ec 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Attributes.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Attributes.java @@ -1,25 +1,25 @@ -package com.jd.blockchain.utils; - -import java.util.Properties; -import java.util.Set; - -public class Attributes extends Properties implements AttributeMap { - - private static final long serialVersionUID = 142263972661078077L; - - @Override - public Set getAttributeNames() { - return stringPropertyNames(); - } - - @Override - public boolean containAttribute(String name) { - return containsKey(name); - } - - @Override - public String getAttribute(String name) { - return getProperty(name); - } - -} +package com.jd.blockchain.utils; + +import java.util.Properties; +import java.util.Set; + +public class Attributes extends Properties implements AttributeMap { + + private static final long serialVersionUID = 142263972661078077L; + + @Override + public Set getAttributeNames() { + return stringPropertyNames(); + } + + @Override + public boolean containAttribute(String name) { + return containsKey(name); + } + + @Override + public String getAttribute(String name) { + return getProperty(name); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java index 890748e5..97bdd9cd 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BaseConstant.java @@ -1,33 +1,33 @@ -package com.jd.blockchain.utils; - -/** - * - * @author zhaogw - * date 2018/5/4 14:20 - */ -public class BaseConstant { - public static final String DELIMETER_COMMA = ","; //逗号分隔符; - public static final String DELIMETER_SEMICOLON = ";"; //分号分隔符; - public static final String DELIMETER_SLASH = "/"; //斜线分隔符; - public static final String DELIMETER_DOT = "."; //点号分隔符; - public static final String DELIMETER_UNDERLINE = "_"; //斜线分隔符; - public static final String DELIMITER_EQUAL = "="; - public static final String DELIMETER_QUESTION = "?"; //逗号分隔符; - public static final String DELIMETER_DOUBLE_ALARM = "##"; //双警号分隔符; - public static final String CHARSET_UTF_8 = "utf-8"; //utf-8编码; - //合约系统使用的配置信息; - public static final String SYS_CONTRACT_CONF = "SYS_CONTRACT_CONF"; - 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 PACKAGE_BLACKLIST = "BLACKLIST"; - - //根据列表读取时,每次允许的最大获取数量; - public static final int QUERY_LIST_MAX=100; - - public static final String CONTRACT_SERVICE_PROVIDER = "com.jd.blockchain.contract.jvm.JVMContractServiceProvider"; - public static final String SPRING_CF_LOCATION = "-sp"; -} +package com.jd.blockchain.utils; + +/** + * + * @author zhaogw + * date 2018/5/4 14:20 + */ +public class BaseConstant { + public static final String DELIMETER_COMMA = ","; //逗号分隔符; + public static final String DELIMETER_SEMICOLON = ";"; //分号分隔符; + public static final String DELIMETER_SLASH = "/"; //斜线分隔符; + public static final String DELIMETER_DOT = "."; //点号分隔符; + public static final String DELIMETER_UNDERLINE = "_"; //斜线分隔符; + public static final String DELIMITER_EQUAL = "="; + public static final String DELIMETER_QUESTION = "?"; //逗号分隔符; + public static final String DELIMETER_DOUBLE_ALARM = "##"; //双警号分隔符; + public static final String CHARSET_UTF_8 = "utf-8"; //utf-8编码; + //合约系统使用的配置信息; + public static final String SYS_CONTRACT_CONF = "SYS_CONTRACT_CONF"; + 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 PACKAGE_BLACKLIST = "BLACKLIST"; + + //根据列表读取时,每次允许的最大获取数量; + public static final int QUERY_LIST_MAX=100; + + public static final String CONTRACT_SERVICE_PROVIDER = "com.jd.blockchain.contract.jvm.JVMContractServiceProvider"; + public static final String SPRING_CF_LOCATION = "-sp"; +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BusinessException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BusinessException.java index 5dc7fffa..f212a6eb 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BusinessException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/BusinessException.java @@ -1,47 +1,47 @@ -package com.jd.blockchain.utils; - -public class BusinessException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = -1934407327912767401L; - - private Integer errorCode; // 错误代码 - - public BusinessException() { - super(); - } - - public BusinessException(int errorCode) { - super(""); - this.errorCode = errorCode; - } - - public BusinessException(String message) { - super(message); - } - - public BusinessException(String message, Throwable throwable) { - super(message, throwable); - } - - public BusinessException(int code, String message) { - super(message); - this.errorCode = code; - } - - public BusinessException(int code, String message, Throwable throwable) { - super(message, throwable); - this.errorCode = code; - } - - public Integer getErrorCode() { - return errorCode; - } - - public void setErrorCode(int errorCode) { - this.errorCode = errorCode; - } - -} +package com.jd.blockchain.utils; + +public class BusinessException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = -1934407327912767401L; + + private Integer errorCode; // 错误代码 + + public BusinessException() { + super(); + } + + public BusinessException(int errorCode) { + super(""); + this.errorCode = errorCode; + } + + public BusinessException(String message) { + super(message); + } + + public BusinessException(String message, Throwable throwable) { + super(message, throwable); + } + + public BusinessException(int code, String message) { + super(message); + this.errorCode = code; + } + + public BusinessException(int code, String message, Throwable throwable) { + super(message, throwable); + this.errorCode = code; + } + + public Integer getErrorCode() { + return errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java index b02fa524..12ea5d54 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/DataEntry.java @@ -1,17 +1,17 @@ -package com.jd.blockchain.utils; - -/** - * Versioning Key-Value data entry; - * - * @author huanghaiquan - * - */ -public interface DataEntry { - - public K getKey(); - - public long getVersion(); - - public V getValue(); - +package com.jd.blockchain.utils; + +/** + * Versioning Key-Value data entry; + * + * @author huanghaiquan + * + */ +public interface DataEntry { + + public K getKey(); + + public long getVersion(); + + public V getValue(); + } \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Disposable.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Disposable.java index 5a72d94b..98eb973a 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Disposable.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/Disposable.java @@ -1,7 +1,7 @@ -package com.jd.blockchain.utils; - -public interface Disposable { - - public void dispose(); - -} +package com.jd.blockchain.utils; + +public interface Disposable { + + public void dispose(); + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/EmptyProperties.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/EmptyProperties.java index 285ce7fb..91607296 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/EmptyProperties.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/EmptyProperties.java @@ -1,111 +1,111 @@ -package com.jd.blockchain.utils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.InvalidPropertiesFormatException; -import java.util.Properties; -import java.util.Set; - -public class EmptyProperties extends Properties { - - private static final long serialVersionUID = 5941797426076447165L; - - public static Properties INSTANCE = new EmptyProperties(); - - private EmptyProperties() { - } - - @Override - public String getProperty(String key) { - return null; - } - - @Override - public String getProperty(String key, String defaultValue) { - return defaultValue; - } - - @Override - public Enumeration propertyNames() { - return Collections.enumeration(Collections.emptyList()); -// return Collections.emptyEnumeration(); - } - - @Override - public int size() { - return 0; - } - - @Override - public boolean isEmpty() { - return true; - } - - @Override - public boolean containsKey(Object key) { - return false; - } - - @Override - public boolean containsValue(Object value) { - return false; - } - - @Override - public synchronized Object get(Object key) { - return null; - } - - @SuppressWarnings("unchecked") - @Override - public Set keySet() { - return Collections.EMPTY_SET; - } - - @SuppressWarnings("unchecked") - @Override - public Collection values() { - return Collections.EMPTY_SET; - } - - @SuppressWarnings("unchecked") - @Override - public Set> entrySet() { - return Collections.EMPTY_SET; - } - - @Override - public synchronized void load(InputStream inStream) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void load(Reader reader) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException { - throw new UnsupportedOperationException(); - } - - @Override - public Object put(Object key, Object value) { - throw new UnsupportedOperationException(); - } - - @Override - public Enumeration keys() { - return Collections.enumeration(Collections.emptyList()); - } - - @Override - public Object setProperty(String key, String value) { - throw new UnsupportedOperationException(); - } - -} +package com.jd.blockchain.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.InvalidPropertiesFormatException; +import java.util.Properties; +import java.util.Set; + +public class EmptyProperties extends Properties { + + private static final long serialVersionUID = 5941797426076447165L; + + public static Properties INSTANCE = new EmptyProperties(); + + private EmptyProperties() { + } + + @Override + public String getProperty(String key) { + return null; + } + + @Override + public String getProperty(String key, String defaultValue) { + return defaultValue; + } + + @Override + public Enumeration propertyNames() { + return Collections.enumeration(Collections.emptyList()); +// return Collections.emptyEnumeration(); + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public boolean containsKey(Object key) { + return false; + } + + @Override + public boolean containsValue(Object value) { + return false; + } + + @Override + public synchronized Object get(Object key) { + return null; + } + + @SuppressWarnings("unchecked") + @Override + public Set keySet() { + return Collections.EMPTY_SET; + } + + @SuppressWarnings("unchecked") + @Override + public Collection values() { + return Collections.EMPTY_SET; + } + + @SuppressWarnings("unchecked") + @Override + public Set> entrySet() { + return Collections.EMPTY_SET; + } + + @Override + public synchronized void load(InputStream inStream) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void load(Reader reader) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void loadFromXML(InputStream in) throws IOException, InvalidPropertiesFormatException { + throw new UnsupportedOperationException(); + } + + @Override + public Object put(Object key, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration keys() { + return Collections.enumeration(Collections.emptyList()); + } + + @Override + public Object setProperty(String key, String value) { + throw new UnsupportedOperationException(); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/IllegalDataException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/IllegalDataException.java index d7abaef2..8d1f0da7 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/IllegalDataException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/IllegalDataException.java @@ -1,23 +1,23 @@ -package com.jd.blockchain.utils; - -/** - * 无效数据异常; - * - * @author haiq - * - */ -public class IllegalDataException extends RuntimeException{ - - private static final long serialVersionUID = 5834019788898871654L; - - public IllegalDataException() { - } - - public IllegalDataException(String message) { - super(message); - } - - public IllegalDataException(String message, Throwable cause) { - super(message, cause); - } -} +package com.jd.blockchain.utils; + +/** + * 无效数据异常; + * + * @author haiq + * + */ +public class IllegalDataException extends RuntimeException{ + + private static final long serialVersionUID = 5834019788898871654L; + + public IllegalDataException() { + } + + public IllegalDataException(String message) { + super(message); + } + + public IllegalDataException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/IteratorWrapper.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/IteratorWrapper.java index 7d898c30..8f8f8783 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/IteratorWrapper.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/IteratorWrapper.java @@ -1,33 +1,33 @@ -package com.jd.blockchain.utils; - -import java.util.Iterator; - -/** - * IteratorWrapper 是一个针对迭代器的适配器; - * - * @author haiq - * - * @param T1 - * @param T2 - */ -public abstract class IteratorWrapper implements Iterator { - - protected Iterator wrappedIterator; - - public IteratorWrapper(Iterator itr) { - this.wrappedIterator = itr; - } - - @Override - public boolean hasNext() { - return wrappedIterator.hasNext(); - } - - @Override - public T1 next() { - return wrap(wrappedIterator.next()); - } - - protected abstract T1 wrap(T2 t2); - -} +package com.jd.blockchain.utils; + +import java.util.Iterator; + +/** + * IteratorWrapper 是一个针对迭代器的适配器; + * + * @author haiq + * + * @param T1 + * @param T2 + */ +public abstract class IteratorWrapper implements Iterator { + + protected Iterator wrappedIterator; + + public IteratorWrapper(Iterator itr) { + this.wrappedIterator = itr; + } + + @Override + public boolean hasNext() { + return wrappedIterator.hasNext(); + } + + @Override + public T1 next() { + return wrap(wrappedIterator.next()); + } + + protected abstract T1 wrap(T2 t2); + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PathUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PathUtils.java index 4ba89daa..ba413010 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PathUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PathUtils.java @@ -1,117 +1,117 @@ -package com.jd.blockchain.utils; - -import org.springframework.util.StringUtils; - -public abstract class PathUtils { - - public static final String PATH_SEPERATOR = "/"; - public static final char PATH_SEPERATOR_CHAR = '/'; - - public static final String WINDOWS_PATH_SEPERATOR = "\\"; - - public static final String SCHEMA_SEPERATOR = ":"; - - /** - * 标准化指定的路径; - * - * 标准化的过程包括: - * 1、清理字符串中的 "."; - * 2、清除字符串中的 ".."以及路径中相应的上一级路径;(例如:ab/../cd 处理后变为 cd ) - * 2、将 windows 的分隔符"\"替换为标准分隔符"/"; - * 3、将连续重复的分隔符替换为单个分隔符; - * 4、去除结尾的分隔符; - * 5、去除其中的空白字符; - * - * 注:以冒号":"分隔的 schema 头将被保留; - * - * @param path path - * @return String - */ - public static String standardize(String path) { - path = StringUtils.trimAllWhitespace(path); - path = StringUtils.cleanPath(path); - path = cleanRepeatlySeperator(path); - if (path.endsWith(PATH_SEPERATOR)) { - return path.substring(0, path.length() - 1); - } - return path; - } - - /** - * 将指定的路径转换为绝对路径; - * - * 方法将检测指定的路径如果既没有以路径分隔符"/"开头,也没有冒号":"分隔的 schema 开头(例如 file:), - * - * 则在开头加上路径分隔符"/"返回; - * - * 注:方法不会检测路径是否标准,也不会自动将其标准化; - * - * @param path path - * @return String - */ - public static String absolute(String path) { - if (path.startsWith(PATH_SEPERATOR)) { - return path; - } - if (path.indexOf(SCHEMA_SEPERATOR) >= 0) { - return path; - } - return PATH_SEPERATOR + path; - } - - /** - * 清除路径中的重复分隔符; - * - * @param path path - * @return String - */ - public static String cleanRepeatlySeperator(String path) { - // 去除重复的分隔符; - String schema = ""; - String pathToProcess = path; - int index = path.indexOf("://"); - if (index >= 0) { - schema = path.substring(0, index + 3); - for (index = index + 3; index < path.length(); index++) { - if (path.charAt(index) != PATH_SEPERATOR_CHAR) { - break; - } - } - pathToProcess = path.substring(index); - } - StringBuilder pathToUse = new StringBuilder(); - boolean hit = false; - char ch; - for (int i = 0; i < pathToProcess.length(); i++) { - ch = pathToProcess.charAt(i); - if (ch == PATH_SEPERATOR_CHAR) { - if (hit) { - continue; - } else { - hit = true; - } - } else { - hit = false; - } - pathToUse.append(ch); - } - return schema + pathToUse; - } - - /** - * concatPaths - * @param paths path - * @return String - */ - public static String concatPaths(String... paths){ - if (paths == null || paths.length == 0) { - return ""; - } - StringBuilder path = new StringBuilder(); - for (String p : paths) { - path.append(p); - path.append(PATH_SEPERATOR_CHAR); - } - return standardize(path.toString()); - } -} +package com.jd.blockchain.utils; + +import org.springframework.util.StringUtils; + +public abstract class PathUtils { + + public static final String PATH_SEPERATOR = "/"; + public static final char PATH_SEPERATOR_CHAR = '/'; + + public static final String WINDOWS_PATH_SEPERATOR = "\\"; + + public static final String SCHEMA_SEPERATOR = ":"; + + /** + * 标准化指定的路径; + * + * 标准化的过程包括: + * 1、清理字符串中的 "."; + * 2、清除字符串中的 ".."以及路径中相应的上一级路径;(例如:ab/../cd 处理后变为 cd ) + * 2、将 windows 的分隔符"\"替换为标准分隔符"/"; + * 3、将连续重复的分隔符替换为单个分隔符; + * 4、去除结尾的分隔符; + * 5、去除其中的空白字符; + * + * 注:以冒号":"分隔的 schema 头将被保留; + * + * @param path path + * @return String + */ + public static String standardize(String path) { + path = StringUtils.trimAllWhitespace(path); + path = StringUtils.cleanPath(path); + path = cleanRepeatlySeperator(path); + if (path.endsWith(PATH_SEPERATOR)) { + return path.substring(0, path.length() - 1); + } + return path; + } + + /** + * 将指定的路径转换为绝对路径; + * + * 方法将检测指定的路径如果既没有以路径分隔符"/"开头,也没有冒号":"分隔的 schema 开头(例如 file:), + * + * 则在开头加上路径分隔符"/"返回; + * + * 注:方法不会检测路径是否标准,也不会自动将其标准化; + * + * @param path path + * @return String + */ + public static String absolute(String path) { + if (path.startsWith(PATH_SEPERATOR)) { + return path; + } + if (path.indexOf(SCHEMA_SEPERATOR) >= 0) { + return path; + } + return PATH_SEPERATOR + path; + } + + /** + * 清除路径中的重复分隔符; + * + * @param path path + * @return String + */ + public static String cleanRepeatlySeperator(String path) { + // 去除重复的分隔符; + String schema = ""; + String pathToProcess = path; + int index = path.indexOf("://"); + if (index >= 0) { + schema = path.substring(0, index + 3); + for (index = index + 3; index < path.length(); index++) { + if (path.charAt(index) != PATH_SEPERATOR_CHAR) { + break; + } + } + pathToProcess = path.substring(index); + } + StringBuilder pathToUse = new StringBuilder(); + boolean hit = false; + char ch; + for (int i = 0; i < pathToProcess.length(); i++) { + ch = pathToProcess.charAt(i); + if (ch == PATH_SEPERATOR_CHAR) { + if (hit) { + continue; + } else { + hit = true; + } + } else { + hit = false; + } + pathToUse.append(ch); + } + return schema + pathToUse; + } + + /** + * concatPaths + * @param paths path + * @return String + */ + public static String concatPaths(String... paths){ + if (paths == null || paths.length == 0) { + return ""; + } + StringBuilder path = new StringBuilder(); + for (String p : paths) { + path.append(p); + path.append(PATH_SEPERATOR_CHAR); + } + return standardize(path.toString()); + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PrimitiveUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PrimitiveUtils.java index 496e4951..e545d095 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PrimitiveUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PrimitiveUtils.java @@ -1,418 +1,418 @@ -package com.jd.blockchain.utils; - -import java.util.HashMap; -import java.util.Map; - -public class PrimitiveUtils { - - private static Map, Converter> converters = new HashMap, Converter>(); - - static { - converters.put(Boolean.class, new BooleanConverter()); - converters.put(boolean.class, new BooleanValueConverter()); - converters.put(Byte.class, new ByteConverter()); - converters.put(byte.class, new ByteValueConverter()); - converters.put(Character.class, new CharConverter()); - converters.put(char.class, new CharValueConverter()); - converters.put(Integer.class, new IntegerConverter()); - converters.put(int.class, new IntegerValueConverter()); - converters.put(Long.class, new LongConverter()); - converters.put(long.class, new LongValueConverter()); - converters.put(Double.class, new DoubleConverter()); - converters.put(double.class, new DoubleValueConverter()); - converters.put(Float.class, new FloatConverter()); - converters.put(float.class, new FloatValueConverter()); - } - - /** - * 判断指定的两个类型是否互为包装类; - * - * @param type1 type1 - * @param type2 type2 - * @return boolean - */ - public static boolean isWrapping(Class type1, Class type2) { - Converter converter = converters.get(type1); - return converter != null && converter.isWrapping(type2); - } - - /** - * 判断指定的类型是否是基本类型或者基本类型的包装类; - * - * @param clazz clazz - * @return boolean - */ - public static boolean isPrimitiveType(Class clazz) { - return converters.containsKey(clazz); - } - - /** - * 返回指定类型的默认值; - * - * 如果指定类型是原生类型,则返回默认的原始类型的值;否则,返回 null; - * - * @param clazz clazz - * @return Object - */ - public static Object getDefaultValue(Class clazz) { - Converter converter = converters.get(clazz); - if (converter == null) { - return null; - } - return converter.defaultValue(); - } - - /** - * 将指定的数据转为指定的类型;
- * 如果指定的类型不是基本类型,则总是返回 null; - * @param data data - * @param clazz clazz - * @param class - * @return T - */ - @SuppressWarnings("unchecked") - public static T castTo(Object data, Class clazz) { - Converter converter = converters.get(clazz); - if (converter == null) { - return null; - } - return (T) converter.convert(data); - } - - private static interface Converter { - - Object defaultValue(); - - Object convert(Object data); - - boolean isWrapping(Class type); - - } - - private static class BooleanConverter implements Converter { - - @Override - public Object convert(Object data) { - if (data == null) { - return null; - } - if (data instanceof Boolean) { - return (Boolean) data; - } - return Boolean.parseBoolean(data.toString()); - } - - @Override - public Object defaultValue() { - return null; - } - - @Override - public boolean isWrapping(Class type) { - return type == boolean.class || type == Boolean.class; - } - } - - private static class BooleanValueConverter extends BooleanConverter { - - @Override - public Object convert(Object data) { - Boolean value = (Boolean) super.convert(data); - if (value == null) { - return false; - } - return value; - } - - @Override - public Object defaultValue() { - return false; - } - } - - private static class CharConverter implements Converter { - - @Override - public Object convert(Object data) { - if (data == null) { - return null; - } - if (data instanceof Character) { - return (char) ((Character) data).charValue(); - } - if (data instanceof Byte) { - return (char) ((Byte) data).byteValue(); - } - if (data instanceof String) { - String str = (String) data; - if (str.length() == 1) { - return str.charAt(0); - } - } - throw new IllegalArgumentException("Cann't conver [" + data + "] to charater!"); - } - - @Override - public Object defaultValue() { - return null; - } - - @Override - public boolean isWrapping(Class type) { - return type == char.class || type == Character.class; - } - } - - private static class CharValueConverter extends CharConverter { - - @Override - public Object convert(Object data) { - Character value = (Character) super.convert(data); - if (value == null) { - throw new IllegalArgumentException("Cann't convert null charater to char!"); - } - return value; - } - - @Override - public Object defaultValue() { - return (char) 0; - } - } - - private static class ByteConverter implements Converter { - - @Override - public Object convert(Object data) { - if (data == null) { - return null; - } - if (data instanceof Byte) { - return (int) ((Byte) data).byteValue(); - } - return Byte.parseByte(data.toString()); - } - - @Override - public Object defaultValue() { - return null; - } - - @Override - public boolean isWrapping(Class type) { - return type == byte.class || type == Byte.class; - } - } - - private static class ByteValueConverter extends ByteConverter { - - @Override - public Object convert(Object data) { - Byte value = (Byte) super.convert(data); - if (value == null) { - return Byte.valueOf((byte) 0); - } - return value; - } - - @Override - public Object defaultValue() { - return (byte) 0; - } - } - - private static class IntegerConverter implements Converter { - - @Override - public Object convert(Object data) { - if (data == null) { - return null; - } - if (data instanceof Integer) { - return (Integer) data; - } - if (data instanceof Byte) { - return ((Byte) data).intValue(); - } - return Integer.parseInt(data.toString()); - } - - @Override - public Object defaultValue() { - return null; - } - - @Override - public boolean isWrapping(Class type) { - return type == int.class || type == Integer.class; - } - } - - private static class IntegerValueConverter extends IntegerConverter { - - @Override - public Object convert(Object data) { - Integer value = (Integer) super.convert(data); - if (value == null) { - return 0; - } - return value; - } - - @Override - public Object defaultValue() { - return (int) 0; - } - } - - private static class LongConverter implements Converter { - - @Override - public Object convert(Object data) { - if (data == null) { - return null; - } - if (data instanceof Long) { - return (Long) data; - } - if (data instanceof Integer) { - return ((Integer) data).longValue(); - } - if (data instanceof Byte) { - return ((Byte) data).longValue(); - } - return Long.parseLong(data.toString()); - } - - @Override - public Object defaultValue() { - return null; - } - - @Override - public boolean isWrapping(Class type) { - return type == long.class || type == Long.class; - } - } - - private static class LongValueConverter extends LongConverter { - - @Override - public Object convert(Object data) { - Long value = (Long) super.convert(data); - if (value == null) { - return Long.valueOf(0); - } - return value; - } - - @Override - public Object defaultValue() { - return 0L; - } - } - - private static class DoubleConverter implements Converter { - - @Override - public Object convert(Object data) { - if (data == null) { - return null; - } - if (data instanceof Double) { - return (Double) data; - } - if (data instanceof Float) { - return ((Float) data).doubleValue(); - } - if (data instanceof Long) { - return ((Long) data).doubleValue(); - } - if (data instanceof Integer) { - return ((Integer) data).doubleValue(); - } - if (data instanceof Byte) { - return ((Byte) data).doubleValue(); - } - return Double.parseDouble(data.toString()); - } - - @Override - public Object defaultValue() { - return null; - } - - @Override - public boolean isWrapping(Class type) { - return type == double.class || type == Double.class; - } - } - - private static class DoubleValueConverter extends DoubleConverter { - - @Override - public Object convert(Object data) { - Long value = (Long) super.convert(data); - if (value == null) { - return Long.valueOf(0); - } - return value; - } - - @Override - public Object defaultValue() { - return (double) 0; - } - } - - private static class FloatConverter implements Converter { - - @Override - public Object convert(Object data) { - if (data == null) { - return null; - } - if (data instanceof Float) { - return (Float) data; - } - if (data instanceof Long) { - return ((Long) data).floatValue(); - } - if (data instanceof Integer) { - return ((Integer) data).floatValue(); - } - if (data instanceof Byte) { - return ((Byte) data).floatValue(); - } - return Float.parseFloat(data.toString()); - } - - @Override - public Object defaultValue() { - return null; - } - - @Override - public boolean isWrapping(Class type) { - return type == float.class || type == Float.class; - } - } - - private static class FloatValueConverter extends FloatConverter { - private static final Float DEFAULT_FLOAT = Float.valueOf(0); - - @Override - public Object convert(Object data) { - Float value = (Float) super.convert(data); - if (value == null) { - return DEFAULT_FLOAT; - } - return value; - } - - @Override - public Object defaultValue() { - return (float) 0; - } - } -} +package com.jd.blockchain.utils; + +import java.util.HashMap; +import java.util.Map; + +public class PrimitiveUtils { + + private static Map, Converter> converters = new HashMap, Converter>(); + + static { + converters.put(Boolean.class, new BooleanConverter()); + converters.put(boolean.class, new BooleanValueConverter()); + converters.put(Byte.class, new ByteConverter()); + converters.put(byte.class, new ByteValueConverter()); + converters.put(Character.class, new CharConverter()); + converters.put(char.class, new CharValueConverter()); + converters.put(Integer.class, new IntegerConverter()); + converters.put(int.class, new IntegerValueConverter()); + converters.put(Long.class, new LongConverter()); + converters.put(long.class, new LongValueConverter()); + converters.put(Double.class, new DoubleConverter()); + converters.put(double.class, new DoubleValueConverter()); + converters.put(Float.class, new FloatConverter()); + converters.put(float.class, new FloatValueConverter()); + } + + /** + * 判断指定的两个类型是否互为包装类; + * + * @param type1 type1 + * @param type2 type2 + * @return boolean + */ + public static boolean isWrapping(Class type1, Class type2) { + Converter converter = converters.get(type1); + return converter != null && converter.isWrapping(type2); + } + + /** + * 判断指定的类型是否是基本类型或者基本类型的包装类; + * + * @param clazz clazz + * @return boolean + */ + public static boolean isPrimitiveType(Class clazz) { + return converters.containsKey(clazz); + } + + /** + * 返回指定类型的默认值; + * + * 如果指定类型是原生类型,则返回默认的原始类型的值;否则,返回 null; + * + * @param clazz clazz + * @return Object + */ + public static Object getDefaultValue(Class clazz) { + Converter converter = converters.get(clazz); + if (converter == null) { + return null; + } + return converter.defaultValue(); + } + + /** + * 将指定的数据转为指定的类型;
+ * 如果指定的类型不是基本类型,则总是返回 null; + * @param data data + * @param clazz clazz + * @param class + * @return T + */ + @SuppressWarnings("unchecked") + public static T castTo(Object data, Class clazz) { + Converter converter = converters.get(clazz); + if (converter == null) { + return null; + } + return (T) converter.convert(data); + } + + private static interface Converter { + + Object defaultValue(); + + Object convert(Object data); + + boolean isWrapping(Class type); + + } + + private static class BooleanConverter implements Converter { + + @Override + public Object convert(Object data) { + if (data == null) { + return null; + } + if (data instanceof Boolean) { + return (Boolean) data; + } + return Boolean.parseBoolean(data.toString()); + } + + @Override + public Object defaultValue() { + return null; + } + + @Override + public boolean isWrapping(Class type) { + return type == boolean.class || type == Boolean.class; + } + } + + private static class BooleanValueConverter extends BooleanConverter { + + @Override + public Object convert(Object data) { + Boolean value = (Boolean) super.convert(data); + if (value == null) { + return false; + } + return value; + } + + @Override + public Object defaultValue() { + return false; + } + } + + private static class CharConverter implements Converter { + + @Override + public Object convert(Object data) { + if (data == null) { + return null; + } + if (data instanceof Character) { + return (char) ((Character) data).charValue(); + } + if (data instanceof Byte) { + return (char) ((Byte) data).byteValue(); + } + if (data instanceof String) { + String str = (String) data; + if (str.length() == 1) { + return str.charAt(0); + } + } + throw new IllegalArgumentException("Cann't conver [" + data + "] to charater!"); + } + + @Override + public Object defaultValue() { + return null; + } + + @Override + public boolean isWrapping(Class type) { + return type == char.class || type == Character.class; + } + } + + private static class CharValueConverter extends CharConverter { + + @Override + public Object convert(Object data) { + Character value = (Character) super.convert(data); + if (value == null) { + throw new IllegalArgumentException("Cann't convert null charater to char!"); + } + return value; + } + + @Override + public Object defaultValue() { + return (char) 0; + } + } + + private static class ByteConverter implements Converter { + + @Override + public Object convert(Object data) { + if (data == null) { + return null; + } + if (data instanceof Byte) { + return (int) ((Byte) data).byteValue(); + } + return Byte.parseByte(data.toString()); + } + + @Override + public Object defaultValue() { + return null; + } + + @Override + public boolean isWrapping(Class type) { + return type == byte.class || type == Byte.class; + } + } + + private static class ByteValueConverter extends ByteConverter { + + @Override + public Object convert(Object data) { + Byte value = (Byte) super.convert(data); + if (value == null) { + return Byte.valueOf((byte) 0); + } + return value; + } + + @Override + public Object defaultValue() { + return (byte) 0; + } + } + + private static class IntegerConverter implements Converter { + + @Override + public Object convert(Object data) { + if (data == null) { + return null; + } + if (data instanceof Integer) { + return (Integer) data; + } + if (data instanceof Byte) { + return ((Byte) data).intValue(); + } + return Integer.parseInt(data.toString()); + } + + @Override + public Object defaultValue() { + return null; + } + + @Override + public boolean isWrapping(Class type) { + return type == int.class || type == Integer.class; + } + } + + private static class IntegerValueConverter extends IntegerConverter { + + @Override + public Object convert(Object data) { + Integer value = (Integer) super.convert(data); + if (value == null) { + return 0; + } + return value; + } + + @Override + public Object defaultValue() { + return (int) 0; + } + } + + private static class LongConverter implements Converter { + + @Override + public Object convert(Object data) { + if (data == null) { + return null; + } + if (data instanceof Long) { + return (Long) data; + } + if (data instanceof Integer) { + return ((Integer) data).longValue(); + } + if (data instanceof Byte) { + return ((Byte) data).longValue(); + } + return Long.parseLong(data.toString()); + } + + @Override + public Object defaultValue() { + return null; + } + + @Override + public boolean isWrapping(Class type) { + return type == long.class || type == Long.class; + } + } + + private static class LongValueConverter extends LongConverter { + + @Override + public Object convert(Object data) { + Long value = (Long) super.convert(data); + if (value == null) { + return Long.valueOf(0); + } + return value; + } + + @Override + public Object defaultValue() { + return 0L; + } + } + + private static class DoubleConverter implements Converter { + + @Override + public Object convert(Object data) { + if (data == null) { + return null; + } + if (data instanceof Double) { + return (Double) data; + } + if (data instanceof Float) { + return ((Float) data).doubleValue(); + } + if (data instanceof Long) { + return ((Long) data).doubleValue(); + } + if (data instanceof Integer) { + return ((Integer) data).doubleValue(); + } + if (data instanceof Byte) { + return ((Byte) data).doubleValue(); + } + return Double.parseDouble(data.toString()); + } + + @Override + public Object defaultValue() { + return null; + } + + @Override + public boolean isWrapping(Class type) { + return type == double.class || type == Double.class; + } + } + + private static class DoubleValueConverter extends DoubleConverter { + + @Override + public Object convert(Object data) { + Long value = (Long) super.convert(data); + if (value == null) { + return Long.valueOf(0); + } + return value; + } + + @Override + public Object defaultValue() { + return (double) 0; + } + } + + private static class FloatConverter implements Converter { + + @Override + public Object convert(Object data) { + if (data == null) { + return null; + } + if (data instanceof Float) { + return (Float) data; + } + if (data instanceof Long) { + return ((Long) data).floatValue(); + } + if (data instanceof Integer) { + return ((Integer) data).floatValue(); + } + if (data instanceof Byte) { + return ((Byte) data).floatValue(); + } + return Float.parseFloat(data.toString()); + } + + @Override + public Object defaultValue() { + return null; + } + + @Override + public boolean isWrapping(Class type) { + return type == float.class || type == Float.class; + } + } + + private static class FloatValueConverter extends FloatConverter { + private static final Float DEFAULT_FLOAT = Float.valueOf(0); + + @Override + public Object convert(Object data) { + Float value = (Float) super.convert(data); + if (value == null) { + return DEFAULT_FLOAT; + } + return value; + } + + @Override + public Object defaultValue() { + return (float) 0; + } + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java index aaaed113..6f30093e 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/PropertiesUtils.java @@ -1,337 +1,337 @@ -package com.jd.blockchain.utils; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.util.Arrays; -import java.util.Properties; -import java.util.Set; - -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.beans.MutablePropertyValues; -import org.springframework.core.io.FileSystemResource; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; - -/** - * PropertiesUtils 定义了从 properties 文件到 pojo 对象的转换方法; - * - * 用于对充当配置文件的 properties 文件到定义了配置信息的 POJO 的转换; - * - * 支持 properties 的 key 到 POJO 的字段转换,支持层级的 key 的转换,例如: "user.name" 到 user 字段的对象的 - * name 属性; - * - * @author haiq - * - */ -public abstract class PropertiesUtils { - - private PropertiesUtils() { - } - - /** - * 创建配置对象的实例,并且从指定的属性表中初始化对应的实例字段; - * - * @param configClass configClass - * @param properties properties - * @param T - * @return T - */ - @SuppressWarnings("unchecked") - public static T createInstance(Class configClass, Properties properties) { - BeanWrapper confBean = new BeanWrapperImpl(configClass); - confBean.setAutoGrowNestedPaths(true); - - MutablePropertyValues values = new MutablePropertyValues(properties); - confBean.setPropertyValues(values, true); - - return (T) confBean.getWrappedInstance(); - } - - /** - * 创建配置对象的实例,并且从指定的属性表中初始化对应的实例字段; - * - * @param configClass 配置对象的类型; - * @param properties 属性表; - * @param propsPrefix 在属性表中与配置对象相关的属性的key的前缀; - * @param T - * @return T - */ - public static T createInstance(Class configClass, Properties properties, String propsPrefix) { - if (propsPrefix == null || propsPrefix.trim().length() == 0) { - return createInstance(configClass, properties); - } - propsPrefix = propsPrefix.trim(); - Properties configProperties = subset(properties, propsPrefix, true); - return createInstance(configClass, configProperties); - } - - /** - * 设置配置值; - * - * @param obj 配置对象;配置值将设置到此对象匹配的属性; - * @param configValues 配置值; - * @param propPrefix 自动加入的属性前缀; - */ - public static void setValues(Object obj, Properties configValues, String propPrefix) { - Properties values = new Properties(); - setValues(obj, values); - mergeFrom(configValues, values, propPrefix); - } - - /** - * 设置配置值; - * - * @param obj 配置对象;配置值将设置到此对象匹配的属性; - * @param configValues 配置值; - */ - public static void setValues(Object obj, Properties configValues) { - BeanWrapper confBean = new BeanWrapperImpl(obj); - confBean.setAutoGrowNestedPaths(true); - - MutablePropertyValues values = new MutablePropertyValues(configValues); - confBean.setPropertyValues(values, true); - } - - /** - * 从指定的路径加载配置; - * - * @param configClass 配置对象的类型; - * @param configFilePathPattern properties配置文件的路径;可以指定 spring 资源路径表达式; - * @param charset 字符集; - * @param class - * @return T - * @throws IOException exception - */ - public static T load(Class configClass, String configFilePathPattern, String charset) throws IOException { - Properties props = loadProperties(configFilePathPattern, charset); - return createInstance(configClass, props); - } - - /** - * 从指定的路径加载配置; - * - * @param obj 配置对象;配置文件的值将设置到此对象匹配的属性; - * @param configFilePathPattern properties配置文件的路径;可以指定 spring 资源路径表达式; - * @param charset 字符集; - * @throws IOException exception - */ - public static void load(Object obj, String configFilePathPattern, String charset) throws IOException { - Properties props = loadProperties(configFilePathPattern, charset); - setValues(obj, props); - } - - public static Properties loadProperties(String configFilePathPattern, String charset) throws IOException { - ResourcePatternResolver resResolver = new PathMatchingResourcePatternResolver(); - Resource configResource = resResolver.getResource(configFilePathPattern); - InputStream in = configResource.getInputStream(); - try { - return load(in, charset); - } finally { - in.close(); - } - } - - public static Properties loadProperties(File configFile, String charset) throws IOException { - FileSystemResource resource = new FileSystemResource(configFile); - InputStream in = resource.getInputStream(); - try { - return load(in, charset); - } finally { - in.close(); - } - } - - public static Properties load(InputStream in, String charset) throws IOException { - Properties props = new Properties(); - InputStreamReader reader = new InputStreamReader(in, charset); - try { - props.load(reader); - } finally { - reader.close(); - } - return props; - } - - public static Properties load(byte[] bytes, String charset) throws IOException { - ByteArrayInputStream in = new ByteArrayInputStream(bytes); - return load(in, charset); - } - - /** - * 合并两个 properties ; - * - * @param props 要将其它值合并进来的属性集合;操作将对其产生修改; - * @param from 属性值将要合并进入其它属性集合;操作不对其产生修改; - */ - public static void mergeFrom(Properties props, Properties from) { - mergeFrom(props, from, null); - } - - /** - * 合并两个 properties ; - * - * @param props 要将其它值合并进来的属性集合;操作将对其产生修改; - * @param from 属性值将要合并进入其它属性集合;操作不对其产生修改; - * @param propertyNamePrefix 属性名称前缀; - */ - public static void mergeFrom(Properties props, Properties from, String propertyNamePrefix) { - if (propertyNamePrefix == null || propertyNamePrefix.length() == 0) { - for (String name : from.stringPropertyNames()) { - props.setProperty(name, from.getProperty(name)); - } - } else { - for (String name : from.stringPropertyNames()) { - props.setProperty(propertyNamePrefix + name, from.getProperty(name)); - } - } - } - - /** - * 获取指定 properties 中以指定的前缀开头的子集; - * - * @param props 要抽取的属性集合; - * @param propertyNamePrefix 属性名称前缀; - * @param trimPrefix 是否在复制的新的属性集合去掉指定的前缀; - * @return properties - */ - public static Properties subset(Properties props, String propertyNamePrefix, boolean trimPrefix) { - Properties subProperties = new Properties(); - Set names = props.stringPropertyNames(); - String newName; - for (String name : names) { - if (name.startsWith(propertyNamePrefix)) { - newName = name; - if (trimPrefix) { - newName = name.substring(propertyNamePrefix.length()); - } - subProperties.setProperty(newName, props.getProperty(name)); - } - } - return subProperties; - } - - public static Properties cloneFrom(Properties props) { - Properties newProps = new Properties(); - Set names = props.stringPropertyNames(); - for (String name : names) { - newProps.setProperty(name, props.getProperty(name)); - } - return newProps; - } - - public static byte[] toBytes(Properties props, String charsetName) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(out, charsetName); - try { - props.store(writer, null); - writer.flush(); - } finally { - writer.close(); - } - return out.toByteArray(); - } catch (IOException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - public static int getInt(Properties props, String key) { - String value = getRequiredProperty(props, key); - return Integer.parseInt(value); - } - - public static boolean getBoolean(Properties props, String key) { - String value = getRequiredProperty(props, key); - return Boolean.parseBoolean(value); - } - - public static boolean getBooleanOptional(Properties props, String key, boolean defaultValue) { - String value = getProperty(props, key, false); - if (value == null) { - return defaultValue; - } - return Boolean.parseBoolean(value); - } - - /** - * 返回指定的属性;
- * 如果不存在,或者返回值为空(null 或 空白字符),则抛出 {@link IllegalArgumentException} 异常; - * - * @param props props - * @param key key - * @return String - */ - public static String getRequiredProperty(Properties props, String key) { - return getProperty(props, key, true); - } - - public static String getOptionalProperty(Properties props, String key) { - return getProperty(props, key, false); - } - - public static String getOptionalProperty(Properties props, String key, String defaultValue) { - String value = getProperty(props, key, false); - if (value == null) { - return defaultValue; - } - return value; - } - - /** - * 返回指定的属性;
- * - * @param props 属性表; - * @param key 要查找的 key; - * @param required 值为 false 时,如果不存在则返回 null;值为 true 时,如果不存在,或者返回值为空(null 或 - * 空白字符),则抛出 {@link IllegalArgumentException} 异常; - * @return - */ - public static String getProperty(Properties props, String key, boolean required) { - String value = props.getProperty(key); - if (value == null) { - if (required) { - throw new IllegalArgumentException("Miss property[" + key + "]!"); - } - return null; - } - value = value.trim(); - if (value.length() == 0) { - if (required) { - throw new IllegalArgumentException("Miss property[" + key + "]!"); - } - return null; - } - return value; - - } - - public static Property[] getOrderedValues(Properties props) { - Property[] values = new Property[props.size()]; - String[] propNames = props.stringPropertyNames().toArray(new String[props.size()]); - Arrays.sort(propNames, (n1, n2) -> n1.compareTo(n2)); - for (int i = 0; i < propNames.length; i++) { - values[i] = new Property(propNames[i], props.getProperty(propNames[i])); - } - return values; - } - - public static Properties createProperties(Property[] propValues) { - Properties props = new Properties(); - setValues(props, propValues); - return props; - } - - public static Properties setValues(Properties props, Property[] propValues) { - for (Property p : propValues) { - props.setProperty(p.getName(), p.getValue()); - } - return props; - } -} +package com.jd.blockchain.utils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.util.Arrays; +import java.util.Properties; +import java.util.Set; + +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; + +/** + * PropertiesUtils 定义了从 properties 文件到 pojo 对象的转换方法; + * + * 用于对充当配置文件的 properties 文件到定义了配置信息的 POJO 的转换; + * + * 支持 properties 的 key 到 POJO 的字段转换,支持层级的 key 的转换,例如: "user.name" 到 user 字段的对象的 + * name 属性; + * + * @author haiq + * + */ +public abstract class PropertiesUtils { + + private PropertiesUtils() { + } + + /** + * 创建配置对象的实例,并且从指定的属性表中初始化对应的实例字段; + * + * @param configClass configClass + * @param properties properties + * @param T + * @return T + */ + @SuppressWarnings("unchecked") + public static T createInstance(Class configClass, Properties properties) { + BeanWrapper confBean = new BeanWrapperImpl(configClass); + confBean.setAutoGrowNestedPaths(true); + + MutablePropertyValues values = new MutablePropertyValues(properties); + confBean.setPropertyValues(values, true); + + return (T) confBean.getWrappedInstance(); + } + + /** + * 创建配置对象的实例,并且从指定的属性表中初始化对应的实例字段; + * + * @param configClass 配置对象的类型; + * @param properties 属性表; + * @param propsPrefix 在属性表中与配置对象相关的属性的key的前缀; + * @param T + * @return T + */ + public static T createInstance(Class configClass, Properties properties, String propsPrefix) { + if (propsPrefix == null || propsPrefix.trim().length() == 0) { + return createInstance(configClass, properties); + } + propsPrefix = propsPrefix.trim(); + Properties configProperties = subset(properties, propsPrefix, true); + return createInstance(configClass, configProperties); + } + + /** + * 设置配置值; + * + * @param obj 配置对象;配置值将设置到此对象匹配的属性; + * @param configValues 配置值; + * @param propPrefix 自动加入的属性前缀; + */ + public static void setValues(Object obj, Properties configValues, String propPrefix) { + Properties values = new Properties(); + setValues(obj, values); + mergeFrom(configValues, values, propPrefix); + } + + /** + * 设置配置值; + * + * @param obj 配置对象;配置值将设置到此对象匹配的属性; + * @param configValues 配置值; + */ + public static void setValues(Object obj, Properties configValues) { + BeanWrapper confBean = new BeanWrapperImpl(obj); + confBean.setAutoGrowNestedPaths(true); + + MutablePropertyValues values = new MutablePropertyValues(configValues); + confBean.setPropertyValues(values, true); + } + + /** + * 从指定的路径加载配置; + * + * @param configClass 配置对象的类型; + * @param configFilePathPattern properties配置文件的路径;可以指定 spring 资源路径表达式; + * @param charset 字符集; + * @param class + * @return T + * @throws IOException exception + */ + public static T load(Class configClass, String configFilePathPattern, String charset) throws IOException { + Properties props = loadProperties(configFilePathPattern, charset); + return createInstance(configClass, props); + } + + /** + * 从指定的路径加载配置; + * + * @param obj 配置对象;配置文件的值将设置到此对象匹配的属性; + * @param configFilePathPattern properties配置文件的路径;可以指定 spring 资源路径表达式; + * @param charset 字符集; + * @throws IOException exception + */ + public static void load(Object obj, String configFilePathPattern, String charset) throws IOException { + Properties props = loadProperties(configFilePathPattern, charset); + setValues(obj, props); + } + + public static Properties loadProperties(String configFilePathPattern, String charset) throws IOException { + ResourcePatternResolver resResolver = new PathMatchingResourcePatternResolver(); + Resource configResource = resResolver.getResource(configFilePathPattern); + InputStream in = configResource.getInputStream(); + try { + return load(in, charset); + } finally { + in.close(); + } + } + + public static Properties loadProperties(File configFile, String charset) throws IOException { + FileSystemResource resource = new FileSystemResource(configFile); + InputStream in = resource.getInputStream(); + try { + return load(in, charset); + } finally { + in.close(); + } + } + + public static Properties load(InputStream in, String charset) throws IOException { + Properties props = new Properties(); + InputStreamReader reader = new InputStreamReader(in, charset); + try { + props.load(reader); + } finally { + reader.close(); + } + return props; + } + + public static Properties load(byte[] bytes, String charset) throws IOException { + ByteArrayInputStream in = new ByteArrayInputStream(bytes); + return load(in, charset); + } + + /** + * 合并两个 properties ; + * + * @param props 要将其它值合并进来的属性集合;操作将对其产生修改; + * @param from 属性值将要合并进入其它属性集合;操作不对其产生修改; + */ + public static void mergeFrom(Properties props, Properties from) { + mergeFrom(props, from, null); + } + + /** + * 合并两个 properties ; + * + * @param props 要将其它值合并进来的属性集合;操作将对其产生修改; + * @param from 属性值将要合并进入其它属性集合;操作不对其产生修改; + * @param propertyNamePrefix 属性名称前缀; + */ + public static void mergeFrom(Properties props, Properties from, String propertyNamePrefix) { + if (propertyNamePrefix == null || propertyNamePrefix.length() == 0) { + for (String name : from.stringPropertyNames()) { + props.setProperty(name, from.getProperty(name)); + } + } else { + for (String name : from.stringPropertyNames()) { + props.setProperty(propertyNamePrefix + name, from.getProperty(name)); + } + } + } + + /** + * 获取指定 properties 中以指定的前缀开头的子集; + * + * @param props 要抽取的属性集合; + * @param propertyNamePrefix 属性名称前缀; + * @param trimPrefix 是否在复制的新的属性集合去掉指定的前缀; + * @return properties + */ + public static Properties subset(Properties props, String propertyNamePrefix, boolean trimPrefix) { + Properties subProperties = new Properties(); + Set names = props.stringPropertyNames(); + String newName; + for (String name : names) { + if (name.startsWith(propertyNamePrefix)) { + newName = name; + if (trimPrefix) { + newName = name.substring(propertyNamePrefix.length()); + } + subProperties.setProperty(newName, props.getProperty(name)); + } + } + return subProperties; + } + + public static Properties cloneFrom(Properties props) { + Properties newProps = new Properties(); + Set names = props.stringPropertyNames(); + for (String name : names) { + newProps.setProperty(name, props.getProperty(name)); + } + return newProps; + } + + public static byte[] toBytes(Properties props, String charsetName) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(out, charsetName); + try { + props.store(writer, null); + writer.flush(); + } finally { + writer.close(); + } + return out.toByteArray(); + } catch (IOException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + public static int getInt(Properties props, String key) { + String value = getRequiredProperty(props, key); + return Integer.parseInt(value); + } + + public static boolean getBoolean(Properties props, String key) { + String value = getRequiredProperty(props, key); + return Boolean.parseBoolean(value); + } + + public static boolean getBooleanOptional(Properties props, String key, boolean defaultValue) { + String value = getProperty(props, key, false); + if (value == null) { + return defaultValue; + } + return Boolean.parseBoolean(value); + } + + /** + * 返回指定的属性;
+ * 如果不存在,或者返回值为空(null 或 空白字符),则抛出 {@link IllegalArgumentException} 异常; + * + * @param props props + * @param key key + * @return String + */ + public static String getRequiredProperty(Properties props, String key) { + return getProperty(props, key, true); + } + + public static String getOptionalProperty(Properties props, String key) { + return getProperty(props, key, false); + } + + public static String getOptionalProperty(Properties props, String key, String defaultValue) { + String value = getProperty(props, key, false); + if (value == null) { + return defaultValue; + } + return value; + } + + /** + * 返回指定的属性;
+ * + * @param props 属性表; + * @param key 要查找的 key; + * @param required 值为 false 时,如果不存在则返回 null;值为 true 时,如果不存在,或者返回值为空(null 或 + * 空白字符),则抛出 {@link IllegalArgumentException} 异常; + * @return + */ + public static String getProperty(Properties props, String key, boolean required) { + String value = props.getProperty(key); + if (value == null) { + if (required) { + throw new IllegalArgumentException("Miss property[" + key + "]!"); + } + return null; + } + value = value.trim(); + if (value.length() == 0) { + if (required) { + throw new IllegalArgumentException("Miss property[" + key + "]!"); + } + return null; + } + return value; + + } + + public static Property[] getOrderedValues(Properties props) { + Property[] values = new Property[props.size()]; + String[] propNames = props.stringPropertyNames().toArray(new String[props.size()]); + Arrays.sort(propNames, (n1, n2) -> n1.compareTo(n2)); + for (int i = 0; i < propNames.length; i++) { + values[i] = new Property(propNames[i], props.getProperty(propNames[i])); + } + return values; + } + + public static Properties createProperties(Property[] propValues) { + Properties props = new Properties(); + setValues(props, propValues); + return props; + } + + public static Properties setValues(Properties props, Property[] propValues) { + for (Property p : propValues) { + props.setProperty(p.getName(), p.getValue()); + } + return props; + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ReadonlyArrayListWrapper.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ReadonlyArrayListWrapper.java index 668ccd41..f5995d37 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ReadonlyArrayListWrapper.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ReadonlyArrayListWrapper.java @@ -1,55 +1,55 @@ -package com.jd.blockchain.utils; - -import java.util.AbstractList; - -/** - * ReadonlyArrayListWrapper 将数组包装为只读的 List; - * @author haiq - * - * @param class - */ -public class ReadonlyArrayListWrapper extends AbstractList{ - - private T[] array; - - private int fromIndex; - - private int toIndex; - - public ReadonlyArrayListWrapper(T[] array) { - this(array, 0, array.length); - } - - public ReadonlyArrayListWrapper(T[] array, int fromIndex) { - this(array, fromIndex, array.length); - } - - public ReadonlyArrayListWrapper(T[] array, int fromIndex, int toIndex) { - if (toIndex < fromIndex) { - throw new IllegalArgumentException("The toIndex less than fromIndex!"); - } - if (fromIndex < 0) { - throw new IllegalArgumentException("The fromIndex is negative!"); - } - if (toIndex > array.length) { - throw new IllegalArgumentException("The toIndex great than the length of array!"); - } - this.array = array; - this.fromIndex = fromIndex; - this.toIndex = toIndex; - } - - @Override - public T get(int index) { - if (index < 0 || index >= size()) { - throw new IndexOutOfBoundsException(); - } - return array[fromIndex + index]; - } - - @Override - public int size() { - return toIndex- fromIndex; - } - -} +package com.jd.blockchain.utils; + +import java.util.AbstractList; + +/** + * ReadonlyArrayListWrapper 将数组包装为只读的 List; + * @author haiq + * + * @param class + */ +public class ReadonlyArrayListWrapper extends AbstractList{ + + private T[] array; + + private int fromIndex; + + private int toIndex; + + public ReadonlyArrayListWrapper(T[] array) { + this(array, 0, array.length); + } + + public ReadonlyArrayListWrapper(T[] array, int fromIndex) { + this(array, fromIndex, array.length); + } + + public ReadonlyArrayListWrapper(T[] array, int fromIndex, int toIndex) { + if (toIndex < fromIndex) { + throw new IllegalArgumentException("The toIndex less than fromIndex!"); + } + if (fromIndex < 0) { + throw new IllegalArgumentException("The fromIndex is negative!"); + } + if (toIndex > array.length) { + throw new IllegalArgumentException("The toIndex great than the length of array!"); + } + this.array = array; + this.fromIndex = fromIndex; + this.toIndex = toIndex; + } + + @Override + public T get(int index) { + if (index < 0 || index >= size()) { + throw new IndexOutOfBoundsException(); + } + return array[fromIndex + index]; + } + + @Override + public int size() { + return toIndex- fromIndex; + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ServiceFactory.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ServiceFactory.java index 5209f455..7175a511 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ServiceFactory.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/ServiceFactory.java @@ -1,9 +1,9 @@ -package com.jd.blockchain.utils; - -import java.io.Closeable; - -public interface ServiceFactory extends Closeable{ - - T getService(Class serviceClazz); - +package com.jd.blockchain.utils; + +import java.io.Closeable; + +public interface ServiceFactory extends Closeable{ + + T getService(Class serviceClazz); + } \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/Base58Utils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/Base58Utils.java index 584d7c04..75ae0030 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/Base58Utils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/Base58Utils.java @@ -1,170 +1,170 @@ -package com.jd.blockchain.utils.codec; - -public class Base58Utils { - - private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" - .toCharArray(); - private static final int BASE_58 = ALPHABET.length; - private static final int BASE_256 = 256; - - private static final int[] INDEXES = new int[128]; - static { - for (int i = 0; i < INDEXES.length; i++) { - INDEXES[i] = -1; - } - for (int i = 0; i < ALPHABET.length; i++) { - INDEXES[ALPHABET[i]] = i; - } - } - - - - public static String encode(byte[] input) { - if (input.length == 0) { - // paying with the same coin - return ""; - } - - // - // Make a copy of the input since we are going to modify it. - // - input = copyOfRange(input, 0, input.length); - - // - // Count leading zeroes - // - int zeroCount = 0; - while (zeroCount < input.length && input[zeroCount] == 0) { - ++zeroCount; - } - - // - // The actual encoding - // - byte[] temp = new byte[input.length * 2]; - int j = temp.length; - - int startAt = zeroCount; - while (startAt < input.length) { - byte mod = divmod58(input, startAt); - if (input[startAt] == 0) { - ++startAt; - } - - temp[--j] = (byte) ALPHABET[mod]; - } - - // - // Strip extra '1' if any - // - while (j < temp.length && temp[j] == ALPHABET[0]) { - ++j; - } - - // - // Add as many leading '1' as there were leading zeros. - // - while (--zeroCount >= 0) { - temp[--j] = (byte) ALPHABET[0]; - } - - byte[] output = copyOfRange(temp, j, temp.length); - return new String(output); - } - - public static byte[] decode(String input) { - if(HexUtils.isHex(input)){ - return HexUtils.decode(input); - } - if (input.length() == 0) { - // paying with the same coin - return new byte[0]; - } - - byte[] input58 = new byte[input.length()]; - // - // Transform the String to a base58 byte sequence - // - for (int i = 0; i < input.length(); ++i) { - char c = input.charAt(i); - - int digit58 = -1; - if (c >= 0 && c < 128) { - digit58 = INDEXES[c]; - } - if (digit58 < 0) { - throw new RuntimeException("Not a Base58 input ddd: " + input); - } - - input58[i] = (byte) digit58; - } - - // - // Count leading zeroes - // - int zeroCount = 0; - while (zeroCount < input58.length && input58[zeroCount] == 0) { - ++zeroCount; - } - - // - // The encoding - // - byte[] temp = new byte[input.length()]; - int j = temp.length; - - int startAt = zeroCount; - while (startAt < input58.length) { - byte mod = divmod256(input58, startAt); - if (input58[startAt] == 0) { - ++startAt; - } - - temp[--j] = mod; - } - - // - // Do no add extra leading zeroes, move j to first non null byte. - // - while (j < temp.length && temp[j] == 0) { - ++j; - } - - return copyOfRange(temp, j - zeroCount, temp.length); - } - - private static byte divmod58(byte[] number, int startAt) { - int remainder = 0; - for (int i = startAt; i < number.length; i++) { - int digit256 = (int) number[i] & 0xFF; - int temp = remainder * BASE_256 + digit256; - - number[i] = (byte) (temp / BASE_58); - - remainder = temp % BASE_58; - } - - return (byte) remainder; - } - - private static byte divmod256(byte[] number58, int startAt) { - int remainder = 0; - for (int i = startAt; i < number58.length; i++) { - int digit58 = (int) number58[i] & 0xFF; - int temp = remainder * BASE_58 + digit58; - - number58[i] = (byte) (temp / BASE_256); - - remainder = temp % BASE_256; - } - - return (byte) remainder; - } - - private static byte[] copyOfRange(byte[] source, int from, int to) { - byte[] range = new byte[to - from]; - System.arraycopy(source, from, range, 0, range.length); - - return range; - } +package com.jd.blockchain.utils.codec; + +public class Base58Utils { + + private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" + .toCharArray(); + private static final int BASE_58 = ALPHABET.length; + private static final int BASE_256 = 256; + + private static final int[] INDEXES = new int[128]; + static { + for (int i = 0; i < INDEXES.length; i++) { + INDEXES[i] = -1; + } + for (int i = 0; i < ALPHABET.length; i++) { + INDEXES[ALPHABET[i]] = i; + } + } + + + + public static String encode(byte[] input) { + if (input.length == 0) { + // paying with the same coin + return ""; + } + + // + // Make a copy of the input since we are going to modify it. + // + input = copyOfRange(input, 0, input.length); + + // + // Count leading zeroes + // + int zeroCount = 0; + while (zeroCount < input.length && input[zeroCount] == 0) { + ++zeroCount; + } + + // + // The actual encoding + // + byte[] temp = new byte[input.length * 2]; + int j = temp.length; + + int startAt = zeroCount; + while (startAt < input.length) { + byte mod = divmod58(input, startAt); + if (input[startAt] == 0) { + ++startAt; + } + + temp[--j] = (byte) ALPHABET[mod]; + } + + // + // Strip extra '1' if any + // + while (j < temp.length && temp[j] == ALPHABET[0]) { + ++j; + } + + // + // Add as many leading '1' as there were leading zeros. + // + while (--zeroCount >= 0) { + temp[--j] = (byte) ALPHABET[0]; + } + + byte[] output = copyOfRange(temp, j, temp.length); + return new String(output); + } + + public static byte[] decode(String input) { + if(HexUtils.isHex(input)){ + return HexUtils.decode(input); + } + if (input.length() == 0) { + // paying with the same coin + return new byte[0]; + } + + byte[] input58 = new byte[input.length()]; + // + // Transform the String to a base58 byte sequence + // + for (int i = 0; i < input.length(); ++i) { + char c = input.charAt(i); + + int digit58 = -1; + if (c >= 0 && c < 128) { + digit58 = INDEXES[c]; + } + if (digit58 < 0) { + throw new RuntimeException("Not a Base58 input ddd: " + input); + } + + input58[i] = (byte) digit58; + } + + // + // Count leading zeroes + // + int zeroCount = 0; + while (zeroCount < input58.length && input58[zeroCount] == 0) { + ++zeroCount; + } + + // + // The encoding + // + byte[] temp = new byte[input.length()]; + int j = temp.length; + + int startAt = zeroCount; + while (startAt < input58.length) { + byte mod = divmod256(input58, startAt); + if (input58[startAt] == 0) { + ++startAt; + } + + temp[--j] = mod; + } + + // + // Do no add extra leading zeroes, move j to first non null byte. + // + while (j < temp.length && temp[j] == 0) { + ++j; + } + + return copyOfRange(temp, j - zeroCount, temp.length); + } + + private static byte divmod58(byte[] number, int startAt) { + int remainder = 0; + for (int i = startAt; i < number.length; i++) { + int digit256 = (int) number[i] & 0xFF; + int temp = remainder * BASE_256 + digit256; + + number[i] = (byte) (temp / BASE_58); + + remainder = temp % BASE_58; + } + + return (byte) remainder; + } + + private static byte divmod256(byte[] number58, int startAt) { + int remainder = 0; + for (int i = startAt; i < number58.length; i++) { + int digit58 = (int) number58[i] & 0xFF; + int temp = remainder * BASE_58 + digit58; + + number58[i] = (byte) (temp / BASE_256); + + remainder = temp % BASE_256; + } + + return (byte) remainder; + } + + private static byte[] copyOfRange(byte[] source, int from, int to) { + byte[] range = new byte[to - from]; + System.arraycopy(source, from, range, 0, range.length); + + return range; + } } \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/DataDecodeException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/DataDecodeException.java index 30968f48..b53617dc 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/DataDecodeException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/DataDecodeException.java @@ -1,23 +1,23 @@ -package com.jd.blockchain.utils.codec; - -/** - * 无效数据异常; - * - * @author haiq - * - */ -public class DataDecodeException extends RuntimeException{ - - private static final long serialVersionUID = 5834019788898871654L; - - public DataDecodeException() { - } - - public DataDecodeException(String message) { - super(message); - } - - public DataDecodeException(String message, Throwable cause) { - super(message, cause); - } -} +package com.jd.blockchain.utils.codec; + +/** + * 无效数据异常; + * + * @author haiq + * + */ +public class DataDecodeException extends RuntimeException{ + + private static final long serialVersionUID = 5834019788898871654L; + + public DataDecodeException() { + } + + public DataDecodeException(String message) { + super(message); + } + + public DataDecodeException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/HexUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/HexUtils.java index 480ecbe7..55f4118d 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/HexUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/codec/HexUtils.java @@ -1,49 +1,49 @@ -package com.jd.blockchain.utils.codec; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; - -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.binary.Hex; - -public class HexUtils { - - public static byte[] decode(String hexString) { - try { - return Hex.decodeHex(hexString.toCharArray()); - } catch (DecoderException e) { - throw new DataDecodeException(e.getMessage(), e); - } - } - - public static String encode(byte[] bytes) { - return Hex.encodeHexString(bytes); - } - - public static String encode(ByteBuffer bytes) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - byte[] buf = new byte[64]; - int len; - while (bytes.remaining() > 0) { - len = Math.min(buf.length, bytes.remaining()); - bytes.get(buf, 0, len); - out.write(buf, 0, len); - } - return Hex.encodeHexString(out.toByteArray()); - } - - /** - * 判断是否16进制字符串 - * - * @param hexString hexString - * @return boolean - */ - public static boolean isHex(String hexString) { - String regex = "^[A-Fa-f0-9]+$"; - if (hexString.matches(regex)) { - return true; - } - return false; - } - -} +package com.jd.blockchain.utils.codec; + +import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; + +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; + +public class HexUtils { + + public static byte[] decode(String hexString) { + try { + return Hex.decodeHex(hexString.toCharArray()); + } catch (DecoderException e) { + throw new DataDecodeException(e.getMessage(), e); + } + } + + public static String encode(byte[] bytes) { + return Hex.encodeHexString(bytes); + } + + public static String encode(ByteBuffer bytes) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buf = new byte[64]; + int len; + while (bytes.remaining() > 0) { + len = Math.min(buf.length, bytes.remaining()); + bytes.get(buf, 0, len); + out.write(buf, 0, len); + } + return Hex.encodeHexString(out.toByteArray()); + } + + /** + * 判断是否16进制字符串 + * + * @param hexString hexString + * @return boolean + */ + public static boolean isHex(String hexString) { + String regex = "^[A-Fa-f0-9]+$"; + if (hexString.matches(regex)) { + return true; + } + return false; + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/AsyncFuture.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/AsyncFuture.java index 4e02e151..38b05fd6 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/AsyncFuture.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/AsyncFuture.java @@ -1,58 +1,58 @@ -package com.jd.blockchain.utils.concurrent; - -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -/** - * 提供对异步操作的结果描述; - * @param class - */ -public interface AsyncFuture { - - /** - * 返回异步操作的结果;
- * - * 注:此方法将堵塞当前线程直至异步操作完成并返回结果; - * - * @return v - */ - V get(); - - V get(long timeout, TimeUnit unit); - - /** - * 操作是否已完成; - * - * 当操作成功返回或者异常返回时,都表示为已完成; - * - * @return boolean - */ - boolean isDone(); - - /** - * 操作是否已成功; - * - * @return boolean - */ - boolean isExceptionally(); - - public AsyncFuture thenAccept(Consumer action); - - public AsyncFuture thenAcceptAsync(Consumer action); - - public AsyncFuture thenAcceptAsync(Consumer action, Executor executor); - - public AsyncFuture thenRun(Runnable action); - - public AsyncFuture thenRunAsync(Runnable action); - - public AsyncFuture thenRunAsync(Runnable action, Executor executor); - - public AsyncFuture whenComplete(AsyncHandle action); - - public AsyncFuture whenCompleteAsync(AsyncHandle action); - - public AsyncFuture whenCompleteAsync(AsyncHandle action, Executor executor); - -} +package com.jd.blockchain.utils.concurrent; + +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +/** + * 提供对异步操作的结果描述; + * @param class + */ +public interface AsyncFuture { + + /** + * 返回异步操作的结果;
+ * + * 注:此方法将堵塞当前线程直至异步操作完成并返回结果; + * + * @return v + */ + V get(); + + V get(long timeout, TimeUnit unit); + + /** + * 操作是否已完成; + * + * 当操作成功返回或者异常返回时,都表示为已完成; + * + * @return boolean + */ + boolean isDone(); + + /** + * 操作是否已成功; + * + * @return boolean + */ + boolean isExceptionally(); + + public AsyncFuture thenAccept(Consumer action); + + public AsyncFuture thenAcceptAsync(Consumer action); + + public AsyncFuture thenAcceptAsync(Consumer action, Executor executor); + + public AsyncFuture thenRun(Runnable action); + + public AsyncFuture thenRunAsync(Runnable action); + + public AsyncFuture thenRunAsync(Runnable action, Executor executor); + + public AsyncFuture whenComplete(AsyncHandle action); + + public AsyncFuture whenCompleteAsync(AsyncHandle action); + + public AsyncFuture whenCompleteAsync(AsyncHandle action, Executor executor); + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/AsyncFutureListener.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/AsyncFutureListener.java index d2e979cb..9696f214 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/AsyncFutureListener.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/AsyncFutureListener.java @@ -1,7 +1,7 @@ -package com.jd.blockchain.utils.concurrent; - -public interface AsyncFutureListener { - - public void complete(AsyncFuture future); - -} +package com.jd.blockchain.utils.concurrent; + +public interface AsyncFutureListener { + + public void complete(AsyncFuture future); + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/CompletableAsyncFuture.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/CompletableAsyncFuture.java index 60495059..8f5290c4 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/CompletableAsyncFuture.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/CompletableAsyncFuture.java @@ -1,189 +1,189 @@ -package com.jd.blockchain.utils.concurrent; - -import java.util.concurrent.Callable; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.function.Consumer; -import java.util.function.Supplier; - -public class CompletableAsyncFuture implements AsyncFuture { - - private CompletableFuture cf; - - public CompletableAsyncFuture() { - this.cf = new CompletableFuture(); - } - - private CompletableAsyncFuture(CompletableFuture cf) { - this.cf = cf; - } - - public static CompletableAsyncFuture completeFuture(T value) { - CompletableFuture cf = CompletableFuture.completedFuture(value); - return new CompletableAsyncFuture<>(cf); - } - - public static CompletableAsyncFuture runAsync(Runnable runnable){ - CompletableFuture cf = CompletableFuture.runAsync(runnable); - return new CompletableAsyncFuture<>(cf); - } - - public static CompletableAsyncFuture runAsync(Runnable runnable, Executor executor){ - CompletableFuture cf = CompletableFuture.runAsync(runnable, executor); - return new CompletableAsyncFuture<>(cf); - } - - public static CompletableAsyncFuture callAsync(Callable callable){ - CompletableFuture cf = CompletableFuture.supplyAsync(new Supplier() { - @Override - public T get() { - try { - return callable.call(); - } catch (Exception e) { - throw new RuntimeExecutionException(e.getMessage(), e); - } - } - }); - return new CompletableAsyncFuture<>(cf); - } - - public static CompletableAsyncFuture callAsync(Callable callable, Executor executor){ - CompletableFuture cf = CompletableFuture.supplyAsync(new Supplier() { - @Override - public T get() { - try { - return callable.call(); - } catch (Exception e) { - throw new RuntimeExecutionException(e.getMessage(), e); - } - } - }, executor); - return new CompletableAsyncFuture<>(cf); - } - - public static CompletableAsyncFuture callAsync(Supplier supplier){ - CompletableFuture cf = CompletableFuture.supplyAsync(supplier); - return new CompletableAsyncFuture<>(cf); - } - - public static CompletableAsyncFuture callAsync(Supplier supplier, Executor executor){ - CompletableFuture cf = CompletableFuture.supplyAsync(supplier, executor); - return new CompletableAsyncFuture<>(cf); - } - - /** - * 如果尚未完成,则设置 {@link #get()} 方法的返回值,并置为已完成状态; - * - * @param value - * 正常返回的结果; - * @return true - 表示此操作使得状态从“未完成”状态转为“已完成”状态; - */ - public boolean complete(T value) { - return cf.complete(value); - } - - public boolean error(Throwable ex) { - return cf.completeExceptionally(ex); - } - - @Override - public T get() { - try { - return cf.get(); - } catch (InterruptedException e) { - throw new RuntimeInterruptedException(e.getMessage(), e); - } catch (ExecutionException e) { - Throwable cause = e.getCause(); - if (cause == null) { - cause = e; - } - throw new RuntimeExecutionException(cause.getMessage(), cause); - } - } - - @Override - public T get(long timeout, TimeUnit unit) { - try { - return cf.get(timeout, unit); - } catch (InterruptedException e) { - throw new RuntimeInterruptedException(e.getMessage(), e); - } catch (ExecutionException e) { - Throwable cause = e.getCause(); - if (cause == null) { - cause = e; - } - throw new RuntimeExecutionException(cause.getMessage(), cause); - } catch (TimeoutException e) { - throw new RuntimeTimeoutException(e.getMessage(), e); - } - } - - @Override - public boolean isDone() { - return cf.isDone(); - } - - @Override - public boolean isExceptionally() { - return cf.isCompletedExceptionally(); - } - - @Override - public AsyncFuture thenAccept(Consumer action) { - cf.thenAccept(action); - return this; - } - - @Override - public AsyncFuture thenAcceptAsync(Consumer action) { - cf.thenAcceptAsync(action); - return this; - } - - @Override - public AsyncFuture thenAcceptAsync(Consumer action, Executor executor) { - cf.thenAcceptAsync(action, executor); - return this; - } - - @Override - public AsyncFuture thenRun(Runnable action) { - cf.thenRun(action); - return this; - } - - @Override - public AsyncFuture thenRunAsync(Runnable action) { - cf.thenRunAsync(action); - return this; - } - - @Override - public AsyncFuture thenRunAsync(Runnable action, Executor executor) { - cf.thenRunAsync(action, executor); - return this; - } - - @Override - public AsyncFuture whenComplete(AsyncHandle action) { - cf.whenComplete(action); - return this; - } - - @Override - public AsyncFuture whenCompleteAsync(AsyncHandle action) { - cf.whenCompleteAsync(action); - return this; - } - - @Override - public AsyncFuture whenCompleteAsync(AsyncHandle action, Executor executor) { - cf.whenCompleteAsync(action, executor); - cf.whenCompleteAsync((a, b) -> action.accept(a, b), executor); - return this; - } - -} +package com.jd.blockchain.utils.concurrent; + +import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class CompletableAsyncFuture implements AsyncFuture { + + private CompletableFuture cf; + + public CompletableAsyncFuture() { + this.cf = new CompletableFuture(); + } + + private CompletableAsyncFuture(CompletableFuture cf) { + this.cf = cf; + } + + public static CompletableAsyncFuture completeFuture(T value) { + CompletableFuture cf = CompletableFuture.completedFuture(value); + return new CompletableAsyncFuture<>(cf); + } + + public static CompletableAsyncFuture runAsync(Runnable runnable){ + CompletableFuture cf = CompletableFuture.runAsync(runnable); + return new CompletableAsyncFuture<>(cf); + } + + public static CompletableAsyncFuture runAsync(Runnable runnable, Executor executor){ + CompletableFuture cf = CompletableFuture.runAsync(runnable, executor); + return new CompletableAsyncFuture<>(cf); + } + + public static CompletableAsyncFuture callAsync(Callable callable){ + CompletableFuture cf = CompletableFuture.supplyAsync(new Supplier() { + @Override + public T get() { + try { + return callable.call(); + } catch (Exception e) { + throw new RuntimeExecutionException(e.getMessage(), e); + } + } + }); + return new CompletableAsyncFuture<>(cf); + } + + public static CompletableAsyncFuture callAsync(Callable callable, Executor executor){ + CompletableFuture cf = CompletableFuture.supplyAsync(new Supplier() { + @Override + public T get() { + try { + return callable.call(); + } catch (Exception e) { + throw new RuntimeExecutionException(e.getMessage(), e); + } + } + }, executor); + return new CompletableAsyncFuture<>(cf); + } + + public static CompletableAsyncFuture callAsync(Supplier supplier){ + CompletableFuture cf = CompletableFuture.supplyAsync(supplier); + return new CompletableAsyncFuture<>(cf); + } + + public static CompletableAsyncFuture callAsync(Supplier supplier, Executor executor){ + CompletableFuture cf = CompletableFuture.supplyAsync(supplier, executor); + return new CompletableAsyncFuture<>(cf); + } + + /** + * 如果尚未完成,则设置 {@link #get()} 方法的返回值,并置为已完成状态; + * + * @param value + * 正常返回的结果; + * @return true - 表示此操作使得状态从“未完成”状态转为“已完成”状态; + */ + public boolean complete(T value) { + return cf.complete(value); + } + + public boolean error(Throwable ex) { + return cf.completeExceptionally(ex); + } + + @Override + public T get() { + try { + return cf.get(); + } catch (InterruptedException e) { + throw new RuntimeInterruptedException(e.getMessage(), e); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + if (cause == null) { + cause = e; + } + throw new RuntimeExecutionException(cause.getMessage(), cause); + } + } + + @Override + public T get(long timeout, TimeUnit unit) { + try { + return cf.get(timeout, unit); + } catch (InterruptedException e) { + throw new RuntimeInterruptedException(e.getMessage(), e); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + if (cause == null) { + cause = e; + } + throw new RuntimeExecutionException(cause.getMessage(), cause); + } catch (TimeoutException e) { + throw new RuntimeTimeoutException(e.getMessage(), e); + } + } + + @Override + public boolean isDone() { + return cf.isDone(); + } + + @Override + public boolean isExceptionally() { + return cf.isCompletedExceptionally(); + } + + @Override + public AsyncFuture thenAccept(Consumer action) { + cf.thenAccept(action); + return this; + } + + @Override + public AsyncFuture thenAcceptAsync(Consumer action) { + cf.thenAcceptAsync(action); + return this; + } + + @Override + public AsyncFuture thenAcceptAsync(Consumer action, Executor executor) { + cf.thenAcceptAsync(action, executor); + return this; + } + + @Override + public AsyncFuture thenRun(Runnable action) { + cf.thenRun(action); + return this; + } + + @Override + public AsyncFuture thenRunAsync(Runnable action) { + cf.thenRunAsync(action); + return this; + } + + @Override + public AsyncFuture thenRunAsync(Runnable action, Executor executor) { + cf.thenRunAsync(action, executor); + return this; + } + + @Override + public AsyncFuture whenComplete(AsyncHandle action) { + cf.whenComplete(action); + return this; + } + + @Override + public AsyncFuture whenCompleteAsync(AsyncHandle action) { + cf.whenCompleteAsync(action); + return this; + } + + @Override + public AsyncFuture whenCompleteAsync(AsyncHandle action, Executor executor) { + cf.whenCompleteAsync(action, executor); + cf.whenCompleteAsync((a, b) -> action.accept(a, b), executor); + return this; + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/NamedThreadFactory.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/NamedThreadFactory.java index 5d5b35b8..15251500 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/NamedThreadFactory.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/NamedThreadFactory.java @@ -1,75 +1,75 @@ -package com.jd.blockchain.utils.concurrent; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 可对线程命名的线程工厂; - * - * @author haiq - * - */ -public class NamedThreadFactory implements ThreadFactory { - - private String name; - - private boolean indexThread = false; - - private AtomicLong index; - - private boolean deamon; - - /** - * 创建 NamedThreadFactory 实例; - * - * @param name - * 名称; - */ - public NamedThreadFactory(String name) { - this(name, false, false); - } - - /** - * 创建 NamedThreadFactory 实例; - * - * @param name - * 名称; - * @param deamon - * 是否守护线程; - */ - public NamedThreadFactory(String name, boolean deamon) { - this(name, false, deamon); - } - - /** - * 创建 NamedThreadFactory 实例; - * - * @param name - * 名称; - * @param indexThread - * 是否记录创建的线程个数;如果是,则通过在指定的线程名称前加上索引值构成最终的线程名称,诸如:"threadName-0,threadName-1"; - * @param deamon - * 是否守护线程; - */ - public NamedThreadFactory(String name, boolean indexThread, boolean deamon) { - this.name = name; - this.indexThread = indexThread; - if (indexThread) { - index = new AtomicLong(0); - } - this.deamon = deamon; - } - - @Override - public Thread newThread(Runnable r) { - String thrdName = name; - if (indexThread) { - long i = index.incrementAndGet(); - thrdName = name +"-" + i; - } - Thread thrd = new Thread(r, thrdName); - thrd.setDaemon(deamon); - return thrd; - } - -} +package com.jd.blockchain.utils.concurrent; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; + +/** + * 可对线程命名的线程工厂; + * + * @author haiq + * + */ +public class NamedThreadFactory implements ThreadFactory { + + private String name; + + private boolean indexThread = false; + + private AtomicLong index; + + private boolean deamon; + + /** + * 创建 NamedThreadFactory 实例; + * + * @param name + * 名称; + */ + public NamedThreadFactory(String name) { + this(name, false, false); + } + + /** + * 创建 NamedThreadFactory 实例; + * + * @param name + * 名称; + * @param deamon + * 是否守护线程; + */ + public NamedThreadFactory(String name, boolean deamon) { + this(name, false, deamon); + } + + /** + * 创建 NamedThreadFactory 实例; + * + * @param name + * 名称; + * @param indexThread + * 是否记录创建的线程个数;如果是,则通过在指定的线程名称前加上索引值构成最终的线程名称,诸如:"threadName-0,threadName-1"; + * @param deamon + * 是否守护线程; + */ + public NamedThreadFactory(String name, boolean indexThread, boolean deamon) { + this.name = name; + this.indexThread = indexThread; + if (indexThread) { + index = new AtomicLong(0); + } + this.deamon = deamon; + } + + @Override + public Thread newThread(Runnable r) { + String thrdName = name; + if (indexThread) { + long i = index.incrementAndGet(); + thrdName = name +"-" + i; + } + Thread thrd = new Thread(r, thrdName); + thrd.setDaemon(deamon); + return thrd; + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeExecutionException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeExecutionException.java index 0bcde672..8ea773f8 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeExecutionException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeExecutionException.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.utils.concurrent; - -/** - * 未预期的中断异常; - * - * @author haiq - * - */ -public class RuntimeExecutionException extends RuntimeException { - - private static final long serialVersionUID = -4404758941888371638L; - - public RuntimeExecutionException() { - } - - public RuntimeExecutionException(String message) { - super(message); - } - - public RuntimeExecutionException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.utils.concurrent; + +/** + * 未预期的中断异常; + * + * @author haiq + * + */ +public class RuntimeExecutionException extends RuntimeException { + + private static final long serialVersionUID = -4404758941888371638L; + + public RuntimeExecutionException() { + } + + public RuntimeExecutionException(String message) { + super(message); + } + + public RuntimeExecutionException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeInterruptedException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeInterruptedException.java index c6ff9623..2bcf3206 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeInterruptedException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeInterruptedException.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.utils.concurrent; - -/** - * 未预期的中断异常; - * - * @author haiq - * - */ -public class RuntimeInterruptedException extends RuntimeException { - - private static final long serialVersionUID = -4404758941888371638L; - - public RuntimeInterruptedException() { - } - - public RuntimeInterruptedException(String message) { - super(message); - } - - public RuntimeInterruptedException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.utils.concurrent; + +/** + * 未预期的中断异常; + * + * @author haiq + * + */ +public class RuntimeInterruptedException extends RuntimeException { + + private static final long serialVersionUID = -4404758941888371638L; + + public RuntimeInterruptedException() { + } + + public RuntimeInterruptedException(String message) { + super(message); + } + + public RuntimeInterruptedException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeTimeoutException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeTimeoutException.java index 64a09ac4..98fa0e5e 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeTimeoutException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/RuntimeTimeoutException.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.utils.concurrent; - -/** - * 未预期的超时异常; - * - * @author haiq - * - */ -public class RuntimeTimeoutException extends RuntimeException { - - private static final long serialVersionUID = -4404758941888371638L; - - public RuntimeTimeoutException() { - } - - public RuntimeTimeoutException(String message) { - super(message); - } - - public RuntimeTimeoutException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.utils.concurrent; + +/** + * 未预期的超时异常; + * + * @author haiq + * + */ +public class RuntimeTimeoutException extends RuntimeException { + + private static final long serialVersionUID = -4404758941888371638L; + + public RuntimeTimeoutException() { + } + + public RuntimeTimeoutException(String message) { + super(message); + } + + public RuntimeTimeoutException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/SyncFutureAdaptor.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/SyncFutureAdaptor.java index e2655c65..50c9628e 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/SyncFutureAdaptor.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/SyncFutureAdaptor.java @@ -1,135 +1,135 @@ -package com.jd.blockchain.utils.concurrent; -//package my.utils.concurrent; -// -///** -// * 用于适配同步操作的 AsyncFuture 实现; -// * -// * @author haiq -// * -// * @param -// */ -//public class SyncFutureAdaptor implements AsyncFuture { -// -// private TSource source; -// -// private boolean success = false; -// private Throwable exception; -// private String errorCode; -// -// /** -// * 创建 SyncFutureAdaptor 实例; -// * -// * @param source -// * 操作对象; -// * @param exception -// * 操作完成后引发的异常;如果指定为 null 则表示操作成功返回而没有引发异常; -// * @param errorCode 错误码 -// */ -// private SyncFutureAdaptor(TSource source, Throwable exception, String errorCode) { -// this.source = source; -// this.success = exception == null; -// this.exception = exception; -// this.errorCode = errorCode; -// } -// -// /** -// * 创建表示成功完成操作的 AsyncFuture 实例; -// * -// * @param source -// * 执行操作的对象; -// * @return AsyncFuture 实例; -// */ -// public static AsyncFuture createSuccessFuture(T source) { -// return new SyncFutureAdaptor(source, null, null); -// } -// -// /** -// * 创建表示操作引发异常返回的 AsyncFuture 实例; -// * -// * @param source -// * 执行操作的对象; -// * @param exception -// * 操作引发的异常;不允许为 null; -// * @return AsyncFuture 实例; -// */ -// public static AsyncFuture createErrorFuture(T source, Throwable exception) { -// if (exception == null) { -// throw new IllegalArgumentException("Exception is null!"); -// } -// return new SyncFutureAdaptor(source, exception, null); -// } -// -// /** -// * 创建表示操作引发异常返回的 AsyncFuture 实例; -// * -// * @param source -// * 执行操作的对象; -// * @param errorCode -// * 操作引发的错误代码; -// * @return AsyncFuture 实例; -// */ -// public static AsyncFuture createErrorFuture(T source, String errorCode) { -// if (errorCode == null || errorCode.length() == 0) { -// throw new IllegalArgumentException("ErrorCode is empty!"); -// } -// return new SyncFutureAdaptor(source, null, errorCode); -// } -// -// @Override -// public TSource get() { -// return source; -// } -// -// @Override -// public boolean isDone() { -// return true; -// } -// -// @Override -// public boolean isSuccess() { -// return success; -// } -// -// @Override -// public Throwable getException() { -// return exception; -// } -// -// // @Override -// // public void addListener(AsyncFutureListener> -// // listener) { -// // -// // } -// -// @Override -// public void await() throws InterruptedException { -// return; -// } -// -// @Override -// public boolean await(long timeoutMillis) throws InterruptedException { -// return true; -// } -// -// @Override -// public void awaitUninterruptibly() { -// return; -// } -// -// @Override -// public boolean awaitUninterruptibly(long timeoutMillis) { -// return true; -// } -// -// @Override -// public void addListener(AsyncFutureListener listener) { -// // 同步操作已经完成; -// listener.complete(this); -// } -// -// @Override -// public String getErrorCode() { -// return this.errorCode; -// } -// -//} +package com.jd.blockchain.utils.concurrent; +//package my.utils.concurrent; +// +///** +// * 用于适配同步操作的 AsyncFuture 实现; +// * +// * @author haiq +// * +// * @param +// */ +//public class SyncFutureAdaptor implements AsyncFuture { +// +// private TSource source; +// +// private boolean success = false; +// private Throwable exception; +// private String errorCode; +// +// /** +// * 创建 SyncFutureAdaptor 实例; +// * +// * @param source +// * 操作对象; +// * @param exception +// * 操作完成后引发的异常;如果指定为 null 则表示操作成功返回而没有引发异常; +// * @param errorCode 错误码 +// */ +// private SyncFutureAdaptor(TSource source, Throwable exception, String errorCode) { +// this.source = source; +// this.success = exception == null; +// this.exception = exception; +// this.errorCode = errorCode; +// } +// +// /** +// * 创建表示成功完成操作的 AsyncFuture 实例; +// * +// * @param source +// * 执行操作的对象; +// * @return AsyncFuture 实例; +// */ +// public static AsyncFuture createSuccessFuture(T source) { +// return new SyncFutureAdaptor(source, null, null); +// } +// +// /** +// * 创建表示操作引发异常返回的 AsyncFuture 实例; +// * +// * @param source +// * 执行操作的对象; +// * @param exception +// * 操作引发的异常;不允许为 null; +// * @return AsyncFuture 实例; +// */ +// public static AsyncFuture createErrorFuture(T source, Throwable exception) { +// if (exception == null) { +// throw new IllegalArgumentException("Exception is null!"); +// } +// return new SyncFutureAdaptor(source, exception, null); +// } +// +// /** +// * 创建表示操作引发异常返回的 AsyncFuture 实例; +// * +// * @param source +// * 执行操作的对象; +// * @param errorCode +// * 操作引发的错误代码; +// * @return AsyncFuture 实例; +// */ +// public static AsyncFuture createErrorFuture(T source, String errorCode) { +// if (errorCode == null || errorCode.length() == 0) { +// throw new IllegalArgumentException("ErrorCode is empty!"); +// } +// return new SyncFutureAdaptor(source, null, errorCode); +// } +// +// @Override +// public TSource get() { +// return source; +// } +// +// @Override +// public boolean isDone() { +// return true; +// } +// +// @Override +// public boolean isSuccess() { +// return success; +// } +// +// @Override +// public Throwable getException() { +// return exception; +// } +// +// // @Override +// // public void addListener(AsyncFutureListener> +// // listener) { +// // +// // } +// +// @Override +// public void await() throws InterruptedException { +// return; +// } +// +// @Override +// public boolean await(long timeoutMillis) throws InterruptedException { +// return true; +// } +// +// @Override +// public void awaitUninterruptibly() { +// return; +// } +// +// @Override +// public boolean awaitUninterruptibly(long timeoutMillis) { +// return true; +// } +// +// @Override +// public void addListener(AsyncFutureListener listener) { +// // 同步操作已经完成; +// listener.complete(this); +// } +// +// @Override +// public String getErrorCode() { +// return this.errorCode; +// } +// +//} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/ThreadUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/ThreadUtils.java index fdbdadd8..fe966da1 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/ThreadUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/concurrent/ThreadUtils.java @@ -1,23 +1,23 @@ -package com.jd.blockchain.utils.concurrent; - -public abstract class ThreadUtils { - - /** - * 以不可中断的方式使当前线程 sleep 指定时长; - * - * @param millis 要等待的时长;单位毫秒; - */ - public static void sleepUninterrupted(long millis){ - long start = System.currentTimeMillis(); - long elapseTime = 0; - while(elapseTime < millis){ - try { - Thread.sleep(elapseTime); - } catch (InterruptedException e) { - // ignore ; - } - elapseTime = System.currentTimeMillis() - start; - } - } - -} +package com.jd.blockchain.utils.concurrent; + +public abstract class ThreadUtils { + + /** + * 以不可中断的方式使当前线程 sleep 指定时长; + * + * @param millis 要等待的时长;单位毫秒; + */ + public static void sleepUninterrupted(long millis){ + long start = System.currentTimeMillis(); + long elapseTime = 0; + while(elapseTime < millis){ + try { + Thread.sleep(elapseTime); + } catch (InterruptedException e) { + // ignore ; + } + elapseTime = System.currentTimeMillis() - start; + } + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/console/CommandConsole.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/console/CommandConsole.java index 2aadfe77..38411854 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/console/CommandConsole.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/console/CommandConsole.java @@ -1,141 +1,141 @@ -package com.jd.blockchain.utils.console; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.StringUtils; - -public class CommandConsole { - - private Map processors = new ConcurrentHashMap(); - - private CommondProcessor defaultProcessor; - - private boolean monitoring = false; - - private BufferedReader in; - - private PrintStream out; - - private String prompt; - - public PrintStream out() { - return out; - } - - /** - * @param input - * 命令输入流; - * @param output - * 结果输出流; - * @param prompt - * 提示符; - */ - public CommandConsole(InputStream input, PrintStream output, String prompt) { - try { - this.in = new BufferedReader(new InputStreamReader(input, "GBK")); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e.getMessage(), e); - } - this.out = output; - this.prompt = prompt; - - // 定义默认的命令处理器; - defaultProcessor = new CommondProcessor() { - @Override - public void onEnter(String command, String[] args, CommandConsole console) { - console.out().println("Unsupported command [" + command + "]!"); - } - }; - } - - public void setDefaultCommandProcessor(CommondProcessor processor) { - if (processor == null) { - throw new IllegalArgumentException("Null argument!"); - } - this.defaultProcessor = processor; - } - - /** - * 注册命令处理器; - * - * 一个命令只能有一个处理器,重复注册多个处理器将引发异常; - * - * @param command 命令文本; 自动忽略大小写; - * @param processor processor - */ - public synchronized void register(String command, CommondProcessor processor) { - if (StringUtils.containsWhitespace(command)) { - throw new IllegalArgumentException("Can't register command with white space character!"); - } - if (processors.containsKey(command)) { - throw new IllegalStateException("The command[" + command + "] has been registered!"); - } - processors.put(command.toLowerCase(), processor); - } - - /** - * 开始监控命令; - * - * 方法将堵塞当前线程; - * - */ - public synchronized void open() { - monitoring = true; - while (monitoring) { - // 输出提示; - out.println(); - out.print(prompt); - - // 读入命令; - String command; - try { - command = in.readLine(); - } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); - } - if (command == null) { - continue; - } - String[] cmdArgs = StringUtils.tokenizeToStringArray(command, " "); - if (cmdArgs.length == 0) { - continue; - } - String cmd = cmdArgs[0]; - String[] args; - if (cmdArgs.length > 1) { - args = Arrays.copyOfRange(cmdArgs, 1, cmdArgs.length); - } else { - args = new String[0]; - } - CommondProcessor processor = processors.get(cmd.toLowerCase()); - try { - if (processor != null) { - processor.onEnter(cmd, args, this); - } else { - defaultProcessor.onEnter(cmd, args, this); - } - } catch (Exception e) { - out.println("Error!!--" + e.getMessage()); - logger.error(e.getMessage(), e); - } - } - } - - /** - * 停止命令控制台; - */ - public synchronized void close() { - monitoring = false; - } - private Logger logger = LoggerFactory.getLogger(CommandConsole.class); -} +package com.jd.blockchain.utils.console; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +public class CommandConsole { + + private Map processors = new ConcurrentHashMap(); + + private CommondProcessor defaultProcessor; + + private boolean monitoring = false; + + private BufferedReader in; + + private PrintStream out; + + private String prompt; + + public PrintStream out() { + return out; + } + + /** + * @param input + * 命令输入流; + * @param output + * 结果输出流; + * @param prompt + * 提示符; + */ + public CommandConsole(InputStream input, PrintStream output, String prompt) { + try { + this.in = new BufferedReader(new InputStreamReader(input, "GBK")); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + this.out = output; + this.prompt = prompt; + + // 定义默认的命令处理器; + defaultProcessor = new CommondProcessor() { + @Override + public void onEnter(String command, String[] args, CommandConsole console) { + console.out().println("Unsupported command [" + command + "]!"); + } + }; + } + + public void setDefaultCommandProcessor(CommondProcessor processor) { + if (processor == null) { + throw new IllegalArgumentException("Null argument!"); + } + this.defaultProcessor = processor; + } + + /** + * 注册命令处理器; + * + * 一个命令只能有一个处理器,重复注册多个处理器将引发异常; + * + * @param command 命令文本; 自动忽略大小写; + * @param processor processor + */ + public synchronized void register(String command, CommondProcessor processor) { + if (StringUtils.containsWhitespace(command)) { + throw new IllegalArgumentException("Can't register command with white space character!"); + } + if (processors.containsKey(command)) { + throw new IllegalStateException("The command[" + command + "] has been registered!"); + } + processors.put(command.toLowerCase(), processor); + } + + /** + * 开始监控命令; + * + * 方法将堵塞当前线程; + * + */ + public synchronized void open() { + monitoring = true; + while (monitoring) { + // 输出提示; + out.println(); + out.print(prompt); + + // 读入命令; + String command; + try { + command = in.readLine(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + if (command == null) { + continue; + } + String[] cmdArgs = StringUtils.tokenizeToStringArray(command, " "); + if (cmdArgs.length == 0) { + continue; + } + String cmd = cmdArgs[0]; + String[] args; + if (cmdArgs.length > 1) { + args = Arrays.copyOfRange(cmdArgs, 1, cmdArgs.length); + } else { + args = new String[0]; + } + CommondProcessor processor = processors.get(cmd.toLowerCase()); + try { + if (processor != null) { + processor.onEnter(cmd, args, this); + } else { + defaultProcessor.onEnter(cmd, args, this); + } + } catch (Exception e) { + out.println("Error!!--" + e.getMessage()); + logger.error(e.getMessage(), e); + } + } + } + + /** + * 停止命令控制台; + */ + public synchronized void close() { + monitoring = false; + } + private Logger logger = LoggerFactory.getLogger(CommandConsole.class); +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/console/CommondProcessor.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/console/CommondProcessor.java index 24b16601..6d3a45bf 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/console/CommondProcessor.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/console/CommondProcessor.java @@ -1,15 +1,15 @@ -package com.jd.blockchain.utils.console; - -import java.io.PrintStream; - -/** - * 命令处理器; - * - * @author haiq - * - */ -public interface CommondProcessor { - - public void onEnter(String command, String[] args, CommandConsole console); - -} +package com.jd.blockchain.utils.console; + +import java.io.PrintStream; + +/** + * 命令处理器; + * + * @author haiq + * + */ +public interface CommondProcessor { + + public void onEnter(String command, String[] args, CommandConsole console); + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/DefaultExceptionHandle.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/DefaultExceptionHandle.java index 5ff08720..c63b723e 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/DefaultExceptionHandle.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/DefaultExceptionHandle.java @@ -1,27 +1,27 @@ -package com.jd.blockchain.utils.event; - -import java.lang.reflect.Method; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DefaultExceptionHandle implements ExceptionHandle { - - @Override - public void handle(Exception ex, TListener listener, Method method, Object[] args) { - String argsValue = null; - if (args!=null) { - StringBuilder argsFormat = new StringBuilder(); - for (int i = 0; i < args.length; i++) { - argsFormat.append("arg["); - argsFormat.append(i); - argsFormat.append("]=%s;"); - } - argsValue = String.format(argsFormat.toString(), args); - } - String message = String.format("Error occurred while firing event!--[listener.class=%s][method=%s][args=%s]--[%s]%s", - listener.getClass().getName(), method.getName(), argsValue, ex.getClass().getName(), ex.getMessage()); - logger.error(message, ex); - } - private Logger logger = LoggerFactory.getLogger(DefaultExceptionHandle.class); -} +package com.jd.blockchain.utils.event; + +import java.lang.reflect.Method; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DefaultExceptionHandle implements ExceptionHandle { + + @Override + public void handle(Exception ex, TListener listener, Method method, Object[] args) { + String argsValue = null; + if (args!=null) { + StringBuilder argsFormat = new StringBuilder(); + for (int i = 0; i < args.length; i++) { + argsFormat.append("arg["); + argsFormat.append(i); + argsFormat.append("]=%s;"); + } + argsValue = String.format(argsFormat.toString(), args); + } + String message = String.format("Error occurred while firing event!--[listener.class=%s][method=%s][args=%s]--[%s]%s", + listener.getClass().getName(), method.getName(), argsValue, ex.getClass().getName(), ex.getMessage()); + logger.error(message, ex); + } + private Logger logger = LoggerFactory.getLogger(DefaultExceptionHandle.class); +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/EventMulticaster.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/EventMulticaster.java index aa9e2010..86f2d1b6 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/EventMulticaster.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/EventMulticaster.java @@ -1,131 +1,131 @@ -package com.jd.blockchain.utils.event; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.ReflectionUtils; - -import com.jd.blockchain.utils.Disposable; - -/** - * 将针对一个特定的 listener 的方法调用事件广播到多个 listener对应的方法; - * - * 只支持无返回值的,非 Object 类的方法; - * - * @author haiq - * - * @param TListener - */ -public class EventMulticaster implements Disposable { - - private TListener listenerProxy; - - private Method[] supportedMethods; - - private List listeners = new CopyOnWriteArrayList(); - - private ExceptionHandle exHandle; - - public EventMulticaster(Class listenerClass) { - this(listenerClass, (ExceptionHandle) null); - } - - public EventMulticaster(Class listenerClass, Logger errorLogger) { - this(listenerClass, new RethrowExceptionHandler(errorLogger)); - } - - @SuppressWarnings("unchecked") - public EventMulticaster(Class listenerClass, ExceptionHandle exHandle) { - if (!listenerClass.isInterface()) { - throw new IllegalArgumentException("The specified class of listener does not represent an interface!"); - } - // 初始化错误处理器; - this.exHandle = exHandle == null - ? new RethrowExceptionHandler(LoggerFactory.getLogger(EventMulticaster.class)) - : exHandle; - - // 解析出不支持的方法; - Method[] methods = ReflectionUtils.getAllDeclaredMethods(listenerClass); - List supMths = new ArrayList(); - for (Method method : methods) { - if (method.getDeclaringClass() == Object.class) { - // 不支持 Object 方法; - continue; - } - if (method.getReturnType() != void.class) { - // 不支持带返回值的方法; - continue; - } - supMths.add(method); - } - supportedMethods = supMths.toArray(new Method[supMths.size()]); - - // 生成代理类; - listenerProxy = (TListener) Proxy.newProxyInstance(listenerClass.getClassLoader(), - new Class[] { listenerClass }, new InvocationHandler() { - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - multicast(proxy, method, args); - return null; - } - }); - } - - private void multicast(Object proxy, Method method, Object[] args) { - boolean supported = false; - for (Method mth : supportedMethods) { - if (mth.equals(method)) { - supported = true; - break; - } - } - if (supported) { - doNotify(listeners, method, args); - } else { - // 调用了不支持的方法; - throw new UnsupportedOperationException("Unsupported method for event multicasting!"); - } - } - - protected void doNotify(List listeners, Method method, Object[] args) { - for (TListener listener : listeners) { - doNotifySingle(listener, method, args); - } - } - - protected void doNotifySingle(TListener listener, Method method, Object[] args) { - try { - ReflectionUtils.invokeMethod(method, listener, args); - } catch (Exception e) { - exHandle.handle(e, listener, method, args); - } - } - - public void addListener(TListener listener) { - listeners.add(listener); - } - - public void removeListener(TListener listener) { - listeners.remove(listener); - } - - public TListener getBroadcaster() { - return listenerProxy; - } - - @Override - public void dispose() { - listeners.clear(); - listeners = null; - listenerProxy = null; - supportedMethods = null; - exHandle = null; - } - -} +package com.jd.blockchain.utils.event; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ReflectionUtils; + +import com.jd.blockchain.utils.Disposable; + +/** + * 将针对一个特定的 listener 的方法调用事件广播到多个 listener对应的方法; + * + * 只支持无返回值的,非 Object 类的方法; + * + * @author haiq + * + * @param TListener + */ +public class EventMulticaster implements Disposable { + + private TListener listenerProxy; + + private Method[] supportedMethods; + + private List listeners = new CopyOnWriteArrayList(); + + private ExceptionHandle exHandle; + + public EventMulticaster(Class listenerClass) { + this(listenerClass, (ExceptionHandle) null); + } + + public EventMulticaster(Class listenerClass, Logger errorLogger) { + this(listenerClass, new RethrowExceptionHandler(errorLogger)); + } + + @SuppressWarnings("unchecked") + public EventMulticaster(Class listenerClass, ExceptionHandle exHandle) { + if (!listenerClass.isInterface()) { + throw new IllegalArgumentException("The specified class of listener does not represent an interface!"); + } + // 初始化错误处理器; + this.exHandle = exHandle == null + ? new RethrowExceptionHandler(LoggerFactory.getLogger(EventMulticaster.class)) + : exHandle; + + // 解析出不支持的方法; + Method[] methods = ReflectionUtils.getAllDeclaredMethods(listenerClass); + List supMths = new ArrayList(); + for (Method method : methods) { + if (method.getDeclaringClass() == Object.class) { + // 不支持 Object 方法; + continue; + } + if (method.getReturnType() != void.class) { + // 不支持带返回值的方法; + continue; + } + supMths.add(method); + } + supportedMethods = supMths.toArray(new Method[supMths.size()]); + + // 生成代理类; + listenerProxy = (TListener) Proxy.newProxyInstance(listenerClass.getClassLoader(), + new Class[] { listenerClass }, new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + multicast(proxy, method, args); + return null; + } + }); + } + + private void multicast(Object proxy, Method method, Object[] args) { + boolean supported = false; + for (Method mth : supportedMethods) { + if (mth.equals(method)) { + supported = true; + break; + } + } + if (supported) { + doNotify(listeners, method, args); + } else { + // 调用了不支持的方法; + throw new UnsupportedOperationException("Unsupported method for event multicasting!"); + } + } + + protected void doNotify(List listeners, Method method, Object[] args) { + for (TListener listener : listeners) { + doNotifySingle(listener, method, args); + } + } + + protected void doNotifySingle(TListener listener, Method method, Object[] args) { + try { + ReflectionUtils.invokeMethod(method, listener, args); + } catch (Exception e) { + exHandle.handle(e, listener, method, args); + } + } + + public void addListener(TListener listener) { + listeners.add(listener); + } + + public void removeListener(TListener listener) { + listeners.remove(listener); + } + + public TListener getBroadcaster() { + return listenerProxy; + } + + @Override + public void dispose() { + listeners.clear(); + listeners = null; + listenerProxy = null; + supportedMethods = null; + exHandle = null; + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/ExceptionHandle.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/ExceptionHandle.java index d39d75f0..36967d5c 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/ExceptionHandle.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/ExceptionHandle.java @@ -1,27 +1,27 @@ -package com.jd.blockchain.utils.event; - -import java.lang.reflect.Method; - -/** - * ExceptionHandle 定义了在对事件监听器进行事件通知时出现的异常的处理接口; - * - * @author haiq - * - * @param TListener - */ -public interface ExceptionHandle { - - /** - * 处理监听器异常; - * - * @param ex - * 异常; - * @param listener - * 发生异常的监听器实例; - * @param method - * 发生异常的方法; - * @param args - * 方法参数; - */ - public void handle(Exception ex, TListener listener, Method method, Object[] args); -} +package com.jd.blockchain.utils.event; + +import java.lang.reflect.Method; + +/** + * ExceptionHandle 定义了在对事件监听器进行事件通知时出现的异常的处理接口; + * + * @author haiq + * + * @param TListener + */ +public interface ExceptionHandle { + + /** + * 处理监听器异常; + * + * @param ex + * 异常; + * @param listener + * 发生异常的监听器实例; + * @param method + * 发生异常的方法; + * @param args + * 方法参数; + */ + public void handle(Exception ex, TListener listener, Method method, Object[] args); +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/ExceptionLoggingHandle.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/ExceptionLoggingHandle.java index 772030d2..fdf01ee2 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/ExceptionLoggingHandle.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/ExceptionLoggingHandle.java @@ -1,32 +1,32 @@ -package com.jd.blockchain.utils.event; - -import java.lang.reflect.Method; - -import org.slf4j.Logger; - -public class ExceptionLoggingHandle implements ExceptionHandle { - - private Logger logger; - - public ExceptionLoggingHandle(Logger logger) { - this.logger = logger; - } - - @Override - public void handle(Exception ex, TListener listener, Method method, Object[] args) { - String argsValue = null; - if (args!=null) { - StringBuilder argsFormat = new StringBuilder(); - for (int i = 0; i < args.length; i++) { - argsFormat.append("arg["); - argsFormat.append(i); - argsFormat.append("]=%s;"); - } - argsValue = String.format(argsFormat.toString(), args); - } - String message = String.format("Error occurred on firing event!--[listener.class=%s][method=%s][args=%s]--[%s]%s", - listener.getClass().getName(), method.getName(), argsValue, ex.getClass().getName(), ex.getMessage()); - logger.error(message, ex); - } - -} +package com.jd.blockchain.utils.event; + +import java.lang.reflect.Method; + +import org.slf4j.Logger; + +public class ExceptionLoggingHandle implements ExceptionHandle { + + private Logger logger; + + public ExceptionLoggingHandle(Logger logger) { + this.logger = logger; + } + + @Override + public void handle(Exception ex, TListener listener, Method method, Object[] args) { + String argsValue = null; + if (args!=null) { + StringBuilder argsFormat = new StringBuilder(); + for (int i = 0; i < args.length; i++) { + argsFormat.append("arg["); + argsFormat.append(i); + argsFormat.append("]=%s;"); + } + argsValue = String.format(argsFormat.toString(), args); + } + String message = String.format("Error occurred on firing event!--[listener.class=%s][method=%s][args=%s]--[%s]%s", + listener.getClass().getName(), method.getName(), argsValue, ex.getClass().getName(), ex.getMessage()); + logger.error(message, ex); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/RethrowExceptionHandler.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/RethrowExceptionHandler.java index 84d27018..f5b88417 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/RethrowExceptionHandler.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/event/RethrowExceptionHandler.java @@ -1,23 +1,23 @@ -package com.jd.blockchain.utils.event; - -import java.lang.reflect.Method; -import java.lang.reflect.UndeclaredThrowableException; - -import org.slf4j.Logger; - -public class RethrowExceptionHandler extends ExceptionLoggingHandle { - - public RethrowExceptionHandler(Logger logger) { - super(logger); - } - - @Override - public void handle(Exception ex, TListener listener, Method method, Object[] args) { - super.handle(ex, listener, method, args); - if (ex instanceof RuntimeException) { - throw (RuntimeException)ex; - } - throw new UndeclaredThrowableException(ex); - } - -} +package com.jd.blockchain.utils.event; + +import java.lang.reflect.Method; +import java.lang.reflect.UndeclaredThrowableException; + +import org.slf4j.Logger; + +public class RethrowExceptionHandler extends ExceptionLoggingHandle { + + public RethrowExceptionHandler(Logger logger) { + super(logger); + } + + @Override + public void handle(Exception ex, TListener listener, Method method, Object[] args) { + super.handle(ex, listener, method, args); + if (ex instanceof RuntimeException) { + throw (RuntimeException)ex; + } + throw new UndeclaredThrowableException(ex); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/hash/Hashing.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/hash/Hashing.java index 6d3203ae..0f10e1be 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/hash/Hashing.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/hash/Hashing.java @@ -1,17 +1,17 @@ -package com.jd.blockchain.utils.hash; - -import com.jd.blockchain.utils.hash.MurmurHash3; - -public interface Hashing { - - public static final Hashing MURMUR3_HASH = new Hashing() { - - public int hash32(CharSequence id) { - return MurmurHash3.murmurhash3_x86_32(id, 0, id.length(), 1024); - } - }; - - public int hash32(CharSequence id); - - -} +package com.jd.blockchain.utils.hash; + +import com.jd.blockchain.utils.hash.MurmurHash3; + +public interface Hashing { + + public static final Hashing MURMUR3_HASH = new Hashing() { + + public int hash32(CharSequence id) { + return MurmurHash3.murmurhash3_x86_32(id, 0, id.length(), 1024); + } + }; + + public int hash32(CharSequence id); + + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/hash/MurmurHash3.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/hash/MurmurHash3.java index 5c28e751..d745160b 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/hash/MurmurHash3.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/hash/MurmurHash3.java @@ -1,320 +1,320 @@ -package com.jd.blockchain.utils.hash; - -/** - * The MurmurHash3 algorithm was created by Austin Appleby and placed in the public domain. - * This java port was authored by Yonik Seeley and also placed into the public domain. - * The author hereby disclaims copyright to this source code. - *

- * This produces exactly the same hash values as the final C++ - * version of MurmurHash3 and is thus suitable for producing the same hash values across - * platforms. - *

- * The 32 bit x86 version of this hash should be the fastest variant for relatively short keys like ids. - * murmurhash3_x64_128 is a good choice for longer strings or if you need more than 32 bits of hash. - *

- * Note - The x86 and x64 versions do _not_ produce the same results, as the - * algorithms are optimized for their respective platforms. - *

- * See http://github.com/yonik/java_util for future updates to this file. - */ -public final class MurmurHash3 { - - /** 128 bits of state */ - public static final class LongPair { - public long val1; - public long val2; - } - - public static final int fmix32(int h) { - h ^= h >>> 16; - h *= 0x85ebca6b; - h ^= h >>> 13; - h *= 0xc2b2ae35; - h ^= h >>> 16; - return h; - } - - public static final long fmix64(long k) { - k ^= k >>> 33; - k *= 0xff51afd7ed558ccdL; - k ^= k >>> 33; - k *= 0xc4ceb9fe1a85ec53L; - k ^= k >>> 33; - return k; - } - - /** - * Gets a long from a byte buffer in little endian byte order. - * @param buf buf - * @param offset offset - * @return long - */ - public static final long getLongLittleEndian(byte[] buf, int offset) { - return ((long)buf[offset+7] << 56) // no mask needed - | ((buf[offset+6] & 0xffL) << 48) - | ((buf[offset+5] & 0xffL) << 40) - | ((buf[offset+4] & 0xffL) << 32) - | ((buf[offset+3] & 0xffL) << 24) - | ((buf[offset+2] & 0xffL) << 16) - | ((buf[offset+1] & 0xffL) << 8) - | ((buf[offset ] & 0xffL)); // no shift needed - } - - - /** - * Returns the MurmurHash3_x86_32 hash. - * @param data data - * @param offset offset - * @param len len - * @param seed seed - * @return int - */ - public static int murmurhash3_x86_32(byte[] data, int offset, int len, int seed) { - - final int c1 = 0xcc9e2d51; - final int c2 = 0x1b873593; - - int h1 = seed; - int roundedEnd = offset + (len & 0xfffffffc); // round down to 4 byte block - - for (int i=offset; i>> 17); // ROTL32(k1,15); - k1 *= c2; - - h1 ^= k1; - h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13); - h1 = h1*5+0xe6546b64; - } - - // tail - int k1 = 0; - - switch(len & 0x03) { - case 3: - k1 = (data[roundedEnd + 2] & 0xff) << 16; - // fallthrough - case 2: - k1 |= (data[roundedEnd + 1] & 0xff) << 8; - // fallthrough - case 1: - k1 |= (data[roundedEnd] & 0xff); - k1 *= c1; - k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); - k1 *= c2; - h1 ^= k1; - } - - // finalization - h1 ^= len; - - // fmix(h1); - h1 ^= h1 >>> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >>> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >>> 16; - - return h1; - } - - /** - * Returns the MurmurHash3_x86_32 hash of the UTF-8 bytes of the String without actually encoding - * the string to a temporary buffer. This is more than 2x faster than hashing the result - * of String.getBytes(). - * @param data data - * @param offset offset - * @param len len - * @param seed seed - * @return int - */ - public static int murmurhash3_x86_32(CharSequence data, int offset, int len, int seed) { - - final int c1 = 0xcc9e2d51; - final int c2 = 0x1b873593; - - int h1 = seed; - - int pos = offset; - int end = offset + len; - int k1 = 0; - int k2 = 0; - int shift = 0; - int bits = 0; - int nBytes = 0; // length in UTF8 bytes - - - while (pos < end) { - int code = data.charAt(pos++); - if (code < 0x80) { - k2 = code; - bits = 8; - - /*** - // optimized ascii implementation (currently slower!!! code size?) - if (shift == 24) { - k1 = k1 | (code << 24); - k1 *= c1; - k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); - k1 *= c2; - h1 ^= k1; - h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13); - h1 = h1*5+0xe6546b64; - shift = 0; - nBytes += 4; - k1 = 0; - } else { - k1 |= code << shift; - shift += 8; - } - continue; - ***/ - - } - else if (code < 0x800) { - k2 = (0xC0 | (code >> 6)) - | ((0x80 | (code & 0x3F)) << 8); - bits = 16; - } - else if (code < 0xD800 || code > 0xDFFF || pos>=end) { - // we check for pos>=end to encode an unpaired surrogate as 3 bytes. - k2 = (0xE0 | (code >> 12)) - | ((0x80 | ((code >> 6) & 0x3F)) << 8) - | ((0x80 | (code & 0x3F)) << 16); - bits = 24; - } else { - // surrogate pair - // int utf32 = pos < end ? (int) data.charAt(pos++) : 0; - int utf32 = (int) data.charAt(pos++); - utf32 = ((code - 0xD7C0) << 10) + (utf32 & 0x3FF); - k2 = (0xff & (0xF0 | (utf32 >> 18))) - | ((0x80 | ((utf32 >> 12) & 0x3F))) << 8 - | ((0x80 | ((utf32 >> 6) & 0x3F))) << 16 - | (0x80 | (utf32 & 0x3F)) << 24; - bits = 32; - } - - - k1 |= k2 << shift; - - // int used_bits = 32 - shift; // how many bits of k2 were used in k1. - // int unused_bits = bits - used_bits; // (bits-(32-shift)) == bits+shift-32 == bits-newshift - - shift += bits; - if (shift >= 32) { - // mix after we have a complete word - - k1 *= c1; - k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); - k1 *= c2; - - h1 ^= k1; - h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13); - h1 = h1*5+0xe6546b64; - - shift -= 32; - // unfortunately, java won't let you shift 32 bits off, so we need to check for 0 - if (shift != 0) { - k1 = k2 >>> (bits-shift); // bits used == bits - newshift - } else { - k1 = 0; - } - nBytes += 4; - } - - } // inner - - // handle tail - if (shift > 0) { - nBytes += shift >> 3; - k1 *= c1; - k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); - k1 *= c2; - h1 ^= k1; - } - - // finalization - h1 ^= nBytes; - - // fmix(h1); - h1 ^= h1 >>> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >>> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >>> 16; - - return h1; - } - - - /** - * Returns the MurmurHash3_x64_128 hash, placing the result in "out". - * @param key key - * @param offset offset - * @param len len - * @param seed seed - * @param out out - */ - public static void murmurhash3_x64_128(byte[] key, int offset, int len, int seed, LongPair out) { - // The original algorithm does have a 32 bit unsigned seed. - // We have to mask to match the behavior of the unsigned types and prevent sign extension. - long h1 = seed & 0x00000000FFFFFFFFL; - long h2 = seed & 0x00000000FFFFFFFFL; - - final long c1 = 0x87c37b91114253d5L; - final long c2 = 0x4cf5ad432745937fL; - - int roundedEnd = offset + (len & 0xFFFFFFF0); // round down to 16 byte block - for (int i=offset; i + * This produces exactly the same hash values as the final C++ + * version of MurmurHash3 and is thus suitable for producing the same hash values across + * platforms. + *

+ * The 32 bit x86 version of this hash should be the fastest variant for relatively short keys like ids. + * murmurhash3_x64_128 is a good choice for longer strings or if you need more than 32 bits of hash. + *

+ * Note - The x86 and x64 versions do _not_ produce the same results, as the + * algorithms are optimized for their respective platforms. + *

+ * See http://github.com/yonik/java_util for future updates to this file. + */ +public final class MurmurHash3 { + + /** 128 bits of state */ + public static final class LongPair { + public long val1; + public long val2; + } + + public static final int fmix32(int h) { + h ^= h >>> 16; + h *= 0x85ebca6b; + h ^= h >>> 13; + h *= 0xc2b2ae35; + h ^= h >>> 16; + return h; + } + + public static final long fmix64(long k) { + k ^= k >>> 33; + k *= 0xff51afd7ed558ccdL; + k ^= k >>> 33; + k *= 0xc4ceb9fe1a85ec53L; + k ^= k >>> 33; + return k; + } + + /** + * Gets a long from a byte buffer in little endian byte order. + * @param buf buf + * @param offset offset + * @return long + */ + public static final long getLongLittleEndian(byte[] buf, int offset) { + return ((long)buf[offset+7] << 56) // no mask needed + | ((buf[offset+6] & 0xffL) << 48) + | ((buf[offset+5] & 0xffL) << 40) + | ((buf[offset+4] & 0xffL) << 32) + | ((buf[offset+3] & 0xffL) << 24) + | ((buf[offset+2] & 0xffL) << 16) + | ((buf[offset+1] & 0xffL) << 8) + | ((buf[offset ] & 0xffL)); // no shift needed + } + + + /** + * Returns the MurmurHash3_x86_32 hash. + * @param data data + * @param offset offset + * @param len len + * @param seed seed + * @return int + */ + public static int murmurhash3_x86_32(byte[] data, int offset, int len, int seed) { + + final int c1 = 0xcc9e2d51; + final int c2 = 0x1b873593; + + int h1 = seed; + int roundedEnd = offset + (len & 0xfffffffc); // round down to 4 byte block + + for (int i=offset; i>> 17); // ROTL32(k1,15); + k1 *= c2; + + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13); + h1 = h1*5+0xe6546b64; + } + + // tail + int k1 = 0; + + switch(len & 0x03) { + case 3: + k1 = (data[roundedEnd + 2] & 0xff) << 16; + // fallthrough + case 2: + k1 |= (data[roundedEnd + 1] & 0xff) << 8; + // fallthrough + case 1: + k1 |= (data[roundedEnd] & 0xff); + k1 *= c1; + k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); + k1 *= c2; + h1 ^= k1; + } + + // finalization + h1 ^= len; + + // fmix(h1); + h1 ^= h1 >>> 16; + h1 *= 0x85ebca6b; + h1 ^= h1 >>> 13; + h1 *= 0xc2b2ae35; + h1 ^= h1 >>> 16; + + return h1; + } + + /** + * Returns the MurmurHash3_x86_32 hash of the UTF-8 bytes of the String without actually encoding + * the string to a temporary buffer. This is more than 2x faster than hashing the result + * of String.getBytes(). + * @param data data + * @param offset offset + * @param len len + * @param seed seed + * @return int + */ + public static int murmurhash3_x86_32(CharSequence data, int offset, int len, int seed) { + + final int c1 = 0xcc9e2d51; + final int c2 = 0x1b873593; + + int h1 = seed; + + int pos = offset; + int end = offset + len; + int k1 = 0; + int k2 = 0; + int shift = 0; + int bits = 0; + int nBytes = 0; // length in UTF8 bytes + + + while (pos < end) { + int code = data.charAt(pos++); + if (code < 0x80) { + k2 = code; + bits = 8; + + /*** + // optimized ascii implementation (currently slower!!! code size?) + if (shift == 24) { + k1 = k1 | (code << 24); + k1 *= c1; + k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); + k1 *= c2; + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13); + h1 = h1*5+0xe6546b64; + shift = 0; + nBytes += 4; + k1 = 0; + } else { + k1 |= code << shift; + shift += 8; + } + continue; + ***/ + + } + else if (code < 0x800) { + k2 = (0xC0 | (code >> 6)) + | ((0x80 | (code & 0x3F)) << 8); + bits = 16; + } + else if (code < 0xD800 || code > 0xDFFF || pos>=end) { + // we check for pos>=end to encode an unpaired surrogate as 3 bytes. + k2 = (0xE0 | (code >> 12)) + | ((0x80 | ((code >> 6) & 0x3F)) << 8) + | ((0x80 | (code & 0x3F)) << 16); + bits = 24; + } else { + // surrogate pair + // int utf32 = pos < end ? (int) data.charAt(pos++) : 0; + int utf32 = (int) data.charAt(pos++); + utf32 = ((code - 0xD7C0) << 10) + (utf32 & 0x3FF); + k2 = (0xff & (0xF0 | (utf32 >> 18))) + | ((0x80 | ((utf32 >> 12) & 0x3F))) << 8 + | ((0x80 | ((utf32 >> 6) & 0x3F))) << 16 + | (0x80 | (utf32 & 0x3F)) << 24; + bits = 32; + } + + + k1 |= k2 << shift; + + // int used_bits = 32 - shift; // how many bits of k2 were used in k1. + // int unused_bits = bits - used_bits; // (bits-(32-shift)) == bits+shift-32 == bits-newshift + + shift += bits; + if (shift >= 32) { + // mix after we have a complete word + + k1 *= c1; + k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); + k1 *= c2; + + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); // ROTL32(h1,13); + h1 = h1*5+0xe6546b64; + + shift -= 32; + // unfortunately, java won't let you shift 32 bits off, so we need to check for 0 + if (shift != 0) { + k1 = k2 >>> (bits-shift); // bits used == bits - newshift + } else { + k1 = 0; + } + nBytes += 4; + } + + } // inner + + // handle tail + if (shift > 0) { + nBytes += shift >> 3; + k1 *= c1; + k1 = (k1 << 15) | (k1 >>> 17); // ROTL32(k1,15); + k1 *= c2; + h1 ^= k1; + } + + // finalization + h1 ^= nBytes; + + // fmix(h1); + h1 ^= h1 >>> 16; + h1 *= 0x85ebca6b; + h1 ^= h1 >>> 13; + h1 *= 0xc2b2ae35; + h1 ^= h1 >>> 16; + + return h1; + } + + + /** + * Returns the MurmurHash3_x64_128 hash, placing the result in "out". + * @param key key + * @param offset offset + * @param len len + * @param seed seed + * @param out out + */ + public static void murmurhash3_x64_128(byte[] key, int offset, int len, int seed, LongPair out) { + // The original algorithm does have a 32 bit unsigned seed. + // We have to mask to match the behavior of the unsigned types and prevent sign extension. + long h1 = seed & 0x00000000FFFFFFFFL; + long h2 = seed & 0x00000000FFFFFFFFL; + + final long c1 = 0x87c37b91114253d5L; + final long c2 = 0x4cf5ad432745937fL; + + int roundedEnd = offset + (len & 0xFFFFFFF0); // round down to 16 byte block + for (int i=offset; i -1; i--) { - if (indexes[i] == baseChars[i].length) { - if (i > 0) { - // 进位; - indexes[i - 1]++; - } else { - // 溢出;忽略; - } - indexes[i] = 0; - } - } - return key.toString(); - } - - } - -} +package com.jd.blockchain.utils.id; + +public class KeyGeneratorFactory { + + private static final char[] base36 = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' }; + + private char[][] baseChars; + + /** + * + * @param baseChars + * 数位的基;一个二元数组,其长度表示生成的 key 的位数以及每一位的取值的字符范围; + */ + private KeyGeneratorFactory(char[][] baseChars) { + if (baseChars.length == 0) { + throw new IllegalArgumentException("Empty baseChars!"); + } + for (char[] cs : baseChars) { + if (cs == null || cs.length == 0) { + throw new IllegalArgumentException("Empty baseChars!"); + } + } + this.baseChars = baseChars; + } + + /** + * 创建基为 36 的 KeyGenerator 的工厂实例; + * + * @param len key的长度; + * @return KeyGeneratorFactory + */ + public static KeyGeneratorFactory createBase36Instance(int len){ + if (len <= 0) { + throw new IllegalArgumentException("The len is less than or equal zero!"); + } + char[][] baseChars = new char[len][]; + for (int i = 0; i < baseChars.length; i++) { + baseChars[i] = base36; + } + return new KeyGeneratorFactory(baseChars); + } + + /** + * 创建一个 KeyGenerator 实例; + * + * 注:此方法返回的 KeyGenerator 的实现不是线程安全的; + * + * @return KeyGenerator + */ + public KeyGenerator createKeyGenerator() { + return new CommonKeyGenerator(); + } + + private class CommonKeyGenerator implements KeyGenerator { + + private int[] indexes; + + /** + * 创建一个 KeyGenerator 的实例; + * + * @param baseChars + * 数位的基;一个二元数组,其长度表示生成的 key 的位数以及每一位的取值的字符范围; + */ + private CommonKeyGenerator() { + indexes = new int[baseChars.length]; + } + + @Override + public String next() { + StringBuilder key = new StringBuilder(); + for (int i = 0; i < baseChars.length; i++) { + key.append(baseChars[i][indexes[i]]); + } + indexes[baseChars.length - 1]++; + for (int i = indexes.length - 1; i > -1; i--) { + if (indexes[i] == baseChars[i].length) { + if (i > 0) { + // 进位; + indexes[i - 1]++; + } else { + // 溢出;忽略; + } + indexes[i] = 0; + } + } + return key.toString(); + } + + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/ByteArray.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/ByteArray.java index 322762cb..34a58150 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/ByteArray.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/ByteArray.java @@ -1,317 +1,317 @@ -package com.jd.blockchain.utils.io; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.Externalizable; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.util.Arrays; -import org.springframework.util.Base64Utils; - -import com.jd.blockchain.utils.codec.Base58Utils; -import com.jd.blockchain.utils.codec.HexUtils; - -/** - * ByteArray 二进制字节块是对字节数组的包装,目的是提供一种不可变的二进制数据结构; - * - * @author huanghaiquan - * - */ -public class ByteArray implements Externalizable { - - public static final ByteArray EMPTY = ByteArray.wrap(new byte[0]); - - private byte[] bytes; - - private int hashCode; - - private ByteArray readonlyWrapper = null; - - private ByteArray(byte[] bytes) { - this(bytes, false); - } - - private ByteArray(byte[] bytes, boolean readonly) { - this.bytes = bytes; - this.hashCode = Arrays.hashCode(bytes); -// this.readonly = readonly; - } - - public int size() { - return bytes.length; - } - - public byte get(int i) { - return bytes[i]; - } - -// public boolean isReadonly() { -// return readonly; -// } - - public void copy(int srcPos, byte[] dest, int destPos, int length) { - System.arraycopy(bytes, srcPos, dest, destPos, length); - } - - public ByteArray() {} - - @Override - public boolean equals(Object obj) { - if (super.equals(obj)) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof ByteArray)) { - return false; - } - ByteArray target = (ByteArray) obj; - if (this.bytes == target.bytes) { - return true; - } - return BytesUtils.equals(target.bytes, this.bytes); - } - - @Override - public int hashCode() { - return Arrays.hashCode(bytes); - } - - /** - * 对指定的字节数组的副本进行包装; - * - * @param bytes bytes - * @return ByteArray - */ - public static ByteArray wrapCopy(byte[] bytes) { - byte[] replica = Arrays.copyOf(bytes, bytes.length); - return new ByteArray(replica); - } - - /** - * 对指定的字节数组直接进行包装; - * - * @param bytes bytes - * @return ByteArray - */ - public static ByteArray wrap(byte[] bytes) { - return new ByteArray(bytes); - } - - /** - * 对指定的字节数组直接进行包装; - * - * @param oneByte oneByte - * @return ByteArray - */ - public static ByteArray wrap(byte oneByte) { - return new ByteArray(new byte[] { oneByte }); - } - - /** - * 对指定的字节数组的副本进行包装; - * - * @param bytes bytes - * @return ByteArray - */ - public static ByteArray wrapCopyReadonly(byte[] bytes) { - byte[] replica = Arrays.copyOf(bytes, bytes.length); - return new ByteArray(replica, true); - } - - /** - * 对指定的字节数组直接进行包装; - * - * @param bytes bytes - * @return ByteArray - */ - public static ByteArray wrapReadonly(byte[] bytes) { - return new ByteArray(bytes, true); - } - - /** - * 对指定的字节数组直接进行包装; - * - * @param oneByte oneByte - * @return ByteArray - */ - public static ByteArray wrapReadonly(byte oneByte) { - return new ByteArray(new byte[] { oneByte }, true); - } - - /** - * 将字节内容完整写入指定的输出流; - * @param out out - * @return int - */ - public int writeTo(OutputStream out) { - try { - out.write(bytes); - return bytes.length; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public InputStream asInputStream() { - return new ByteArrayInputStream(bytes); - } - - public ByteBuffer asReadOnlyBuffer() { - return ByteBuffer.wrap(bytes).asReadOnlyBuffer(); - } - -// public ByteArray asReadonly() { -// if (readonly) { -// return this; -// } -// if (readonlyWrapper == null) { -// readonlyWrapper = new ByteArray(bytes, true); -// } -// return readonlyWrapper; -// } - - /** - * 返回原始的二进制数组的副本;
- * - * 注:使用者要注意此操作代理的内存性能的影响; - * - * @return byte array; - */ - public byte[] bytesCopy() { - return Arrays.copyOf(bytes, bytes.length); - } - - /** - * 返回原始的字节数组; - * - *
- * 如果字节数组被标识为只读,调用此方法将引发异常 IllegalStateException; - * - * 注:应谨慎操作此方法返回的字节数组,通常的原则是不应更改返回的字节数组,用于只读的情形; - * - * @return byte array; - */ - public byte[] bytes() { -// if (readonly) { -// throw new IllegalStateException("This byte array is readonly!"); -// } - return bytes; - } - - public String toHex() { - return toHex(bytes); - } - - public String toBase64() { - return toBase64(bytes); - } - - public String toBase58() { - return toBase58(bytes); - } - - /** - * 返回 ByteArray 的 Base58 字符; - */ - @Override - public String toString() { - return toBase58(); - } - - public static ByteArray parseHex(String hexString) { - return wrap(fromHex(hexString)); - } - - public static ByteArray parseBase58(String base58String) { - return wrap(fromBase58(base58String)); - } - - public static ByteArray parseBase64(String base64String) { - return wrap(fromBase64(base64String)); - } - - public static ByteArray parseString(String str, String charset) { - return wrap(fromString(str, charset)); - } - - public static String toHex(byte[] bytes) { - return HexUtils.encode(bytes); - } - - public static String toBase58(byte[] bytes) { - return Base58Utils.encode(bytes); - } - public static String toBase64(byte[] bytes) { - return Base64Utils.encodeToUrlSafeString(bytes); - } - - public String toString(String charset) { - return BytesUtils.toString(bytes, charset); - } - - public static byte[] fromHex(String hexString) { - return HexUtils.decode(hexString); - } - - public static byte[] fromBase58(String base58String) { - return Base58Utils.decode(base58String); - } - - public static byte[] fromBase64(String base64String) { - return Base64Utils.decodeFromUrlSafeString(base64String); - } - - public static byte[] fromString(String str, String charset) { - return BytesUtils.toBytes(str, charset); - } - - /** - * The object implements the writeExternal method to save its contents - * by calling the methods of DataOutput for its primitive values or - * calling the writeObject method of ObjectOutput for objects, strings, - * and arrays. - * - * @param out the stream to write the object to - * @throws IOException Includes any I/O exceptions that may occur - * @serialData Overriding methods should use this tag to describe - * the data layout of this Externalizable object. - * List the sequence of element types and, if possible, - * relate the element to a public/protected field and/or - * method of this Externalizable class. - */ - @Override - public void writeExternal(ObjectOutput out) throws IOException { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - writeTo(os); - byte[] bts = os.toByteArray(); - out.writeInt(bts.length); - out.write(bts); - } - - /** - * The object implements the readExternal method to restore its - * contents by calling the methods of DataInput for primitive - * types and readObject for objects, strings and arrays. The - * readExternal method must read the values in the same sequence - * and with the same types as were written by writeExternal. - * - * @param in the stream to read data from in order to restore the object - * @throws IOException if I/O errors occur - * @throws ClassNotFoundException If the class for an object being - * restored cannot be found. - */ - @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - int len = in.readInt(); - byte[] bts = new byte[len]; - in.readFully(bts); - - this.bytes = bts; - } -} +package com.jd.blockchain.utils.io; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Externalizable; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.util.Arrays; +import org.springframework.util.Base64Utils; + +import com.jd.blockchain.utils.codec.Base58Utils; +import com.jd.blockchain.utils.codec.HexUtils; + +/** + * ByteArray 二进制字节块是对字节数组的包装,目的是提供一种不可变的二进制数据结构; + * + * @author huanghaiquan + * + */ +public class ByteArray implements Externalizable { + + public static final ByteArray EMPTY = ByteArray.wrap(new byte[0]); + + private byte[] bytes; + + private int hashCode; + + private ByteArray readonlyWrapper = null; + + private ByteArray(byte[] bytes) { + this(bytes, false); + } + + private ByteArray(byte[] bytes, boolean readonly) { + this.bytes = bytes; + this.hashCode = Arrays.hashCode(bytes); +// this.readonly = readonly; + } + + public int size() { + return bytes.length; + } + + public byte get(int i) { + return bytes[i]; + } + +// public boolean isReadonly() { +// return readonly; +// } + + public void copy(int srcPos, byte[] dest, int destPos, int length) { + System.arraycopy(bytes, srcPos, dest, destPos, length); + } + + public ByteArray() {} + + @Override + public boolean equals(Object obj) { + if (super.equals(obj)) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof ByteArray)) { + return false; + } + ByteArray target = (ByteArray) obj; + if (this.bytes == target.bytes) { + return true; + } + return BytesUtils.equals(target.bytes, this.bytes); + } + + @Override + public int hashCode() { + return Arrays.hashCode(bytes); + } + + /** + * 对指定的字节数组的副本进行包装; + * + * @param bytes bytes + * @return ByteArray + */ + public static ByteArray wrapCopy(byte[] bytes) { + byte[] replica = Arrays.copyOf(bytes, bytes.length); + return new ByteArray(replica); + } + + /** + * 对指定的字节数组直接进行包装; + * + * @param bytes bytes + * @return ByteArray + */ + public static ByteArray wrap(byte[] bytes) { + return new ByteArray(bytes); + } + + /** + * 对指定的字节数组直接进行包装; + * + * @param oneByte oneByte + * @return ByteArray + */ + public static ByteArray wrap(byte oneByte) { + return new ByteArray(new byte[] { oneByte }); + } + + /** + * 对指定的字节数组的副本进行包装; + * + * @param bytes bytes + * @return ByteArray + */ + public static ByteArray wrapCopyReadonly(byte[] bytes) { + byte[] replica = Arrays.copyOf(bytes, bytes.length); + return new ByteArray(replica, true); + } + + /** + * 对指定的字节数组直接进行包装; + * + * @param bytes bytes + * @return ByteArray + */ + public static ByteArray wrapReadonly(byte[] bytes) { + return new ByteArray(bytes, true); + } + + /** + * 对指定的字节数组直接进行包装; + * + * @param oneByte oneByte + * @return ByteArray + */ + public static ByteArray wrapReadonly(byte oneByte) { + return new ByteArray(new byte[] { oneByte }, true); + } + + /** + * 将字节内容完整写入指定的输出流; + * @param out out + * @return int + */ + public int writeTo(OutputStream out) { + try { + out.write(bytes); + return bytes.length; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public InputStream asInputStream() { + return new ByteArrayInputStream(bytes); + } + + public ByteBuffer asReadOnlyBuffer() { + return ByteBuffer.wrap(bytes).asReadOnlyBuffer(); + } + +// public ByteArray asReadonly() { +// if (readonly) { +// return this; +// } +// if (readonlyWrapper == null) { +// readonlyWrapper = new ByteArray(bytes, true); +// } +// return readonlyWrapper; +// } + + /** + * 返回原始的二进制数组的副本;
+ * + * 注:使用者要注意此操作代理的内存性能的影响; + * + * @return byte array; + */ + public byte[] bytesCopy() { + return Arrays.copyOf(bytes, bytes.length); + } + + /** + * 返回原始的字节数组; + * + *
+ * 如果字节数组被标识为只读,调用此方法将引发异常 IllegalStateException; + * + * 注:应谨慎操作此方法返回的字节数组,通常的原则是不应更改返回的字节数组,用于只读的情形; + * + * @return byte array; + */ + public byte[] bytes() { +// if (readonly) { +// throw new IllegalStateException("This byte array is readonly!"); +// } + return bytes; + } + + public String toHex() { + return toHex(bytes); + } + + public String toBase64() { + return toBase64(bytes); + } + + public String toBase58() { + return toBase58(bytes); + } + + /** + * 返回 ByteArray 的 Base58 字符; + */ + @Override + public String toString() { + return toBase58(); + } + + public static ByteArray parseHex(String hexString) { + return wrap(fromHex(hexString)); + } + + public static ByteArray parseBase58(String base58String) { + return wrap(fromBase58(base58String)); + } + + public static ByteArray parseBase64(String base64String) { + return wrap(fromBase64(base64String)); + } + + public static ByteArray parseString(String str, String charset) { + return wrap(fromString(str, charset)); + } + + public static String toHex(byte[] bytes) { + return HexUtils.encode(bytes); + } + + public static String toBase58(byte[] bytes) { + return Base58Utils.encode(bytes); + } + public static String toBase64(byte[] bytes) { + return Base64Utils.encodeToUrlSafeString(bytes); + } + + public String toString(String charset) { + return BytesUtils.toString(bytes, charset); + } + + public static byte[] fromHex(String hexString) { + return HexUtils.decode(hexString); + } + + public static byte[] fromBase58(String base58String) { + return Base58Utils.decode(base58String); + } + + public static byte[] fromBase64(String base64String) { + return Base64Utils.decodeFromUrlSafeString(base64String); + } + + public static byte[] fromString(String str, String charset) { + return BytesUtils.toBytes(str, charset); + } + + /** + * The object implements the writeExternal method to save its contents + * by calling the methods of DataOutput for its primitive values or + * calling the writeObject method of ObjectOutput for objects, strings, + * and arrays. + * + * @param out the stream to write the object to + * @throws IOException Includes any I/O exceptions that may occur + * @serialData Overriding methods should use this tag to describe + * the data layout of this Externalizable object. + * List the sequence of element types and, if possible, + * relate the element to a public/protected field and/or + * method of this Externalizable class. + */ + @Override + public void writeExternal(ObjectOutput out) throws IOException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + writeTo(os); + byte[] bts = os.toByteArray(); + out.writeInt(bts.length); + out.write(bts); + } + + /** + * The object implements the readExternal method to restore its + * contents by calling the methods of DataInput for primitive + * types and readObject for objects, strings and arrays. The + * readExternal method must read the values in the same sequence + * and with the same types as were written by writeExternal. + * + * @param in the stream to read data from in order to restore the object + * @throws IOException if I/O errors occur + * @throws ClassNotFoundException If the class for an object being + * restored cannot be found. + */ + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + int len = in.readInt(); + byte[] bts = new byte[len]; + in.readFully(bts); + + this.bytes = bts; + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesBlob.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesBlob.java index 356b8a5e..50006049 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesBlob.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesBlob.java @@ -1,5 +1,5 @@ -package com.jd.blockchain.utils.io; - -public interface BytesBlob extends BytesWriter, BytesReader, BytesSerializable{ - -} +package com.jd.blockchain.utils.io; + +public interface BytesBlob extends BytesWriter, BytesReader, BytesSerializable{ + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesChunkReader.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesChunkReader.java index 625d0048..dcd08304 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesChunkReader.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesChunkReader.java @@ -1,162 +1,162 @@ -package com.jd.blockchain.utils.io; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; - -import com.jd.blockchain.utils.IllegalDataException; - -/** - * 字节块读取; - * - * 执行与 {@link BytesChunkWriter} 的写入过程相对应的读取逻辑,分块读出内容; - * - * 在创建 BytesChunkReader 实例时,会先校验魔术字节,如果模式字节校验失败,将抛出 IllegalDataException ; - * - * 注:BytesChunkReader 不是线程安全的; - * - * @author haiq - * - */ -public class BytesChunkReader implements Closeable { - - private byte[] magicBytes; - - private InputStream in; - - /** - * 创建 BytesChunkReader 实例; - * - * 如果模式字节校验失败,将抛出 IllegalDataException ; - * - * @param magicString - * 魔术字符;将被以 UTF-8 编码转码为二进制字节参与校验; - * @param in - * 输入流; - * @throws IOException exception - */ - public BytesChunkReader(String magicString, InputStream in) throws IOException { - this.magicBytes = magicString.getBytes("UTF-8"); - this.in = in; - - checkMagic(); - } - - /** - * 创建 BytesChunkReader 实例; - * - * 如果模式字节校验失败,将抛出 IllegalDataException ; - * - * @param magicBytes - * 魔术字节; - * @param in - * 输入流; - * @throws IOException exception - */ - public BytesChunkReader(byte[] magicBytes, InputStream in) throws IOException { - this.magicBytes = magicBytes; - this.in = in; - - checkMagic(); - } - - private void checkMagic() throws IOException { - byte[] buff = new byte[magicBytes.length]; - int len = in.read(buff); - if (len <= 0) { - throw new IllegalDataException("No data to read!"); - } - if (len < magicBytes.length) { - throw new IllegalDataException("Mismatch magic bytes!"); - } - if (!BytesUtils.equals(magicBytes, buff)) { - throw new IllegalDataException("Mismatch magic bytes!"); - } - } - - /** - * 读取下一个数据块; - * @return 数据块;如果已经没有数据块可读,则返回 null,并关闭输入流; - * @throws IOException exception - */ - public byte[] read() throws IOException { - int len = readNextLengthHeader(); - if (len < 0) { - // No chunk; - return null; - } - ByteArrayOutputStream out = new ByteArrayOutputStream(); - int reallyLen = BytesUtils.copy(in, out, len); - if (reallyLen < len) { - throw new IllegalDataException( - "No enough data as the length header indicated to read from the input stream !"); - } - return out.toByteArray();// ByteArrayOutputStream is not necessary to - // close; - } - - /** - * 读取下一个数据块; - * @param out 输出流; - * @return 数据块;如果已经没有数据块可读,则返回 -1,并关闭输入流; - * @throws IOException exception - */ - public int read(OutputStream out) throws IOException { - int len = readNextLengthHeader(); - if (len < 0) { - // No chunk; - return -1; - } - int cpLen = BytesUtils.copy(in, out, len); - if (cpLen < len) { - throw new IllegalDataException( - "No enough data as the length header indicated to read from the input stream!"); - } - return len; - } - - /** - * 返回下一个长度头; - * - * 如果已到结尾,则返回 -1,并关闭输入流; - * - * @return - * @throws IOException - */ - private int readNextLengthHeader() throws IOException{ - int len = BytesUtils.readInt(in); - if (len <= 0) { - // No chunk; - close(); - return -1; - } - return len; - } - - @Override - public void close() throws IOException { - in.close(); - } - - public static byte[][] extract(byte[] magicBytes, byte[] compactedBytes) throws IOException{ - ByteArrayInputStream in = new ByteArrayInputStream(compactedBytes); - BytesChunkReader reader = new BytesChunkReader(magicBytes, in); - List dataBytesList; - try { - dataBytesList = new ArrayList(); - byte[] dataBytes = null; - while ((dataBytes = reader.read()) != null) { - dataBytesList.add(dataBytes); - } - } finally{ - reader.close(); - } - - return dataBytesList.toArray(new byte[dataBytesList.size()][]); - } -} +package com.jd.blockchain.utils.io; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import com.jd.blockchain.utils.IllegalDataException; + +/** + * 字节块读取; + * + * 执行与 {@link BytesChunkWriter} 的写入过程相对应的读取逻辑,分块读出内容; + * + * 在创建 BytesChunkReader 实例时,会先校验魔术字节,如果模式字节校验失败,将抛出 IllegalDataException ; + * + * 注:BytesChunkReader 不是线程安全的; + * + * @author haiq + * + */ +public class BytesChunkReader implements Closeable { + + private byte[] magicBytes; + + private InputStream in; + + /** + * 创建 BytesChunkReader 实例; + * + * 如果模式字节校验失败,将抛出 IllegalDataException ; + * + * @param magicString + * 魔术字符;将被以 UTF-8 编码转码为二进制字节参与校验; + * @param in + * 输入流; + * @throws IOException exception + */ + public BytesChunkReader(String magicString, InputStream in) throws IOException { + this.magicBytes = magicString.getBytes("UTF-8"); + this.in = in; + + checkMagic(); + } + + /** + * 创建 BytesChunkReader 实例; + * + * 如果模式字节校验失败,将抛出 IllegalDataException ; + * + * @param magicBytes + * 魔术字节; + * @param in + * 输入流; + * @throws IOException exception + */ + public BytesChunkReader(byte[] magicBytes, InputStream in) throws IOException { + this.magicBytes = magicBytes; + this.in = in; + + checkMagic(); + } + + private void checkMagic() throws IOException { + byte[] buff = new byte[magicBytes.length]; + int len = in.read(buff); + if (len <= 0) { + throw new IllegalDataException("No data to read!"); + } + if (len < magicBytes.length) { + throw new IllegalDataException("Mismatch magic bytes!"); + } + if (!BytesUtils.equals(magicBytes, buff)) { + throw new IllegalDataException("Mismatch magic bytes!"); + } + } + + /** + * 读取下一个数据块; + * @return 数据块;如果已经没有数据块可读,则返回 null,并关闭输入流; + * @throws IOException exception + */ + public byte[] read() throws IOException { + int len = readNextLengthHeader(); + if (len < 0) { + // No chunk; + return null; + } + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int reallyLen = BytesUtils.copy(in, out, len); + if (reallyLen < len) { + throw new IllegalDataException( + "No enough data as the length header indicated to read from the input stream !"); + } + return out.toByteArray();// ByteArrayOutputStream is not necessary to + // close; + } + + /** + * 读取下一个数据块; + * @param out 输出流; + * @return 数据块;如果已经没有数据块可读,则返回 -1,并关闭输入流; + * @throws IOException exception + */ + public int read(OutputStream out) throws IOException { + int len = readNextLengthHeader(); + if (len < 0) { + // No chunk; + return -1; + } + int cpLen = BytesUtils.copy(in, out, len); + if (cpLen < len) { + throw new IllegalDataException( + "No enough data as the length header indicated to read from the input stream!"); + } + return len; + } + + /** + * 返回下一个长度头; + * + * 如果已到结尾,则返回 -1,并关闭输入流; + * + * @return + * @throws IOException + */ + private int readNextLengthHeader() throws IOException{ + int len = BytesUtils.readInt(in); + if (len <= 0) { + // No chunk; + close(); + return -1; + } + return len; + } + + @Override + public void close() throws IOException { + in.close(); + } + + public static byte[][] extract(byte[] magicBytes, byte[] compactedBytes) throws IOException{ + ByteArrayInputStream in = new ByteArrayInputStream(compactedBytes); + BytesChunkReader reader = new BytesChunkReader(magicBytes, in); + List dataBytesList; + try { + dataBytesList = new ArrayList(); + byte[] dataBytes = null; + while ((dataBytes = reader.read()) != null) { + dataBytesList.add(dataBytes); + } + } finally{ + reader.close(); + } + + return dataBytesList.toArray(new byte[dataBytesList.size()][]); + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesChunkWriter.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesChunkWriter.java index 28016337..537155b1 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesChunkWriter.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesChunkWriter.java @@ -1,157 +1,157 @@ -package com.jd.blockchain.utils.io; - -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; - -/** - * 字节块写入; - * - * BytesChunkWriter 定义了魔术字节(magic bytes)作为字节块流的开端,写入在所有的内容之前; - * - * 在写入每一个字节块之前,先把块长度作为一个 4 字节的二进制数组写入,然后跟着写入块的内容; - * - * 当完成全部写入之后,写入 -1 的 4 字节二进制格式作为结尾标识; - * - * 注:BytesChunkReader 不是线程安全的; - * - * @author haiq - * - */ -public class BytesChunkWriter implements Closeable { - - private static byte[] END_BYTES = BytesUtils.toBytes(-1); - - private byte[] magicBytes; - - private OutputStream out; - - private boolean enclose = false; - - /** - * 创建一个 BytesChunkWriter 实例; - * - * @param magicString - * 魔术字符;作为字节块流的起始标识; - * @param out - * 要写入的流; - * @throws IOException exception - */ - public BytesChunkWriter(String magicString, OutputStream out) throws IOException { - try { - this.out = out; - this.magicBytes = magicString.getBytes("UTF-8"); - writeMagic(); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - /** - * 创建一个 BytesChunkWriter 实例; - * - * @param magicBytes - * 魔术字符;作为字节块流的起始标识; - * @param out out - * @throws IOException exception - */ - public BytesChunkWriter(byte[] magicBytes, OutputStream out) throws IOException { - this.magicBytes = magicBytes; - this.out = out; - writeMagic(); - } - - private void writeMagic() throws IOException { - if (magicBytes.length == 0) { - throw new IllegalArgumentException("The magicBytes is empty!"); - } - out.write(magicBytes); - } - - /** - * 写入字节块; - * - * 在写入字节块之前先写入 4 个字节的块长度头,然后写入内容; - * - * @param bytes bytes - * @throws IOException exception - */ - public void write(byte[] bytes) throws IOException{ - checkEncosed(); - byte[] lenHeader = BytesUtils.toBytes(bytes.length); - out.write(lenHeader); - out.write(bytes); - } - - /** - * 从指定的流读入指定长度的块并写入流; - * - * 如果读入的长度不足指定的值,将抛出 IllegalArgumentException 异常; - * - * @param len 块长度; - * @param in 要读入数据的流; - * @throws IOException exception - */ - public void write(int len, InputStream in) throws IOException{ - if (len < 1) { - throw new IllegalArgumentException("The len must be positive!"); - } - byte[] lenHeader = BytesUtils.toBytes(len); - out.write(lenHeader); - int wrLen = BytesUtils.copy(in, out, len); - if (wrLen < len) { - throw new IllegalArgumentException("The length of the input stream is less than the specified len of chunk!"); - } - } - - public void flush() throws IOException{ - out.flush(); - } - - private void encloseChunk() throws IOException{ - if (enclose) { - return; - } - out.write(END_BYTES); - enclose = true; - } - - private void checkEncosed(){ - if (enclose) { - throw new IllegalStateException("This BytesChunkWriter instance is enclosed!"); - } - } - - /** - * 结束并关闭流; - * - * @throws IOException exception - */ - @Override - public void close() throws IOException { - if (!enclose) { - encloseChunk(); - flush(); - } - out.close(); - } - - public static byte[] compact(byte[] magicBytes, byte[]... dataBytes) throws IOException{ - ByteArrayOutputStream out = new ByteArrayOutputStream(); - BytesChunkWriter writer = new BytesChunkWriter(magicBytes, out); - try { - if (dataBytes != null) { - for (byte[] bs : dataBytes) { - writer.write(bs);; - } - } - writer.flush(); - } finally{ - writer.close(); - } - return out.toByteArray(); - } -} +package com.jd.blockchain.utils.io; + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +/** + * 字节块写入; + * + * BytesChunkWriter 定义了魔术字节(magic bytes)作为字节块流的开端,写入在所有的内容之前; + * + * 在写入每一个字节块之前,先把块长度作为一个 4 字节的二进制数组写入,然后跟着写入块的内容; + * + * 当完成全部写入之后,写入 -1 的 4 字节二进制格式作为结尾标识; + * + * 注:BytesChunkReader 不是线程安全的; + * + * @author haiq + * + */ +public class BytesChunkWriter implements Closeable { + + private static byte[] END_BYTES = BytesUtils.toBytes(-1); + + private byte[] magicBytes; + + private OutputStream out; + + private boolean enclose = false; + + /** + * 创建一个 BytesChunkWriter 实例; + * + * @param magicString + * 魔术字符;作为字节块流的起始标识; + * @param out + * 要写入的流; + * @throws IOException exception + */ + public BytesChunkWriter(String magicString, OutputStream out) throws IOException { + try { + this.out = out; + this.magicBytes = magicString.getBytes("UTF-8"); + writeMagic(); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + /** + * 创建一个 BytesChunkWriter 实例; + * + * @param magicBytes + * 魔术字符;作为字节块流的起始标识; + * @param out out + * @throws IOException exception + */ + public BytesChunkWriter(byte[] magicBytes, OutputStream out) throws IOException { + this.magicBytes = magicBytes; + this.out = out; + writeMagic(); + } + + private void writeMagic() throws IOException { + if (magicBytes.length == 0) { + throw new IllegalArgumentException("The magicBytes is empty!"); + } + out.write(magicBytes); + } + + /** + * 写入字节块; + * + * 在写入字节块之前先写入 4 个字节的块长度头,然后写入内容; + * + * @param bytes bytes + * @throws IOException exception + */ + public void write(byte[] bytes) throws IOException{ + checkEncosed(); + byte[] lenHeader = BytesUtils.toBytes(bytes.length); + out.write(lenHeader); + out.write(bytes); + } + + /** + * 从指定的流读入指定长度的块并写入流; + * + * 如果读入的长度不足指定的值,将抛出 IllegalArgumentException 异常; + * + * @param len 块长度; + * @param in 要读入数据的流; + * @throws IOException exception + */ + public void write(int len, InputStream in) throws IOException{ + if (len < 1) { + throw new IllegalArgumentException("The len must be positive!"); + } + byte[] lenHeader = BytesUtils.toBytes(len); + out.write(lenHeader); + int wrLen = BytesUtils.copy(in, out, len); + if (wrLen < len) { + throw new IllegalArgumentException("The length of the input stream is less than the specified len of chunk!"); + } + } + + public void flush() throws IOException{ + out.flush(); + } + + private void encloseChunk() throws IOException{ + if (enclose) { + return; + } + out.write(END_BYTES); + enclose = true; + } + + private void checkEncosed(){ + if (enclose) { + throw new IllegalStateException("This BytesChunkWriter instance is enclosed!"); + } + } + + /** + * 结束并关闭流; + * + * @throws IOException exception + */ + @Override + public void close() throws IOException { + if (!enclose) { + encloseChunk(); + flush(); + } + out.close(); + } + + public static byte[] compact(byte[] magicBytes, byte[]... dataBytes) throws IOException{ + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BytesChunkWriter writer = new BytesChunkWriter(magicBytes, out); + try { + if (dataBytes != null) { + for (byte[] bs : dataBytes) { + writer.write(bs);; + } + } + writer.flush(); + } finally{ + writer.close(); + } + return out.toByteArray(); + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesEncoding.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesEncoding.java index 0bff40f0..60941d1c 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesEncoding.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesEncoding.java @@ -1,171 +1,171 @@ -package com.jd.blockchain.utils.io; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public class BytesEncoding { - - public static int writeInNormal(byte[] data, OutputStream out) { - return write(data, NumberMask.NORMAL, out); - } - - public static int writeInShort(byte[] data, OutputStream out) { - return write(data, NumberMask.SHORT, out); - } - - public static int writeInTiny(byte[] data, OutputStream out) { - return write(data, NumberMask.TINY, out); - } - - /** - * 写入字节数据; - * - * 先写入字节长度的头部,再写入数据; - * - * 如果字节数据的长度为 0,则只写入一个空的头部; - * - * @param data data - * @param dataLengthMask dataLengthMask - * @param out out - * @return 返回写入的字节数; - */ - public static int write(byte[] data, NumberMask dataLengthMask, OutputStream out) { - try { - int s = dataLengthMask.writeMask(data == null ? 0 : data.length, out); - if (data != null) { - out.write(data, 0, data.length); - s += data.length; - } - return s; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - /** - * getOutputSizeInNormal - * @param dataSize dataSize - * @return int - */ - public static int getOutputSizeInNormal(int dataSize) { - return NumberMask.NORMAL.getMaskLength(dataSize) + dataSize; - } - - public static int writeInNormal(byte[] data, byte[] buffer) { - return write(NumberMask.NORMAL, data, 0, buffer, 0, data.length); - } - - public static int writeInNormal(byte[] data, byte[] buffer, int bufferOffset) { - return write(NumberMask.NORMAL, data, 0, buffer, bufferOffset, data.length); - } - - public static int writeInNormal(byte[] data, byte[] buffer, int bufferOffset, int length) { - return write(NumberMask.NORMAL, data, 0, buffer, bufferOffset, length); - } - - public static int writeInNormal(byte[] data, int dataOffset, byte[] buffer, int bufferOffset, int length) { - return write(NumberMask.NORMAL, data, dataOffset, buffer, bufferOffset, length); - } - - public static int write(NumberMask dataLengthMask, byte[] data, byte[] buffer) { - return write(dataLengthMask, data, 0, buffer, 0, data.length); - } - - public static int write(NumberMask dataLengthMask, byte[] data, byte[] buffer, int bufferOffset) { - return write(dataLengthMask, data, 0, buffer, bufferOffset, data.length); - } - - public static int write(NumberMask dataLengthMask, byte[] data, byte[] buffer, int bufferOffset, int length) { - return write(dataLengthMask, data, 0, buffer, bufferOffset, length); - } - - public static int write(NumberMask dataLengthMask, byte[] data, int dataOffset, byte[] buffer, int bufferOffset, - int length) { - int s = dataLengthMask.writeMask(data == null ? 0 : data.length, buffer, bufferOffset); - bufferOffset += s; - if (data != null) { - System.arraycopy(data, dataOffset, buffer, bufferOffset, length); - s += length; - } - return s; - } - - public static byte[] readInTiny(byte[] buffer, int offset) { - return read(NumberMask.TINY, buffer, offset); - } - - public static byte[] readInShort(byte[] buffer, int offset) { - return read(NumberMask.SHORT, buffer, offset); - } - - public static byte[] readInNormal(byte[] buffer, int offset) { - return read(NumberMask.NORMAL, buffer, offset); - } - - public static byte[] read(NumberMask dataLengthMask, byte[] buffer, int offset) { - int size = dataLengthMask.resolveMaskedNumber(buffer, offset); - int maskLen = dataLengthMask.resolveMaskLength(buffer[offset]); - offset += maskLen; - byte[] data = new byte[size]; - System.arraycopy(buffer, offset, data, 0, size); - return data; - } - - public static int write(ByteArray data, NumberMask dataLengthMask, OutputStream out) { - int s = dataLengthMask.writeMask(data == null ? 0 : data.size(), out); - if (data != null) { - s += data.writeTo(out); - } - return s; - } - - public static byte[] readInTiny(InputStream in) { - return read(NumberMask.TINY, in); - } - - public static byte[] readInNormal(InputStream in) { - return read(NumberMask.NORMAL, in); - } - - public static byte[] readInShort(InputStream in) { - return read(NumberMask.SHORT, in); - } - - /** - * 读取头部和内容; - * 如果头部标识的数据长度为 0,则返回一个长度为 0 的字节数组; - * @param dataLengthMask dataLengthMask - * @param in in - * @return byte[] - */ - public static byte[] read(NumberMask dataLengthMask, InputStream in) { - try { - int size = dataLengthMask.resolveMaskedNumber(in); - if (size == 0) { - return BytesUtils.EMPTY_BYTES; - } - byte[] data = new byte[size]; - int len = in.read(data, 0, size); - if (len < size) { - throw new IllegalArgumentException("No enough bytes was read as the size header indicated!"); - } - return data; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - -// /** -// * 读取头部和内容; -// * @param headerMask headerMask -// * @param in in -// * @return byteArray -// * @throws IOException exception -// */ -// public static ByteArray readAsByteArray(NumberMask headerMask, InputStream in) throws IOException { -// byte[] data = read(headerMask, in); -// return ByteArray.wrap(data); -// } - -} +package com.jd.blockchain.utils.io; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class BytesEncoding { + + public static int writeInNormal(byte[] data, OutputStream out) { + return write(data, NumberMask.NORMAL, out); + } + + public static int writeInShort(byte[] data, OutputStream out) { + return write(data, NumberMask.SHORT, out); + } + + public static int writeInTiny(byte[] data, OutputStream out) { + return write(data, NumberMask.TINY, out); + } + + /** + * 写入字节数据; + * + * 先写入字节长度的头部,再写入数据; + * + * 如果字节数据的长度为 0,则只写入一个空的头部; + * + * @param data data + * @param dataLengthMask dataLengthMask + * @param out out + * @return 返回写入的字节数; + */ + public static int write(byte[] data, NumberMask dataLengthMask, OutputStream out) { + try { + int s = dataLengthMask.writeMask(data == null ? 0 : data.length, out); + if (data != null) { + out.write(data, 0, data.length); + s += data.length; + } + return s; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + /** + * getOutputSizeInNormal + * @param dataSize dataSize + * @return int + */ + public static int getOutputSizeInNormal(int dataSize) { + return NumberMask.NORMAL.getMaskLength(dataSize) + dataSize; + } + + public static int writeInNormal(byte[] data, byte[] buffer) { + return write(NumberMask.NORMAL, data, 0, buffer, 0, data.length); + } + + public static int writeInNormal(byte[] data, byte[] buffer, int bufferOffset) { + return write(NumberMask.NORMAL, data, 0, buffer, bufferOffset, data.length); + } + + public static int writeInNormal(byte[] data, byte[] buffer, int bufferOffset, int length) { + return write(NumberMask.NORMAL, data, 0, buffer, bufferOffset, length); + } + + public static int writeInNormal(byte[] data, int dataOffset, byte[] buffer, int bufferOffset, int length) { + return write(NumberMask.NORMAL, data, dataOffset, buffer, bufferOffset, length); + } + + public static int write(NumberMask dataLengthMask, byte[] data, byte[] buffer) { + return write(dataLengthMask, data, 0, buffer, 0, data.length); + } + + public static int write(NumberMask dataLengthMask, byte[] data, byte[] buffer, int bufferOffset) { + return write(dataLengthMask, data, 0, buffer, bufferOffset, data.length); + } + + public static int write(NumberMask dataLengthMask, byte[] data, byte[] buffer, int bufferOffset, int length) { + return write(dataLengthMask, data, 0, buffer, bufferOffset, length); + } + + public static int write(NumberMask dataLengthMask, byte[] data, int dataOffset, byte[] buffer, int bufferOffset, + int length) { + int s = dataLengthMask.writeMask(data == null ? 0 : data.length, buffer, bufferOffset); + bufferOffset += s; + if (data != null) { + System.arraycopy(data, dataOffset, buffer, bufferOffset, length); + s += length; + } + return s; + } + + public static byte[] readInTiny(byte[] buffer, int offset) { + return read(NumberMask.TINY, buffer, offset); + } + + public static byte[] readInShort(byte[] buffer, int offset) { + return read(NumberMask.SHORT, buffer, offset); + } + + public static byte[] readInNormal(byte[] buffer, int offset) { + return read(NumberMask.NORMAL, buffer, offset); + } + + public static byte[] read(NumberMask dataLengthMask, byte[] buffer, int offset) { + int size = dataLengthMask.resolveMaskedNumber(buffer, offset); + int maskLen = dataLengthMask.resolveMaskLength(buffer[offset]); + offset += maskLen; + byte[] data = new byte[size]; + System.arraycopy(buffer, offset, data, 0, size); + return data; + } + + public static int write(ByteArray data, NumberMask dataLengthMask, OutputStream out) { + int s = dataLengthMask.writeMask(data == null ? 0 : data.size(), out); + if (data != null) { + s += data.writeTo(out); + } + return s; + } + + public static byte[] readInTiny(InputStream in) { + return read(NumberMask.TINY, in); + } + + public static byte[] readInNormal(InputStream in) { + return read(NumberMask.NORMAL, in); + } + + public static byte[] readInShort(InputStream in) { + return read(NumberMask.SHORT, in); + } + + /** + * 读取头部和内容; + * 如果头部标识的数据长度为 0,则返回一个长度为 0 的字节数组; + * @param dataLengthMask dataLengthMask + * @param in in + * @return byte[] + */ + public static byte[] read(NumberMask dataLengthMask, InputStream in) { + try { + int size = dataLengthMask.resolveMaskedNumber(in); + if (size == 0) { + return BytesUtils.EMPTY_BYTES; + } + byte[] data = new byte[size]; + int len = in.read(data, 0, size); + if (len < size) { + throw new IllegalArgumentException("No enough bytes was read as the size header indicated!"); + } + return data; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + +// /** +// * 读取头部和内容; +// * @param headerMask headerMask +// * @param in in +// * @return byteArray +// * @throws IOException exception +// */ +// public static ByteArray readAsByteArray(NumberMask headerMask, InputStream in) throws IOException { +// byte[] data = read(headerMask, in); +// return ByteArray.wrap(data); +// } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesReader.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesReader.java index 46bfbb50..116e8fb5 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesReader.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesReader.java @@ -1,10 +1,10 @@ -package com.jd.blockchain.utils.io; - -import java.io.IOException; -import java.io.InputStream; - -public interface BytesReader { - - void resolvFrom(InputStream in) throws IOException; - -} +package com.jd.blockchain.utils.io; + +import java.io.IOException; +import java.io.InputStream; + +public interface BytesReader { + + void resolvFrom(InputStream in) throws IOException; + +} 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 3f0a7256..8c16d0fa 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 @@ -1,689 +1,689 @@ -package com.jd.blockchain.utils.io; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -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; - -/** - * 二进制工具类; - * - * @author haiq - * - */ -public class BytesUtils { - - public static final String DEFAULT_CHARSET = "UTF-8"; - - public static final byte[] EMPTY_BYTES = {}; - - public static final int MAX_BUFFER_SIZE = 1024 * 1024 * 1024; - public static final int BUFFER_SIZE = 64; - - public static final byte TRUE_BYTE = 1; - - public static final byte FALSE_BYTE = 0; - - private BytesUtils() { - } - - /** - * 比较指定的两个字节数组是否一致; - *

- * - * 此方法不处理两者其中之一为 null 的情形,因为无法定义相等性,所以将引发 {@link NullPointerException} 异常; - * - * @param bytes1 bytes1 - * @param bytes2 bytes2 - * @return boolean - */ - public static boolean equals(byte[] bytes1, byte[] bytes2) { - if (bytes1 == bytes2) { - return true; - } - if (bytes1 == null || bytes2 == null) { - return false; - } - if (bytes1.length != bytes2.length) { - return false; - } - for (int i = 0; i < bytes1.length; i++) { - if (bytes1[i] != bytes2[i]) { - return false; - } - } - return true; - } - - public static byte[] toBytes(BytesWriter bytesWriter) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - bytesWriter.writeTo(out); - return out.toByteArray(); - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - - } - - /** - * 将输入流的所有内容都读入到字节数组返回; 如果输入流的长度超出 MAX_BUFFER_SIZE 定义的值,则抛出 - * IllegalArgumentException ; - * - * @param in in - * @return byte[] - */ - public static byte[] copyToBytes(InputStream in) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - byte[] buffer = new byte[BUFFER_SIZE]; - int len = 0; - long size = 0; - while ((len = in.read(buffer)) > 0) { - size += len; - if (size > MAX_BUFFER_SIZE) { - throw new IllegalArgumentException( - "The size of the InputStream exceed the max buffer size [" + MAX_BUFFER_SIZE + "]!"); - } - out.write(buffer, 0, len); - } - return out.toByteArray(); - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static int copy(InputStream in, OutputStream out) throws IOException { - return copy(in, out, Integer.MAX_VALUE); - } - - /** - * 将输入流复制到输出流; - * - * @param in 输入流; - * @param out 输出流; - * @param maxSize 最大字节大小; - * @return 返回实际复制的字节数; - * @throws IOException exception - */ - public static int copy(InputStream in, OutputStream out, int maxSize) throws IOException { - byte[] buffer = new byte[BUFFER_SIZE]; - int len = 0; - int left = maxSize; - int readLen = buffer.length; - while (left > 0) { - readLen = Math.min(left, buffer.length); - len = in.read(buffer, 0, readLen); - if (len > 0) { - out.write(buffer, 0, len); - left = left - len; - } else { - break; - } - } - return maxSize - left; - } - - /** - * 将 int 值转为4字节的二进制数组; - * - * @param value value - * @return 转换后的二进制数组,高位在前,低位在后; - */ - public static byte[] toBytes(int value) { - byte[] bytes = new byte[4]; - toBytes(value, bytes, 0); - return bytes; - } - - public static byte[] toBytes(short value) { - byte[] bytes = new byte[2]; - toBytes(value, bytes, 0); - return bytes; - } - - public static byte[] toBytes(boolean value) { - return new byte[] { value ? TRUE_BYTE : FALSE_BYTE }; - } - - /** - * 将 long 值转为8字节的二进制数组; - * - * @param value value - * @return 转换后的二进制数组,高位在前,低位在后; - */ - public static byte[] toBytes(long value) { - byte[] bytes = new byte[8]; - toBytes(value, bytes, 0); - return bytes; - } - - /** - * 将 int 值转为4字节的二进制数组; - * - * @param value 要转换的int整数; - * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 0 开始的4个元素; - */ - public static void toBytes(short value, byte[] bytes) { - toBytes(value, bytes, 0); - } - - public static int toBytes(int value, byte[] bytes) { - return toBytes(value, bytes, 0); - } - - /** - * 将 int 值转为4字节的二进制数组; - *

- * 以“高位在前”的方式转换,即:数值的高位保存在数组地址的低位; - * - * @param value 要转换的int整数; - * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; - * @param offset 写入转换结果的起始位置; - * @return 返回写入的长度; - */ - public static int toBytes(int value, byte[] bytes, int offset) { - bytes[offset] = (byte) ((value >>> 24) & 0x00FF); - bytes[offset + 1] = (byte) ((value >>> 16) & 0x00FF); - bytes[offset + 2] = (byte) ((value >>> 8) & 0x00FF); - bytes[offset + 3] = (byte) (value & 0x00FF); - return 4; - } - - /** - * 将 int 值转为4字节的二进制数组; - *

- * 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位; - * - * @param value 要转换的int整数; - * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; - * @param offset 写入转换结果的起始位置; - * @return 返回写入的长度; - */ - public static int toBytesInReverse(int value, byte[] bytes, int offset) { - bytes[offset] = (byte) (value & 0x00FF); - bytes[offset + 1] = (byte) ((value >>> 8) & 0x00FF); - bytes[offset + 2] = (byte) ((value >>> 16) & 0x00FF); - bytes[offset + 3] = (byte) ((value >>> 24) & 0x00FF); - return 4; - } - - /** - * 将 int 值转为4字节的二进制数组; - *

- * 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位; - * - * @param value 要转换的int整数; - * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; - * @param offset 写入转换结果的起始位置; - * @param len 写入长度;必须大于 0 ,小于等于 4; - * @return 返回写入的长度; - */ - public static int toBytesInReverse(int value, byte[] bytes, int offset, int len) { - int i = 0; - int l = len > 4 ? 4 : len; - for (; i < l; i++) { - bytes[offset + i] = (byte) ((value >>> (8 * i)) & 0x00FF); - } - - return i; - } - - // public static int toBytes(int value, OutputStream out) { - // try { - // out.write((value >>> 24) & 0x00FF); - // out.write((value >>> 16) & 0x00FF); - // out.write((value >>> 8) & 0x00FF); - // out.write(value & 0x00FF); - // return 4; - // } catch (IOException e) { - // throw new RuntimeIOException(e.getMessage(), e); - // } - // } - - public static void toBytes(short value, byte[] bytes, int offset) { - bytes[offset] = (byte) ((value >>> 8) & 0x00FF); - bytes[offset + 1] = (byte) (value & 0x00FF); - } - - public static void toBytes(char value, byte[] bytes, int offset) { - bytes[offset] = (byte) ((value >>> 8) & 0x00FF); - bytes[offset + 1] = (byte) (value & 0x00FF); - } - - /** - * 将 long 值转为8字节的二进制数组; - * - * @param value 要转换的long整数; - * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的8个元素; - * @param offset 写入转换结果的起始位置; - * @return 返回写入的长度; - */ - public static int toBytes(long value, byte[] bytes, int offset) { - bytes[offset] = (byte) ((value >>> 56) & 0x00FF); - bytes[offset + 1] = (byte) ((value >>> 48) & 0x00FF); - bytes[offset + 2] = (byte) ((value >>> 40) & 0x00FF); - bytes[offset + 3] = (byte) ((value >>> 32) & 0x00FF); - bytes[offset + 4] = (byte) ((value >>> 24) & 0x00FF); - bytes[offset + 5] = (byte) ((value >>> 16) & 0x00FF); - bytes[offset + 6] = (byte) ((value >>> 8) & 0x00FF); - bytes[offset + 7] = (byte) (value & 0x00FF); - return 8; - } - - // public static int toBytes(long value, OutputStream out) { - // try { - // out.write((int) ((value >>> 56) & 0x00FF)); - // out.write((int) ((value >>> 48) & 0x00FF)); - // out.write((int) ((value >>> 40) & 0x00FF)); - // out.write((int) ((value >>> 32) & 0x00FF)); - // out.write((int) ((value >>> 24) & 0x00FF)); - // out.write((int) ((value >>> 16) & 0x00FF)); - // out.write((int) ((value >>> 8) & 0x00FF)); - // out.write((int) (value & 0x00FF)); - // return 8; - // } catch (IOException e) { - // throw new RuntimeIOException(e.getMessage(), e); - // } - // } - - public static byte[] toBytes(String str) { - return toBytes(str, DEFAULT_CHARSET); - } - - public static byte[] toBytes(String str, String charset) { - try { - byte[] bytes = str.getBytes(charset); - return bytes; - } catch (UnsupportedEncodingException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - /** - * @param bytes - * @return - */ - public static String toString(byte[] bytes) { - return toString(bytes, DEFAULT_CHARSET); - } - - public static String toString(byte[] bytes, int offset) { - return toString(bytes, offset, bytes.length - offset, DEFAULT_CHARSET); - } - - public static String toString(byte[] bytes, int offset, int len) { - return toString(bytes, offset, len, DEFAULT_CHARSET); - } - - public static String toString(byte[] bytes, String charset) { - return toString(bytes, 0, bytes.length, charset); - } - - public static String toString(byte[] bytes, int offset, int len, String charset) { - try { - if (bytes == null) { - return null; - } - if (len == 0) { - return ""; - } - return new String(bytes, offset, len, charset); - } catch (UnsupportedEncodingException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static boolean toBoolean(byte value) { - return value != FALSE_BYTE; - } - - /** - * 按从高位到低位的顺序将指定二进制数组从位置 0 开始的 4 个字节转换为 int 整数; - * - * @param bytes 要转换的二进制数组; - * @return 转换后的 int 整数; - */ - public static int toInt(byte[] bytes) { - return toInt(bytes, 0); - // value = (value | (bytes[0] & 0xFF)) << 8; - // value = (value | (bytes[1] & 0xFF)) << 8; - // value = (value | (bytes[2] & 0xFF)) << 8; - // value = value | (bytes[3] & 0xFF); - // - // return value; - } - - /** - * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 2 个字节转换为 short 整数; - * - * @param bytes 要转换的二进制数组; - * @param offset 要读取数据的开始位置 - * @return 转换后的 short 整数; - */ - public static short toShort(byte[] bytes, int offset) { - short value = 0; - value = (short) ((value | (bytes[offset] & 0xFF)) << 8); - value = (short) (value | (bytes[offset + 1] & 0xFF)); - - 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); - value = (char) (value | (bytes[offset + 1] & 0xFF)); - - return value; - } - - /** - * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; - * - * @param bytes 要转换的二进制数组; - * @param offset 要读取数据的开始位置 - * @return 转换后的 int 整数; - */ - public static int toInt(byte[] bytes, int offset) { - // int value = 0; - // value = (value | (bytes[offset] & 0xFF)) << 8; - // value = (value | (bytes[offset + 1] & 0xFF)) << 8; - // value = (value | (bytes[offset + 2] & 0xFF)) << 8; - // value = value | (bytes[offset + 3] & 0xFF); - // - // return value; - return toInt(bytes, offset, 4); - } - - /** - * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; - * - * @param bytes 要转换的二进制数组; - * @param offset 要读取数据的开始位置 - * @return 转换后的 int 整数; - * - * @param len 长度;len 必须满足: len 大于等于 1 且小于等于4; - * @return 转换后的 int 整数; - */ - public static int toInt(byte[] bytes, int offset, int len) { - // if (len < 1 || len > 4) { - // throw new IllegalArgumentException("Len less than 1 or greate than 4!"); - // } - // int value = 0; - // for (int i = 0; i < len; i++) { - // value = value | ((bytes[offset + i] & 0xFF) << (8 * (3 - i))); - // } - // - // return value; - return toInt(bytes, offset, len, true); - } - - /** - * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; - * - * @param bytes 要转换的二进制数组; - * @param offset 要读取数据的开始位置 - * @return 转换后的 int 整数; - * - * @param len 长度;len 必须满足: len 大于等于 1 且小于等于4; - * @param highAlign 是否高位对齐;
- * true 表示参数 bytes 的首个字节对应为整数的最高8位;
- * false 表示参数 bytes 的最后字节对应为整数的最低8位; - * @return 转换后的 int 整数; - */ - public static int toInt(byte[] bytes, int offset, int len, boolean highAlign) { - if (len < 1 || len > 4) { - throw new IllegalArgumentException("Len less than 1 or greate than 4!"); - } - int value = 0; - if (highAlign) { - for (int i = 0; i < len; i++) { - value = value | ((bytes[offset + i] & 0xFF) << (8 * (3 - i))); - } - } else { - for (int i = 0; i < len; i++) { - value = value | ((bytes[offset + i] & 0xFF) << (8 * (len - 1 - i))); - } - } - - return value; - } - - public static long toLong(byte[] bytes) { - return toLong(bytes, 0); - } - - /** - * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 8个字节转换为 long 整数; - * - * @param bytes 要转换的二进制数组; - * @param offset 要读取数据的开始位置 - * @return 转换后的 long 整数; - */ - public static long toLong(byte[] bytes, int offset) { - long value = 0; - value = (value | (bytes[offset] & 0xFF)) << 8; - value = (value | (bytes[offset + 1] & 0xFF)) << 8; - value = (value | (bytes[offset + 2] & 0xFF)) << 8; - value = (value | (bytes[offset + 3] & 0xFF)) << 8; - value = (value | (bytes[offset + 4] & 0xFF)) << 8; - value = (value | (bytes[offset + 5] & 0xFF)) << 8; - value = (value | (bytes[offset + 6] & 0xFF)) << 8; - value = value | (bytes[offset + 7] & 0xFF); - - return value; - } - - /** - * 从指定的输入流中读入2个字节,由前到后按由高位到低位的方式转为 short 整数; - * - * @param in in - * @return short - */ - public static short readShort(InputStream in) { - try { - int v = in.read(); - if (v < 0) { - throw new IllegalDataException("No enough data to read as short from the specified input stream!"); - } - int value = (v & 0xFF) << 8; - - v = in.read(); - if (v < 0) { - throw new IllegalDataException("No enough data to read as short from the specified input stream!"); - } - value = value | (v & 0xFF); - return (short) value; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static int writeShort(short value, OutputStream out) { - try { - out.write((value >>> 8) & 0x00FF); - out.write(value & 0x00FF); - return 2; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - /** - * 从指定的输入流中读入4个字节,由前到后按由高位到低位的方式转为 int 整数; - * - * @param in in - * @return int - */ - public static int readInt(InputStream in) { - try { - int value = 0; - int v; - for (int i = 0; i < 4; i++) { - v = in.read(); - if (v < 0) { - throw new IllegalDataException( - "No enough data to read as integer from the specified input stream!"); - } - value = value | ((v & 0xFF) << (8 * (3 - i))); - } - return value; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static int writeInt(int value, OutputStream out) { - try { - out.write((value >>> 24) & 0x00FF); - out.write((value >>> 16) & 0x00FF); - out.write((value >>> 8) & 0x00FF); - out.write(value & 0x00FF); - return 4; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static long readLong(InputStream in) { - try { - long value = 0; - int v; - for (int i = 0; i < 7; i++) { - v = in.read(); - if (v < 0) { - throw new IllegalDataException( - "No enough data to read as long integer from the specified input stream!"); - } - value = (value | (v & 0xFF)) << 8; - } - value = value | (in.read() & 0xFF); - - return value; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static int writeLong(long value, OutputStream out) { - try { - out.write((int) ((value >>> 56) & 0x00FF)); - out.write((int) ((value >>> 48) & 0x00FF)); - out.write((int) ((value >>> 40) & 0x00FF)); - out.write((int) ((value >>> 32) & 0x00FF)); - out.write((int) ((value >>> 24) & 0x00FF)); - out.write((int) ((value >>> 16) & 0x00FF)); - out.write((int) ((value >>> 8) & 0x00FF)); - out.write((int) (value & 0x00FF)); - return 8; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static byte readByte(InputStream in) { - try { - int value = in.read(); - if (value < 0) { - throw new IllegalDataException("No byte to read from the input stream!"); - } - return (byte) value; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static byte[] readBytes(InputStream in) { - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - try { - byte[] buffer = new byte[BUFFER_SIZE]; - int len = -1; - while ((len = in.read(buffer)) != -1) { - outStream.write(buffer, 0, len); - } - outStream.close(); - return outStream.toByteArray(); - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static void writeByte(byte value, OutputStream out) { - try { - out.write(value); - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static byte[] concat(byte[]... bytesList) { - int size = 0; - for (byte[] bs : bytesList) { - size += bs.length; - } - byte[] bytesAll = new byte[size]; - size = 0; - for (byte[] bs : bytesList) { - System.arraycopy(bs, 0, bytesAll, size, bs.length); - size += bs.length; - } - - return bytesAll; - } - - public static long toLong(ByteArray byteArray) { - return toLong(byteArray.bytes()); - } - - /** - * 从字节数组获取对象 - * - * @param objBytes objBytes - * @return object - * @throws Exception exception - */ - // public static Object getObjectFromBytes(byte[] objBytes) throws Exception { - // if (objBytes == null || objBytes.length == 0) { - // return null; - // } - // ByteArrayInputStream bi = new ByteArrayInputStream(objBytes); - // ObjectInputStream oi = new ObjectInputStream(bi); - // return oi.readObject(); - // } - - /** - * 从对象获取一个字节数组; - * - * @param obj obj - * @return byte array - * @throws Exception exception - */ - public static byte[] getBytesFromObject(Object obj) throws Exception { - if (obj == null) { - return null; - } - ByteArrayOutputStream bo = new ByteArrayOutputStream(); - ObjectOutputStream oo = new ObjectOutputStream(bo); - oo.writeObject(obj); - return bo.toByteArray(); - } - - public static boolean startsWith(byte[] srcBytes, byte[] prefixBytes) { - for (int i = 0; i < prefixBytes.length; i++) { - if (prefixBytes[i] != srcBytes[i]) { - return false; - } - } - return true; - } - -} +package com.jd.blockchain.utils.io; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +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; + +/** + * 二进制工具类; + * + * @author haiq + * + */ +public class BytesUtils { + + public static final String DEFAULT_CHARSET = "UTF-8"; + + public static final byte[] EMPTY_BYTES = {}; + + public static final int MAX_BUFFER_SIZE = 1024 * 1024 * 1024; + public static final int BUFFER_SIZE = 64; + + public static final byte TRUE_BYTE = 1; + + public static final byte FALSE_BYTE = 0; + + private BytesUtils() { + } + + /** + * 比较指定的两个字节数组是否一致; + *

+ * + * 此方法不处理两者其中之一为 null 的情形,因为无法定义相等性,所以将引发 {@link NullPointerException} 异常; + * + * @param bytes1 bytes1 + * @param bytes2 bytes2 + * @return boolean + */ + public static boolean equals(byte[] bytes1, byte[] bytes2) { + if (bytes1 == bytes2) { + return true; + } + if (bytes1 == null || bytes2 == null) { + return false; + } + if (bytes1.length != bytes2.length) { + return false; + } + for (int i = 0; i < bytes1.length; i++) { + if (bytes1[i] != bytes2[i]) { + return false; + } + } + return true; + } + + public static byte[] toBytes(BytesWriter bytesWriter) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + bytesWriter.writeTo(out); + return out.toByteArray(); + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + + } + + /** + * 将输入流的所有内容都读入到字节数组返回; 如果输入流的长度超出 MAX_BUFFER_SIZE 定义的值,则抛出 + * IllegalArgumentException ; + * + * @param in in + * @return byte[] + */ + public static byte[] copyToBytes(InputStream in) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[BUFFER_SIZE]; + int len = 0; + long size = 0; + while ((len = in.read(buffer)) > 0) { + size += len; + if (size > MAX_BUFFER_SIZE) { + throw new IllegalArgumentException( + "The size of the InputStream exceed the max buffer size [" + MAX_BUFFER_SIZE + "]!"); + } + out.write(buffer, 0, len); + } + return out.toByteArray(); + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static int copy(InputStream in, OutputStream out) throws IOException { + return copy(in, out, Integer.MAX_VALUE); + } + + /** + * 将输入流复制到输出流; + * + * @param in 输入流; + * @param out 输出流; + * @param maxSize 最大字节大小; + * @return 返回实际复制的字节数; + * @throws IOException exception + */ + public static int copy(InputStream in, OutputStream out, int maxSize) throws IOException { + byte[] buffer = new byte[BUFFER_SIZE]; + int len = 0; + int left = maxSize; + int readLen = buffer.length; + while (left > 0) { + readLen = Math.min(left, buffer.length); + len = in.read(buffer, 0, readLen); + if (len > 0) { + out.write(buffer, 0, len); + left = left - len; + } else { + break; + } + } + return maxSize - left; + } + + /** + * 将 int 值转为4字节的二进制数组; + * + * @param value value + * @return 转换后的二进制数组,高位在前,低位在后; + */ + public static byte[] toBytes(int value) { + byte[] bytes = new byte[4]; + toBytes(value, bytes, 0); + return bytes; + } + + public static byte[] toBytes(short value) { + byte[] bytes = new byte[2]; + toBytes(value, bytes, 0); + return bytes; + } + + public static byte[] toBytes(boolean value) { + return new byte[] { value ? TRUE_BYTE : FALSE_BYTE }; + } + + /** + * 将 long 值转为8字节的二进制数组; + * + * @param value value + * @return 转换后的二进制数组,高位在前,低位在后; + */ + public static byte[] toBytes(long value) { + byte[] bytes = new byte[8]; + toBytes(value, bytes, 0); + return bytes; + } + + /** + * 将 int 值转为4字节的二进制数组; + * + * @param value 要转换的int整数; + * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 0 开始的4个元素; + */ + public static void toBytes(short value, byte[] bytes) { + toBytes(value, bytes, 0); + } + + public static int toBytes(int value, byte[] bytes) { + return toBytes(value, bytes, 0); + } + + /** + * 将 int 值转为4字节的二进制数组; + *

+ * 以“高位在前”的方式转换,即:数值的高位保存在数组地址的低位; + * + * @param value 要转换的int整数; + * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; + * @param offset 写入转换结果的起始位置; + * @return 返回写入的长度; + */ + public static int toBytes(int value, byte[] bytes, int offset) { + bytes[offset] = (byte) ((value >>> 24) & 0x00FF); + bytes[offset + 1] = (byte) ((value >>> 16) & 0x00FF); + bytes[offset + 2] = (byte) ((value >>> 8) & 0x00FF); + bytes[offset + 3] = (byte) (value & 0x00FF); + return 4; + } + + /** + * 将 int 值转为4字节的二进制数组; + *

+ * 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位; + * + * @param value 要转换的int整数; + * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; + * @param offset 写入转换结果的起始位置; + * @return 返回写入的长度; + */ + public static int toBytesInReverse(int value, byte[] bytes, int offset) { + bytes[offset] = (byte) (value & 0x00FF); + bytes[offset + 1] = (byte) ((value >>> 8) & 0x00FF); + bytes[offset + 2] = (byte) ((value >>> 16) & 0x00FF); + bytes[offset + 3] = (byte) ((value >>> 24) & 0x00FF); + return 4; + } + + /** + * 将 int 值转为4字节的二进制数组; + *

+ * 以“高位在后”的方式转换,即:数值的高位保存在数组地址的高位; + * + * @param value 要转换的int整数; + * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的4个元素; + * @param offset 写入转换结果的起始位置; + * @param len 写入长度;必须大于 0 ,小于等于 4; + * @return 返回写入的长度; + */ + public static int toBytesInReverse(int value, byte[] bytes, int offset, int len) { + int i = 0; + int l = len > 4 ? 4 : len; + for (; i < l; i++) { + bytes[offset + i] = (byte) ((value >>> (8 * i)) & 0x00FF); + } + + return i; + } + + // public static int toBytes(int value, OutputStream out) { + // try { + // out.write((value >>> 24) & 0x00FF); + // out.write((value >>> 16) & 0x00FF); + // out.write((value >>> 8) & 0x00FF); + // out.write(value & 0x00FF); + // return 4; + // } catch (IOException e) { + // throw new RuntimeIOException(e.getMessage(), e); + // } + // } + + public static void toBytes(short value, byte[] bytes, int offset) { + bytes[offset] = (byte) ((value >>> 8) & 0x00FF); + bytes[offset + 1] = (byte) (value & 0x00FF); + } + + public static void toBytes(char value, byte[] bytes, int offset) { + bytes[offset] = (byte) ((value >>> 8) & 0x00FF); + bytes[offset + 1] = (byte) (value & 0x00FF); + } + + /** + * 将 long 值转为8字节的二进制数组; + * + * @param value 要转换的long整数; + * @param bytes 要保存转换结果的二进制数组;转换结果将从高位至低位的顺序写入数组从 offset 指定位置开始的8个元素; + * @param offset 写入转换结果的起始位置; + * @return 返回写入的长度; + */ + public static int toBytes(long value, byte[] bytes, int offset) { + bytes[offset] = (byte) ((value >>> 56) & 0x00FF); + bytes[offset + 1] = (byte) ((value >>> 48) & 0x00FF); + bytes[offset + 2] = (byte) ((value >>> 40) & 0x00FF); + bytes[offset + 3] = (byte) ((value >>> 32) & 0x00FF); + bytes[offset + 4] = (byte) ((value >>> 24) & 0x00FF); + bytes[offset + 5] = (byte) ((value >>> 16) & 0x00FF); + bytes[offset + 6] = (byte) ((value >>> 8) & 0x00FF); + bytes[offset + 7] = (byte) (value & 0x00FF); + return 8; + } + + // public static int toBytes(long value, OutputStream out) { + // try { + // out.write((int) ((value >>> 56) & 0x00FF)); + // out.write((int) ((value >>> 48) & 0x00FF)); + // out.write((int) ((value >>> 40) & 0x00FF)); + // out.write((int) ((value >>> 32) & 0x00FF)); + // out.write((int) ((value >>> 24) & 0x00FF)); + // out.write((int) ((value >>> 16) & 0x00FF)); + // out.write((int) ((value >>> 8) & 0x00FF)); + // out.write((int) (value & 0x00FF)); + // return 8; + // } catch (IOException e) { + // throw new RuntimeIOException(e.getMessage(), e); + // } + // } + + public static byte[] toBytes(String str) { + return toBytes(str, DEFAULT_CHARSET); + } + + public static byte[] toBytes(String str, String charset) { + try { + byte[] bytes = str.getBytes(charset); + return bytes; + } catch (UnsupportedEncodingException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + /** + * @param bytes + * @return + */ + public static String toString(byte[] bytes) { + return toString(bytes, DEFAULT_CHARSET); + } + + public static String toString(byte[] bytes, int offset) { + return toString(bytes, offset, bytes.length - offset, DEFAULT_CHARSET); + } + + public static String toString(byte[] bytes, int offset, int len) { + return toString(bytes, offset, len, DEFAULT_CHARSET); + } + + public static String toString(byte[] bytes, String charset) { + return toString(bytes, 0, bytes.length, charset); + } + + public static String toString(byte[] bytes, int offset, int len, String charset) { + try { + if (bytes == null) { + return null; + } + if (len == 0) { + return ""; + } + return new String(bytes, offset, len, charset); + } catch (UnsupportedEncodingException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static boolean toBoolean(byte value) { + return value != FALSE_BYTE; + } + + /** + * 按从高位到低位的顺序将指定二进制数组从位置 0 开始的 4 个字节转换为 int 整数; + * + * @param bytes 要转换的二进制数组; + * @return 转换后的 int 整数; + */ + public static int toInt(byte[] bytes) { + return toInt(bytes, 0); + // value = (value | (bytes[0] & 0xFF)) << 8; + // value = (value | (bytes[1] & 0xFF)) << 8; + // value = (value | (bytes[2] & 0xFF)) << 8; + // value = value | (bytes[3] & 0xFF); + // + // return value; + } + + /** + * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 2 个字节转换为 short 整数; + * + * @param bytes 要转换的二进制数组; + * @param offset 要读取数据的开始位置 + * @return 转换后的 short 整数; + */ + public static short toShort(byte[] bytes, int offset) { + short value = 0; + value = (short) ((value | (bytes[offset] & 0xFF)) << 8); + value = (short) (value | (bytes[offset + 1] & 0xFF)); + + 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); + value = (char) (value | (bytes[offset + 1] & 0xFF)); + + return value; + } + + /** + * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; + * + * @param bytes 要转换的二进制数组; + * @param offset 要读取数据的开始位置 + * @return 转换后的 int 整数; + */ + public static int toInt(byte[] bytes, int offset) { + // int value = 0; + // value = (value | (bytes[offset] & 0xFF)) << 8; + // value = (value | (bytes[offset + 1] & 0xFF)) << 8; + // value = (value | (bytes[offset + 2] & 0xFF)) << 8; + // value = value | (bytes[offset + 3] & 0xFF); + // + // return value; + return toInt(bytes, offset, 4); + } + + /** + * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; + * + * @param bytes 要转换的二进制数组; + * @param offset 要读取数据的开始位置 + * @return 转换后的 int 整数; + * + * @param len 长度;len 必须满足: len 大于等于 1 且小于等于4; + * @return 转换后的 int 整数; + */ + public static int toInt(byte[] bytes, int offset, int len) { + // if (len < 1 || len > 4) { + // throw new IllegalArgumentException("Len less than 1 or greate than 4!"); + // } + // int value = 0; + // for (int i = 0; i < len; i++) { + // value = value | ((bytes[offset + i] & 0xFF) << (8 * (3 - i))); + // } + // + // return value; + return toInt(bytes, offset, len, true); + } + + /** + * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 4 个字节转换为 int 整数; + * + * @param bytes 要转换的二进制数组; + * @param offset 要读取数据的开始位置 + * @return 转换后的 int 整数; + * + * @param len 长度;len 必须满足: len 大于等于 1 且小于等于4; + * @param highAlign 是否高位对齐;
+ * true 表示参数 bytes 的首个字节对应为整数的最高8位;
+ * false 表示参数 bytes 的最后字节对应为整数的最低8位; + * @return 转换后的 int 整数; + */ + public static int toInt(byte[] bytes, int offset, int len, boolean highAlign) { + if (len < 1 || len > 4) { + throw new IllegalArgumentException("Len less than 1 or greate than 4!"); + } + int value = 0; + if (highAlign) { + for (int i = 0; i < len; i++) { + value = value | ((bytes[offset + i] & 0xFF) << (8 * (3 - i))); + } + } else { + for (int i = 0; i < len; i++) { + value = value | ((bytes[offset + i] & 0xFF) << (8 * (len - 1 - i))); + } + } + + return value; + } + + public static long toLong(byte[] bytes) { + return toLong(bytes, 0); + } + + /** + * 按从高位到低位的顺序将指定二进制数组从 offset 参数指定的位置开始的 8个字节转换为 long 整数; + * + * @param bytes 要转换的二进制数组; + * @param offset 要读取数据的开始位置 + * @return 转换后的 long 整数; + */ + public static long toLong(byte[] bytes, int offset) { + long value = 0; + value = (value | (bytes[offset] & 0xFF)) << 8; + value = (value | (bytes[offset + 1] & 0xFF)) << 8; + value = (value | (bytes[offset + 2] & 0xFF)) << 8; + value = (value | (bytes[offset + 3] & 0xFF)) << 8; + value = (value | (bytes[offset + 4] & 0xFF)) << 8; + value = (value | (bytes[offset + 5] & 0xFF)) << 8; + value = (value | (bytes[offset + 6] & 0xFF)) << 8; + value = value | (bytes[offset + 7] & 0xFF); + + return value; + } + + /** + * 从指定的输入流中读入2个字节,由前到后按由高位到低位的方式转为 short 整数; + * + * @param in in + * @return short + */ + public static short readShort(InputStream in) { + try { + int v = in.read(); + if (v < 0) { + throw new IllegalDataException("No enough data to read as short from the specified input stream!"); + } + int value = (v & 0xFF) << 8; + + v = in.read(); + if (v < 0) { + throw new IllegalDataException("No enough data to read as short from the specified input stream!"); + } + value = value | (v & 0xFF); + return (short) value; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static int writeShort(short value, OutputStream out) { + try { + out.write((value >>> 8) & 0x00FF); + out.write(value & 0x00FF); + return 2; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + /** + * 从指定的输入流中读入4个字节,由前到后按由高位到低位的方式转为 int 整数; + * + * @param in in + * @return int + */ + public static int readInt(InputStream in) { + try { + int value = 0; + int v; + for (int i = 0; i < 4; i++) { + v = in.read(); + if (v < 0) { + throw new IllegalDataException( + "No enough data to read as integer from the specified input stream!"); + } + value = value | ((v & 0xFF) << (8 * (3 - i))); + } + return value; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static int writeInt(int value, OutputStream out) { + try { + out.write((value >>> 24) & 0x00FF); + out.write((value >>> 16) & 0x00FF); + out.write((value >>> 8) & 0x00FF); + out.write(value & 0x00FF); + return 4; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static long readLong(InputStream in) { + try { + long value = 0; + int v; + for (int i = 0; i < 7; i++) { + v = in.read(); + if (v < 0) { + throw new IllegalDataException( + "No enough data to read as long integer from the specified input stream!"); + } + value = (value | (v & 0xFF)) << 8; + } + value = value | (in.read() & 0xFF); + + return value; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static int writeLong(long value, OutputStream out) { + try { + out.write((int) ((value >>> 56) & 0x00FF)); + out.write((int) ((value >>> 48) & 0x00FF)); + out.write((int) ((value >>> 40) & 0x00FF)); + out.write((int) ((value >>> 32) & 0x00FF)); + out.write((int) ((value >>> 24) & 0x00FF)); + out.write((int) ((value >>> 16) & 0x00FF)); + out.write((int) ((value >>> 8) & 0x00FF)); + out.write((int) (value & 0x00FF)); + return 8; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static byte readByte(InputStream in) { + try { + int value = in.read(); + if (value < 0) { + throw new IllegalDataException("No byte to read from the input stream!"); + } + return (byte) value; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static byte[] readBytes(InputStream in) { + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + try { + byte[] buffer = new byte[BUFFER_SIZE]; + int len = -1; + while ((len = in.read(buffer)) != -1) { + outStream.write(buffer, 0, len); + } + outStream.close(); + return outStream.toByteArray(); + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static void writeByte(byte value, OutputStream out) { + try { + out.write(value); + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static byte[] concat(byte[]... bytesList) { + int size = 0; + for (byte[] bs : bytesList) { + size += bs.length; + } + byte[] bytesAll = new byte[size]; + size = 0; + for (byte[] bs : bytesList) { + System.arraycopy(bs, 0, bytesAll, size, bs.length); + size += bs.length; + } + + return bytesAll; + } + + public static long toLong(ByteArray byteArray) { + return toLong(byteArray.bytes()); + } + + /** + * 从字节数组获取对象 + * + * @param objBytes objBytes + * @return object + * @throws Exception exception + */ + // public static Object getObjectFromBytes(byte[] objBytes) throws Exception { + // if (objBytes == null || objBytes.length == 0) { + // return null; + // } + // ByteArrayInputStream bi = new ByteArrayInputStream(objBytes); + // ObjectInputStream oi = new ObjectInputStream(bi); + // return oi.readObject(); + // } + + /** + * 从对象获取一个字节数组; + * + * @param obj obj + * @return byte array + * @throws Exception exception + */ + public static byte[] getBytesFromObject(Object obj) throws Exception { + if (obj == null) { + return null; + } + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + ObjectOutputStream oo = new ObjectOutputStream(bo); + oo.writeObject(obj); + return bo.toByteArray(); + } + + public static boolean startsWith(byte[] srcBytes, byte[] prefixBytes) { + for (int i = 0; i < prefixBytes.length; i++) { + if (prefixBytes[i] != srcBytes[i]) { + return false; + } + } + return true; + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesWriter.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesWriter.java index 83248269..75ba9aeb 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesWriter.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/BytesWriter.java @@ -1,8 +1,8 @@ -package com.jd.blockchain.utils.io; - -import java.io.IOException; -import java.io.OutputStream; - -public interface BytesWriter { - void writeTo(OutputStream out) throws IOException; -} +package com.jd.blockchain.utils.io; + +import java.io.IOException; +import java.io.OutputStream; + +public interface BytesWriter { + void writeTo(OutputStream out) throws IOException; +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/EmptyInputStream.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/EmptyInputStream.java index 26992c72..d79f74ee 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/EmptyInputStream.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/EmptyInputStream.java @@ -1,18 +1,18 @@ -package com.jd.blockchain.utils.io; - -import java.io.IOException; -import java.io.InputStream; - -public class EmptyInputStream extends InputStream{ - - public static final EmptyInputStream INSTANCE = new EmptyInputStream(); - - private EmptyInputStream() { - } - - @Override - public int read() throws IOException { - return -1; - } - -} +package com.jd.blockchain.utils.io; + +import java.io.IOException; +import java.io.InputStream; + +public class EmptyInputStream extends InputStream{ + + public static final EmptyInputStream INSTANCE = new EmptyInputStream(); + + private EmptyInputStream() { + } + + @Override + public int read() throws IOException { + return -1; + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/ForwardReadonlyInputStream.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/ForwardReadonlyInputStream.java index 0df903fd..0569f390 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/ForwardReadonlyInputStream.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/ForwardReadonlyInputStream.java @@ -1,40 +1,40 @@ -package com.jd.blockchain.utils.io; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * - * 通过 {@link ForwardReadonlyInputStream} 对输入流进行包装,限制只能对输入流进行向前读取的操作,不允许调用 {@link #mark(int)}、 {@link #reset()}、{@link #close()}操作; - * - * @author huanghaiquan - * - */ -public class ForwardReadonlyInputStream extends FilterInputStream{ - - protected ForwardReadonlyInputStream(InputStream in) { - super(in); - } - - - @Override - public boolean markSupported() { - return false; - } - - @Override - public synchronized void mark(int readlimit) { - // forward readonly, so do nothing instead here; - } - - @Override - public synchronized void reset() throws IOException { - // forward readonly, so do nothing instead here; - } - - @Override - public void close() throws IOException { - // forward readonly, cann't be closed, so do nothing instead here; - } -} +package com.jd.blockchain.utils.io; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * + * 通过 {@link ForwardReadonlyInputStream} 对输入流进行包装,限制只能对输入流进行向前读取的操作,不允许调用 {@link #mark(int)}、 {@link #reset()}、{@link #close()}操作; + * + * @author huanghaiquan + * + */ +public class ForwardReadonlyInputStream extends FilterInputStream{ + + protected ForwardReadonlyInputStream(InputStream in) { + super(in); + } + + + @Override + public boolean markSupported() { + return false; + } + + @Override + public synchronized void mark(int readlimit) { + // forward readonly, so do nothing instead here; + } + + @Override + public synchronized void reset() throws IOException { + // forward readonly, so do nothing instead here; + } + + @Override + public void close() throws IOException { + // forward readonly, cann't be closed, so do nothing instead here; + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/NumberMask.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/NumberMask.java index e13154d0..4e9f3b64 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/NumberMask.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/NumberMask.java @@ -1,371 +1,371 @@ -package com.jd.blockchain.utils.io; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * {@link NumberMask} 数值掩码;
- * - * {@link NumberMask} 定义了使用有限的字节表示一个特定范围的正整数的格式;
- * - * {@link NumberMask} 用于表示数值的字节长度是动态的,根据数值的范围而定;
- * - * 这个特点使得 {@link NumberMask} 适用于表示小数据片的头部尺寸;尤其当一个数据块是由大量表示不同属性的小数据片构成时,使用 - * {@link NumberMask} 可以得到更紧凑的字节流; - * - *

- * 注:{@link NumberMask} 处理的数值范围处于 32 位整数(int)的范围,不处理 64 位整数(long)的情况;
- * 这样的设计一方面是因为 {@link NumberMask#NORMAL} 已经可以表示通常情况下的足够大的数值范围(1G),而 64 - * 位整数(long)表示的长度已经远远超出单台计算机能够处理的内存数量;
- * 另一方面是,采用嵌套的方式使用{@link NumberMask}也可以达到表示无限大小的数据的目的(如:使用 {@link NumberMask} - * 表示数据片数量,对每一个数据片再用一个{@link NumberMask}表示其数据长度); - * - * @author huanghaiquan - * - */ -public enum NumberMask { - - /** - * 最短的头部,占用1字节;
- * - * 表示字节内容的长度小于 256 (2^8); - */ - TINY((byte) 0), - - /** - * 短的头部,最多占用2字节;
- * - *

-	 * 记录字节数据大小的头部占用的字节数是动态的,根据数据的大小而定,最少1个字节,最大2个字节;
-	 * 
-	 * 使用首个字节的最高两位作为标识位指示头部的长度;
-	 * 
-	 * 当字节内容的长度小于 128 (2^7),则头部占用1个字节,最高位标识为 0 ;
-	 * 
-	 * 当字节内容的长度小于 32768 (2^15, 32KB),则头部占用2个字节,最高位标识为 1 ;
-	 * 
-	 * 
-	 * 
- */ - SHORT((byte) 1), - - /** - * 短的头部,最多占用4字节;
- * - *
-	 * 记录字节数据大小的头部占用的字节数是动态的,根据数据的大小而定,最少1个字节,最大4个字节;
-	 * 
-	 * 使用首个字节的最高两位作为标识位指示头部的长度;
-	 * 
-	 * 当字节内容的长度小于 64 (2^6),则头部占用1个字节,最高位标识为 0 ;
-	 * 
-	 * 当字节内容的长度小于 16384 (2^14, 16KB),则头部占用2个字节,最高位标识为 1 ;
-	 * 
-	 * 当字节内容的长度小于 4194304 (2^22, 4MB),则头部占用3个字节,最高位标识为 2 ;
-	 * 
-	 * 当字节内容的长度小于 1073741824 (2^30, 1GB),则头部占用4个字节,最高位标识为 3 ;
-	 * 
-	 * 
- */ - NORMAL((byte) 2); - - // 不考虑 long 的情况,因为 long 的数值表示的长度已经远远超出单台计算机能够处理的内存数量; - - // /** - // * 短的头部,最多占用8字节; - // */ - // LONG((byte) 3); - - /** - * 掩码位的个数; - */ - public final byte BIT_COUNT; - - /** - * 头部长度的最大值; - */ - public final int MAX_HEADER_LENGTH; - - public final int MAX_BOUNDARY_SIZE; - - /** - * 此常量对于 TINY、SHORT、NORMAL 有效; - */ - public final int BOUNDARY_SIZE_0; - public final int BOUNDARY_SIZE_1; - public final int BOUNDARY_SIZE_2; - public final int BOUNDARY_SIZE_3; - - private int[] boundarySizes; - - private NumberMask(byte bitCount) { - this.BIT_COUNT = bitCount; - this.MAX_HEADER_LENGTH = 1 << bitCount; - this.boundarySizes = new int[MAX_HEADER_LENGTH]; - for (byte i = 0; i < MAX_HEADER_LENGTH; i++) { - boundarySizes[i] = computeBoundarySize((byte) (i + 1)); - } - - this.MAX_BOUNDARY_SIZE = boundarySizes[MAX_HEADER_LENGTH - 1]; - if (bitCount == 0) { - // TINY; - BOUNDARY_SIZE_0 = boundarySizes[0]; - BOUNDARY_SIZE_1 = -1; - BOUNDARY_SIZE_2 = -1; - BOUNDARY_SIZE_3 = -1; - } else if (bitCount == 1) { - // SHORT; - BOUNDARY_SIZE_0 = boundarySizes[0]; - BOUNDARY_SIZE_1 = boundarySizes[1]; - BOUNDARY_SIZE_2 = -1; - BOUNDARY_SIZE_3 = -1; - } else if (bitCount == 2) { - // NORMAL; - BOUNDARY_SIZE_0 = boundarySizes[0]; - BOUNDARY_SIZE_1 = boundarySizes[1]; - BOUNDARY_SIZE_2 = boundarySizes[2]; - BOUNDARY_SIZE_3 = boundarySizes[3]; - } else { - throw new IllegalArgumentException("Illegal bitCount!"); - } - } - - /** - * 在指定的头部长度下能够表示的数据大小的临界值(不含); - * - * @param headerLength - * 值范围必须大于 0 ,且小于等于 {@link #MAX_HEADER_LENGTH} - * @return - */ - public int getBoundarySize(int headerLength) { - return boundarySizes[headerLength - 1]; - } - - private int computeBoundarySize(int headerLength) { - // 不考虑 long 的情况; - // long boundarySize = 1L << (headerLength * 8 - BIT_COUNT); - - int boundarySize = 1 << (headerLength * 8 - BIT_COUNT); - return boundarySize; - } - - /** - * 获取能够表示指定的数值的掩码长度,即掩码所需的字节数;
- * - * @param number - * 要表示的数值;如果值范围超出掩码的有效范围,将抛出 {@link IllegalArgumentException} 异常; - * @return - */ - public int getMaskLength(int number) { - if (number > -1) { - if (number < BOUNDARY_SIZE_0) { - return 1; - } - if (number < BOUNDARY_SIZE_1) { - return 2; - } - if (number < BOUNDARY_SIZE_2) { - return 3; - } - if (number < BOUNDARY_SIZE_3) { - return 4; - } - } - throw new IllegalArgumentException("Number is out of the illegal range! --[number=" + number + "]"); - } - - /** - * 生成指定数值的掩码; - * - * @param number - * 要表示的数值;如果值范围超出掩码的有效范围,将抛出 {@link IllegalArgumentException} 异常; - * @return - */ - public byte[] generateMask(int number) { - // 计算掩码占用的字节长度; - int maskLen = getMaskLength(number); - byte[] maskBytes = new byte[maskLen]; - writeMask(number, maskLen, maskBytes, 0); - return maskBytes; - } - - public int writeMask(int number, byte[] buffer, int offset) { - // 计算掩码占用的字节长度; - int maskLen = getMaskLength(number); - return writeMask(number, maskLen, buffer, offset); - } - - private int writeMask(int number, int maskLen, byte[] buffer, int offset) { - // 计算掩码占用的字节长度; - for (int i = maskLen; i > 0; i--) { - buffer[offset + i - 1] = (byte) ((number >>> 8 * (maskLen - i)) & 0xFF); - } - - // 计算头字节的标识位; - byte indicatorByte = (byte) ((maskLen - 1) << (8 - BIT_COUNT)); - // 设置标识位; - buffer[offset] = (byte) (indicatorByte | buffer[offset]); - return maskLen; - } - - /** - * 生成指定数值的掩码并写入到指定的输出流; - * - * @param number - * @param out - * @return 写入的字节数; - */ - public int writeMask(int number, OutputStream out) { - // 生成数据尺寸掩码; - byte[] maskBytes = generateMask(number); - - try { - out.write(maskBytes); - return maskBytes.length; - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - /** - * 解析掩码的头字节获得该掩码实例的完整长度; - * - * @param bytes - * 掩码的头字节;即掩码的字节序列的首个字节; - * @return 返回掩码实例的完整长度;
- * 注:在字节流中,对首字节解析获取该值后减 1,可以得到该掩码后续要读取的字节长度; - */ - public int resolveMaskLength(BytesSlice bytes) { - return resolveMaskLength(bytes.getByte()); - } - - public int resolveMaskLength(BytesSlice bytes, int offset) { - return resolveMaskLength(bytes.getByte(offset)); - } - - /** - * 解析掩码的头字节获得该掩码实例的完整长度; - * - * @param headByte - * 掩码的头字节;即掩码的字节序列的首个字节; - * @return 返回掩码实例的完整长度;
- * 注:在字节流中,对首字节解析获取该值后减 1,可以得到该掩码后续要读取的字节长度; - */ - public int resolveMaskLength(byte headByte) { - int len = ((headByte & 0xFF) >>> (8 - BIT_COUNT)) + 1; - if (len < 1) { - throw new IllegalArgumentException( - "Illegal length [" + len + "] was resolved from the head byte of NumberMask!"); - } - if (len > MAX_HEADER_LENGTH) { - throw new IllegalArgumentException( - "Illegal length [" + len + "] was resolved from the head byte of NumberMask!"); - } - return len; - } - - public int resolveMaskedNumber(byte[] markBytes) { - return resolveMaskedNumber(markBytes, 0); - } - - /** - * 从字节中解析掩码表示的数值; - * - * @param markBytes - * @param headPos - * @return - */ - public int resolveMaskedNumber(byte[] markBytes, int headPos) { - int maskLen = resolveMaskLength(markBytes[headPos]); - - // 清除首字节的标识位; - byte numberHead = (byte) (markBytes[headPos] & (0xFF >>> BIT_COUNT)); - - // 转换字节大小; - int number = numberHead & 0xFF; - for (int i = 1; i < maskLen; i++) { - number = (number << 8) | (markBytes[headPos + i] & 0xFF); - } - - return number; - } - - /** - * 从字节中解析掩码表示的数值; - * @param bytes bytes - * @return int - */ - public int resolveMaskedNumber(BytesSlice bytes) { - return resolveMaskedNumber(bytes, 0); - } - - /** - * 从字节中解析掩码表示的数值; - * @param bytes bytes - * @param offset offset - * @return int - */ - public int resolveMaskedNumber(BytesSlice bytes, int offset) { - byte headByte = bytes.getByte(offset); - int maskLen = resolveMaskLength(headByte); - - // 清除首字节的标识位; - byte numberHead = (byte) (headByte & (0xFF >>> BIT_COUNT)); - - // 转换字节大小; - int number = numberHead & 0xFF; - for (int i = 1; i < maskLen; i++) { - number = (number << 8) | (bytes.getByte(offset + i) & 0xFF); - } - - return number; - } - - /** - * 从字节中解析掩码表示的数值; - * @param bytesStream - * @return int - */ - public int resolveMaskedNumber(BytesInputStream bytesStream) { - byte headByte = bytesStream.readByte(); - int maskLen = resolveMaskLength(headByte); - - // 清除首字节的标识位; - byte numberHead = (byte) (headByte & (0xFF >>> BIT_COUNT)); - - // 转换字节大小; - int number = numberHead & 0xFF; - for (int i = 1; i < maskLen; i++) { - number = (number << 8) | (bytesStream.readByte() & 0xFF); - } - - return number; - } - - /** - * 从字节流解析掩码表示的数值; - * - * @param in - * @return - */ - public int resolveMaskedNumber(InputStream in) { - try { - byte[] buff = new byte[MAX_HEADER_LENGTH]; - // 解析头字节; - int len = in.read(buff, 0, 1); - if (len < 1) { - throw new IllegalArgumentException("No enough bytes for the size header's indicator byte!"); - } - int maskLen = resolveMaskLength(buff[0]); - if (maskLen > 1) { - in.read(buff, 1, maskLen - 1); - } - - return resolveMaskedNumber(buff, 0); - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - +package com.jd.blockchain.utils.io; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * {@link NumberMask} 数值掩码;
+ * + * {@link NumberMask} 定义了使用有限的字节表示一个特定范围的正整数的格式;
+ * + * {@link NumberMask} 用于表示数值的字节长度是动态的,根据数值的范围而定;
+ * + * 这个特点使得 {@link NumberMask} 适用于表示小数据片的头部尺寸;尤其当一个数据块是由大量表示不同属性的小数据片构成时,使用 + * {@link NumberMask} 可以得到更紧凑的字节流; + * + *

+ * 注:{@link NumberMask} 处理的数值范围处于 32 位整数(int)的范围,不处理 64 位整数(long)的情况;
+ * 这样的设计一方面是因为 {@link NumberMask#NORMAL} 已经可以表示通常情况下的足够大的数值范围(1G),而 64 + * 位整数(long)表示的长度已经远远超出单台计算机能够处理的内存数量;
+ * 另一方面是,采用嵌套的方式使用{@link NumberMask}也可以达到表示无限大小的数据的目的(如:使用 {@link NumberMask} + * 表示数据片数量,对每一个数据片再用一个{@link NumberMask}表示其数据长度); + * + * @author huanghaiquan + * + */ +public enum NumberMask { + + /** + * 最短的头部,占用1字节;
+ * + * 表示字节内容的长度小于 256 (2^8); + */ + TINY((byte) 0), + + /** + * 短的头部,最多占用2字节;
+ * + *

+	 * 记录字节数据大小的头部占用的字节数是动态的,根据数据的大小而定,最少1个字节,最大2个字节;
+	 * 
+	 * 使用首个字节的最高两位作为标识位指示头部的长度;
+	 * 
+	 * 当字节内容的长度小于 128 (2^7),则头部占用1个字节,最高位标识为 0 ;
+	 * 
+	 * 当字节内容的长度小于 32768 (2^15, 32KB),则头部占用2个字节,最高位标识为 1 ;
+	 * 
+	 * 
+	 * 
+ */ + SHORT((byte) 1), + + /** + * 短的头部,最多占用4字节;
+ * + *
+	 * 记录字节数据大小的头部占用的字节数是动态的,根据数据的大小而定,最少1个字节,最大4个字节;
+	 * 
+	 * 使用首个字节的最高两位作为标识位指示头部的长度;
+	 * 
+	 * 当字节内容的长度小于 64 (2^6),则头部占用1个字节,最高位标识为 0 ;
+	 * 
+	 * 当字节内容的长度小于 16384 (2^14, 16KB),则头部占用2个字节,最高位标识为 1 ;
+	 * 
+	 * 当字节内容的长度小于 4194304 (2^22, 4MB),则头部占用3个字节,最高位标识为 2 ;
+	 * 
+	 * 当字节内容的长度小于 1073741824 (2^30, 1GB),则头部占用4个字节,最高位标识为 3 ;
+	 * 
+	 * 
+ */ + NORMAL((byte) 2); + + // 不考虑 long 的情况,因为 long 的数值表示的长度已经远远超出单台计算机能够处理的内存数量; + + // /** + // * 短的头部,最多占用8字节; + // */ + // LONG((byte) 3); + + /** + * 掩码位的个数; + */ + public final byte BIT_COUNT; + + /** + * 头部长度的最大值; + */ + public final int MAX_HEADER_LENGTH; + + public final int MAX_BOUNDARY_SIZE; + + /** + * 此常量对于 TINY、SHORT、NORMAL 有效; + */ + public final int BOUNDARY_SIZE_0; + public final int BOUNDARY_SIZE_1; + public final int BOUNDARY_SIZE_2; + public final int BOUNDARY_SIZE_3; + + private int[] boundarySizes; + + private NumberMask(byte bitCount) { + this.BIT_COUNT = bitCount; + this.MAX_HEADER_LENGTH = 1 << bitCount; + this.boundarySizes = new int[MAX_HEADER_LENGTH]; + for (byte i = 0; i < MAX_HEADER_LENGTH; i++) { + boundarySizes[i] = computeBoundarySize((byte) (i + 1)); + } + + this.MAX_BOUNDARY_SIZE = boundarySizes[MAX_HEADER_LENGTH - 1]; + if (bitCount == 0) { + // TINY; + BOUNDARY_SIZE_0 = boundarySizes[0]; + BOUNDARY_SIZE_1 = -1; + BOUNDARY_SIZE_2 = -1; + BOUNDARY_SIZE_3 = -1; + } else if (bitCount == 1) { + // SHORT; + BOUNDARY_SIZE_0 = boundarySizes[0]; + BOUNDARY_SIZE_1 = boundarySizes[1]; + BOUNDARY_SIZE_2 = -1; + BOUNDARY_SIZE_3 = -1; + } else if (bitCount == 2) { + // NORMAL; + BOUNDARY_SIZE_0 = boundarySizes[0]; + BOUNDARY_SIZE_1 = boundarySizes[1]; + BOUNDARY_SIZE_2 = boundarySizes[2]; + BOUNDARY_SIZE_3 = boundarySizes[3]; + } else { + throw new IllegalArgumentException("Illegal bitCount!"); + } + } + + /** + * 在指定的头部长度下能够表示的数据大小的临界值(不含); + * + * @param headerLength + * 值范围必须大于 0 ,且小于等于 {@link #MAX_HEADER_LENGTH} + * @return + */ + public int getBoundarySize(int headerLength) { + return boundarySizes[headerLength - 1]; + } + + private int computeBoundarySize(int headerLength) { + // 不考虑 long 的情况; + // long boundarySize = 1L << (headerLength * 8 - BIT_COUNT); + + int boundarySize = 1 << (headerLength * 8 - BIT_COUNT); + return boundarySize; + } + + /** + * 获取能够表示指定的数值的掩码长度,即掩码所需的字节数;
+ * + * @param number + * 要表示的数值;如果值范围超出掩码的有效范围,将抛出 {@link IllegalArgumentException} 异常; + * @return + */ + public int getMaskLength(int number) { + if (number > -1) { + if (number < BOUNDARY_SIZE_0) { + return 1; + } + if (number < BOUNDARY_SIZE_1) { + return 2; + } + if (number < BOUNDARY_SIZE_2) { + return 3; + } + if (number < BOUNDARY_SIZE_3) { + return 4; + } + } + throw new IllegalArgumentException("Number is out of the illegal range! --[number=" + number + "]"); + } + + /** + * 生成指定数值的掩码; + * + * @param number + * 要表示的数值;如果值范围超出掩码的有效范围,将抛出 {@link IllegalArgumentException} 异常; + * @return + */ + public byte[] generateMask(int number) { + // 计算掩码占用的字节长度; + int maskLen = getMaskLength(number); + byte[] maskBytes = new byte[maskLen]; + writeMask(number, maskLen, maskBytes, 0); + return maskBytes; + } + + public int writeMask(int number, byte[] buffer, int offset) { + // 计算掩码占用的字节长度; + int maskLen = getMaskLength(number); + return writeMask(number, maskLen, buffer, offset); + } + + private int writeMask(int number, int maskLen, byte[] buffer, int offset) { + // 计算掩码占用的字节长度; + for (int i = maskLen; i > 0; i--) { + buffer[offset + i - 1] = (byte) ((number >>> 8 * (maskLen - i)) & 0xFF); + } + + // 计算头字节的标识位; + byte indicatorByte = (byte) ((maskLen - 1) << (8 - BIT_COUNT)); + // 设置标识位; + buffer[offset] = (byte) (indicatorByte | buffer[offset]); + return maskLen; + } + + /** + * 生成指定数值的掩码并写入到指定的输出流; + * + * @param number + * @param out + * @return 写入的字节数; + */ + public int writeMask(int number, OutputStream out) { + // 生成数据尺寸掩码; + byte[] maskBytes = generateMask(number); + + try { + out.write(maskBytes); + return maskBytes.length; + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + /** + * 解析掩码的头字节获得该掩码实例的完整长度; + * + * @param bytes + * 掩码的头字节;即掩码的字节序列的首个字节; + * @return 返回掩码实例的完整长度;
+ * 注:在字节流中,对首字节解析获取该值后减 1,可以得到该掩码后续要读取的字节长度; + */ + public int resolveMaskLength(BytesSlice bytes) { + return resolveMaskLength(bytes.getByte()); + } + + public int resolveMaskLength(BytesSlice bytes, int offset) { + return resolveMaskLength(bytes.getByte(offset)); + } + + /** + * 解析掩码的头字节获得该掩码实例的完整长度; + * + * @param headByte + * 掩码的头字节;即掩码的字节序列的首个字节; + * @return 返回掩码实例的完整长度;
+ * 注:在字节流中,对首字节解析获取该值后减 1,可以得到该掩码后续要读取的字节长度; + */ + public int resolveMaskLength(byte headByte) { + int len = ((headByte & 0xFF) >>> (8 - BIT_COUNT)) + 1; + if (len < 1) { + throw new IllegalArgumentException( + "Illegal length [" + len + "] was resolved from the head byte of NumberMask!"); + } + if (len > MAX_HEADER_LENGTH) { + throw new IllegalArgumentException( + "Illegal length [" + len + "] was resolved from the head byte of NumberMask!"); + } + return len; + } + + public int resolveMaskedNumber(byte[] markBytes) { + return resolveMaskedNumber(markBytes, 0); + } + + /** + * 从字节中解析掩码表示的数值; + * + * @param markBytes + * @param headPos + * @return + */ + public int resolveMaskedNumber(byte[] markBytes, int headPos) { + int maskLen = resolveMaskLength(markBytes[headPos]); + + // 清除首字节的标识位; + byte numberHead = (byte) (markBytes[headPos] & (0xFF >>> BIT_COUNT)); + + // 转换字节大小; + int number = numberHead & 0xFF; + for (int i = 1; i < maskLen; i++) { + number = (number << 8) | (markBytes[headPos + i] & 0xFF); + } + + return number; + } + + /** + * 从字节中解析掩码表示的数值; + * @param bytes bytes + * @return int + */ + public int resolveMaskedNumber(BytesSlice bytes) { + return resolveMaskedNumber(bytes, 0); + } + + /** + * 从字节中解析掩码表示的数值; + * @param bytes bytes + * @param offset offset + * @return int + */ + public int resolveMaskedNumber(BytesSlice bytes, int offset) { + byte headByte = bytes.getByte(offset); + int maskLen = resolveMaskLength(headByte); + + // 清除首字节的标识位; + byte numberHead = (byte) (headByte & (0xFF >>> BIT_COUNT)); + + // 转换字节大小; + int number = numberHead & 0xFF; + for (int i = 1; i < maskLen; i++) { + number = (number << 8) | (bytes.getByte(offset + i) & 0xFF); + } + + return number; + } + + /** + * 从字节中解析掩码表示的数值; + * @param bytesStream + * @return int + */ + public int resolveMaskedNumber(BytesInputStream bytesStream) { + byte headByte = bytesStream.readByte(); + int maskLen = resolveMaskLength(headByte); + + // 清除首字节的标识位; + byte numberHead = (byte) (headByte & (0xFF >>> BIT_COUNT)); + + // 转换字节大小; + int number = numberHead & 0xFF; + for (int i = 1; i < maskLen; i++) { + number = (number << 8) | (bytesStream.readByte() & 0xFF); + } + + return number; + } + + /** + * 从字节流解析掩码表示的数值; + * + * @param in + * @return + */ + public int resolveMaskedNumber(InputStream in) { + try { + byte[] buff = new byte[MAX_HEADER_LENGTH]; + // 解析头字节; + int len = in.read(buff, 0, 1); + if (len < 1) { + throw new IllegalArgumentException("No enough bytes for the size header's indicator byte!"); + } + int maskLen = resolveMaskLength(buff[0]); + if (maskLen > 1) { + in.read(buff, 1, maskLen - 1); + } + + return resolveMaskedNumber(buff, 0); + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + } \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/RuntimeIOException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/RuntimeIOException.java index 704284bf..4f94de35 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/RuntimeIOException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/RuntimeIOException.java @@ -1,15 +1,15 @@ -package com.jd.blockchain.utils.io; - -public class RuntimeIOException extends RuntimeException{ - - private static final long serialVersionUID = 6863237161295632635L; - - public RuntimeIOException(String message) { - super(message); - } - - public RuntimeIOException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.utils.io; + +public class RuntimeIOException extends RuntimeException{ + + private static final long serialVersionUID = 6863237161295632635L; + + public RuntimeIOException(String message) { + super(message); + } + + public RuntimeIOException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/UnclosableOutputStream.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/UnclosableOutputStream.java index e55daeb3..3488c928 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/UnclosableOutputStream.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/io/UnclosableOutputStream.java @@ -1,23 +1,23 @@ -package com.jd.blockchain.utils.io; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * {@link UnclosableOutputStream} 限制了对输出流执行关闭操作,调用 {@link #close()} 方法将不起任何作用,用在需要防止对输出流的使用中误关闭的情形; - * - * @author huanghaiquan - * - */ -public class UnclosableOutputStream extends FilterOutputStream { - - public UnclosableOutputStream(OutputStream out) { - super(out); - } - - @Override - public void close() throws IOException { - // do nothing for avoiding closing the inner outputstream; - } -} +package com.jd.blockchain.utils.io; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * {@link UnclosableOutputStream} 限制了对输出流执行关闭操作,调用 {@link #close()} 方法将不起任何作用,用在需要防止对输出流的使用中误关闭的情形; + * + * @author huanghaiquan + * + */ +public class UnclosableOutputStream extends FilterOutputStream { + + public UnclosableOutputStream(OutputStream out) { + super(out); + } + + @Override + public void close() throws IOException { + // do nothing for avoiding closing the inner outputstream; + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/net/NetworkAddress.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/net/NetworkAddress.java index 5e969bef..ca1bd978 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/net/NetworkAddress.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/net/NetworkAddress.java @@ -1,110 +1,110 @@ -package com.jd.blockchain.utils.net; - -import java.io.Serializable; -import java.util.Arrays; - -import com.jd.blockchain.utils.io.BytesOutputBuffer; -import com.jd.blockchain.utils.io.BytesSerializable; -import com.jd.blockchain.utils.io.BytesUtils; - -/** - * 网络地址; - * - * @author haiq - * - */ -public class NetworkAddress implements BytesSerializable, Serializable { - - private static final long serialVersionUID = -4565279525154132393L; - - private String host; - - private int port; - - private boolean secure; - - public NetworkAddress() { - } - - public NetworkAddress(String host, int port) { - this(host, port, false); - } - - public NetworkAddress(String host, int port, boolean secure) { - this.host = host; - this.port = port; - this.secure = secure; - } - - /** - * 用于二进制反序列化的构造器; - * - * @param serializeBytes - */ - public NetworkAddress(byte[] serializeBytes) { - secure = serializeBytes[0] == (byte) 1; - port = BytesUtils.toInt(serializeBytes, 1); - host = BytesUtils.toString(serializeBytes, 5); - } - - public String getHost() { - return host; - } - - public int getPort() { - return port; - } - - public boolean isSecure() { - return secure; - } - - public void setHost(String host) { - this.host = host; - } - - public void setPort(int port) { - this.port = port; - } - - public void setSecure(boolean secure) { - this.secure = secure; - } - - @Override - public String toString() { - return secure ? String.format("secure://%s:%s", host, port) : String.format("%s:%s", host, port); - } - - @Override - public int hashCode() { - return Arrays.hashCode(new Object[] { host, port, secure }); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (obj instanceof NetworkAddress) { - NetworkAddress other = (NetworkAddress) obj; - return this.host.equals(other.host) && this.port == other.port && this.secure == other.secure; - } - return false; - } - - @Override - public byte[] toBytes() { - BytesOutputBuffer buffer = new BytesOutputBuffer(); - byte[] bf1 = new byte[5]; - bf1[0] = secure ? (byte) 1 : (byte) 0; - BytesUtils.toBytes(port, bf1, 1); - buffer.write(bf1); - buffer.write(BytesUtils.toBytes(host)); - return buffer.toBytes(); - } - -} +package com.jd.blockchain.utils.net; + +import java.io.Serializable; +import java.util.Arrays; + +import com.jd.blockchain.utils.io.BytesOutputBuffer; +import com.jd.blockchain.utils.io.BytesSerializable; +import com.jd.blockchain.utils.io.BytesUtils; + +/** + * 网络地址; + * + * @author haiq + * + */ +public class NetworkAddress implements BytesSerializable, Serializable { + + private static final long serialVersionUID = -4565279525154132393L; + + private String host; + + private int port; + + private boolean secure; + + public NetworkAddress() { + } + + public NetworkAddress(String host, int port) { + this(host, port, false); + } + + public NetworkAddress(String host, int port, boolean secure) { + this.host = host; + this.port = port; + this.secure = secure; + } + + /** + * 用于二进制反序列化的构造器; + * + * @param serializeBytes + */ + public NetworkAddress(byte[] serializeBytes) { + secure = serializeBytes[0] == (byte) 1; + port = BytesUtils.toInt(serializeBytes, 1); + host = BytesUtils.toString(serializeBytes, 5); + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public boolean isSecure() { + return secure; + } + + public void setHost(String host) { + this.host = host; + } + + public void setPort(int port) { + this.port = port; + } + + public void setSecure(boolean secure) { + this.secure = secure; + } + + @Override + public String toString() { + return secure ? String.format("secure://%s:%s", host, port) : String.format("%s:%s", host, port); + } + + @Override + public int hashCode() { + return Arrays.hashCode(new Object[] { host, port, secure }); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (obj instanceof NetworkAddress) { + NetworkAddress other = (NetworkAddress) obj; + return this.host.equals(other.host) && this.port == other.port && this.secure == other.secure; + } + return false; + } + + @Override + public byte[] toBytes() { + BytesOutputBuffer buffer = new BytesOutputBuffer(); + byte[] bf1 = new byte[5]; + bf1[0] = secure ? (byte) 1 : (byte) 0; + BytesUtils.toBytes(port, bf1, 1); + buffer.write(bf1); + buffer.write(BytesUtils.toBytes(host)); + return buffer.toBytes(); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/net/NetworkException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/net/NetworkException.java index fd94cc36..45633917 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/net/NetworkException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/net/NetworkException.java @@ -1,17 +1,17 @@ -package com.jd.blockchain.utils.net; - -public class NetworkException extends RuntimeException{ - - private static final long serialVersionUID = 2231122547918937867L; - - public NetworkException() { - } - public NetworkException(String message) { - super(message); - } - public NetworkException(String message, Throwable cause) { - super(message, cause); - } - - -} +package com.jd.blockchain.utils.net; + +public class NetworkException extends RuntimeException{ + + private static final long serialVersionUID = 2231122547918937867L; + + public NetworkException() { + } + public NetworkException(String message) { + super(message); + } + public NetworkException(String message, Throwable cause) { + super(message, cause); + } + + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/AESUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/AESUtils.java index 35408b67..a2dd7c44 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/AESUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/AESUtils.java @@ -1,169 +1,169 @@ -package com.jd.blockchain.utils.security; - -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -import com.jd.blockchain.utils.codec.HexUtils; - -/** - * AES 加密算法工具类; - * - * @author haiq - * - */ -public class AESUtils { - - /** - * 用指定的种子生成 128 位的密钥;
- * - * 如果指定的种子为空(null 或长度为 0 ),则生成随机的密钥; - * - * @param seed - * 种子; - * @return - */ - public static String generateKey128_Hex(byte[] seed) { - byte[] keyBytes = generateKey128_Bytes(seed); - return HexUtils.encode(keyBytes); - } - - /** - * 用指定的种子生成 128 位的密钥; - * - * @param seed - * 种子; - * @return - */ - public static byte[] generateKey128_Bytes(byte[] seed) { - SecretKey key = generateKey128(seed); - return key.getEncoded(); - } - - /** - * 用指定的种子生成 128 位的密钥; - * - * @param seed - * 种子; 不允许为空; - * @return - */ - public static SecretKey generateKey128(byte[] seed) { - if (seed == null || seed.length == 0) { - throw new IllegalArgumentException("Empty seed!"); - } - // 注:AES 算法只支持 128 位,不支持 192, 256 位的密钥加密; - byte[] hashBytes = ShaUtils.hash_128(seed); - return new SecretKeySpec(hashBytes, "AES"); - - //注:由于同一个种子有可能产生不同的随机数序列,不能基于随机数机制来生成;by huanghaiquan at 2017-08-25; -// byte[] random = RandomUtils.generateRandomBytes(16, seed); -// return new SecretKeySpec(random, "AES"); - } - - /** - * 生成 128 位的随机密钥; - * - * @return - */ - public static SecretKey generateKey128() { - byte[] randBytes = RandomUtils.generateRandomBytes(16); - return new SecretKeySpec(randBytes, "AES"); - } - - /** - * 生成以 16 进制编码的 128 位的随机密钥; - * - * @return - */ - public static String generateKey128_Hex() { - byte[] keyBytes = generateKey128_Bytes(); - return HexUtils.encode(keyBytes); - } - - public static byte[] generateKey128_Bytes() { - SecretKey key = generateKey128(); - return key.getEncoded(); - } - - /** - * 用指定的 16 进制的AES密钥进行加密; - * - * @param content - * @param key - * 16进制编码的 AES 密钥; - * @return - */ - public static byte[] encrypt(byte[] content, String key) { - return encrypt(content, HexUtils.decode(key)); - } - - public static byte[] encrypt(byte[] content, byte[] secretKey) { - SecretKey aesKey = new SecretKeySpec(secretKey, "AES"); - return encrypt(content, aesKey); - } - - /** - * - * @param plainBytes - * @param key - * @return - */ - public static byte[] encrypt(byte[] plainBytes, SecretKey key) { - try { - Cipher cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.ENCRYPT_MODE, key); - return cipher.doFinal(plainBytes); - } catch (InvalidKeyException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (NoSuchAlgorithmException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (NoSuchPaddingException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (IllegalBlockSizeException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (BadPaddingException e) { - throw new EncryptionException(e.getMessage(), e); - } - } - - /** - * 解密; - * - * @param encryptedBytes - * @param key - * @return - */ - public static byte[] decrypt(byte[] encryptedBytes, String key) { - return decrypt(encryptedBytes, HexUtils.decode(key)); - } - - public static byte[] decrypt(byte[] encryptedBytes, byte[] key) { - SecretKey aesKey = new SecretKeySpec(key, "AES"); - return decrypt(encryptedBytes, aesKey); - } - - public static byte[] decrypt(byte[] encryptedBytes, SecretKey secretKey) { - try { - Cipher cipher = Cipher.getInstance("AES"); - cipher.init(Cipher.DECRYPT_MODE, secretKey); - return cipher.doFinal(encryptedBytes); - } catch (InvalidKeyException e) { - throw new DecryptionException(e.getMessage(), e); - } catch (NoSuchAlgorithmException e) { - throw new DecryptionException(e.getMessage(), e); - } catch (NoSuchPaddingException e) { - throw new DecryptionException(e.getMessage(), e); - } catch (IllegalBlockSizeException e) { - throw new DecryptionException(e.getMessage(), e); - } catch (BadPaddingException e) { - throw new DecryptionException(e.getMessage(), e); - } - } - +package com.jd.blockchain.utils.security; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import com.jd.blockchain.utils.codec.HexUtils; + +/** + * AES 加密算法工具类; + * + * @author haiq + * + */ +public class AESUtils { + + /** + * 用指定的种子生成 128 位的密钥;
+ * + * 如果指定的种子为空(null 或长度为 0 ),则生成随机的密钥; + * + * @param seed + * 种子; + * @return + */ + public static String generateKey128_Hex(byte[] seed) { + byte[] keyBytes = generateKey128_Bytes(seed); + return HexUtils.encode(keyBytes); + } + + /** + * 用指定的种子生成 128 位的密钥; + * + * @param seed + * 种子; + * @return + */ + public static byte[] generateKey128_Bytes(byte[] seed) { + SecretKey key = generateKey128(seed); + return key.getEncoded(); + } + + /** + * 用指定的种子生成 128 位的密钥; + * + * @param seed + * 种子; 不允许为空; + * @return + */ + public static SecretKey generateKey128(byte[] seed) { + if (seed == null || seed.length == 0) { + throw new IllegalArgumentException("Empty seed!"); + } + // 注:AES 算法只支持 128 位,不支持 192, 256 位的密钥加密; + byte[] hashBytes = ShaUtils.hash_128(seed); + return new SecretKeySpec(hashBytes, "AES"); + + //注:由于同一个种子有可能产生不同的随机数序列,不能基于随机数机制来生成;by huanghaiquan at 2017-08-25; +// byte[] random = RandomUtils.generateRandomBytes(16, seed); +// return new SecretKeySpec(random, "AES"); + } + + /** + * 生成 128 位的随机密钥; + * + * @return + */ + public static SecretKey generateKey128() { + byte[] randBytes = RandomUtils.generateRandomBytes(16); + return new SecretKeySpec(randBytes, "AES"); + } + + /** + * 生成以 16 进制编码的 128 位的随机密钥; + * + * @return + */ + public static String generateKey128_Hex() { + byte[] keyBytes = generateKey128_Bytes(); + return HexUtils.encode(keyBytes); + } + + public static byte[] generateKey128_Bytes() { + SecretKey key = generateKey128(); + return key.getEncoded(); + } + + /** + * 用指定的 16 进制的AES密钥进行加密; + * + * @param content + * @param key + * 16进制编码的 AES 密钥; + * @return + */ + public static byte[] encrypt(byte[] content, String key) { + return encrypt(content, HexUtils.decode(key)); + } + + public static byte[] encrypt(byte[] content, byte[] secretKey) { + SecretKey aesKey = new SecretKeySpec(secretKey, "AES"); + return encrypt(content, aesKey); + } + + /** + * + * @param plainBytes + * @param key + * @return + */ + public static byte[] encrypt(byte[] plainBytes, SecretKey key) { + try { + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.ENCRYPT_MODE, key); + return cipher.doFinal(plainBytes); + } catch (InvalidKeyException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (NoSuchAlgorithmException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (NoSuchPaddingException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (IllegalBlockSizeException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (BadPaddingException e) { + throw new EncryptionException(e.getMessage(), e); + } + } + + /** + * 解密; + * + * @param encryptedBytes + * @param key + * @return + */ + public static byte[] decrypt(byte[] encryptedBytes, String key) { + return decrypt(encryptedBytes, HexUtils.decode(key)); + } + + public static byte[] decrypt(byte[] encryptedBytes, byte[] key) { + SecretKey aesKey = new SecretKeySpec(key, "AES"); + return decrypt(encryptedBytes, aesKey); + } + + public static byte[] decrypt(byte[] encryptedBytes, SecretKey secretKey) { + try { + Cipher cipher = Cipher.getInstance("AES"); + cipher.init(Cipher.DECRYPT_MODE, secretKey); + return cipher.doFinal(encryptedBytes); + } catch (InvalidKeyException e) { + throw new DecryptionException(e.getMessage(), e); + } catch (NoSuchAlgorithmException e) { + throw new DecryptionException(e.getMessage(), e); + } catch (NoSuchPaddingException e) { + throw new DecryptionException(e.getMessage(), e); + } catch (IllegalBlockSizeException e) { + throw new DecryptionException(e.getMessage(), e); + } catch (BadPaddingException e) { + throw new DecryptionException(e.getMessage(), e); + } + } + } \ No newline at end of file diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/AuthenticationException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/AuthenticationException.java index 2b235712..c25dcea7 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/AuthenticationException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/AuthenticationException.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.utils.security; - -/** - * 认证异常; - * - * @author haiq - * - */ -public class AuthenticationException extends RuntimeException { - - private static final long serialVersionUID = 2188866951704920121L; - - public AuthenticationException(String message) { - super(message); - } - - public AuthenticationException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.utils.security; + +/** + * 认证异常; + * + * @author haiq + * + */ +public class AuthenticationException extends RuntimeException { + + private static final long serialVersionUID = 2188866951704920121L; + + public AuthenticationException(String message) { + super(message); + } + + public AuthenticationException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/DESUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/DESUtils.java index 064f8a1b..b5ef1c2e 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/DESUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/DESUtils.java @@ -1,62 +1,62 @@ -package com.jd.blockchain.utils.security; - -import com.jd.blockchain.utils.io.BytesUtils; - -import javax.crypto.Cipher; -import javax.crypto.KeyGenerator; -import javax.crypto.SecretKey; -import javax.crypto.SecretKeyFactory; -import javax.crypto.spec.DESKeySpec; - -/** - * DES 算法的工具类; - * - * @author haiq - * - */ -public class DESUtils { - - private static final String DES = "DES"; - private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding"; - - /** - * 加密 - * - * @param code - * @param keyBytes - * {key+adress}.length=8*n - * @return - * @throws Exception - */ - public static byte[] encrypt(String code, byte[] keyBytes) throws Exception { - Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM); - DESKeySpec keySpec = new DESKeySpec(keyBytes); - SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES); - SecretKey secretKey = keyFactory.generateSecret(keySpec); - cipher.init(Cipher.ENCRYPT_MODE, secretKey); - return cipher.doFinal(BytesUtils.toBytes(code)); - } - - /** DES解密 */ - public static byte[] decrypt(byte[] codeBytes, byte[] keyBytes) throws Exception { - Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM); - DESKeySpec keySpec = new DESKeySpec(keyBytes); - SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES); - SecretKey secretKey = keyFactory.generateSecret(keySpec); - cipher.init(Cipher.DECRYPT_MODE, secretKey); - return cipher.doFinal(codeBytes); - } - - /** - * 生成key - * - * @return - * @throws Exception - */ - public static byte[] initKey() throws Exception { - KeyGenerator kg = KeyGenerator.getInstance(DES); - kg.init(56); - SecretKey secretKey = kg.generateKey(); - return secretKey.getEncoded(); - } -} +package com.jd.blockchain.utils.security; + +import com.jd.blockchain.utils.io.BytesUtils; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; + +/** + * DES 算法的工具类; + * + * @author haiq + * + */ +public class DESUtils { + + private static final String DES = "DES"; + private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding"; + + /** + * 加密 + * + * @param code + * @param keyBytes + * {key+adress}.length=8*n + * @return + * @throws Exception + */ + public static byte[] encrypt(String code, byte[] keyBytes) throws Exception { + Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM); + DESKeySpec keySpec = new DESKeySpec(keyBytes); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES); + SecretKey secretKey = keyFactory.generateSecret(keySpec); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + return cipher.doFinal(BytesUtils.toBytes(code)); + } + + /** DES解密 */ + public static byte[] decrypt(byte[] codeBytes, byte[] keyBytes) throws Exception { + Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM); + DESKeySpec keySpec = new DESKeySpec(keyBytes); + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES); + SecretKey secretKey = keyFactory.generateSecret(keySpec); + cipher.init(Cipher.DECRYPT_MODE, secretKey); + return cipher.doFinal(codeBytes); + } + + /** + * 生成key + * + * @return + * @throws Exception + */ + public static byte[] initKey() throws Exception { + KeyGenerator kg = KeyGenerator.getInstance(DES); + kg.init(56); + SecretKey secretKey = kg.generateKey(); + return secretKey.getEncoded(); + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/DecryptionException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/DecryptionException.java index f582853c..08515b62 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/DecryptionException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/DecryptionException.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.utils.security; - -/** - * 解密异常; - * - * @author haiq - * - */ -public class DecryptionException extends RuntimeException { - - private static final long serialVersionUID = 2188866951704920121L; - - public DecryptionException(String message) { - super(message); - } - - public DecryptionException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.utils.security; + +/** + * 解密异常; + * + * @author haiq + * + */ +public class DecryptionException extends RuntimeException { + + private static final long serialVersionUID = 2188866951704920121L; + + public DecryptionException(String message) { + super(message); + } + + public DecryptionException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/Ed25519Utils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/Ed25519Utils.java index 07dc93f8..c81a5521 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/Ed25519Utils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/Ed25519Utils.java @@ -1,85 +1,85 @@ -package com.jd.blockchain.utils.security; - -import java.nio.ByteBuffer; -import java.security.InvalidKeyException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.SignatureException; - -import net.i2p.crypto.eddsa.EdDSAEngine; -import net.i2p.crypto.eddsa.EdDSAPrivateKey; -import net.i2p.crypto.eddsa.EdDSAPublicKey; -import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; -import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec; -import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; -import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; - -public class Ed25519Utils { - - /** - * 用指定的私钥执行签名; - * - * @param data - * @param privateKey - * @return 返回签名摘要; - */ - public static byte[] sign_512(byte[] data, byte[] privateKey) { - return sign_512(ByteBuffer.wrap(data), privateKey); - } - - /** - * 用指定的私钥执行签名; - * - * @param data - * @param privateKey - * @return 返回签名摘要; - */ - public static byte[] sign_512(ByteBuffer data, byte[] privateKey) { - try { - java.security.Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512")); - EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512); - EdDSAPrivateKeySpec privateKeySpec = new EdDSAPrivateKeySpec(privateKey, spec); - PrivateKey privKey = new EdDSAPrivateKey(privateKeySpec); - sgr.initSign(privKey); - sgr.update(data); - return sgr.sign(); - } catch (InvalidKeyException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException(e.getMessage(), e); - } catch (SignatureException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - /** - * 验证签名; - * - * @param plainData - * 明文; - * @param pubKeyBytes - * 公钥; - * @param signatureBytes - * 摘要; - * @return - */ - public static boolean verify(byte[] plainData, byte[] pubKeyBytes, byte[] signatureBytes) { - try { - java.security.Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512")); - EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512"); - EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(pubKeyBytes, spec); - EdDSAPublicKey pubKey = new EdDSAPublicKey(pubKeySpec); - sgr.initVerify(pubKey); - sgr.update(plainData); - return sgr.verify(signatureBytes); - } catch (InvalidKeyException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException(e.getMessage(), e); - } catch (SignatureException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - -} +package com.jd.blockchain.utils.security; + +import java.nio.ByteBuffer; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.SignatureException; + +import net.i2p.crypto.eddsa.EdDSAEngine; +import net.i2p.crypto.eddsa.EdDSAPrivateKey; +import net.i2p.crypto.eddsa.EdDSAPublicKey; +import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; +import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec; +import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; +import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec; + +public class Ed25519Utils { + + /** + * 用指定的私钥执行签名; + * + * @param data + * @param privateKey + * @return 返回签名摘要; + */ + public static byte[] sign_512(byte[] data, byte[] privateKey) { + return sign_512(ByteBuffer.wrap(data), privateKey); + } + + /** + * 用指定的私钥执行签名; + * + * @param data + * @param privateKey + * @return 返回签名摘要; + */ + public static byte[] sign_512(ByteBuffer data, byte[] privateKey) { + try { + java.security.Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512")); + EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512); + EdDSAPrivateKeySpec privateKeySpec = new EdDSAPrivateKeySpec(privateKey, spec); + PrivateKey privKey = new EdDSAPrivateKey(privateKeySpec); + sgr.initSign(privKey); + sgr.update(data); + return sgr.sign(); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e.getMessage(), e); + } catch (SignatureException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + /** + * 验证签名; + * + * @param plainData + * 明文; + * @param pubKeyBytes + * 公钥; + * @param signatureBytes + * 摘要; + * @return + */ + public static boolean verify(byte[] plainData, byte[] pubKeyBytes, byte[] signatureBytes) { + try { + java.security.Signature sgr = new EdDSAEngine(MessageDigest.getInstance("SHA-512")); + EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("ed25519-sha-512"); + EdDSAPublicKeySpec pubKeySpec = new EdDSAPublicKeySpec(pubKeyBytes, spec); + EdDSAPublicKey pubKey = new EdDSAPublicKey(pubKeySpec); + sgr.initVerify(pubKey); + sgr.update(plainData); + return sgr.verify(signatureBytes); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e.getMessage(), e); + } catch (SignatureException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/EncryptionException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/EncryptionException.java index 8086d896..a9167df2 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/EncryptionException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/EncryptionException.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.utils.security; - -/** - * 加密异常; - * - * @author haiq - * - */ -public class EncryptionException extends RuntimeException { - - private static final long serialVersionUID = 2188866951704920121L; - - public EncryptionException(String message) { - super(message); - } - - public EncryptionException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.utils.security; + +/** + * 加密异常; + * + * @author haiq + * + */ +public class EncryptionException extends RuntimeException { + + private static final long serialVersionUID = 2188866951704920121L; + + public EncryptionException(String message) { + super(message); + } + + public EncryptionException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyGenerationException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyGenerationException.java index a27b8fc3..e671e5e8 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyGenerationException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyGenerationException.java @@ -1,18 +1,18 @@ -package com.jd.blockchain.utils.security; - -public class KeyGenerationException extends RuntimeException { - - private static final long serialVersionUID = 1729427276871753983L; - - public KeyGenerationException() { - } - - public KeyGenerationException(String message) { - super(message); - } - - public KeyGenerationException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.utils.security; + +public class KeyGenerationException extends RuntimeException { + + private static final long serialVersionUID = 1729427276871753983L; + + public KeyGenerationException() { + } + + public KeyGenerationException(String message) { + super(message); + } + + public KeyGenerationException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyStoreException.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyStoreException.java index b12f1306..611f927c 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyStoreException.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyStoreException.java @@ -1,18 +1,18 @@ -package com.jd.blockchain.utils.security; - -public class KeyStoreException extends RuntimeException { - - private static final long serialVersionUID = 1729427276871753983L; - - public KeyStoreException() { - } - - public KeyStoreException(String message) { - super(message); - } - - public KeyStoreException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.utils.security; + +public class KeyStoreException extends RuntimeException { + + private static final long serialVersionUID = 1729427276871753983L; + + public KeyStoreException() { + } + + public KeyStoreException(String message) { + super(message); + } + + public KeyStoreException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyStoreUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyStoreUtils.java index da71c818..10b65cdf 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyStoreUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/KeyStoreUtils.java @@ -1,30 +1,30 @@ -package com.jd.blockchain.utils.security; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; - -public class KeyStoreUtils { - - public static final String P12_KEYSTORE_TYPE = "PKCS12"; - - public static void validateP12(byte[] certicate, String password) throws KeyStoreException{ - try { - ByteArrayInputStream certStream = new ByteArrayInputStream(certicate); - char[] pwdChars = password.toCharArray(); - KeyStore ks = KeyStore.getInstance(P12_KEYSTORE_TYPE); - ks.load(certStream, pwdChars); - } catch (java.security.KeyStoreException e) { - throw new KeyStoreException(e.getMessage(), e); - } catch (NoSuchAlgorithmException e) { - throw new KeyStoreException(e.getMessage(), e); - } catch (CertificateException e) { - throw new KeyStoreException(e.getMessage(), e); - } catch (IOException e) { - throw new KeyStoreException(e.getMessage(), e); - } - } - -} +package com.jd.blockchain.utils.security; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +public class KeyStoreUtils { + + public static final String P12_KEYSTORE_TYPE = "PKCS12"; + + public static void validateP12(byte[] certicate, String password) throws KeyStoreException{ + try { + ByteArrayInputStream certStream = new ByteArrayInputStream(certicate); + char[] pwdChars = password.toCharArray(); + KeyStore ks = KeyStore.getInstance(P12_KEYSTORE_TYPE); + ks.load(certStream, pwdChars); + } catch (java.security.KeyStoreException e) { + throw new KeyStoreException(e.getMessage(), e); + } catch (NoSuchAlgorithmException e) { + throw new KeyStoreException(e.getMessage(), e); + } catch (CertificateException e) { + throw new KeyStoreException(e.getMessage(), e); + } catch (IOException e) { + throw new KeyStoreException(e.getMessage(), e); + } + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RSAKeyPair.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RSAKeyPair.java index fd9fe3da..6acdaff1 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RSAKeyPair.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RSAKeyPair.java @@ -1,41 +1,41 @@ -package com.jd.blockchain.utils.security; - -import java.nio.ByteBuffer; - -import com.jd.blockchain.utils.codec.Base58Utils; - -public class RSAKeyPair { - - private byte[] publicKey; - - private String publicKey_Base58; - - private byte[] privateKey; - - private String privateKey_Base58; - - public RSAKeyPair(byte[] publicKey, byte[] privateKey) { - this.publicKey = publicKey; - this.privateKey = privateKey; - - this.publicKey_Base58 = Base58Utils.encode(publicKey); - this.privateKey_Base58 = Base58Utils.encode(privateKey); - } - - public ByteBuffer getPublicKey() { - return ByteBuffer.wrap(publicKey).asReadOnlyBuffer(); - } - - public ByteBuffer getPrivateKey() { - return ByteBuffer.wrap(privateKey).asReadOnlyBuffer(); - } - - public String getPublicKey_Base58() { - return publicKey_Base58; - } - - public String getPrivateKey_Base58() { - return privateKey_Base58; - } - -} +package com.jd.blockchain.utils.security; + +import java.nio.ByteBuffer; + +import com.jd.blockchain.utils.codec.Base58Utils; + +public class RSAKeyPair { + + private byte[] publicKey; + + private String publicKey_Base58; + + private byte[] privateKey; + + private String privateKey_Base58; + + public RSAKeyPair(byte[] publicKey, byte[] privateKey) { + this.publicKey = publicKey; + this.privateKey = privateKey; + + this.publicKey_Base58 = Base58Utils.encode(publicKey); + this.privateKey_Base58 = Base58Utils.encode(privateKey); + } + + public ByteBuffer getPublicKey() { + return ByteBuffer.wrap(publicKey).asReadOnlyBuffer(); + } + + public ByteBuffer getPrivateKey() { + return ByteBuffer.wrap(privateKey).asReadOnlyBuffer(); + } + + public String getPublicKey_Base58() { + return publicKey_Base58; + } + + public String getPrivateKey_Base58() { + return privateKey_Base58; + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RSAUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RSAUtils.java index b86f2e5b..6f94c863 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RSAUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RSAUtils.java @@ -1,131 +1,131 @@ -package com.jd.blockchain.utils.security; - -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; - -import javax.crypto.BadPaddingException; -import javax.crypto.Cipher; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; - -import com.jd.blockchain.utils.codec.Base58Utils; - -/** - * RSA 加密算法的工具类; - * - * @author haiq - * - */ -public class RSAUtils { - public static final String ALG_RSA = "RSA"; - public static final String KEYPAIR_PUBKEY = "pubKey"; - public static final String KEYPAIR_PRIKEY = "priKey"; - - public static RSAKeyPair generateKey512() { - try { - KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALG_RSA); - keyPairGen.initialize(512, new SecureRandom()); - KeyPair keyPair = keyPairGen.generateKeyPair(); - RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); - RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); - - return new RSAKeyPair(publicKey.getEncoded(), privateKey.getEncoded()); - } catch (NoSuchAlgorithmException e) { - throw new KeyGenerationException(e.getMessage(), e); - } - } - - public static RSAKeyPair generateKey2048() { - try { - KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALG_RSA); - keyPairGen.initialize(2048, new SecureRandom()); - KeyPair keyPair = keyPairGen.generateKeyPair(); - RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); - RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); - - return new RSAKeyPair(publicKey.getEncoded(), privateKey.getEncoded()); - } catch (NoSuchAlgorithmException e) { - throw new KeyGenerationException(e.getMessage(), e); - } - } - - public static byte[] encryptByPublicKey_Base58(byte[] data, String publicKey_Base58) { - byte[] publicKey = Base58Utils.decode(publicKey_Base58); - return encryptByPublicKey(data, publicKey); - } - - public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) { - if (publicKey == null) { - throw new IllegalArgumentException("Public key is empty!"); - } - try { - RSAPublicKey pubKey = loadPublicKey(publicKey); - Cipher cipher = Cipher.getInstance(ALG_RSA); - cipher.init(Cipher.ENCRYPT_MODE, pubKey); - return cipher.doFinal(data); - } catch (InvalidKeyException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (NoSuchAlgorithmException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (InvalidKeySpecException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (NoSuchPaddingException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (IllegalBlockSizeException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (BadPaddingException e) { - throw new EncryptionException(e.getMessage(), e); - } - } - - public static byte[] decryptByPrivateKey_Base58(byte[] data, String privateKey_Base58) { - byte[] privateKey = Base58Utils.decode(privateKey_Base58); - return decryptByPrivateKey(data, privateKey); - } - - public static byte[] decryptByPrivateKey(byte[] cipherData, byte[] privateKey) { - if (privateKey == null) { - throw new IllegalArgumentException("Private key is empty!"); - } - try { - RSAPrivateKey privKey = loadPrivateKey(privateKey); - Cipher cipher = Cipher.getInstance(ALG_RSA); - cipher.init(Cipher.DECRYPT_MODE, privKey); - return cipher.doFinal(cipherData); - } catch (InvalidKeyException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (NoSuchAlgorithmException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (InvalidKeySpecException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (NoSuchPaddingException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (IllegalBlockSizeException e) { - throw new EncryptionException(e.getMessage(), e); - } catch (BadPaddingException e) { - throw new EncryptionException(e.getMessage(), e); - } - } - - private static RSAPublicKey loadPublicKey(byte[] pubKey) throws NoSuchAlgorithmException, InvalidKeySpecException { - KeyFactory keyFactory = KeyFactory.getInstance(ALG_RSA); - X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKey); - return (RSAPublicKey) keyFactory.generatePublic(keySpec); - } - - private static RSAPrivateKey loadPrivateKey(byte[] priKey) - throws NoSuchAlgorithmException, InvalidKeySpecException { - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priKey); - KeyFactory keyFactory = KeyFactory.getInstance(ALG_RSA); - return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); - } -} +package com.jd.blockchain.utils.security; + +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; + +import com.jd.blockchain.utils.codec.Base58Utils; + +/** + * RSA 加密算法的工具类; + * + * @author haiq + * + */ +public class RSAUtils { + public static final String ALG_RSA = "RSA"; + public static final String KEYPAIR_PUBKEY = "pubKey"; + public static final String KEYPAIR_PRIKEY = "priKey"; + + public static RSAKeyPair generateKey512() { + try { + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALG_RSA); + keyPairGen.initialize(512, new SecureRandom()); + KeyPair keyPair = keyPairGen.generateKeyPair(); + RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + + return new RSAKeyPair(publicKey.getEncoded(), privateKey.getEncoded()); + } catch (NoSuchAlgorithmException e) { + throw new KeyGenerationException(e.getMessage(), e); + } + } + + public static RSAKeyPair generateKey2048() { + try { + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(ALG_RSA); + keyPairGen.initialize(2048, new SecureRandom()); + KeyPair keyPair = keyPairGen.generateKeyPair(); + RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + + return new RSAKeyPair(publicKey.getEncoded(), privateKey.getEncoded()); + } catch (NoSuchAlgorithmException e) { + throw new KeyGenerationException(e.getMessage(), e); + } + } + + public static byte[] encryptByPublicKey_Base58(byte[] data, String publicKey_Base58) { + byte[] publicKey = Base58Utils.decode(publicKey_Base58); + return encryptByPublicKey(data, publicKey); + } + + public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) { + if (publicKey == null) { + throw new IllegalArgumentException("Public key is empty!"); + } + try { + RSAPublicKey pubKey = loadPublicKey(publicKey); + Cipher cipher = Cipher.getInstance(ALG_RSA); + cipher.init(Cipher.ENCRYPT_MODE, pubKey); + return cipher.doFinal(data); + } catch (InvalidKeyException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (NoSuchAlgorithmException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (InvalidKeySpecException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (NoSuchPaddingException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (IllegalBlockSizeException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (BadPaddingException e) { + throw new EncryptionException(e.getMessage(), e); + } + } + + public static byte[] decryptByPrivateKey_Base58(byte[] data, String privateKey_Base58) { + byte[] privateKey = Base58Utils.decode(privateKey_Base58); + return decryptByPrivateKey(data, privateKey); + } + + public static byte[] decryptByPrivateKey(byte[] cipherData, byte[] privateKey) { + if (privateKey == null) { + throw new IllegalArgumentException("Private key is empty!"); + } + try { + RSAPrivateKey privKey = loadPrivateKey(privateKey); + Cipher cipher = Cipher.getInstance(ALG_RSA); + cipher.init(Cipher.DECRYPT_MODE, privKey); + return cipher.doFinal(cipherData); + } catch (InvalidKeyException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (NoSuchAlgorithmException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (InvalidKeySpecException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (NoSuchPaddingException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (IllegalBlockSizeException e) { + throw new EncryptionException(e.getMessage(), e); + } catch (BadPaddingException e) { + throw new EncryptionException(e.getMessage(), e); + } + } + + private static RSAPublicKey loadPublicKey(byte[] pubKey) throws NoSuchAlgorithmException, InvalidKeySpecException { + KeyFactory keyFactory = KeyFactory.getInstance(ALG_RSA); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pubKey); + return (RSAPublicKey) keyFactory.generatePublic(keySpec); + } + + private static RSAPrivateKey loadPrivateKey(byte[] priKey) + throws NoSuchAlgorithmException, InvalidKeySpecException { + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(priKey); + KeyFactory keyFactory = KeyFactory.getInstance(ALG_RSA); + return (RSAPrivateKey) keyFactory.generatePrivate(keySpec); + } +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RandomUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RandomUtils.java index 576ea7a4..96c42592 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RandomUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RandomUtils.java @@ -1,42 +1,42 @@ -package com.jd.blockchain.utils.security; - -import java.security.SecureRandom; - -/** - * 随机数生成工具类; - * - * @author haiq - * - */ -public class RandomUtils { - - public static byte[] generateRandomBytes(int sizeOfRandom) { - return generateRandomBytes(sizeOfRandom, null); - } - - /** - * 用指定的种子生成秘钥; - *

- * - * 注:需要注意,同一个种子有可能产生不同的随机数序列; - * - * @param sizeOfRandom - * 要输出的随机数的长度;(单位:字节) - * @param seed - * 随机种子; - * @return 随机数;长度等于 sizeOfRandom 参数指定的值; - */ - public static byte[] generateRandomBytes(int sizeOfRandom, byte[] seed) { - SecureRandom sr = null; - if (seed == null || seed.length == 0) { - // 随机; - sr = new SecureRandom(); - } else { - sr = new SecureRandom(seed); - } - byte[] randomBytes = new byte[sizeOfRandom]; - sr.nextBytes(randomBytes); - return randomBytes; - } - -} +package com.jd.blockchain.utils.security; + +import java.security.SecureRandom; + +/** + * 随机数生成工具类; + * + * @author haiq + * + */ +public class RandomUtils { + + public static byte[] generateRandomBytes(int sizeOfRandom) { + return generateRandomBytes(sizeOfRandom, null); + } + + /** + * 用指定的种子生成秘钥; + *

+ * + * 注:需要注意,同一个种子有可能产生不同的随机数序列; + * + * @param sizeOfRandom + * 要输出的随机数的长度;(单位:字节) + * @param seed + * 随机种子; + * @return 随机数;长度等于 sizeOfRandom 参数指定的值; + */ + public static byte[] generateRandomBytes(int sizeOfRandom, byte[] seed) { + SecureRandom sr = null; + if (seed == null || seed.length == 0) { + // 随机; + sr = new SecureRandom(); + } else { + sr = new SecureRandom(seed); + } + byte[] randomBytes = new byte[sizeOfRandom]; + sr.nextBytes(randomBytes); + return randomBytes; + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RipeMD160Utils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RipeMD160Utils.java index c3173dbd..c4faff13 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RipeMD160Utils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/RipeMD160Utils.java @@ -1,25 +1,25 @@ -package com.jd.blockchain.utils.security; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.Security; - -import org.bouncycastle.jce.provider.BouncyCastleProvider; - -public class RipeMD160Utils { - - static { - Security.addProvider(new BouncyCastleProvider()); - } - - public static byte[] hash(byte[] bytes) { - try { - MessageDigest md160 = MessageDigest.getInstance("RIPEMD160"); - return md160.digest(bytes); - } catch (NoSuchAlgorithmException e) { - throw new EncryptionException(e.getMessage(), e); - } - - } - -} +package com.jd.blockchain.utils.security; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +public class RipeMD160Utils { + + static { + Security.addProvider(new BouncyCastleProvider()); + } + + public static byte[] hash(byte[] bytes) { + try { + MessageDigest md160 = MessageDigest.getInstance("RIPEMD160"); + return md160.digest(bytes); + } catch (NoSuchAlgorithmException e) { + throw new EncryptionException(e.getMessage(), e); + } + + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/ShaUtils.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/ShaUtils.java index 34ee84f6..782cde5c 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/ShaUtils.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/security/ShaUtils.java @@ -1,150 +1,150 @@ -package com.jd.blockchain.utils.security; - -import java.io.IOException; -import java.io.InputStream; -import java.security.DigestException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; - -/** - * 摘要工具类 - * - * @author haiq - * - */ -public class ShaUtils { - - /** - * 对指定的字节数组进行 SHA128 哈希; - * @param bytes bytes - * @return 返回长度为 16 的字节数组; - */ - public static byte[] hash_128(byte[] bytes) { - byte[] hash256Bytes = hash_256(bytes); - return Arrays.copyOf(hash256Bytes, 16); - } - - /** - * 对指定的字节数组进行 SHA256 哈希; - * @param bytes bytes - * @return 返回长度为 32 的字节数组; - */ - public static byte[] hash_256(byte[] bytes) { - MessageDigest md = null; - try { - md = MessageDigest.getInstance("SHA-256"); - md.update(bytes); - return md.digest(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - /** - * 对指定的字节数组进行 SHA256 哈希; - * @param bytes bytes - * @param outputBuffer outputBuffer - * @return 返回长度为 32 的字节数组; - */ - public static int hash_256(byte[] bytes, byte[] outputBuffer) { - return hash_256(bytes, outputBuffer, 0, outputBuffer.length); - } - - /** - * 对指定的字节数组进行 SHA256 哈希; - * @param bytes bytes - * @param outputBuffer outputBuffer - * @param offset offset - * @param length length - * @return 返回长度为 32 的字节数组; - */ - public static int hash_256(byte[] bytes, byte[] outputBuffer, int offset, int length) { - MessageDigest md = null; - try { - md = MessageDigest.getInstance("SHA-256"); - md.update(bytes); - return md.digest(outputBuffer, offset, length); - } catch (NoSuchAlgorithmException | DigestException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - public static byte[] hash_256(InputStream input) { - MessageDigest md = null; - try { - md = MessageDigest.getInstance("SHA-256"); - byte[] buff = new byte[64]; - int len = 0; - while ((len = input.read(buff)) > 0) { - md.update(buff, 0, len); - } - return md.digest(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException(e.getMessage(), e); - } catch (IOException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - public static SHA256Hash hash_256() { - try { - MessageDigest md = MessageDigest.getInstance("SHA-256"); - return new SHA256HashImpl(md); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - // /** - // * 组装待签名数据 - // * - // * @param userAgent - // * 客户端 - // * @param url - // * 请求路径 - // * @param requestBody - // * 请求体 可为空 - // * @return - // */ - // @Deprecated - // public static byte[] getData(byte[] userAgent, byte[] url, byte[] - // requestBody) { - // - // byte[] bytes = new byte[userAgent.length + url.length + (requestBody == null - // ? 0 : requestBody.length)]; - // System.arraycopy(userAgent, 0, bytes, 0, userAgent.length); - // System.arraycopy(url, 0, bytes, userAgent.length, url.length); - // if (requestBody != null) { - // System.arraycopy(requestBody, 0, bytes, userAgent.length + url.length, - // requestBody.length); - // } - // return bytes; - // } - - private static class SHA256HashImpl implements SHA256Hash { - - private MessageDigest md; - - public SHA256HashImpl(MessageDigest md) { - this.md = md; - } - - @Override - public void update(byte[] bytes) { - md.update(bytes, 0, bytes.length); - } - - @Override - public void update(byte[] bytes, int offset, int len) { - md.update(bytes, offset, len); - } - - @Override - public byte[] complete() { - return md.digest(); - } - - } - -} +package com.jd.blockchain.utils.security; + +import java.io.IOException; +import java.io.InputStream; +import java.security.DigestException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +/** + * 摘要工具类 + * + * @author haiq + * + */ +public class ShaUtils { + + /** + * 对指定的字节数组进行 SHA128 哈希; + * @param bytes bytes + * @return 返回长度为 16 的字节数组; + */ + public static byte[] hash_128(byte[] bytes) { + byte[] hash256Bytes = hash_256(bytes); + return Arrays.copyOf(hash256Bytes, 16); + } + + /** + * 对指定的字节数组进行 SHA256 哈希; + * @param bytes bytes + * @return 返回长度为 32 的字节数组; + */ + public static byte[] hash_256(byte[] bytes) { + MessageDigest md = null; + try { + md = MessageDigest.getInstance("SHA-256"); + md.update(bytes); + return md.digest(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + /** + * 对指定的字节数组进行 SHA256 哈希; + * @param bytes bytes + * @param outputBuffer outputBuffer + * @return 返回长度为 32 的字节数组; + */ + public static int hash_256(byte[] bytes, byte[] outputBuffer) { + return hash_256(bytes, outputBuffer, 0, outputBuffer.length); + } + + /** + * 对指定的字节数组进行 SHA256 哈希; + * @param bytes bytes + * @param outputBuffer outputBuffer + * @param offset offset + * @param length length + * @return 返回长度为 32 的字节数组; + */ + public static int hash_256(byte[] bytes, byte[] outputBuffer, int offset, int length) { + MessageDigest md = null; + try { + md = MessageDigest.getInstance("SHA-256"); + md.update(bytes); + return md.digest(outputBuffer, offset, length); + } catch (NoSuchAlgorithmException | DigestException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + public static byte[] hash_256(InputStream input) { + MessageDigest md = null; + try { + md = MessageDigest.getInstance("SHA-256"); + byte[] buff = new byte[64]; + int len = 0; + while ((len = input.read(buff)) > 0) { + md.update(buff, 0, len); + } + return md.digest(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e.getMessage(), e); + } catch (IOException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + public static SHA256Hash hash_256() { + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + return new SHA256HashImpl(md); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + // /** + // * 组装待签名数据 + // * + // * @param userAgent + // * 客户端 + // * @param url + // * 请求路径 + // * @param requestBody + // * 请求体 可为空 + // * @return + // */ + // @Deprecated + // public static byte[] getData(byte[] userAgent, byte[] url, byte[] + // requestBody) { + // + // byte[] bytes = new byte[userAgent.length + url.length + (requestBody == null + // ? 0 : requestBody.length)]; + // System.arraycopy(userAgent, 0, bytes, 0, userAgent.length); + // System.arraycopy(url, 0, bytes, userAgent.length, url.length); + // if (requestBody != null) { + // System.arraycopy(requestBody, 0, bytes, userAgent.length + url.length, + // requestBody.length); + // } + // return bytes; + // } + + private static class SHA256HashImpl implements SHA256Hash { + + private MessageDigest md; + + public SHA256HashImpl(MessageDigest md) { + this.md = md; + } + + @Override + public void update(byte[] bytes) { + md.update(bytes, 0, bytes.length); + } + + @Override + public void update(byte[] bytes, int offset, int len) { + md.update(bytes, offset, len); + } + + @Override + public byte[] complete() { + return md.digest(); + } + + } + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/transfer/AsyncSendable.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/transfer/AsyncSendable.java index 1e399fa3..446bebd3 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/transfer/AsyncSendable.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/transfer/AsyncSendable.java @@ -1,22 +1,22 @@ -package com.jd.blockchain.utils.transfer; - -import com.jd.blockchain.utils.concurrent.AsyncFuture; - -/** - * AsyncMessageSendable 是对异步发送操作的抽象; - * - * @author haiq - * - * @param - */ -public interface AsyncSendable { - - /** - * 异步发送消息; - * - * @param message - * @return - */ - public AsyncFuture asyncSend(TData message); - -} +package com.jd.blockchain.utils.transfer; + +import com.jd.blockchain.utils.concurrent.AsyncFuture; + +/** + * AsyncMessageSendable 是对异步发送操作的抽象; + * + * @author haiq + * + * @param + */ +public interface AsyncSendable { + + /** + * 异步发送消息; + * + * @param message + * @return + */ + public AsyncFuture asyncSend(TData message); + +} diff --git a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/transfer/Sendable.java b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/transfer/Sendable.java index 27573193..8a67b22a 100644 --- a/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/transfer/Sendable.java +++ b/source/utils/utils-common/src/main/java/com/jd/blockchain/utils/transfer/Sendable.java @@ -1,18 +1,18 @@ -package com.jd.blockchain.utils.transfer; - -/** - * Sendable 是发送操作的抽象; - * - * @author haiq - * - */ -public interface Sendable { - - /** - * 发送消息; - * - * @param message - */ - public void send(TData message); - -} +package com.jd.blockchain.utils.transfer; + +/** + * Sendable 是发送操作的抽象; + * + * @author haiq + * + */ +public interface Sendable { + + /** + * 发送消息; + * + * @param message + */ + public void send(TData message); + +} diff --git a/source/utils/utils-common/src/test/java/test/my/utils/io/BytesEncodingTest.java b/source/utils/utils-common/src/test/java/test/my/utils/io/BytesEncodingTest.java index f7548505..fde0dd9f 100644 --- a/source/utils/utils-common/src/test/java/test/my/utils/io/BytesEncodingTest.java +++ b/source/utils/utils-common/src/test/java/test/my/utils/io/BytesEncodingTest.java @@ -1,86 +1,86 @@ -package test.my.utils.io; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.UnsupportedEncodingException; -import java.util.UUID; - -import org.junit.Test; - -import com.jd.blockchain.utils.io.ByteArray; -import com.jd.blockchain.utils.io.BytesEncoding; -import com.jd.blockchain.utils.io.BytesUtils; -import com.jd.blockchain.utils.io.NumberMask; - -public class BytesEncodingTest { - - @Test - public void testWriteAndRead() throws UnsupportedEncodingException { - // 针对正常数据的测试; - byte[] data = UUID.randomUUID().toString().getBytes("UTF-8"); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - int s = BytesEncoding.write(data, NumberMask.TINY, out); - - byte[] outBytes = out.toByteArray(); - assertEquals(outBytes.length, s); - assertEquals(data.length + 1, s); - - ByteArrayInputStream in = new ByteArrayInputStream(outBytes); - byte[] resovledBytes = BytesEncoding.read(NumberMask.TINY, in); - - assertTrue(BytesUtils.equals(data, resovledBytes)); - - // 针对 null 的测试; - data = null; - - out = new ByteArrayOutputStream(); - s = BytesEncoding.write(data, NumberMask.TINY, out); - - outBytes = out.toByteArray(); - assertEquals(outBytes.length, s); - assertEquals(1, s); - - in = new ByteArrayInputStream(outBytes); - resovledBytes = BytesEncoding.read(NumberMask.TINY, in); - - assertTrue(BytesUtils.equals(BytesUtils.EMPTY_BYTES, resovledBytes)); - } - - @Test - public void testWriteAndRead1() throws UnsupportedEncodingException { - // 针对正常数据的测试; - ByteArray data = ByteArray.parseString(UUID.randomUUID().toString(), "UTF-8"); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - int s = BytesEncoding.write(data, NumberMask.TINY, out); - - byte[] outBytes = out.toByteArray(); - assertEquals(outBytes.length, s); - assertEquals(data.size() + 1, s); - - ByteArrayInputStream in = new ByteArrayInputStream(outBytes); - byte[] resovledBytes = BytesEncoding.read(NumberMask.TINY, in); - - assertTrue(BytesUtils.equals(data.bytes(), resovledBytes)); - - // 针对 null 的测试; - data = null; - - out = new ByteArrayOutputStream(); - s = BytesEncoding.write(data, NumberMask.TINY, out); - - outBytes = out.toByteArray(); - assertEquals(outBytes.length, s); - assertEquals(1, s); - - in = new ByteArrayInputStream(outBytes); - resovledBytes = BytesEncoding.read(NumberMask.TINY, in); - - assertTrue(BytesUtils.equals(BytesUtils.EMPTY_BYTES, resovledBytes)); - } - -} +package test.my.utils.io; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.UnsupportedEncodingException; +import java.util.UUID; + +import org.junit.Test; + +import com.jd.blockchain.utils.io.ByteArray; +import com.jd.blockchain.utils.io.BytesEncoding; +import com.jd.blockchain.utils.io.BytesUtils; +import com.jd.blockchain.utils.io.NumberMask; + +public class BytesEncodingTest { + + @Test + public void testWriteAndRead() throws UnsupportedEncodingException { + // 针对正常数据的测试; + byte[] data = UUID.randomUUID().toString().getBytes("UTF-8"); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int s = BytesEncoding.write(data, NumberMask.TINY, out); + + byte[] outBytes = out.toByteArray(); + assertEquals(outBytes.length, s); + assertEquals(data.length + 1, s); + + ByteArrayInputStream in = new ByteArrayInputStream(outBytes); + byte[] resovledBytes = BytesEncoding.read(NumberMask.TINY, in); + + assertTrue(BytesUtils.equals(data, resovledBytes)); + + // 针对 null 的测试; + data = null; + + out = new ByteArrayOutputStream(); + s = BytesEncoding.write(data, NumberMask.TINY, out); + + outBytes = out.toByteArray(); + assertEquals(outBytes.length, s); + assertEquals(1, s); + + in = new ByteArrayInputStream(outBytes); + resovledBytes = BytesEncoding.read(NumberMask.TINY, in); + + assertTrue(BytesUtils.equals(BytesUtils.EMPTY_BYTES, resovledBytes)); + } + + @Test + public void testWriteAndRead1() throws UnsupportedEncodingException { + // 针对正常数据的测试; + ByteArray data = ByteArray.parseString(UUID.randomUUID().toString(), "UTF-8"); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int s = BytesEncoding.write(data, NumberMask.TINY, out); + + byte[] outBytes = out.toByteArray(); + assertEquals(outBytes.length, s); + assertEquals(data.size() + 1, s); + + ByteArrayInputStream in = new ByteArrayInputStream(outBytes); + byte[] resovledBytes = BytesEncoding.read(NumberMask.TINY, in); + + assertTrue(BytesUtils.equals(data.bytes(), resovledBytes)); + + // 针对 null 的测试; + data = null; + + out = new ByteArrayOutputStream(); + s = BytesEncoding.write(data, NumberMask.TINY, out); + + outBytes = out.toByteArray(); + assertEquals(outBytes.length, s); + assertEquals(1, s); + + in = new ByteArrayInputStream(outBytes); + resovledBytes = BytesEncoding.read(NumberMask.TINY, in); + + assertTrue(BytesUtils.equals(BytesUtils.EMPTY_BYTES, resovledBytes)); + } + +} diff --git a/source/utils/utils-common/src/test/java/test/my/utils/io/BytesUtilsTest.java b/source/utils/utils-common/src/test/java/test/my/utils/io/BytesUtilsTest.java index e3afd01b..5c246b3d 100644 --- a/source/utils/utils-common/src/test/java/test/my/utils/io/BytesUtilsTest.java +++ b/source/utils/utils-common/src/test/java/test/my/utils/io/BytesUtilsTest.java @@ -1,257 +1,257 @@ -package test.my.utils.io; - -import static org.junit.Assert.*; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.util.Random; - -import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; -import org.junit.Test; - -import com.jd.blockchain.utils.io.BytesUtils; - -public class BytesUtilsTest { - - @Test - public void testByteOutputInput() { - // 边界测试; - assertByteOutputInput((byte) 0); - assertByteOutputInput((byte) 1); - assertByteOutputInput((byte) -1); - assertByteOutputInput((byte) 128); - assertByteOutputInput((byte) 255); - assertByteOutputInput(Byte.MAX_VALUE); - assertByteOutputInput(Byte.MIN_VALUE); - - byte[] emptyBytes = {}; - ByteArrayInputStream emptyIn = new ByteArrayInputStream(emptyBytes); - Exception err = null; - try { - BytesUtils.readByte(emptyIn); - } catch (Exception e) { - err = e; - } - assertTrue(err != null); - } - - private void assertByteOutputInput(byte value) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - BytesUtils.writeByte(value, out); - byte[] bytes = out.toByteArray(); - assertEquals(bytes[0], value); - - ByteArrayInputStream in = new ByteArrayInputStream(bytes); - byte val1 = BytesUtils.readByte(in); - - assertEquals(value, val1); - } - - @Test - public void testIntegerToBytes() { - assertIntTest(0); - assertIntTest(Integer.MAX_VALUE); - assertIntTest(Integer.MIN_VALUE); - assertIntTest(255); - assertIntTest(256); - } - - private void assertIntTest(int i) { - byte[] bytes = BytesUtils.toBytes(i); - int reallyInt = BytesUtils.toInt(bytes); - assertEquals(i, reallyInt); - } - - @Test - public void testIntTestLowAlign() { - int n = 65535; - byte[] bytes = BytesUtils.toBytes(n); - int reallyInt = BytesUtils.toInt(bytes, 2, 2, false); - assertEquals(n, reallyInt); - - n = 0; - bytes = BytesUtils.toBytes(n); - reallyInt = BytesUtils.toInt(bytes, 2, 2, false); - assertEquals(n, reallyInt); - - n = 255; - bytes = BytesUtils.toBytes(n); - reallyInt = BytesUtils.toInt(bytes, 2, 2, false); - assertEquals(n, reallyInt); - - n = 256; - bytes = BytesUtils.toBytes(n); - reallyInt = BytesUtils.toInt(bytes, 2, 2, false); - assertEquals(n, reallyInt); - - n = 255; - bytes = BytesUtils.toBytes(n); - reallyInt = BytesUtils.toInt(bytes, 3, 1, false); - assertEquals(n, reallyInt); - - n = 16777215; - bytes = BytesUtils.toBytes(n); - reallyInt = BytesUtils.toInt(bytes, 1, 3, false); - assertEquals(n, reallyInt); - - n = 65535; - bytes = BytesUtils.toBytes(n); - reallyInt = BytesUtils.toInt(bytes, 1, 3, false); - assertEquals(n, reallyInt); - - n = 255; - bytes = BytesUtils.toBytes(n); - reallyInt = BytesUtils.toInt(bytes, 1, 3, false); - assertEquals(n, reallyInt); - - n = 0; - bytes = BytesUtils.toBytes(n); - reallyInt = BytesUtils.toInt(bytes, 1, 3, false); - assertEquals(n, reallyInt); - } - - @Test - public void testLongIntegerToBytes() { - assertLongTest(0); - assertLongTest(Integer.MAX_VALUE); - assertLongTest(Integer.MIN_VALUE); - assertLongTest(Long.MAX_VALUE); - assertLongTest(Long.MIN_VALUE); - assertLongTest(255); - assertLongTest(256); - } - - private void assertLongTest(long i) { - byte[] bytes = BytesUtils.toBytes(i); - long reallyInt = BytesUtils.toLong(bytes); - assertEquals(i, reallyInt); - } - - @Test - public void testIntegerByteCasting() { - testIntByteCasting(0); - testIntByteCasting(-1); - testIntByteCasting(1); - testIntByteCasting(255); - testIntByteCasting(256); - testIntByteCasting(Integer.MAX_VALUE); - testIntByteCasting(Integer.MIN_VALUE); - } - - private void testIntByteCasting(int v) { - byte b1 = (byte) (v & 0xFF); - byte b2 = (byte) v; - assertTrue(b1 == b2); - } - - @Test - public void testWriteByte() { - assertByteWriting((byte) 0); - assertByteWriting((byte) 128); - assertByteWriting((byte) 1); - assertByteWriting((byte) 0x0F); - assertByteWriting((byte) 0xF0); - assertByteWriting((byte) 255); - } - - private void assertByteWriting(byte bt) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - out.write(bt); - byte[] buff = out.toByteArray(); - assertEquals(bt, buff[0]); - - ByteArrayInputStream in = new ByteArrayInputStream(buff); - int val = in.read(); - byte btIn = (byte) (val & 0xFF); - byte btIn1 = (byte) (val); - - assertEquals(bt, btIn); - assertEquals(bt, btIn1); - } - - @Test - public void testShortCasting() { - doTestShortCasting((short) 0); - doTestShortCasting((short) -1); - doTestShortCasting((short) 1); - doTestShortCasting((short) 255); - doTestShortCasting((short) -255); - doTestShortCasting(Short.MIN_VALUE); - doTestShortCasting(Short.MAX_VALUE); - } - - private void doTestShortCasting(short value) { - byte[] bytes = BytesUtils.toBytes(value); - assertEquals(2, bytes.length); - - short deValue = BytesUtils.toShort(bytes, 0); - assertEquals(value, deValue); - } - - @Test - public void testConcatBytes() { - Random rand = new Random(); - byte[] bs1 = new byte[64]; - byte[] bs2 = new byte[0]; - byte[] bs3 = new byte[512]; - - rand.nextBytes(bs1); - rand.nextBytes(bs3); - - byte[] bsAll = BytesUtils.concat(bs1, bs2, bs3); - assertEquals(bs1.length + bs2.length + bs3.length, bsAll.length); - for (int i = 0; i < bs1.length; i++) { - assertEquals(bs1[i], bsAll[i]); - } - for (int i = 0; i < bs3.length; i++) { - assertEquals(bs3[i], bsAll[bs1.length + i]); - } - } - - @Test - public void testStreamingReadWrite() { - testStreamingReadWriteInt(0); - testStreamingReadWriteInt(1); - testStreamingReadWriteInt(2); - testStreamingReadWriteInt(256); - testStreamingReadWriteInt(128); - testStreamingReadWriteInt(-1); - testStreamingReadWriteInt(-128); - testStreamingReadWriteInt(Integer.MAX_VALUE); - testStreamingReadWriteInt(Integer.MIN_VALUE); - - testStreamingReadWriteLong(0); - testStreamingReadWriteLong(1); - testStreamingReadWriteLong(2); - testStreamingReadWriteLong(256); - testStreamingReadWriteLong(128); - testStreamingReadWriteLong(-1); - testStreamingReadWriteLong(-128); - testStreamingReadWriteLong(Integer.MAX_VALUE); - testStreamingReadWriteLong(Integer.MIN_VALUE); - testStreamingReadWriteLong(Long.MAX_VALUE); - testStreamingReadWriteLong(Long.MIN_VALUE); - } - - private void testStreamingReadWriteInt(int value) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - BytesUtils.writeInt(value, out); - byte[] bytes0 = BytesUtils.toBytes(value); - assertTrue(BytesUtils.equals(bytes0, out.toByteArray())); - - ByteArrayInputStream in = new ByteArrayInputStream(bytes0); - int v = BytesUtils.readInt(in); - assertEquals(value, v); - } - - private void testStreamingReadWriteLong(long value) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - BytesUtils.writeLong(value, out); - byte[] bytes0 = BytesUtils.toBytes(value); - assertTrue(BytesUtils.equals(bytes0, out.toByteArray())); - - ByteArrayInputStream in = new ByteArrayInputStream(bytes0); - long v = BytesUtils.readLong(in); - assertEquals(value, v); - } -} +package test.my.utils.io; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.Random; + +import org.bouncycastle.pqc.math.linearalgebra.ByteUtils; +import org.junit.Test; + +import com.jd.blockchain.utils.io.BytesUtils; + +public class BytesUtilsTest { + + @Test + public void testByteOutputInput() { + // 边界测试; + assertByteOutputInput((byte) 0); + assertByteOutputInput((byte) 1); + assertByteOutputInput((byte) -1); + assertByteOutputInput((byte) 128); + assertByteOutputInput((byte) 255); + assertByteOutputInput(Byte.MAX_VALUE); + assertByteOutputInput(Byte.MIN_VALUE); + + byte[] emptyBytes = {}; + ByteArrayInputStream emptyIn = new ByteArrayInputStream(emptyBytes); + Exception err = null; + try { + BytesUtils.readByte(emptyIn); + } catch (Exception e) { + err = e; + } + assertTrue(err != null); + } + + private void assertByteOutputInput(byte value) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BytesUtils.writeByte(value, out); + byte[] bytes = out.toByteArray(); + assertEquals(bytes[0], value); + + ByteArrayInputStream in = new ByteArrayInputStream(bytes); + byte val1 = BytesUtils.readByte(in); + + assertEquals(value, val1); + } + + @Test + public void testIntegerToBytes() { + assertIntTest(0); + assertIntTest(Integer.MAX_VALUE); + assertIntTest(Integer.MIN_VALUE); + assertIntTest(255); + assertIntTest(256); + } + + private void assertIntTest(int i) { + byte[] bytes = BytesUtils.toBytes(i); + int reallyInt = BytesUtils.toInt(bytes); + assertEquals(i, reallyInt); + } + + @Test + public void testIntTestLowAlign() { + int n = 65535; + byte[] bytes = BytesUtils.toBytes(n); + int reallyInt = BytesUtils.toInt(bytes, 2, 2, false); + assertEquals(n, reallyInt); + + n = 0; + bytes = BytesUtils.toBytes(n); + reallyInt = BytesUtils.toInt(bytes, 2, 2, false); + assertEquals(n, reallyInt); + + n = 255; + bytes = BytesUtils.toBytes(n); + reallyInt = BytesUtils.toInt(bytes, 2, 2, false); + assertEquals(n, reallyInt); + + n = 256; + bytes = BytesUtils.toBytes(n); + reallyInt = BytesUtils.toInt(bytes, 2, 2, false); + assertEquals(n, reallyInt); + + n = 255; + bytes = BytesUtils.toBytes(n); + reallyInt = BytesUtils.toInt(bytes, 3, 1, false); + assertEquals(n, reallyInt); + + n = 16777215; + bytes = BytesUtils.toBytes(n); + reallyInt = BytesUtils.toInt(bytes, 1, 3, false); + assertEquals(n, reallyInt); + + n = 65535; + bytes = BytesUtils.toBytes(n); + reallyInt = BytesUtils.toInt(bytes, 1, 3, false); + assertEquals(n, reallyInt); + + n = 255; + bytes = BytesUtils.toBytes(n); + reallyInt = BytesUtils.toInt(bytes, 1, 3, false); + assertEquals(n, reallyInt); + + n = 0; + bytes = BytesUtils.toBytes(n); + reallyInt = BytesUtils.toInt(bytes, 1, 3, false); + assertEquals(n, reallyInt); + } + + @Test + public void testLongIntegerToBytes() { + assertLongTest(0); + assertLongTest(Integer.MAX_VALUE); + assertLongTest(Integer.MIN_VALUE); + assertLongTest(Long.MAX_VALUE); + assertLongTest(Long.MIN_VALUE); + assertLongTest(255); + assertLongTest(256); + } + + private void assertLongTest(long i) { + byte[] bytes = BytesUtils.toBytes(i); + long reallyInt = BytesUtils.toLong(bytes); + assertEquals(i, reallyInt); + } + + @Test + public void testIntegerByteCasting() { + testIntByteCasting(0); + testIntByteCasting(-1); + testIntByteCasting(1); + testIntByteCasting(255); + testIntByteCasting(256); + testIntByteCasting(Integer.MAX_VALUE); + testIntByteCasting(Integer.MIN_VALUE); + } + + private void testIntByteCasting(int v) { + byte b1 = (byte) (v & 0xFF); + byte b2 = (byte) v; + assertTrue(b1 == b2); + } + + @Test + public void testWriteByte() { + assertByteWriting((byte) 0); + assertByteWriting((byte) 128); + assertByteWriting((byte) 1); + assertByteWriting((byte) 0x0F); + assertByteWriting((byte) 0xF0); + assertByteWriting((byte) 255); + } + + private void assertByteWriting(byte bt) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + out.write(bt); + byte[] buff = out.toByteArray(); + assertEquals(bt, buff[0]); + + ByteArrayInputStream in = new ByteArrayInputStream(buff); + int val = in.read(); + byte btIn = (byte) (val & 0xFF); + byte btIn1 = (byte) (val); + + assertEquals(bt, btIn); + assertEquals(bt, btIn1); + } + + @Test + public void testShortCasting() { + doTestShortCasting((short) 0); + doTestShortCasting((short) -1); + doTestShortCasting((short) 1); + doTestShortCasting((short) 255); + doTestShortCasting((short) -255); + doTestShortCasting(Short.MIN_VALUE); + doTestShortCasting(Short.MAX_VALUE); + } + + private void doTestShortCasting(short value) { + byte[] bytes = BytesUtils.toBytes(value); + assertEquals(2, bytes.length); + + short deValue = BytesUtils.toShort(bytes, 0); + assertEquals(value, deValue); + } + + @Test + public void testConcatBytes() { + Random rand = new Random(); + byte[] bs1 = new byte[64]; + byte[] bs2 = new byte[0]; + byte[] bs3 = new byte[512]; + + rand.nextBytes(bs1); + rand.nextBytes(bs3); + + byte[] bsAll = BytesUtils.concat(bs1, bs2, bs3); + assertEquals(bs1.length + bs2.length + bs3.length, bsAll.length); + for (int i = 0; i < bs1.length; i++) { + assertEquals(bs1[i], bsAll[i]); + } + for (int i = 0; i < bs3.length; i++) { + assertEquals(bs3[i], bsAll[bs1.length + i]); + } + } + + @Test + public void testStreamingReadWrite() { + testStreamingReadWriteInt(0); + testStreamingReadWriteInt(1); + testStreamingReadWriteInt(2); + testStreamingReadWriteInt(256); + testStreamingReadWriteInt(128); + testStreamingReadWriteInt(-1); + testStreamingReadWriteInt(-128); + testStreamingReadWriteInt(Integer.MAX_VALUE); + testStreamingReadWriteInt(Integer.MIN_VALUE); + + testStreamingReadWriteLong(0); + testStreamingReadWriteLong(1); + testStreamingReadWriteLong(2); + testStreamingReadWriteLong(256); + testStreamingReadWriteLong(128); + testStreamingReadWriteLong(-1); + testStreamingReadWriteLong(-128); + testStreamingReadWriteLong(Integer.MAX_VALUE); + testStreamingReadWriteLong(Integer.MIN_VALUE); + testStreamingReadWriteLong(Long.MAX_VALUE); + testStreamingReadWriteLong(Long.MIN_VALUE); + } + + private void testStreamingReadWriteInt(int value) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BytesUtils.writeInt(value, out); + byte[] bytes0 = BytesUtils.toBytes(value); + assertTrue(BytesUtils.equals(bytes0, out.toByteArray())); + + ByteArrayInputStream in = new ByteArrayInputStream(bytes0); + int v = BytesUtils.readInt(in); + assertEquals(value, v); + } + + private void testStreamingReadWriteLong(long value) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BytesUtils.writeLong(value, out); + byte[] bytes0 = BytesUtils.toBytes(value); + assertTrue(BytesUtils.equals(bytes0, out.toByteArray())); + + ByteArrayInputStream in = new ByteArrayInputStream(bytes0); + long v = BytesUtils.readLong(in); + assertEquals(value, v); + } +} diff --git a/source/utils/utils-common/src/test/java/test/my/utils/security/AESUtilsTest.java b/source/utils/utils-common/src/test/java/test/my/utils/security/AESUtilsTest.java index ee907916..01c6d6e0 100644 --- a/source/utils/utils-common/src/test/java/test/my/utils/security/AESUtilsTest.java +++ b/source/utils/utils-common/src/test/java/test/my/utils/security/AESUtilsTest.java @@ -1,153 +1,153 @@ -package test.my.utils.security; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; - -import java.io.UnsupportedEncodingException; -import java.util.Random; -import java.util.UUID; - -import org.junit.Test; - -import com.jd.blockchain.utils.codec.HexUtils; -import com.jd.blockchain.utils.io.BytesUtils; -import com.jd.blockchain.utils.security.AESUtils; -import com.jd.blockchain.utils.security.ShaUtils; - -public class AESUtilsTest { - - @Test - public void testAESKeyGeneration() throws UnsupportedEncodingException { - String seedStr = UUID.randomUUID().toString(); - byte[] seed = seedStr.getBytes("UTF-8"); - System.out.println("seed.lenght=" + seed.length); - - // 验证:同一个种子,生成的秘钥总是相同的; - String key1 = AESUtils.generateKey128_Hex(seed); - String key2 = AESUtils.generateKey128_Hex(seed); - String key3 = AESUtils.generateKey128_Hex(seed); - - assertEquals(key1, key2); - assertEquals(key1, key3); - - // 验证:不同的种子,生成的秘钥总是不同的; - byte[] seed2 = UUID.randomUUID().toString().getBytes("UTF-8"); - String newKey = AESUtils.generateKey128_Hex(seed2); - assertNotEquals(key1, newKey); - - // 验证:随机秘钥总是不同的; - String randomKey1 = AESUtils.generateKey128_Hex(); - String randomKey2 = AESUtils.generateKey128_Hex(); - String randomKey3 = AESUtils.generateKey128_Hex(); - assertNotEquals(randomKey1, randomKey2); - assertNotEquals(randomKey1, randomKey3); - assertNotEquals(randomKey2, randomKey3); - - // 验证:更长的种子也可以支持; - byte[] longSeed = (seedStr + seedStr + seedStr + seedStr).getBytes("UTF-8"); - System.out.println("longSeed.length=" + longSeed.length); - String keyFromLongSeed = AESUtils.generateKey128_Hex(longSeed); - String keyFromLongSeed2 = AESUtils.generateKey128_Hex(longSeed); - assertNotEquals(key1, keyFromLongSeed2); - assertEquals(keyFromLongSeed, keyFromLongSeed2); - - // 验证:对更长的种子进行 hash 后再生成 key; - byte[] hashSeed = ShaUtils.hash_256(longSeed); - System.out.println("hashSeed.length=" + hashSeed.length); - String keyFromHashSeed = AESUtils.generateKey128_Hex(hashSeed); - String keyFromHashSeed2 = AESUtils.generateKey128_Hex(hashSeed); - - assertNotEquals(key1, keyFromHashSeed); - assertNotEquals(keyFromLongSeed, keyFromHashSeed); - assertEquals(keyFromHashSeed, keyFromHashSeed2); - } - - @Test - public void testAESEncryptionWithRandomKey() throws UnsupportedEncodingException { - String keyString = AESUtils.generateKey128_Hex(); - - byte[] origBytes = UUID.randomUUID().toString().getBytes("UTF-8"); - - byte[] enBytes = AESUtils.encrypt(origBytes, keyString); - byte[] deBytes = AESUtils.decrypt(enBytes, keyString); - - assertEquals(origBytes.length, deBytes.length); - for (int i = 0; i < origBytes.length; i++) { - assertEquals(origBytes[i], deBytes[i]); - } - } - - /** - * 根据同一个 seed 生成的秘钥,能够加密,并解密恢复原始内容; - * - * @throws UnsupportedEncodingException - */ - @Test - public void testAESEncryptionWithSeed() throws UnsupportedEncodingException { - byte[] seed = UUID.randomUUID().toString().getBytes("UTF-8"); - byte[] encryptedKey = AESUtils.generateKey128_Bytes(seed); - - byte[] plainBytes = UUID.randomUUID().toString().getBytes("UTF-8"); - String plainContent = HexUtils.encode(plainBytes); - byte[] encryptedBytes = AESUtils.encrypt(plainBytes, encryptedKey); - - byte[] decryptedKey = AESUtils.generateKey128_Bytes(seed); - byte[] decryptedBytes = AESUtils.decrypt(encryptedBytes, decryptedKey); - String decryptedContent = HexUtils.encode(decryptedBytes); - - assertEquals(plainContent, decryptedContent); - } - - @Test - public void testAESEnryptionConsistance() throws UnsupportedEncodingException { - byte[] seed = UUID.randomUUID().toString().getBytes("UTF-8"); - byte[] encryptedKey = AESUtils.generateKey128_Bytes(seed); - - byte[] plainBytes = UUID.randomUUID().toString().getBytes("UTF-8"); - - byte[] encryptedBytes = AESUtils.encrypt(plainBytes, encryptedKey); - byte[] encryptedBytes1 = AESUtils.encrypt(plainBytes, encryptedKey); - byte[] encryptedBytes2 = AESUtils.encrypt(plainBytes, encryptedKey); - byte[] encryptedBytes3 = AESUtils.encrypt(plainBytes, encryptedKey); - - assertTrue(BytesUtils.equals(encryptedBytes, encryptedBytes1)); - assertTrue(BytesUtils.equals(encryptedBytes1, encryptedBytes2)); - assertTrue(BytesUtils.equals(encryptedBytes2, encryptedBytes3)); - } - - /** - * 测试对任意长度的明文数据进行加解密的正确性; - */ - @Test - public void testLongBytes() { - testLongBytes_128(101); - testLongBytes_128(171); - testLongBytes_128(1023); - testLongBytes_128(1024); - testLongBytes_128(1025); - } - - /** - * 测试在 128 长度密码下对任意长度的输入进行加密解密的正确性; - * @param size - */ - private void testLongBytes_128(int size) { - byte[] data = new byte[size]; - Random rand = new Random(); - rand.nextBytes(data); - - System.out.println("(" + size + ")Bytes data=[" + HexUtils.encode(data) + "]"); - - byte[] key = AESUtils.generateKey128_Bytes(); - - byte[] encData = AESUtils.encrypt(data, key); - - byte[] decData = AESUtils.decrypt(encData, key); - - assertTrue(BytesUtils.equals(data, decData)); - } - - - -} +package test.my.utils.security; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.io.UnsupportedEncodingException; +import java.util.Random; +import java.util.UUID; + +import org.junit.Test; + +import com.jd.blockchain.utils.codec.HexUtils; +import com.jd.blockchain.utils.io.BytesUtils; +import com.jd.blockchain.utils.security.AESUtils; +import com.jd.blockchain.utils.security.ShaUtils; + +public class AESUtilsTest { + + @Test + public void testAESKeyGeneration() throws UnsupportedEncodingException { + String seedStr = UUID.randomUUID().toString(); + byte[] seed = seedStr.getBytes("UTF-8"); + System.out.println("seed.lenght=" + seed.length); + + // 验证:同一个种子,生成的秘钥总是相同的; + String key1 = AESUtils.generateKey128_Hex(seed); + String key2 = AESUtils.generateKey128_Hex(seed); + String key3 = AESUtils.generateKey128_Hex(seed); + + assertEquals(key1, key2); + assertEquals(key1, key3); + + // 验证:不同的种子,生成的秘钥总是不同的; + byte[] seed2 = UUID.randomUUID().toString().getBytes("UTF-8"); + String newKey = AESUtils.generateKey128_Hex(seed2); + assertNotEquals(key1, newKey); + + // 验证:随机秘钥总是不同的; + String randomKey1 = AESUtils.generateKey128_Hex(); + String randomKey2 = AESUtils.generateKey128_Hex(); + String randomKey3 = AESUtils.generateKey128_Hex(); + assertNotEquals(randomKey1, randomKey2); + assertNotEquals(randomKey1, randomKey3); + assertNotEquals(randomKey2, randomKey3); + + // 验证:更长的种子也可以支持; + byte[] longSeed = (seedStr + seedStr + seedStr + seedStr).getBytes("UTF-8"); + System.out.println("longSeed.length=" + longSeed.length); + String keyFromLongSeed = AESUtils.generateKey128_Hex(longSeed); + String keyFromLongSeed2 = AESUtils.generateKey128_Hex(longSeed); + assertNotEquals(key1, keyFromLongSeed2); + assertEquals(keyFromLongSeed, keyFromLongSeed2); + + // 验证:对更长的种子进行 hash 后再生成 key; + byte[] hashSeed = ShaUtils.hash_256(longSeed); + System.out.println("hashSeed.length=" + hashSeed.length); + String keyFromHashSeed = AESUtils.generateKey128_Hex(hashSeed); + String keyFromHashSeed2 = AESUtils.generateKey128_Hex(hashSeed); + + assertNotEquals(key1, keyFromHashSeed); + assertNotEquals(keyFromLongSeed, keyFromHashSeed); + assertEquals(keyFromHashSeed, keyFromHashSeed2); + } + + @Test + public void testAESEncryptionWithRandomKey() throws UnsupportedEncodingException { + String keyString = AESUtils.generateKey128_Hex(); + + byte[] origBytes = UUID.randomUUID().toString().getBytes("UTF-8"); + + byte[] enBytes = AESUtils.encrypt(origBytes, keyString); + byte[] deBytes = AESUtils.decrypt(enBytes, keyString); + + assertEquals(origBytes.length, deBytes.length); + for (int i = 0; i < origBytes.length; i++) { + assertEquals(origBytes[i], deBytes[i]); + } + } + + /** + * 根据同一个 seed 生成的秘钥,能够加密,并解密恢复原始内容; + * + * @throws UnsupportedEncodingException + */ + @Test + public void testAESEncryptionWithSeed() throws UnsupportedEncodingException { + byte[] seed = UUID.randomUUID().toString().getBytes("UTF-8"); + byte[] encryptedKey = AESUtils.generateKey128_Bytes(seed); + + byte[] plainBytes = UUID.randomUUID().toString().getBytes("UTF-8"); + String plainContent = HexUtils.encode(plainBytes); + byte[] encryptedBytes = AESUtils.encrypt(plainBytes, encryptedKey); + + byte[] decryptedKey = AESUtils.generateKey128_Bytes(seed); + byte[] decryptedBytes = AESUtils.decrypt(encryptedBytes, decryptedKey); + String decryptedContent = HexUtils.encode(decryptedBytes); + + assertEquals(plainContent, decryptedContent); + } + + @Test + public void testAESEnryptionConsistance() throws UnsupportedEncodingException { + byte[] seed = UUID.randomUUID().toString().getBytes("UTF-8"); + byte[] encryptedKey = AESUtils.generateKey128_Bytes(seed); + + byte[] plainBytes = UUID.randomUUID().toString().getBytes("UTF-8"); + + byte[] encryptedBytes = AESUtils.encrypt(plainBytes, encryptedKey); + byte[] encryptedBytes1 = AESUtils.encrypt(plainBytes, encryptedKey); + byte[] encryptedBytes2 = AESUtils.encrypt(plainBytes, encryptedKey); + byte[] encryptedBytes3 = AESUtils.encrypt(plainBytes, encryptedKey); + + assertTrue(BytesUtils.equals(encryptedBytes, encryptedBytes1)); + assertTrue(BytesUtils.equals(encryptedBytes1, encryptedBytes2)); + assertTrue(BytesUtils.equals(encryptedBytes2, encryptedBytes3)); + } + + /** + * 测试对任意长度的明文数据进行加解密的正确性; + */ + @Test + public void testLongBytes() { + testLongBytes_128(101); + testLongBytes_128(171); + testLongBytes_128(1023); + testLongBytes_128(1024); + testLongBytes_128(1025); + } + + /** + * 测试在 128 长度密码下对任意长度的输入进行加密解密的正确性; + * @param size + */ + private void testLongBytes_128(int size) { + byte[] data = new byte[size]; + Random rand = new Random(); + rand.nextBytes(data); + + System.out.println("(" + size + ")Bytes data=[" + HexUtils.encode(data) + "]"); + + byte[] key = AESUtils.generateKey128_Bytes(); + + byte[] encData = AESUtils.encrypt(data, key); + + byte[] decData = AESUtils.decrypt(encData, key); + + assertTrue(BytesUtils.equals(data, decData)); + } + + + +} diff --git a/source/utils/utils-common/src/test/java/test/my/utils/security/RSAUtilsTest.java b/source/utils/utils-common/src/test/java/test/my/utils/security/RSAUtilsTest.java index 216fc50e..1397b5f2 100644 --- a/source/utils/utils-common/src/test/java/test/my/utils/security/RSAUtilsTest.java +++ b/source/utils/utils-common/src/test/java/test/my/utils/security/RSAUtilsTest.java @@ -1,88 +1,88 @@ -package test.my.utils.security; - -import static com.jd.blockchain.utils.security.RSAUtils.ALG_RSA; -import static org.junit.Assert.*; - -import java.io.UnsupportedEncodingException; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; -import java.util.UUID; - -import org.bouncycastle.util.encoders.Base64; -import org.bouncycastle.util.encoders.Hex; -import org.junit.Test; - -import com.jd.blockchain.utils.codec.HexUtils; -import com.jd.blockchain.utils.security.AESUtils; -import com.jd.blockchain.utils.security.RSAKeyPair; -import com.jd.blockchain.utils.security.RSAUtils; - -public class RSAUtilsTest { - - @Test - public void testEncription() throws UnsupportedEncodingException { - // 测试:公钥加密,私钥解密; - RSAKeyPair keyPair = RSAUtils.generateKey512(); - System.out.println("New-PUB-KEY=" + keyPair.getPublicKey_Base58()); - System.out.println("New-PRIV-KEY=" + keyPair.getPrivateKey_Base58()); - - String content = UUID.randomUUID().toString(); - byte[] contentBytes = content.getBytes("UTF-8"); - - System.out.println("要加密的数据长度:" + contentBytes.length); - byte[] enContentBytes = RSAUtils.encryptByPublicKey_Base58(contentBytes, keyPair.getPublicKey_Base58()); - - byte[] deContentBytes = RSAUtils.decryptByPrivateKey_Base58(enContentBytes, keyPair.getPrivateKey_Base58()); - String deContent = new String(deContentBytes, "UTF-8"); - - assertEquals(content, deContent); - } - - public static final String PUB_KEY = "rbanryFCC6yJnCRCQgVWyYXvqkSBz4k8KgpbVavFUopm6EcXY7217hqU7sa5iEvG2RbYUqcswYvdVikJqWADXNh6XDs1AB6MWHdhNrh4ha7rAVfDM6H9ho3KxHWXKSAc"; - - public static final String PRIV_KEY = "2YxGPrDW2hwdAfrXymm5pJb1ftXzKmPqYBqYdgQWAcBRzMk8nDM7sGeDf3cJZEQaremdVbfQqUrhRtz2MV31TX8qABm3ChTsszGUmoxvybJPaVd513adZwLyo54NS1GuyLxPyD2N32uqYnKtKojTrxfWZmoLpACmoqhMzt68Sn69ULd84j24tt8VBpSWEH1Xsr9hCtBB65HT3f6FH5X5HYMU6ueaPrx8Sh4zFiEW5eLM4xJEPLjf3iaWatN9YV9QPeyvavicNYCtmJWQ6sv13xKR9DscWVJ61EjSxTQQMQe1sA9Anewjmk1bRUbnoKebM2kaGK9Q3Gg7qx8QwoAvRfPP9A6pyUPPaE33WuKDKZ2QPzYQ531TXJA8hYwnCvfcixp3cJqGtFNEkhBu7H4DSqchnWfVJ62HJFBB2L96Fxkiudyqh8ejjsweWVKPw1aYoNzreEnRpMHsLoxAN6eRFA3NV"; - - public static final String DATA_HEX = "f61610cba4c92c268a2bd73e963a270b"; - - public static final String CHIPER_DATA = "b127ffbbf6d570cea43aba7494bf04e1d1263d130b922cde32d558de3fdd88f2c205ba8151fdfcae7bb5c075fad10524cfde89b6b3be4ad8b2fb0db38901ea9c"; - - @Test - public void testEncryptAndDecrypt() { - byte[] contentBytes = HexUtils.decode(DATA_HEX); - System.out.println("要加密的数据长度:" + contentBytes.length); - - byte[] enContentBytes = RSAUtils.encryptByPublicKey_Base58(contentBytes, PUB_KEY); - System.out.println("CHIPER-DATA=[" + HexUtils.encode(enContentBytes) + "]"); - - byte[] deContentBytes = RSAUtils.decryptByPrivateKey_Base58(enContentBytes, PRIV_KEY); - String deContent = HexUtils.encode(deContentBytes); - System.out.println("DECRYPT-DATA=[" + HexUtils.encode(enContentBytes) + "]"); - - assertEquals(DATA_HEX, deContent); - - } - - @Test - public void generateKeyPairTest() throws NoSuchAlgorithmException { - KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); - keyPairGen.initialize(2048, new SecureRandom()); - KeyPair keyPair = keyPairGen.generateKeyPair(); - RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); - RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); - - byte[] pubKey = publicKey.getEncoded(); - byte[] privKey = privateKey.getEncoded(); - - System.out.println(Base64.toBase64String(pubKey)); - System.out.println(Base64.toBase64String(privKey)); - - System.out.println(Hex.toHexString(pubKey)); - System.out.println(Hex.toHexString(privKey)); - - } - -} +package test.my.utils.security; + +import static com.jd.blockchain.utils.security.RSAUtils.ALG_RSA; +import static org.junit.Assert.*; + +import java.io.UnsupportedEncodingException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.util.UUID; + +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.encoders.Hex; +import org.junit.Test; + +import com.jd.blockchain.utils.codec.HexUtils; +import com.jd.blockchain.utils.security.AESUtils; +import com.jd.blockchain.utils.security.RSAKeyPair; +import com.jd.blockchain.utils.security.RSAUtils; + +public class RSAUtilsTest { + + @Test + public void testEncription() throws UnsupportedEncodingException { + // 测试:公钥加密,私钥解密; + RSAKeyPair keyPair = RSAUtils.generateKey512(); + System.out.println("New-PUB-KEY=" + keyPair.getPublicKey_Base58()); + System.out.println("New-PRIV-KEY=" + keyPair.getPrivateKey_Base58()); + + String content = UUID.randomUUID().toString(); + byte[] contentBytes = content.getBytes("UTF-8"); + + System.out.println("要加密的数据长度:" + contentBytes.length); + byte[] enContentBytes = RSAUtils.encryptByPublicKey_Base58(contentBytes, keyPair.getPublicKey_Base58()); + + byte[] deContentBytes = RSAUtils.decryptByPrivateKey_Base58(enContentBytes, keyPair.getPrivateKey_Base58()); + String deContent = new String(deContentBytes, "UTF-8"); + + assertEquals(content, deContent); + } + + public static final String PUB_KEY = "rbanryFCC6yJnCRCQgVWyYXvqkSBz4k8KgpbVavFUopm6EcXY7217hqU7sa5iEvG2RbYUqcswYvdVikJqWADXNh6XDs1AB6MWHdhNrh4ha7rAVfDM6H9ho3KxHWXKSAc"; + + public static final String PRIV_KEY = "2YxGPrDW2hwdAfrXymm5pJb1ftXzKmPqYBqYdgQWAcBRzMk8nDM7sGeDf3cJZEQaremdVbfQqUrhRtz2MV31TX8qABm3ChTsszGUmoxvybJPaVd513adZwLyo54NS1GuyLxPyD2N32uqYnKtKojTrxfWZmoLpACmoqhMzt68Sn69ULd84j24tt8VBpSWEH1Xsr9hCtBB65HT3f6FH5X5HYMU6ueaPrx8Sh4zFiEW5eLM4xJEPLjf3iaWatN9YV9QPeyvavicNYCtmJWQ6sv13xKR9DscWVJ61EjSxTQQMQe1sA9Anewjmk1bRUbnoKebM2kaGK9Q3Gg7qx8QwoAvRfPP9A6pyUPPaE33WuKDKZ2QPzYQ531TXJA8hYwnCvfcixp3cJqGtFNEkhBu7H4DSqchnWfVJ62HJFBB2L96Fxkiudyqh8ejjsweWVKPw1aYoNzreEnRpMHsLoxAN6eRFA3NV"; + + public static final String DATA_HEX = "f61610cba4c92c268a2bd73e963a270b"; + + public static final String CHIPER_DATA = "b127ffbbf6d570cea43aba7494bf04e1d1263d130b922cde32d558de3fdd88f2c205ba8151fdfcae7bb5c075fad10524cfde89b6b3be4ad8b2fb0db38901ea9c"; + + @Test + public void testEncryptAndDecrypt() { + byte[] contentBytes = HexUtils.decode(DATA_HEX); + System.out.println("要加密的数据长度:" + contentBytes.length); + + byte[] enContentBytes = RSAUtils.encryptByPublicKey_Base58(contentBytes, PUB_KEY); + System.out.println("CHIPER-DATA=[" + HexUtils.encode(enContentBytes) + "]"); + + byte[] deContentBytes = RSAUtils.decryptByPrivateKey_Base58(enContentBytes, PRIV_KEY); + String deContent = HexUtils.encode(deContentBytes); + System.out.println("DECRYPT-DATA=[" + HexUtils.encode(enContentBytes) + "]"); + + assertEquals(DATA_HEX, deContent); + + } + + @Test + public void generateKeyPairTest() throws NoSuchAlgorithmException { + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); + keyPairGen.initialize(2048, new SecureRandom()); + KeyPair keyPair = keyPairGen.generateKeyPair(); + RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); + + byte[] pubKey = publicKey.getEncoded(); + byte[] privKey = privateKey.getEncoded(); + + System.out.println(Base64.toBase64String(pubKey)); + System.out.println(Base64.toBase64String(privKey)); + + System.out.println(Hex.toHexString(pubKey)); + System.out.println(Hex.toHexString(privKey)); + + } + +} diff --git a/source/utils/utils-common/src/test/java/test/my/utils/security/RandomUtilsTest.java b/source/utils/utils-common/src/test/java/test/my/utils/security/RandomUtilsTest.java index f226cc17..597fd6d8 100644 --- a/source/utils/utils-common/src/test/java/test/my/utils/security/RandomUtilsTest.java +++ b/source/utils/utils-common/src/test/java/test/my/utils/security/RandomUtilsTest.java @@ -1,51 +1,51 @@ -package test.my.utils.security; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.UnsupportedEncodingException; -import java.util.UUID; - -import org.junit.Test; - -import com.jd.blockchain.utils.security.RandomUtils; - -public class RandomUtilsTest { - - @Test - public void testGenerateRandomBytesWithDifferntSeed() throws UnsupportedEncodingException { - String seedStr = UUID.randomUUID().toString(); - byte[] seed = seedStr.getBytes("UTF-8"); - String seedStr2 = UUID.randomUUID().toString(); - byte[] seed2 = seedStr2.getBytes("UTF-8"); - System.out.println("seed.lenght=" + seed.length); - - byte[] random1 = RandomUtils.generateRandomBytes(16, seed); - byte[] random2 = RandomUtils.generateRandomBytes(16, seed2); - - assertNoEqualBytes(random1, random2); - - random1 = RandomUtils.generateRandomBytes(32, seed); - random2 = RandomUtils.generateRandomBytes(32, seed2); - - assertNoEqualBytes(random1, random2); - - random1 = RandomUtils.generateRandomBytes(64, seed); - random2 = RandomUtils.generateRandomBytes(64, seed2); - - assertNoEqualBytes(random1, random2); - } - - private void assertNoEqualBytes(byte[] random1, byte[] random2) { - boolean notEqual = random1.length != random2.length; - assertEquals(random1.length, random2.length); - for (int i = 0; i < random1.length; i++) { - notEqual = notEqual | (random1[i] != random2[i]); - if (notEqual) { - break; - } - } - assertTrue(notEqual); - } - -} +package test.my.utils.security; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.UnsupportedEncodingException; +import java.util.UUID; + +import org.junit.Test; + +import com.jd.blockchain.utils.security.RandomUtils; + +public class RandomUtilsTest { + + @Test + public void testGenerateRandomBytesWithDifferntSeed() throws UnsupportedEncodingException { + String seedStr = UUID.randomUUID().toString(); + byte[] seed = seedStr.getBytes("UTF-8"); + String seedStr2 = UUID.randomUUID().toString(); + byte[] seed2 = seedStr2.getBytes("UTF-8"); + System.out.println("seed.lenght=" + seed.length); + + byte[] random1 = RandomUtils.generateRandomBytes(16, seed); + byte[] random2 = RandomUtils.generateRandomBytes(16, seed2); + + assertNoEqualBytes(random1, random2); + + random1 = RandomUtils.generateRandomBytes(32, seed); + random2 = RandomUtils.generateRandomBytes(32, seed2); + + assertNoEqualBytes(random1, random2); + + random1 = RandomUtils.generateRandomBytes(64, seed); + random2 = RandomUtils.generateRandomBytes(64, seed2); + + assertNoEqualBytes(random1, random2); + } + + private void assertNoEqualBytes(byte[] random1, byte[] random2) { + boolean notEqual = random1.length != random2.length; + assertEquals(random1.length, random2.length); + for (int i = 0; i < random1.length; i++) { + notEqual = notEqual | (random1[i] != random2[i]); + if (notEqual) { + break; + } + } + assertTrue(notEqual); + } + +} diff --git a/source/utils/utils-common/src/test/java/test/my/utils/security/ShaUtilsTest.java b/source/utils/utils-common/src/test/java/test/my/utils/security/ShaUtilsTest.java index dfd6cf3b..6235fdda 100644 --- a/source/utils/utils-common/src/test/java/test/my/utils/security/ShaUtilsTest.java +++ b/source/utils/utils-common/src/test/java/test/my/utils/security/ShaUtilsTest.java @@ -1,102 +1,102 @@ -package test.my.utils.security; - -import static org.junit.Assert.*; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Random; -import java.util.UUID; - -import org.junit.Test; - -import com.jd.blockchain.utils.security.RandomUtils; -import com.jd.blockchain.utils.security.ShaUtils; - -public class ShaUtilsTest { - -// @Test -// public void testHash_128() throws UnsupportedEncodingException { -// String text = "the text with fixed size"; -// byte[] hashBytes = ShaUtils.hash_128(text.getBytes("UTF-8")); -// assertEquals(16, hashBytes.length); -// -// text = UUID.randomUUID().toString(); -// hashBytes = ShaUtils.hash_128(text.getBytes("UTF-8")); -// assertEquals(16, hashBytes.length); -// -// StringBuilder bigText = new StringBuilder(); -// for (int i = 0; i < 256; i++) { -// bigText.append((char)(97+(i% 20))); -// } -// hashBytes = ShaUtils.hash_128(bigText.toString().getBytes("UTF-8")); -// assertEquals(16, hashBytes.length); -// } - - @Test - public void testHash_256ByteArray() throws UnsupportedEncodingException { - String text = "the text with fixed size"; - byte[] hashBytes = ShaUtils.hash_256(text.getBytes("UTF-8")); - assertEquals(32, hashBytes.length); - - text = UUID.randomUUID().toString(); - hashBytes = ShaUtils.hash_256(text.getBytes("UTF-8")); - assertEquals(32, hashBytes.length); - - StringBuilder bigText = new StringBuilder(); - for (int i = 0; i < 512; i++) { - bigText.append((char)(97+(i% 20))); - } - hashBytes = ShaUtils.hash_256(bigText.toString().getBytes("UTF-8")); - assertEquals(32, hashBytes.length); - } - - - /** - * 验证采用不同的缓存数组大小进行 hash 计算是否会影响其计算结果;
- * - * 注:显然,算法本身的效果是不会受算法调用方式的影响的;测试的结果也表明这一点; - */ - @Test - public void testHash_256_withDiffBuffSize() { - byte[] randBytes = RandomUtils.generateRandomBytes(256); - - ByteArrayInputStream in = new ByteArrayInputStream(randBytes); - byte[] hash1 = hash_256(in, 32); - - in = new ByteArrayInputStream(randBytes); - byte[] hash2 = hash_256(in, 32); - - in = new ByteArrayInputStream(randBytes); - byte[] hash3 = hash_256(in, 64); - - in = new ByteArrayInputStream(randBytes); - byte[] hash4 = hash_256(in, 128); - - assertArrayEquals(hash1, hash2); - assertArrayEquals(hash1, hash3); - assertArrayEquals(hash1, hash4); - } - - - private static byte[] hash_256(InputStream input, int buffSize) { - MessageDigest md = null; - try { - md = MessageDigest.getInstance("SHA-256"); - byte[] buff =new byte[buffSize]; - int len = 0; - while((len=input.read(buff)) > 0){ - md.update(buff, 0, len); - } - return md.digest(); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException(e.getMessage(), e); - } catch (IOException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } -} +package test.my.utils.security; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Random; +import java.util.UUID; + +import org.junit.Test; + +import com.jd.blockchain.utils.security.RandomUtils; +import com.jd.blockchain.utils.security.ShaUtils; + +public class ShaUtilsTest { + +// @Test +// public void testHash_128() throws UnsupportedEncodingException { +// String text = "the text with fixed size"; +// byte[] hashBytes = ShaUtils.hash_128(text.getBytes("UTF-8")); +// assertEquals(16, hashBytes.length); +// +// text = UUID.randomUUID().toString(); +// hashBytes = ShaUtils.hash_128(text.getBytes("UTF-8")); +// assertEquals(16, hashBytes.length); +// +// StringBuilder bigText = new StringBuilder(); +// for (int i = 0; i < 256; i++) { +// bigText.append((char)(97+(i% 20))); +// } +// hashBytes = ShaUtils.hash_128(bigText.toString().getBytes("UTF-8")); +// assertEquals(16, hashBytes.length); +// } + + @Test + public void testHash_256ByteArray() throws UnsupportedEncodingException { + String text = "the text with fixed size"; + byte[] hashBytes = ShaUtils.hash_256(text.getBytes("UTF-8")); + assertEquals(32, hashBytes.length); + + text = UUID.randomUUID().toString(); + hashBytes = ShaUtils.hash_256(text.getBytes("UTF-8")); + assertEquals(32, hashBytes.length); + + StringBuilder bigText = new StringBuilder(); + for (int i = 0; i < 512; i++) { + bigText.append((char)(97+(i% 20))); + } + hashBytes = ShaUtils.hash_256(bigText.toString().getBytes("UTF-8")); + assertEquals(32, hashBytes.length); + } + + + /** + * 验证采用不同的缓存数组大小进行 hash 计算是否会影响其计算结果;
+ * + * 注:显然,算法本身的效果是不会受算法调用方式的影响的;测试的结果也表明这一点; + */ + @Test + public void testHash_256_withDiffBuffSize() { + byte[] randBytes = RandomUtils.generateRandomBytes(256); + + ByteArrayInputStream in = new ByteArrayInputStream(randBytes); + byte[] hash1 = hash_256(in, 32); + + in = new ByteArrayInputStream(randBytes); + byte[] hash2 = hash_256(in, 32); + + in = new ByteArrayInputStream(randBytes); + byte[] hash3 = hash_256(in, 64); + + in = new ByteArrayInputStream(randBytes); + byte[] hash4 = hash_256(in, 128); + + assertArrayEquals(hash1, hash2); + assertArrayEquals(hash1, hash3); + assertArrayEquals(hash1, hash4); + } + + + private static byte[] hash_256(InputStream input, int buffSize) { + MessageDigest md = null; + try { + md = MessageDigest.getInstance("SHA-256"); + byte[] buff =new byte[buffSize]; + int len = 0; + while((len=input.read(buff)) > 0){ + md.update(buff, 0, len); + } + return md.digest(); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e.getMessage(), e); + } catch (IOException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } +} diff --git a/source/utils/utils-http/.gitignore b/source/utils/utils-http/.gitignore index 24d64373..b83d2226 100644 --- a/source/utils/utils-http/.gitignore +++ b/source/utils/utils-http/.gitignore @@ -1 +1 @@ -/target/ +/target/ diff --git a/source/utils/utils-http/pom.xml b/source/utils/utils-http/pom.xml index 5f6236f4..c8abb380 100644 --- a/source/utils/utils-http/pom.xml +++ b/source/utils/utils-http/pom.xml @@ -1,76 +1,76 @@ - - 4.0.0 - - com.jd.blockchain - utils - 1.1.2.RELEASE - - - - 0.5.0-SNAPSHOT - 0.5.0-SNAPSHOT - - - utils-http - - - com.jd.blockchain - utils-common - ${project.version} - - - com.jd.blockchain - utils-serialize - ${project.version} - - - com.jd.blockchain - utils-web-server - test - ${project.version} - - - - org.apache.httpcomponents - httpclient - - - org.springframework - spring-core - - - org.springframework - spring-beans - - - org.springframework.boot - spring-boot-starter-log4j2 - test - - - - - - - + + 4.0.0 + + com.jd.blockchain + utils + 1.1.2.RELEASE + + + + 0.5.0-SNAPSHOT + 0.5.0-SNAPSHOT + + + utils-http + + + com.jd.blockchain + utils-common + ${project.version} + + + com.jd.blockchain + utils-serialize + ${project.version} + + + com.jd.blockchain + utils-web-server + test + ${project.version} + + + + org.apache.httpcomponents + httpclient + + + org.springframework + spring-core + + + org.springframework + spring-beans + + + org.springframework.boot + spring-boot-starter-log4j2 + test + + + + + + + diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpAction.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpAction.java index aae7edcf..a2f5ce08 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpAction.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpAction.java @@ -1,66 +1,66 @@ -package com.jd.blockchain.utils.http; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * HTTP 服务方法; - * - * @author haiq - * - */ -@Target({ ElementType.METHOD }) -@Retention(RetentionPolicy.RUNTIME) -public @interface HttpAction { - - /** - * 请求路径; - * - * 默认为空; - * - * 此时按照 service 的 path 属性+方法名 产生最终的请求路径; - * - * @return - */ - public String path() default ""; - - /** - * HTTP 请求方法; - * - * @return - */ - public HttpMethod method(); - - /** - * HTTP 的 Content-Type; - * @return - */ - public String contentType() default ""; - - - - /** - * 自定义的返回值转换器;必须实现 RequestParamFilter 接口; - * - * @return - */ - public Class requestParamFilter() default RequestParamFilter.class; - - /** - * 自定义的返回值转换器;必须实现 ResponseConverter 接口; - * - * @return - */ - public Class responseConverter() default ResponseConverter.class; - - /** - * 当检测到 http 错误时是否在引发的 HttpStatusException 中包含回复的内容; - * - * 默认为 false; - * - * @return - */ - public boolean resolveContentOnHttpError() default false; -} +package com.jd.blockchain.utils.http; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * HTTP 服务方法; + * + * @author haiq + * + */ +@Target({ ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface HttpAction { + + /** + * 请求路径; + * + * 默认为空; + * + * 此时按照 service 的 path 属性+方法名 产生最终的请求路径; + * + * @return + */ + public String path() default ""; + + /** + * HTTP 请求方法; + * + * @return + */ + public HttpMethod method(); + + /** + * HTTP 的 Content-Type; + * @return + */ + public String contentType() default ""; + + + + /** + * 自定义的返回值转换器;必须实现 RequestParamFilter 接口; + * + * @return + */ + public Class requestParamFilter() default RequestParamFilter.class; + + /** + * 自定义的返回值转换器;必须实现 ResponseConverter 接口; + * + * @return + */ + public Class responseConverter() default ResponseConverter.class; + + /** + * 当检测到 http 错误时是否在引发的 HttpStatusException 中包含回复的内容; + * + * 默认为 false; + * + * @return + */ + public boolean resolveContentOnHttpError() default false; +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpMethod.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpMethod.java index 820ca410..aaefd4fb 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpMethod.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpMethod.java @@ -1,19 +1,19 @@ -package com.jd.blockchain.utils.http; - -/** - * HTTP 请求方法; - * - * @author haiq - * - */ -public enum HttpMethod { - - GET, - - POST, - - PUT, - - DELETE - -} +package com.jd.blockchain.utils.http; + +/** + * HTTP 请求方法; + * + * @author haiq + * + */ +public enum HttpMethod { + + GET, + + POST, + + PUT, + + DELETE + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpService.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpService.java index e4bbe2e2..7fe84659 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpService.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpService.java @@ -1,50 +1,50 @@ -package com.jd.blockchain.utils.http; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -public @interface HttpService { - - /** - * 服务的路径; - *
- * 它是所有服务方法的根路径,默认为 /; - * - * @return - */ - public String path() default "/"; - - /** - * 默认的回复转换器; - *
- * 当服务方法未指明自定义的回复转换器时,如果采用此默认回复转换器,如果服务的默认回复转换器也未设置,则采用系统预定义的默认回复转换器; - * - * @return - */ - public ClassdefaultResponseConverter() default ResponseConverter.class; - - /** - * 回复转换器工厂; - *
- * 当服务方法上未指定的回复转换器,同时服务上也未指定默认回复转换器,则通过此属性指定的回复转换器工厂创建每个方法的回复转换器; - *
- * 如果此属性也未设置,则采用系统预定义的默认回复转换器; - - * @return - */ - public Class responseConverterFactory() default ResponseBodyConverterFactory.class; - - /** - * 默认的请求体参数转换器; - *
- * 当 {@link RequestBody} 标注未指定转换器实现时,则采用此处的默认配置; - * - * @return - */ - public Class defaultRequestBodyConverter() default RequestBodyConverter.class; - -} +package com.jd.blockchain.utils.http; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface HttpService { + + /** + * 服务的路径; + *
+ * 它是所有服务方法的根路径,默认为 /; + * + * @return + */ + public String path() default "/"; + + /** + * 默认的回复转换器; + *
+ * 当服务方法未指明自定义的回复转换器时,如果采用此默认回复转换器,如果服务的默认回复转换器也未设置,则采用系统预定义的默认回复转换器; + * + * @return + */ + public ClassdefaultResponseConverter() default ResponseConverter.class; + + /** + * 回复转换器工厂; + *
+ * 当服务方法上未指定的回复转换器,同时服务上也未指定默认回复转换器,则通过此属性指定的回复转换器工厂创建每个方法的回复转换器; + *
+ * 如果此属性也未设置,则采用系统预定义的默认回复转换器; + + * @return + */ + public Class responseConverterFactory() default ResponseBodyConverterFactory.class; + + /** + * 默认的请求体参数转换器; + *
+ * 当 {@link RequestBody} 标注未指定转换器实现时,则采用此处的默认配置; + * + * @return + */ + public Class defaultRequestBodyConverter() default RequestBodyConverter.class; + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceConsts.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceConsts.java index 723eaaf6..dd337a5e 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceConsts.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceConsts.java @@ -1,9 +1,9 @@ -package com.jd.blockchain.utils.http; - -public interface HttpServiceConsts { - - public static final String CHARSET = "utf-8"; - - public static final String PATH_SEPERATOR = "/"; - -} +package com.jd.blockchain.utils.http; + +public interface HttpServiceConsts { + + public static final String CHARSET = "utf-8"; + + public static final String PATH_SEPERATOR = "/"; + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceContext.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceContext.java index c7300a3a..3b4ea20c 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceContext.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceContext.java @@ -1,23 +1,23 @@ -package com.jd.blockchain.utils.http; - -/** - * HttpServiceContext 定义了 HTTP 服务代理上下文的信息; - * - * @author haiq - * - */ -public interface HttpServiceContext { - - /** - * 服务接口的类型; - * @return - */ - Class getServiceClasss(); - - /** - * 创建服务代理实例时由调用者指定的绑定对象; - * @return - */ - Object getProxyBindingData(); - -} +package com.jd.blockchain.utils.http; + +/** + * HttpServiceContext 定义了 HTTP 服务代理上下文的信息; + * + * @author haiq + * + */ +public interface HttpServiceContext { + + /** + * 服务接口的类型; + * @return + */ + Class getServiceClasss(); + + /** + * 创建服务代理实例时由调用者指定的绑定对象; + * @return + */ + Object getProxyBindingData(); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceException.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceException.java index cf76003b..7934b8a8 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceException.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpServiceException.java @@ -1,27 +1,27 @@ -package com.jd.blockchain.utils.http; - -/** - * HTTP 服务异常; - * - * 通过 HTTP Service Agent 调用产生的异常都将包装为 HttpServiceException 抛出; - * - * 注:操作方法通过 throws 关键字声明的异常除外,这些异常将原样抛出; - * - * @author haiq - * - */ -public class HttpServiceException extends RuntimeException{ - - private static final long serialVersionUID = 7316207586307377240L; - - public HttpServiceException() { - } - - public HttpServiceException(String message) { - super(message); - } - - public HttpServiceException(String message, Throwable cause) { - super(message, cause); - } -} +package com.jd.blockchain.utils.http; + +/** + * HTTP 服务异常; + * + * 通过 HTTP Service Agent 调用产生的异常都将包装为 HttpServiceException 抛出; + * + * 注:操作方法通过 throws 关键字声明的异常除外,这些异常将原样抛出; + * + * @author haiq + * + */ +public class HttpServiceException extends RuntimeException{ + + private static final long serialVersionUID = 7316207586307377240L; + + public HttpServiceException() { + } + + public HttpServiceException(String message) { + super(message); + } + + public HttpServiceException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpStatusException.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpStatusException.java index 02c5bbc6..027fea0c 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpStatusException.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/HttpStatusException.java @@ -1,39 +1,39 @@ -package com.jd.blockchain.utils.http; - -/** - * 用于描述调用请求发生的 http 状态码400以上的错误; - * - * @author haiq - * - */ -public class HttpStatusException extends HttpServiceException { - - private static final long serialVersionUID = 9123750807777784421L; - - private int httpCode; - -// private String content; -// -// public HttpStatusException(int httpCode, String message) { -// this(httpCode, message, null); -// } - - public HttpStatusException(int httpCode, String message) { - super(message); - this.httpCode = httpCode; -// this.content = content; - } - - /** - * http 状态吗; - * @return - */ - public int getHttpCode() { - return httpCode; - } - -// public String getContent() { -// return content; -// } - -} +package com.jd.blockchain.utils.http; + +/** + * 用于描述调用请求发生的 http 状态码400以上的错误; + * + * @author haiq + * + */ +public class HttpStatusException extends HttpServiceException { + + private static final long serialVersionUID = 9123750807777784421L; + + private int httpCode; + +// private String content; +// +// public HttpStatusException(int httpCode, String message) { +// this(httpCode, message, null); +// } + + public HttpStatusException(int httpCode, String message) { + super(message); + this.httpCode = httpCode; +// this.content = content; + } + + /** + * http 状态吗; + * @return + */ + public int getHttpCode() { + return httpCode; + } + +// public String getContent() { +// return content; +// } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/PathParam.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/PathParam.java index ac60f0c8..8faf26df 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/PathParam.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/PathParam.java @@ -1,42 +1,42 @@ -package com.jd.blockchain.utils.http; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.jd.blockchain.utils.http.converters.ObjectToStringConverter; - -/** - * 标识方法的一个参数映射为请求路径的一部分; - * - * 一般情况下,应该使用 String 类型作为路径参数并以此类进行标注; - * - * 但如果被标注的参数的类型不是 String 类型而是其它,则通过 toString 方法来获得实际的路径参数值; - * - * @author haiq - * - */ -@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface PathParam { - - /** - * 路径中的变量名; - * - * @return - */ - public String name(); - - /** - * 参数值转换器的类型; - * - * 指定的参数值转换器必须实现 StringConverter 接口; - * - * 如果未指定,则默认通过 toString() 方法获取参数最终的文本值; - * - * @return - */ - public Class converter() default ObjectToStringConverter.class; - -} +package com.jd.blockchain.utils.http; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.jd.blockchain.utils.http.converters.ObjectToStringConverter; + +/** + * 标识方法的一个参数映射为请求路径的一部分; + * + * 一般情况下,应该使用 String 类型作为路径参数并以此类进行标注; + * + * 但如果被标注的参数的类型不是 String 类型而是其它,则通过 toString 方法来获得实际的路径参数值; + * + * @author haiq + * + */ +@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface PathParam { + + /** + * 路径中的变量名; + * + * @return + */ + public String name(); + + /** + * 参数值转换器的类型; + * + * 指定的参数值转换器必须实现 StringConverter 接口; + * + * 如果未指定,则默认通过 toString() 方法获取参数最终的文本值; + * + * @return + */ + public Class converter() default ObjectToStringConverter.class; + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/PropertiesConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/PropertiesConverter.java index 18ea8f6a..6cf45c55 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/PropertiesConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/PropertiesConverter.java @@ -1,7 +1,7 @@ -package com.jd.blockchain.utils.http; - -public interface PropertiesConverter { - - public NamedParamMap toProperties(Object arg); - -} +package com.jd.blockchain.utils.http; + +public interface PropertiesConverter { + + public NamedParamMap toProperties(Object arg); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestBody.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestBody.java index 6117d999..4aca5ca2 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestBody.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestBody.java @@ -1,37 +1,37 @@ -package com.jd.blockchain.utils.http; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 标识一个方法参数如何映射为 http 请求的 body ; - * - * 注意:在一个方法中,最多只允许有一个参数被标识为 RequestBody; - * - * @author haiq - * - */ -@Target({ElementType.PARAMETER}) -@Retention(RetentionPolicy.RUNTIME) -public @interface RequestBody { - - public boolean required() default true; - - /** - * 参数值转换器的类型; - * - * 指定的参数值转换器必须实现 RequestBodyConverter 接口; - * - * 如果未指定, - * - * 对于 InputStream 或 byte 数组类型,则直接输出字节内容; - * - * 对于除此之外的其它类型,则通过 Object.toString() 方法获取文本值按照指定的编码; - * - * @return - */ - public Class converter() default RequestBodyConverter.class; - -} +package com.jd.blockchain.utils.http; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 标识一个方法参数如何映射为 http 请求的 body ; + * + * 注意:在一个方法中,最多只允许有一个参数被标识为 RequestBody; + * + * @author haiq + * + */ +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequestBody { + + public boolean required() default true; + + /** + * 参数值转换器的类型; + * + * 指定的参数值转换器必须实现 RequestBodyConverter 接口; + * + * 如果未指定, + * + * 对于 InputStream 或 byte 数组类型,则直接输出字节内容; + * + * 对于除此之外的其它类型,则通过 Object.toString() 方法获取文本值按照指定的编码; + * + * @return + */ + public Class converter() default RequestBodyConverter.class; + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestBodyConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestBodyConverter.java index f71cbc80..eb6e09cf 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestBodyConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestBodyConverter.java @@ -1,25 +1,25 @@ -package com.jd.blockchain.utils.http; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * 标注了 {@link RequestBody} 的参数的转换器; - * - *
- * 定义了如何将某个参数从特定类型转换为用于发送 http 请求体的输入流; - * - *
- * 如果将多个参数都标注了 {@link RequestBody} ,则会按顺序对每一个参数调用其对应的转换器; - * - *
- * 注:任何时候,实现者都应避免在完成一个参数写入之后主动关闭输出流; - * - * @author haiq - * - */ -public interface RequestBodyConverter { - - void write(Object param, OutputStream out) throws IOException; - -} +package com.jd.blockchain.utils.http; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * 标注了 {@link RequestBody} 的参数的转换器; + * + *
+ * 定义了如何将某个参数从特定类型转换为用于发送 http 请求体的输入流; + * + *
+ * 如果将多个参数都标注了 {@link RequestBody} ,则会按顺序对每一个参数调用其对应的转换器; + * + *
+ * 注:任何时候,实现者都应避免在完成一个参数写入之后主动关闭输出流; + * + * @author haiq + * + */ +public interface RequestBodyConverter { + + void write(Object param, OutputStream out) throws IOException; + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParam.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParam.java index 63c57fe0..68ffb933 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParam.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParam.java @@ -1,74 +1,74 @@ -package com.jd.blockchain.utils.http; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.jd.blockchain.utils.http.converters.ObjectToStringConverter; - -/** - * 用于标识一个方法参数或一个类的成员该如何体现为 http 请求中的一个参数;

- * - * 如果采用 HTTP GET 方法发起请求,则 RequestParam 标识的参数将以查询参数的方式通过 URL 提交;

- * - * 如果采用 HTTP POST 方法发起请求,则 RequestParam 标识的参数将以表单字段的方式提交;

- * - * @author haiq - * - */ -@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface RequestParam { - - /** - * 参数名; - * - * @return - */ - public String name(); - - /** - * 参数是否必须提供;

- * - * 如果必须的参数的值为 null ,将引发异常;

- * - * 如果非必须的参数的值为 null,则忽略此参数;

- * - * 默认为 true; - * - * @return - */ - public boolean required() default true; - - /** - * 是否为数组; - * - *
- * - * 如果设为 true,则参数必须为数组类型,此参数将输出为“列表参数”; - * - * @return - */ - public boolean array() default false; - - /** - * 忽略值; - * - * 仅当 require 为 false 时有效,指示当参数的值为 null 或者与 ignoreValue 相等时将忽略参数; - * - * @return - */ - public String ignoreValue() default ""; - - /** - * 参数值转换器的类型; - * - * 指定的参数值转换器必须实现 StringConverter 接口; - * - * 如果未指定,则默认通过 toString() 方法获取参数最终的文本值; - * - * @return - */ - public Class converter() default ObjectToStringConverter.class; -} +package com.jd.blockchain.utils.http; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import com.jd.blockchain.utils.http.converters.ObjectToStringConverter; + +/** + * 用于标识一个方法参数或一个类的成员该如何体现为 http 请求中的一个参数;

+ * + * 如果采用 HTTP GET 方法发起请求,则 RequestParam 标识的参数将以查询参数的方式通过 URL 提交;

+ * + * 如果采用 HTTP POST 方法发起请求,则 RequestParam 标识的参数将以表单字段的方式提交;

+ * + * @author haiq + * + */ +@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequestParam { + + /** + * 参数名; + * + * @return + */ + public String name(); + + /** + * 参数是否必须提供;

+ * + * 如果必须的参数的值为 null ,将引发异常;

+ * + * 如果非必须的参数的值为 null,则忽略此参数;

+ * + * 默认为 true; + * + * @return + */ + public boolean required() default true; + + /** + * 是否为数组; + * + *
+ * + * 如果设为 true,则参数必须为数组类型,此参数将输出为“列表参数”; + * + * @return + */ + public boolean array() default false; + + /** + * 忽略值; + * + * 仅当 require 为 false 时有效,指示当参数的值为 null 或者与 ignoreValue 相等时将忽略参数; + * + * @return + */ + public String ignoreValue() default ""; + + /** + * 参数值转换器的类型; + * + * 指定的参数值转换器必须实现 StringConverter 接口; + * + * 如果未指定,则默认通过 toString() 方法获取参数最终的文本值; + * + * @return + */ + public Class converter() default ObjectToStringConverter.class; +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParamFilter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParamFilter.java index ffe0f697..54f6b920 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParamFilter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParamFilter.java @@ -1,13 +1,13 @@ -package com.jd.blockchain.utils.http; - -/** - * 请求参数过滤器; - * - * @author haiq - * - */ -public interface RequestParamFilter { - - void filter(HttpMethod requestMethod, NamedParamMap requestParams); - -} +package com.jd.blockchain.utils.http; + +/** + * 请求参数过滤器; + * + * @author haiq + * + */ +public interface RequestParamFilter { + + void filter(HttpMethod requestMethod, NamedParamMap requestParams); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParamMap.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParamMap.java index 3fe6c5c8..48525175 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParamMap.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/RequestParamMap.java @@ -1,58 +1,58 @@ -package com.jd.blockchain.utils.http; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 用于标识一个 POJO 类型的参数将其成员转换为请求参数表; - * - * 此标注应用在方法参数中,并将参数对象中标注为 RequestParam 的属性作为请求参数加入参数表; - * - * @author haiq - * - */ -@Target({ ElementType.PARAMETER }) -@Retention(RetentionPolicy.RUNTIME) -public @interface RequestParamMap { - - /** - * 属性前缀; - * - * 当一个方法中通过 RequestParams 定义了多个参数表时,可通过定义不同的前缀以防止属性名称冲突; - * - * @return - */ - public String prefix() default ""; - - /** - * 属性分隔符; - * - * 最终的参数名由前缀+分隔符+原始参数名构成; - * - * @return - */ - public String seperator() default "."; - - /** - * 参数是否必须提供; - * - * 运行时如果必须的参数为 null 将引发异常; - * - * 默认为 true; - * - * @return - */ - public boolean required() default true; - - /** - * 自定义的转换器; - * - * 必须实现 PropertiesConverter 接口; - * - * @return - */ - public Classconverter() default PropertiesConverter.class; - -} +package com.jd.blockchain.utils.http; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 用于标识一个 POJO 类型的参数将其成员转换为请求参数表; + * + * 此标注应用在方法参数中,并将参数对象中标注为 RequestParam 的属性作为请求参数加入参数表; + * + * @author haiq + * + */ +@Target({ ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +public @interface RequestParamMap { + + /** + * 属性前缀; + * + * 当一个方法中通过 RequestParams 定义了多个参数表时,可通过定义不同的前缀以防止属性名称冲突; + * + * @return + */ + public String prefix() default ""; + + /** + * 属性分隔符; + * + * 最终的参数名由前缀+分隔符+原始参数名构成; + * + * @return + */ + public String seperator() default "."; + + /** + * 参数是否必须提供; + * + * 运行时如果必须的参数为 null 将引发异常; + * + * 默认为 true; + * + * @return + */ + public boolean required() default true; + + /** + * 自定义的转换器; + * + * 必须实现 PropertiesConverter 接口; + * + * @return + */ + public Classconverter() default PropertiesConverter.class; + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/ResponseBodyConverterFactory.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/ResponseBodyConverterFactory.java index c11c8a15..54195bc1 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/ResponseBodyConverterFactory.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/ResponseBodyConverterFactory.java @@ -1,9 +1,9 @@ -package com.jd.blockchain.utils.http; - -import java.lang.reflect.Method; - -public interface ResponseBodyConverterFactory { - - ResponseConverter createResponseConverter(HttpAction actionDef, Method mth); - -} +package com.jd.blockchain.utils.http; + +import java.lang.reflect.Method; + +public interface ResponseBodyConverterFactory { + + ResponseConverter createResponseConverter(HttpAction actionDef, Method mth); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/ResponseConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/ResponseConverter.java index ba496404..e9dbcceb 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/ResponseConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/ResponseConverter.java @@ -1,22 +1,22 @@ -package com.jd.blockchain.utils.http; - -import java.io.InputStream; - -import com.jd.blockchain.utils.http.agent.ServiceRequest; - -/** - * 回复结果转换器; - * - * 用于定义如何从 http 回复的文本结果转换为一个特定的对象; - * - * 当 ResponseConvert 抛出的异常的类型存在于服务接口的操作方法声明 的异常列表中,则异常将被直接返回给调用者; - * - * @author haiq - * - */ -public interface ResponseConverter { - - // TODO 支持按 HTTP 状态进行解析; - public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) throws Exception; - -} +package com.jd.blockchain.utils.http; + +import java.io.InputStream; + +import com.jd.blockchain.utils.http.agent.ServiceRequest; + +/** + * 回复结果转换器; + * + * 用于定义如何从 http 回复的文本结果转换为一个特定的对象; + * + * 当 ResponseConvert 抛出的异常的类型存在于服务接口的操作方法声明 的异常列表中,则异常将被直接返回给调用者; + * + * @author haiq + * + */ +public interface ResponseConverter { + + // TODO 支持按 HTTP 状态进行解析; + public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) throws Exception; + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/StringConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/StringConverter.java index be7f5395..66428032 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/StringConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/StringConverter.java @@ -1,15 +1,15 @@ -package com.jd.blockchain.utils.http; - -/** - * 字符串转换器; - * - * 定义了如何将某个对象转换为字符串; - * - * @author haiq - * - */ -public interface StringConverter { - - String toString(Object args); - -} +package com.jd.blockchain.utils.http; + +/** + * 字符串转换器; + * + * 定义了如何将某个对象转换为字符串; + * + * @author haiq + * + */ +public interface StringConverter { + + String toString(Object args); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ArgDefEntry.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ArgDefEntry.java index 3ed7c15c..5a9ff9c6 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ArgDefEntry.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ArgDefEntry.java @@ -1,29 +1,29 @@ -package com.jd.blockchain.utils.http.agent; - -class ArgDefEntry { - private int index; - - private Class argType; - - private TDef definition; - - public int getIndex() { - return index; - } - - public Class getArgType() { - return argType; - } - - public TDef getDefinition() { - return definition; - } - - public ArgDefEntry(int index, Class argType, TDef definition) { - this.index = index; - this.argType = argType; - this.definition = definition; - } - - +package com.jd.blockchain.utils.http.agent; + +class ArgDefEntry { + private int index; + + private Class argType; + + private TDef definition; + + public int getIndex() { + return index; + } + + public Class getArgType() { + return argType; + } + + public TDef getDefinition() { + return definition; + } + + public ArgDefEntry(int index, Class argType, TDef definition) { + this.index = index; + this.argType = argType; + this.definition = definition; + } + + } \ No newline at end of file diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationAlgs.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationAlgs.java index 1397dafe..0faff6c2 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationAlgs.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationAlgs.java @@ -1,11 +1,11 @@ -package com.jd.blockchain.utils.http.agent; - -/** - * 定义了rest 接口认证算法常量值 - * @author haiq - * - */ -public class AuthorizationAlgs { - - public final static String DEFAULT = "DEFAULT"; -} +package com.jd.blockchain.utils.http.agent; + +/** + * 定义了rest 接口认证算法常量值 + * @author haiq + * + */ +public class AuthorizationAlgs { + + public final static String DEFAULT = "DEFAULT"; +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationHeader.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationHeader.java index 04018364..439235cd 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationHeader.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationHeader.java @@ -1,59 +1,59 @@ -package com.jd.blockchain.utils.http.agent; - - -/*** - * Http Authorization Header; - * - * @author haiq - * - */ -public class AuthorizationHeader implements RequestHeader{ - - /**@see com.jd.blockchain.utils.http.agent.AuthorizationAlgs*/ - private String alg; //算法类型 - - private String senderName; //开发者注册的用户名 - - private String secretKey; //秘钥 - - public AuthorizationHeader(){ - - } - - public AuthorizationHeader(String senderName, String secretKey){ - this(AuthorizationAlgs.DEFAULT, senderName, secretKey); - } - - public AuthorizationHeader(String alg, String senderName, String secretKey){ - this.alg = alg; - this.senderName = senderName; - this.secretKey = secretKey; - } - - public String getAlg() { - return alg; - } - - public String getSenderName() { - return senderName; - } - - public String getSecretKey() { - return secretKey; - } - - @Override - public String getName() { - return "Authorization"; - } - - @Override - public String getValue() { - StringBuilder authBuilder = new StringBuilder(); - authBuilder.append(alg).append(" ").append(senderName).append(":") - .append(secretKey); - return authBuilder.toString(); - } - - -} +package com.jd.blockchain.utils.http.agent; + + +/*** + * Http Authorization Header; + * + * @author haiq + * + */ +public class AuthorizationHeader implements RequestHeader{ + + /**@see com.jd.blockchain.utils.http.agent.AuthorizationAlgs*/ + private String alg; //算法类型 + + private String senderName; //开发者注册的用户名 + + private String secretKey; //秘钥 + + public AuthorizationHeader(){ + + } + + public AuthorizationHeader(String senderName, String secretKey){ + this(AuthorizationAlgs.DEFAULT, senderName, secretKey); + } + + public AuthorizationHeader(String alg, String senderName, String secretKey){ + this.alg = alg; + this.senderName = senderName; + this.secretKey = secretKey; + } + + public String getAlg() { + return alg; + } + + public String getSenderName() { + return senderName; + } + + public String getSecretKey() { + return secretKey; + } + + @Override + public String getName() { + return "Authorization"; + } + + @Override + public String getValue() { + StringBuilder authBuilder = new StringBuilder(); + authBuilder.append(alg).append(" ").append(senderName).append(":") + .append(secretKey); + return authBuilder.toString(); + } + + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationHeaderResovler.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationHeaderResovler.java index fa92569f..3a04093d 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationHeaderResovler.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/AuthorizationHeaderResovler.java @@ -1,13 +1,13 @@ -package com.jd.blockchain.utils.http.agent; - -/** - * AuthorizationHeaderResovler 是一个根据实际的请求生成认证头部的策略接口; - * - * @author haiq - * - */ -public interface AuthorizationHeaderResovler { - - public AuthorizationHeader generateHeader(ServiceRequest request); - -} +package com.jd.blockchain.utils.http.agent; + +/** + * AuthorizationHeaderResovler 是一个根据实际的请求生成认证头部的策略接口; + * + * @author haiq + * + */ +public interface AuthorizationHeaderResovler { + + public AuthorizationHeader generateHeader(ServiceRequest request); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/CustomHeader.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/CustomHeader.java index ef362fa3..85d4c49a 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/CustomHeader.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/CustomHeader.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.utils.http.agent; - -public class CustomHeader implements RequestHeader{ - - private String name; - - private String value; - - public CustomHeader(String name, String value) { - this.name = name; - this.value = value; - } - - @Override - public String getName() { - return name; - } - - @Override - public String getValue() { - return value; - } - -} +package com.jd.blockchain.utils.http.agent; + +public class CustomHeader implements RequestHeader{ + + private String name; + + private String value; + + public CustomHeader(String name, String value) { + this.name = name; + this.value = value; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getValue() { + return value; + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/DefaultResponseConverterFactory.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/DefaultResponseConverterFactory.java index 9f2483fc..da8c41e6 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/DefaultResponseConverterFactory.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/DefaultResponseConverterFactory.java @@ -1,34 +1,34 @@ -package com.jd.blockchain.utils.http.agent; - -import java.lang.reflect.Method; - -import com.jd.blockchain.utils.http.HttpAction; -import com.jd.blockchain.utils.http.ResponseBodyConverterFactory; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.converters.ByteArrayResponseConverter; -import com.jd.blockchain.utils.http.converters.JsonResponseConverter; -import com.jd.blockchain.utils.http.converters.StringResponseConverter; - -public class DefaultResponseConverterFactory implements ResponseBodyConverterFactory { - - public static final DefaultResponseConverterFactory INSTANCE = new DefaultResponseConverterFactory(); - - private DefaultResponseConverterFactory() { - } - - @Override - public ResponseConverter createResponseConverter(HttpAction actionDef, Method mth) { - Class retnClazz = mth.getReturnType(); - // create default response converter; - if (byte[].class == retnClazz) { - return ByteArrayResponseConverter.INSTANCE; - } - if (String.class == retnClazz) { - return StringResponseConverter.INSTANCE; - } - - // TODO:未处理 基本类型、输入输出流; - return new JsonResponseConverter(retnClazz); - } - -} +package com.jd.blockchain.utils.http.agent; + +import java.lang.reflect.Method; + +import com.jd.blockchain.utils.http.HttpAction; +import com.jd.blockchain.utils.http.ResponseBodyConverterFactory; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.converters.ByteArrayResponseConverter; +import com.jd.blockchain.utils.http.converters.JsonResponseConverter; +import com.jd.blockchain.utils.http.converters.StringResponseConverter; + +public class DefaultResponseConverterFactory implements ResponseBodyConverterFactory { + + public static final DefaultResponseConverterFactory INSTANCE = new DefaultResponseConverterFactory(); + + private DefaultResponseConverterFactory() { + } + + @Override + public ResponseConverter createResponseConverter(HttpAction actionDef, Method mth) { + Class retnClazz = mth.getReturnType(); + // create default response converter; + if (byte[].class == retnClazz) { + return ByteArrayResponseConverter.INSTANCE; + } + if (String.class == retnClazz) { + return StringResponseConverter.INSTANCE; + } + + // TODO:未处理 基本类型、输入输出流; + return new JsonResponseConverter(retnClazz); + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/HttpServiceAgent.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/HttpServiceAgent.java index ec8d386d..5cd6b3dd 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/HttpServiceAgent.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/HttpServiceAgent.java @@ -1,1051 +1,1051 @@ -package com.jd.blockchain.utils.http.agent; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.net.URI; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.http.Consts; -import org.apache.http.Header; -import org.apache.http.HttpHeaders; -import org.apache.http.NameValuePair; -import org.apache.http.client.entity.UrlEncodedFormEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpPut; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.entity.ByteArrayEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.springframework.beans.BeanUtils; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; - -import com.jd.blockchain.utils.http.HttpAction; -import com.jd.blockchain.utils.http.HttpMethod; -import com.jd.blockchain.utils.http.HttpService; -import com.jd.blockchain.utils.http.HttpServiceContext; -import com.jd.blockchain.utils.http.HttpServiceException; -import com.jd.blockchain.utils.http.HttpStatusException; -import com.jd.blockchain.utils.http.NamedParam; -import com.jd.blockchain.utils.http.NamedParamMap; -import com.jd.blockchain.utils.http.PathParam; -import com.jd.blockchain.utils.http.RequestBody; -import com.jd.blockchain.utils.http.RequestBodyConverter; -import com.jd.blockchain.utils.http.RequestParam; -import com.jd.blockchain.utils.http.RequestParamFilter; -import com.jd.blockchain.utils.http.RequestParamMap; -import com.jd.blockchain.utils.http.ResponseBodyConverterFactory; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.StringConverter; -import com.jd.blockchain.utils.http.converters.NullResponseConverter; -import com.jd.blockchain.utils.http.converters.StringResponseConverter; - -/** - * http 服务代理; - * - * @author haiq - * - */ -public class HttpServiceAgent { - - private static final NamedParam[] EMPTY_PARAMS = {}; - - private static Map, HttpServiceAgent> serviceAgentMap = new ConcurrentHashMap, HttpServiceAgent>(); - - private Class serviceClass; - - private RequestBodyConverter defaultRequestBodyConverter; - - private ResponseConverter defaultResponseConverter; - - private ResponseBodyConverterFactory responseConverterFactory; - - private AuthorizationHeaderResovler authorizationHeaderResolver; - - private Map actions = new HashMap<>(); - - private HttpServiceAgent(Class serviceClass, - AuthorizationHeaderResovler authResolver) { - this.serviceClass = serviceClass; - this.authorizationHeaderResolver = authResolver; - - resolveService(); - } - - /** - * 创建映射指定服务接口的 HTTP 服务代理; - * - * @param serviceClass - * 服务的接口类型; - * @param serviceEndpoint - * 连接到服务提供者服务器的相关设置; - * @param authorizationHeader - * 安全认证头部; - * @return - */ - public static T createService(Class serviceClass, ServiceEndpoint serviceEndpoint, - RequestHeader... authorizationHeaders) { - return createService(serviceClass, serviceEndpoint, null, null, authorizationHeaders); - } - - /** - * 创建映射指定服务接口的 HTTP 服务代理; - * - * @param serviceClass - * 服务的接口类型; - * @param serviceEndpoint - * 服务终结点; - * @return - */ - public static T createService(Class serviceClass, ServiceEndpoint serviceEndpoint) { - return createService(serviceClass, serviceEndpoint, (AuthorizationHeaderResovler) null); - } - - /** - * 创建映射指定服务接口的 HTTP 服务代理; - * - * @param serviceClass - * 定义了服务的接口类型; - * @param serviceEndpoint - * 服务终结点; - * @param authorizationHeaderResolver - * 安全认证头部的解析器; - * @return - */ - public static T createService(Class serviceClass, ServiceEndpoint serviceEndpoint, - AuthorizationHeaderResovler authorizationHeaderResolver) { - return createService(serviceClass, serviceEndpoint, null, authorizationHeaderResolver); - } - - /** - * 创建映射指定服务接口的 HTTP 服务代理; - * - * @param serviceClass - * 定义了服务的接口类型; - * @param serviceEndpoint - * 服务终结点; - * @param connectionManager - * 连接管理器; - * @param authorizationHeaderResolver - * 安全认证头部的解析器; - * @param headers - * 请求头部; - * @return - */ - public static T createService(Class serviceClass, ServiceEndpoint serviceEndpoint, - ServiceConnectionManager connectionManager, AuthorizationHeaderResovler authorizationHeaderResolver, - RequestHeader... headers) { - ServiceConnection connection = null; - if (connectionManager == null) { - connection = ServiceConnectionManager.connect(serviceEndpoint); - } else { - connection = connectionManager.create(serviceEndpoint); - } - return createService(serviceClass, connection, authorizationHeaderResolver, headers); - } - - /** - * 创建映射指定服务接口的 HTTP 服务代理; - * - * @param serviceClass - * 定义了服务的接口类型; - * @param serviceEndpoint - * 服务终结点; - * @param connectionManager - * 连接管理器; - * @param authorizationHeaderResolver - * 安全认证头部的解析器; - * @param headers - * 请求头部; - * @return - */ - public static T createService(Class serviceClass, ServiceConnection connection, - AuthorizationHeaderResovler authorizationHeaderResolver, RequestHeader... headers) { - return createService(serviceClass, connection, authorizationHeaderResolver, headers, null); - } - - /** - * 创建映射指定服务接口的 HTTP 服务代理; - * - * @param serviceClass - * 定义了服务的接口类型; - * @param serviceEndpoint - * 服务终结点; - * @param connectionManager - * 连接管理器; - * @param authorizationHeaderResolver - * 安全认证头部的解析器; - * @param headers - * 请求头部; - * @param bindingData - * 由调用者指定的绑定对象;
- * 该对象将被关联到 HttpServiceContext 上;调用者可以通过此对象将某些数据对象传递到调用过程的一些处理组件上,例如 - * {@link ResponseConverter}; - * @return - */ - public static T createService(Class serviceClass, ServiceConnection connection, - AuthorizationHeaderResovler authorizationHeaderResolver, RequestHeader[] headers, Object bindingData) { - if (serviceClass == null) { - throw new IllegalArgumentException("Service class is null!"); - } - if (!(connection instanceof HttpServiceConnection)) { - throw new IllegalArgumentException( - "Illegal service connection! It must be created by the ServiceConnectionManager!"); - } - HttpServiceConnection httpConnection = (HttpServiceConnection) connection; - // 避免反复解析同一个服务类型; - HttpServiceAgent agent = serviceAgentMap.get(serviceClass); - if (agent == null) { - synchronized (serviceClass) { - agent = serviceAgentMap.get(serviceClass); - if (agent == null) { - agent = new HttpServiceAgent(serviceClass, authorizationHeaderResolver); - serviceAgentMap.put(serviceClass, agent); - } - } - } - - // CloseableHttpClient httpClient = createHttpClient(serviceEndpoint, - // connectionManager); - - ServiceInvocationHandler invocationHandler = new ServiceInvocationHandler(agent, httpConnection, headers, - bindingData); - - @SuppressWarnings("unchecked") - T serviceProxy = (T) Proxy.newProxyInstance(serviceClass.getClassLoader(), new Class[] { serviceClass }, - invocationHandler); - return serviceProxy; - } - - private void resolveService() { - // 处理服务路径; - HttpService serviceAnno = serviceClass.getAnnotation(HttpService.class); - if (serviceAnno == null) { - throw new IllegalHttpServiceDefinitionException( - "The specific service was not tag with HttpService annotation!"); - } - String servicePath = serviceAnno.path(); - servicePath = StringUtils.cleanPath(servicePath); - if (StringUtils.isEmpty(servicePath)) { - throw new IllegalHttpServiceDefinitionException( - "Illegal path or no path was specified for the HttpService!-- path=" + serviceAnno.path()); - } - - // 实例化服务的默认请求体参数转换器; - Class defaultRequestBodyConverterClazz = serviceAnno.defaultRequestBodyConverter(); - if (defaultRequestBodyConverterClazz != null && defaultRequestBodyConverterClazz != RequestBodyConverter.class) { - if (RequestBodyConverter.class.isAssignableFrom(defaultRequestBodyConverterClazz)) { - defaultRequestBodyConverter = (RequestBodyConverter) BeanUtils.instantiate(defaultRequestBodyConverterClazz); - } else { - throw new IllegalHttpServiceDefinitionException( - "The specified default request body converter of service doesn't implement the interface " - + RequestBodyConverter.class.getName() + "!"); - } - } - - // 实例化服务的默认回复转换器; - Class defaultResponseConverterClazz = serviceAnno.defaultResponseConverter(); - if (defaultResponseConverterClazz != null && defaultResponseConverterClazz != ResponseConverter.class) { - if (ResponseConverter.class.isAssignableFrom(defaultResponseConverterClazz)) { - defaultResponseConverter = (ResponseConverter) BeanUtils.instantiate(defaultResponseConverterClazz); - } else { - throw new IllegalHttpServiceDefinitionException( - "The specified default response converter of service doesn't implement the interface " - + ResponseConverter.class.getName() + "!"); - } - } - Class responseConverterFactoryClazz = serviceAnno.responseConverterFactory(); - if (responseConverterFactoryClazz != null && responseConverterFactoryClazz != ResponseBodyConverterFactory.class) { - if (ResponseBodyConverterFactory.class.isAssignableFrom(responseConverterFactoryClazz)) { - this.responseConverterFactory = (ResponseBodyConverterFactory) BeanUtils - .instantiate(responseConverterFactoryClazz); - } else { - throw new IllegalHttpServiceDefinitionException( - "The specified response converter factory of service doesn't implement the interface " - + ResponseBodyConverterFactory.class.getName() + "!"); - } - - } - - // 解析服务操作; -// Method[] mths = ReflectionUtils.getAllDeclaredMethods(serviceClass); - Method[] mths = serviceClass.getMethods(); - for (Method mth : mths) { - ServiceActionContext actionContext = resolveAction( mth, servicePath); - if (actionContext != null) { - actions.put(mth, actionContext); - } - } - } - - /** - * 解析指定的方法; - * - * 如果指定的方法不符合解析策略则返回 null; - * - * @param serviceEndpoint - * @param mth - * @param servicePath - * @return - */ - private ServiceActionContext resolveAction(Method mth, String servicePath) { - // 生成路径模板; - HttpAction actionAnno = mth.getAnnotation(HttpAction.class); - if (actionAnno == null) { - // 未声明的方法不做解析; - return null; - } - String actionPath = StringUtils.cleanPath(actionAnno.path()); - if (StringUtils.isEmpty(actionPath)) { - actionPath = mth.getName(); - } - RequestPathTemplate pathTemplate = new RequestPathTemplate(servicePath, actionPath); - - // 校验请求你方法; - if (actionAnno.method() == null) { - throw new IllegalHttpServiceDefinitionException("The http method of action was not specified!"); - } - - String contentType = actionAnno.contentType(); - if (contentType != null) { - contentType = contentType.trim(); - if (contentType.length() == 0) { - contentType = null; - } - } - - RequestParamFilter reqParamFilter = createRequestParamFilter(actionAnno); - ResponseConverter responseConverter = createResponseConverter(actionAnno, mth); - - // 获取参数定义; - // 参数列表中, RequestBody 最多只能定义一个; - RequestBodyResolverComposite bodyResolverComposite = new RequestBodyResolverComposite(); - Class[] paramTypes = mth.getParameterTypes(); - Annotation[][] paramAnnos = mth.getParameterAnnotations(); - - List> reqParamAnnos = new LinkedList>(); - List> reqParamMapAnnos = new LinkedList>(); - List> pathParamAnnos = new LinkedList>(); - for (int i = 0; i < paramTypes.length; i++) { - RequestBody reqBodyAnno = findAnnotation(RequestBody.class, paramAnnos[i]); - RequestParam reqParamAnno = findAnnotation(RequestParam.class, paramAnnos[i]); - RequestParamMap reqParamsAnno = findAnnotation(RequestParamMap.class, paramAnnos[i]); - PathParam pathParamAnno = findAnnotation(PathParam.class, paramAnnos[i]); - if (hasConflictiveAnnotation(reqBodyAnno, reqParamAnno, reqParamsAnno, pathParamAnno)) { - // 存在冲突的定义; - throw new IllegalHttpServiceDefinitionException( - "The argument[" + i + "] of action has conflictive definition!"); - } -// if (bodyResolver != null && reqBodyAnno != null) { -// throw new IllegalHttpServiceDefinitionException("Define more than one request body for the action!"); -// } - if (reqBodyAnno != null) { - RequestBodyResolver reqBodyResolver = createBodyResolver(new ArgDefEntry(i, paramTypes[i], reqBodyAnno)); - bodyResolverComposite.addRequestBodyResolver(reqBodyResolver); - } - if (reqParamAnno != null) { - reqParamAnnos.add(new ArgDefEntry(i, paramTypes[i], reqParamAnno)); - } - if (reqParamsAnno != null) { - reqParamMapAnnos.add(new ArgDefEntry(i, paramTypes[i], reqParamsAnno)); - } - if (pathParamAnno != null) { - pathParamAnnos.add(new ArgDefEntry(i, paramTypes[i], pathParamAnno)); - } - } - RequestParamResolver reqParamResolver = createRequestParamResolver(reqParamAnnos, reqParamMapAnnos); - PathParamResolver pathParamResolver = createPathParamResolver(pathParamAnnos); -// if (bodyResolverComposite == null) { -// bodyResolverComposite = RequestBodyResolvers.NULL_BODY_RESOLVER; -// } - - // 获取声明的异常列表; - Class[] thrownExceptionTypes = mth.getExceptionTypes(); - - ServiceActionContext actionContext = new ServiceActionContext(mth, actionAnno.method(), contentType, - pathTemplate, pathParamResolver, reqParamFilter, reqParamResolver, bodyResolverComposite, responseConverter, - thrownExceptionTypes, actionAnno.resolveContentOnHttpError()); - return actionContext; - } - - @SuppressWarnings("unchecked") - private static T findAnnotation(Class clazz, Annotation[] annos) { - for (Annotation annotation : annos) { - if (clazz.isAssignableFrom(annotation.getClass())) { - return (T) annotation; - } - } - return null; - } - - private RequestParamFilter createRequestParamFilter(HttpAction actionDef) { - Class reqParamFilterClass = actionDef.requestParamFilter(); - if (reqParamFilterClass == null || reqParamFilterClass == RequestParamFilter.class) { - return NullRequestParamFilter.INSTANCE; - } - if (RequestParamFilter.class.isAssignableFrom(reqParamFilterClass)) { - return (RequestParamFilter) BeanUtils.instantiate(reqParamFilterClass); - } else { - throw new IllegalHttpServiceDefinitionException( - "The specified RequestParamFilter doesn't implement the interface " - + RequestParamFilter.class.getName() + "!"); - } - } - - /** - * 创建回复结果转换器; - * - * @param actionDef - * @param retnClazz - * @return - */ - private ResponseConverter createResponseConverter(HttpAction actionDef, Method mth) { - Class retnClazz = mth.getReturnType(); - if (Void.class.equals(retnClazz)) { - return NullResponseConverter.INSTANCE; - } - Class respConverterClass = actionDef.responseConverter(); - if (respConverterClass == null || respConverterClass == ResponseConverter.class) { - // 未设置方法级别的回复转换器; - if (defaultResponseConverter != null) { - // 如果未设置方法级别的回复转换器,且设置了服务级别的默认回复转换器,则应用服务级别的默认回复转换器; - return defaultResponseConverter; - } - if (responseConverterFactory != null) { - return responseConverterFactory.createResponseConverter(actionDef, mth); - } - } - if (respConverterClass != null && respConverterClass != ResponseConverter.class) { - if (ResponseConverter.class.isAssignableFrom(respConverterClass)) { - return (ResponseConverter) BeanUtils.instantiate(respConverterClass); - } else { - throw new IllegalHttpServiceDefinitionException( - "The specified response converter doesn't implement the interface " - + ResponseConverter.class.getName() + "!"); - } - } - // create default response converter; - return DefaultResponseConverterFactory.INSTANCE.createResponseConverter(actionDef, mth); - - // if (byte[].class == retnClazz) { - // return ByteArrayResponseConverter.INSTANCE; - // } - // if (String.class == retnClazz) { - // return StringResponseConverter.INSTANCE; - // } - // // TODO:未处理 基本类型、输入输出流; - // return new JsonResponseConverter(retnClazz); - } - - /** - * 创建路径参数解析器; - * - * @param pathParamAnnos - * @return - */ - private PathParamResolver createPathParamResolver(List> pathParamAnnos) { - if (pathParamAnnos.size() == 0) { - return PathParamResolvers.NONE_PATH_PARAM_RESOLVER; - } - List> pathParamDefs = new LinkedList>(); - for (ArgDefEntry entry : pathParamAnnos) { - if (StringUtils.isEmpty(entry.getDefinition().name())) { - throw new IllegalHttpServiceDefinitionException("The name of path parameter is empty!"); - } - - Class converterClazz = entry.getDefinition().converter(); - StringConverter converter = StringConverterFactory.instantiateStringConverter(converterClazz); - ArgDefEntry argDefEntry = new ArgDefEntry(entry.getIndex(), - entry.getArgType(), new PathParamDefinition(entry.getDefinition().name(), converter)); - pathParamDefs.add(argDefEntry); - } - - return PathParamResolvers.createResolver(pathParamDefs); - } - - /** - * 创建请求参数解析器; - * - * @param reqParamAnnos - * @return - */ - private RequestParamResolver createRequestParamResolver(List> reqParamAnnos, - List> reqParamsAnnos) { - List> reqDefs = RequestParamDefinition - .resolveSingleParamDefinitions(reqParamAnnos); - List> reqMapDefs = RequestParamMapDefinition - .resolveParamMapDefinitions(reqParamsAnnos); - - return RequestParamResolvers.createParamMapResolver(reqDefs, reqMapDefs); - - } - - /** - * @param paramIndex - * @param parameter - * @param reqBodyAnnoEntry - * @return - */ - private RequestBodyResolver createBodyResolver(ArgDefEntry reqBodyAnnoEntry) { - Class converterClazz = reqBodyAnnoEntry.getDefinition().converter(); - RequestBodyConverter converter = null; - if (converterClazz == RequestBodyConverter.class || converterClazz == null) { - converter = defaultRequestBodyConverter; - if (converter == null) { - // create default body converter; - converter = new TypeAutoAdaptingRequestBodyConverter(reqBodyAnnoEntry.getArgType()); - } - } else { - if (!ClassUtils.isAssignable(RequestBodyConverter.class, converterClazz)) { - throw new IllegalHttpServiceDefinitionException( - "The specified body converter doesn't implement the interface " - + RequestBodyConverter.class.getName() + "!"); - } - converter = (RequestBodyConverter) BeanUtils.instantiate(converterClazz); - } - - RequestBodyDefinition reqBodyDef = new RequestBodyDefinition(reqBodyAnnoEntry.getDefinition().required(), - converter); - ArgDefEntry reqBodyDefEntry = new ArgDefEntry( - reqBodyAnnoEntry.getIndex(), reqBodyAnnoEntry.getArgType(), reqBodyDef); - return RequestBodyResolvers.createArgumentResolver(reqBodyDefEntry); - } - - /** - * 检查传入的三个参数中是否有两个或两个以上为非空; - * - * @param reqBodyAnno - * @param reqParamAnno - * @param pathParamAnno - * @return 有两个或两个以上为非空时返回 true; - * - * 全部为 null 或只有一个为 null 时,返回 false; - */ - private static boolean hasConflictiveAnnotation(RequestBody reqBodyAnno, RequestParam reqParamAnno, - RequestParamMap reqParamsAnno, PathParam pathParamAnno) { - return 1 < (reqBodyAnno == null ? 0 : 1) + (reqParamAnno == null ? 0 : 1) + (reqParamsAnno == null ? 0 : 1) - + (pathParamAnno == null ? 0 : 1); - } - - /** - * 解析被调用的方法,映射为 http 请求; - */ - private Object invoke(ServiceEndpoint serviceEndpoint, HttpServiceContext serviceContext, CloseableHttpClient httpClient, RequestHeader[] headers, - Method method, Object[] args) throws Throwable { - ServiceActionContext actionContext = actions.get(method); - if (actionContext == null) { - throw new UnsupportedOperationException("The invoked method was not a service action!"); - } - try { - HttpServiceRequest request = resolveRequest(serviceEndpoint, actionContext, args); - - HttpUriRequest httpRequest = buildRequest(request); - - // 设置预定义的头部; - setHeaders(httpRequest, headers); - // 设置解析请求生成的头部; - setHeaders(httpRequest, request.getHeaders()); - if (authorizationHeaderResolver != null) { - AuthorizationHeader auth = authorizationHeaderResolver.generateHeader(request); - // 设置认证属性; - buildAuthorization(httpRequest, auth); - } - - // 设置默认的 Content-Type; - Header[] contentTypeHeaders = httpRequest.getHeaders(HttpHeaders.CONTENT_TYPE); - if (contentTypeHeaders == null || contentTypeHeaders.length == 0) { - httpRequest.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); - } - CloseableHttpClient closeableHttpClient = HttpClientPool.getHttpClient(serviceEndpoint.getHost(), serviceEndpoint.getPort()); - - CloseableHttpResponse response = closeableHttpClient.execute(httpRequest); -// CloseableHttpResponse response = httpClient.execute(httpRequest); - try { - // 引发 http 异常; - if (response.getStatusLine().getStatusCode() >= 400) { - processAndThrowHttpException(actionContext, request, response); - // 注:上一步已抛出异常; - return null; - } - InputStream respStream = response.getEntity().getContent(); - Object respObject = actionContext.getResponseConverter().getResponse(request, respStream, - serviceContext); - return respObject; - } finally { - response.close(); - } - } catch (Exception e) { - if (isCustomThownException(e, actionContext)) { - throw e; - } - if (e instanceof HttpServiceException) { - throw (HttpServiceException) e; - } - throw new HttpServiceException(e.getMessage(), e); - } - } - - private void setHeaders(HttpUriRequest httpRequest, RequestHeader[] headers) { - if (headers == null) { - return; - } - for (RequestHeader header : headers) { - httpRequest.setHeader(header.getName(), header.getValue()); - } - } - - private void setHeaders(HttpUriRequest httpRequest, Properties customHeaders) { - Set names = customHeaders.stringPropertyNames(); - for (String name : names) { - httpRequest.setHeader(name, customHeaders.getProperty(name)); - } - } - - /** - * 判断指定的异常是否属于指定服务操作的接口方法通过 throws 声明的异常; - * - * @param e - * @param actionContext - * @return - */ - private boolean isCustomThownException(Exception e, ServiceActionContext actionContext) { - Class exType = e.getClass(); - Class[] thrownExTypes = actionContext.getThrownExceptionTypes(); - for (Class thrExType : thrownExTypes) { - if (thrExType.isAssignableFrom(exType)) { - return true; - } - } - return false; - } - - /** - * 处理 HTTP 错误,并抛出 HttpStatusException 异常; - * - * @param actionContext - * @param response - */ - private void processAndThrowHttpException(ServiceActionContext actionContext, ServiceRequest request, - CloseableHttpResponse response) throws HttpStatusException { - String content = null; - if (actionContext.isResolveContentOnHttpError()) { - try { - InputStream respStream = response.getEntity().getContent(); - content = (String) StringResponseConverter.INSTANCE.getResponse(request, respStream, null); - } catch (UnsupportedOperationException e) { - throw new HttpServiceException(e.getMessage(), e); - } catch (IOException e) { - throw new HttpServiceException(e.getMessage(), e); - } catch (Exception e) { - if (e instanceof HttpServiceException) { - throw (HttpServiceException) e; - } - throw new HttpServiceException(e.getMessage(), e); - } - } - String errMsg = String.format("[status=%s] %s", response.getStatusLine().getStatusCode(), content); - throw new HttpStatusException(response.getStatusLine().getStatusCode(), errMsg); - } - - private HttpServiceRequest resolveRequest(ServiceEndpoint serviceEndpoint, ServiceActionContext actionContext, Object[] args) throws IOException { - HttpServiceRequest request; - switch (actionContext.getRequestMethod()) { - case GET: - request = resolveGetRequest(serviceEndpoint, actionContext, args); - break; - case POST: - case PUT: - request = resolvePostOrPutRequest(serviceEndpoint, actionContext, args); - break; - case DELETE: - request = resolveDeleteRequest(serviceEndpoint, actionContext, args); - break; - default: - throw new UnsupportedOperationException( - "Unsupported http method '" + actionContext.getRequestMethod() + "'!"); - } - if (actionContext.getContentType() != null) { - request.setHeader(HttpHeaders.CONTENT_TYPE, actionContext.getContentType()); - } - return request; - } - - /** - * 创建请求; - * - * @param actionContext - * @param args - * @return - */ - private HttpUriRequest buildRequest(ServiceRequest request) { - ByteBuffer bodyBytes = null; - if (request.getBody() != null) { - // bodyStream = new ByteArrayInputStream(request.getBody().array()); - - bodyBytes = request.getBody(); - } - NamedParamMap reqParams = request.getRequestParams(); - switch (request.getHttpMethod()) { - case GET: - return new HttpGet(request.getUri()); - case POST: - HttpPost httppost = new HttpPost(request.getUri()); - - if (reqParams != null) { - // 以 form 表单提交; - NamedParam[] propNames = reqParams.getParams(); - List formParams = new ArrayList(); - for (NamedParam param : propNames) { - formParams.add(new BasicNameValuePair(param.getName(), param.getValue())); - } - UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formParams, Consts.UTF_8); - httppost.setEntity(formEntity); - // 设置默认的 Content-Type; - httppost.setHeader(formEntity.getContentType()); - } - if (bodyBytes != null) { - // 查询参数以 Stream body 方式提交; - ByteArrayEntity entity = new ByteArrayEntity(bodyBytes.array()); - // HttpEntity streamEntity = new InputStreamEntity(bodyStream); - httppost.setEntity(entity); - // 设置默认的 Content-Type; - httppost.setHeader(entity.getContentType()); - } - return httppost; - case PUT: - HttpPut httpput = new HttpPut(request.getUri()); - if (reqParams != null) { - // 以 form 表单提交; - NamedParam[] paramValues = reqParams.getParams(); - List formParams = new ArrayList(); - for (NamedParam param : paramValues) { - formParams.add(new BasicNameValuePair(param.getName(), param.getValue())); - } - UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formParams, Consts.UTF_8); - httpput.setEntity(formEntity); - } - if (bodyBytes != null) { - // 查询参数以 Stream body 方式提交; - ByteArrayEntity entity = new ByteArrayEntity(bodyBytes.array()); - // HttpEntity streamEntity = new InputStreamEntity(bodyStream); - httpput.setEntity(entity); - } - return httpput; - case DELETE: - // HttpDelete httpDelete = new HttpDelete(uri); - LocalHttpDelete httpDelete = new LocalHttpDelete(request.getUri()); - // 查询参数以 delete body 方式提交 - if (bodyBytes != null) { - ByteArrayEntity entity = new ByteArrayEntity(bodyBytes.array()); - // HttpEntity entity = new InputStreamEntity(bodyStream); - httpDelete.setEntity(entity); - } - // HttpEntity entity = new InputStreamEntity(bodyStream); - // httpDelete.setEntity(entity); - return httpDelete; - default: - throw new UnsupportedOperationException("Unsupported http method '" + request.getHttpMethod() + "'!"); - } - } - - /** - * 设置http请求头的Authorization属性 - * - * @param request - * @param setting - */ - private void buildAuthorization(HttpUriRequest request, RequestHeader setting) { - request.addHeader(setting.getName(), setting.getValue()); - } - - /** - * 创建 http post 请求; - * - * @param actionContext - * @param args - * @return - * @throws IOException - */ - // private HttpServiceRequest resolvePostRequest(ServiceActionContext - // actionContext, Object[] args) - // throws IOException { - // Map pathParams = - // actionContext.getPathParamResolver().resolve(args); - // Properties reqParams = - // actionContext.getRequestParamResolver().resolve(args); - // InputStream inputStream = - // actionContext.getRequestBodyResolver().resolve(args); - // URI uri = actionContext.getPathTemplate().generateRequestURI(pathParams, - // reqParams, - // ServiceActionContext.DEFAULT_CHARSET); - // byte[] bytes = BytesUtils.copyToBytes(inputStream); - // return new HttpServiceRequest(HttpMethod.POST, uri, - // ByteBuffer.wrap(bytes)); - // } - - /** - * 创建http put请求 - * - * @param actionContext - * @param args - * @return - * @throws IOException - */ - // private HttpServiceRequest resolvePutRequest(ServiceActionContext - // actionContext, Object[] args) throws IOException { - // Map pathParams = - // actionContext.getPathParamResolver().resolve(args); - // Properties reqParams = - // actionContext.getRequestParamResolver().resolve(args); - // InputStream inputStream = - // actionContext.getRequestBodyResolver().resolve(args); - // URI uri = actionContext.getPathTemplate().generateRequestURI(pathParams, - // reqParams, - // ServiceActionContext.DEFAULT_CHARSET); - // byte[] bytes = BytesUtils.copyToBytes(inputStream); - // return new HttpServiceRequest(HttpMethod.PUT, uri, - // ByteBuffer.wrap(bytes)); - // } - - private HttpServiceRequest resolvePostOrPutRequest(ServiceEndpoint serviceEndpoint, ServiceActionContext actionContext, Object[] args) - throws IOException { - // 解析路径参数; - Map pathParams = actionContext.getPathParamResolver().resolve(args); - HttpMethod httpMethod = actionContext.getRequestMethod(); - - // 解析 RequestBody; - ByteArrayOutputStream out = new ByteArrayOutputStream(); - actionContext.getRequestBodyResolver().resolve(args, out); - byte[] bodyBytes = out.toByteArray(); - - boolean noBody = bodyBytes.length == 0; - - // 解析 RequestParam; - NamedParamMap reqParams = actionContext.getRequestParamResolver().resolve(args); - boolean noReqParams = reqParams.isEmpty(); - actionContext.getRequestParamFilter().filter(httpMethod, reqParams); - - // 如果只有 RequestBody 标注的参数,则以 RequestBody 参数的序列化输出作为请求体; - if ((!noBody) && noReqParams) { - URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, new NamedParamMap(), - ServiceActionContext.DEFAULT_CHARSET); - ByteBuffer body = ByteBuffer.wrap(bodyBytes); - return new HttpServiceRequest(httpMethod, uri, null, body, args); - } - // 如果没有 RequestBody 标注的参数,只有 RequestParam ,则 RequestParam 通过请求体以表单格式提交; - if (noBody && (!noReqParams)) { - URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, new NamedParamMap(), - ServiceActionContext.DEFAULT_CHARSET); - return new HttpServiceRequest(httpMethod, uri, reqParams, null, args); - } - - // 如果同时有 RequestBody 标注的参数和 RequestParam 标注的参数,则以 RequestBody - // 参数的序列化输出作为请求体,RequestParam 作为 URL 参数; - if ((!noBody) && (!noReqParams)) { - URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, reqParams, - ServiceActionContext.DEFAULT_CHARSET); - ByteBuffer body = ByteBuffer.wrap(bodyBytes); - return new HttpServiceRequest(httpMethod, uri, null, body, args); - } - - // 既没有 RequestBody,也没有 RequestParam; - URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, new NamedParamMap(), - ServiceActionContext.DEFAULT_CHARSET); - return new HttpServiceRequest(httpMethod, uri, null, null, args); - } - - /** - * 创建http get请求 - * - * @param actionContext - * @param args - * @return - */ - private HttpServiceRequest resolveGetRequest(ServiceEndpoint serviceEndpoint, ServiceActionContext actionContext, Object[] args) { - Map pathParams = actionContext.getPathParamResolver().resolve(args); - NamedParamMap reqParams = actionContext.getRequestParamResolver().resolve(args); - URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, reqParams, - ServiceActionContext.DEFAULT_CHARSET); - // 对于 get 请求,请求参数已经编码到 URI 中,所以不必再传递出去进行处理; - return new HttpServiceRequest(HttpMethod.GET, uri, null, null, args); - } - - /** - * 创建http delete请求 - * - * @param actionContext - * @param args - * @return - * @throws IOException - */ - private HttpServiceRequest resolveDeleteRequest(ServiceEndpoint serviceEndpoint, ServiceActionContext actionContext, Object[] args) - throws IOException { - Map pathParams = actionContext.getPathParamResolver().resolve(args); - - NamedParamMap reqParams = actionContext.getRequestParamResolver().resolve(args); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - actionContext.getRequestBodyResolver().resolve(args, out); - byte[] bodyBytes = out.toByteArray(); - - URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, reqParams, - ServiceActionContext.DEFAULT_CHARSET); - - ByteBuffer body = bodyBytes.length == 0 ? null : ByteBuffer.wrap(bodyBytes); - return new HttpServiceRequest(HttpMethod.DELETE, uri, null, body, args); - } - - private static class ServiceInvocationHandler implements InvocationHandler, HttpServiceContext { - - private HttpServiceAgent serviceAgent; - - private HttpServiceConnection connection; - - private RequestHeader[] headers; - - private Object bindingData; - - public ServiceInvocationHandler(HttpServiceAgent serviceAgent, HttpServiceConnection connection, - RequestHeader[] headers, Object bindingData) { - this.serviceAgent = serviceAgent; - this.connection = connection; - this.headers = headers; - this.bindingData = bindingData; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - return serviceAgent.invoke(connection.getEndpoint(), this, connection.getHttpClient(), headers, method, args); - } - - @Override - public Class getServiceClasss() { - return serviceAgent.serviceClass; - } - - @Override - public Object getProxyBindingData() { - return bindingData; - } - - } - - private static class HttpServiceContextImpl implements HttpServiceContext { - - private Class serviceClass; - - private Object proxyBindingData; - - public HttpServiceContextImpl(Class serviceClass, Object proxyBindingData) { - this.serviceClass = serviceClass; - this.proxyBindingData = proxyBindingData; - } - - @Override - public Class getServiceClasss() { - return serviceClass; - } - - @Override - public Object getProxyBindingData() { - return proxyBindingData; - } - - } - - /** - * HttpServiceRequest 是对一次实际的服务调用转换生成的HTTP请求的模型; - * - * @author haiq - * - */ - private static class HttpServiceRequest implements ServiceRequest { - - private HttpMethod method; - - private URI uri; - - private ByteBuffer body; - - private Properties headers = new Properties(); - - private NamedParamMap requestParams; - - private Object[] args; - - public HttpServiceRequest(HttpMethod method, URI uri, NamedParamMap requestParams, ByteBuffer body, - Object[] args) { - this.method = method; - this.uri = uri; - this.requestParams = requestParams; - this.body = body; - this.args = args; - } - - /* - * (non-Javadoc) - * - * @see my.utils.http.agent.Request#getMethod() - */ - @Override - public HttpMethod getHttpMethod() { - return method; - } - - @Override - public NamedParamMap getRequestParams() { - return requestParams; - } - - /* - * (non-Javadoc) - * - * @see my.utils.http.agent.Request#getUri() - */ - @Override - public URI getUri() { - return uri; - } - - /* - * (non-Javadoc) - * - * @see my.utils.http.agent.Request#getBody() - */ - @Override - public ByteBuffer getBody() { - return body; - } - - @SuppressWarnings("unused") - public void setHeader(String name, String value) { - headers.setProperty(name, value); - } - - public Properties getHeaders() { - return headers; - } - - @Override - public Object[] getArgs() { - return args; - } - - } -} +package com.jd.blockchain.utils.http.agent; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.http.Consts; +import org.apache.http.Header; +import org.apache.http.HttpHeaders; +import org.apache.http.NameValuePair; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.springframework.beans.BeanUtils; +import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; + +import com.jd.blockchain.utils.http.HttpAction; +import com.jd.blockchain.utils.http.HttpMethod; +import com.jd.blockchain.utils.http.HttpService; +import com.jd.blockchain.utils.http.HttpServiceContext; +import com.jd.blockchain.utils.http.HttpServiceException; +import com.jd.blockchain.utils.http.HttpStatusException; +import com.jd.blockchain.utils.http.NamedParam; +import com.jd.blockchain.utils.http.NamedParamMap; +import com.jd.blockchain.utils.http.PathParam; +import com.jd.blockchain.utils.http.RequestBody; +import com.jd.blockchain.utils.http.RequestBodyConverter; +import com.jd.blockchain.utils.http.RequestParam; +import com.jd.blockchain.utils.http.RequestParamFilter; +import com.jd.blockchain.utils.http.RequestParamMap; +import com.jd.blockchain.utils.http.ResponseBodyConverterFactory; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.StringConverter; +import com.jd.blockchain.utils.http.converters.NullResponseConverter; +import com.jd.blockchain.utils.http.converters.StringResponseConverter; + +/** + * http 服务代理; + * + * @author haiq + * + */ +public class HttpServiceAgent { + + private static final NamedParam[] EMPTY_PARAMS = {}; + + private static Map, HttpServiceAgent> serviceAgentMap = new ConcurrentHashMap, HttpServiceAgent>(); + + private Class serviceClass; + + private RequestBodyConverter defaultRequestBodyConverter; + + private ResponseConverter defaultResponseConverter; + + private ResponseBodyConverterFactory responseConverterFactory; + + private AuthorizationHeaderResovler authorizationHeaderResolver; + + private Map actions = new HashMap<>(); + + private HttpServiceAgent(Class serviceClass, + AuthorizationHeaderResovler authResolver) { + this.serviceClass = serviceClass; + this.authorizationHeaderResolver = authResolver; + + resolveService(); + } + + /** + * 创建映射指定服务接口的 HTTP 服务代理; + * + * @param serviceClass + * 服务的接口类型; + * @param serviceEndpoint + * 连接到服务提供者服务器的相关设置; + * @param authorizationHeader + * 安全认证头部; + * @return + */ + public static T createService(Class serviceClass, ServiceEndpoint serviceEndpoint, + RequestHeader... authorizationHeaders) { + return createService(serviceClass, serviceEndpoint, null, null, authorizationHeaders); + } + + /** + * 创建映射指定服务接口的 HTTP 服务代理; + * + * @param serviceClass + * 服务的接口类型; + * @param serviceEndpoint + * 服务终结点; + * @return + */ + public static T createService(Class serviceClass, ServiceEndpoint serviceEndpoint) { + return createService(serviceClass, serviceEndpoint, (AuthorizationHeaderResovler) null); + } + + /** + * 创建映射指定服务接口的 HTTP 服务代理; + * + * @param serviceClass + * 定义了服务的接口类型; + * @param serviceEndpoint + * 服务终结点; + * @param authorizationHeaderResolver + * 安全认证头部的解析器; + * @return + */ + public static T createService(Class serviceClass, ServiceEndpoint serviceEndpoint, + AuthorizationHeaderResovler authorizationHeaderResolver) { + return createService(serviceClass, serviceEndpoint, null, authorizationHeaderResolver); + } + + /** + * 创建映射指定服务接口的 HTTP 服务代理; + * + * @param serviceClass + * 定义了服务的接口类型; + * @param serviceEndpoint + * 服务终结点; + * @param connectionManager + * 连接管理器; + * @param authorizationHeaderResolver + * 安全认证头部的解析器; + * @param headers + * 请求头部; + * @return + */ + public static T createService(Class serviceClass, ServiceEndpoint serviceEndpoint, + ServiceConnectionManager connectionManager, AuthorizationHeaderResovler authorizationHeaderResolver, + RequestHeader... headers) { + ServiceConnection connection = null; + if (connectionManager == null) { + connection = ServiceConnectionManager.connect(serviceEndpoint); + } else { + connection = connectionManager.create(serviceEndpoint); + } + return createService(serviceClass, connection, authorizationHeaderResolver, headers); + } + + /** + * 创建映射指定服务接口的 HTTP 服务代理; + * + * @param serviceClass + * 定义了服务的接口类型; + * @param serviceEndpoint + * 服务终结点; + * @param connectionManager + * 连接管理器; + * @param authorizationHeaderResolver + * 安全认证头部的解析器; + * @param headers + * 请求头部; + * @return + */ + public static T createService(Class serviceClass, ServiceConnection connection, + AuthorizationHeaderResovler authorizationHeaderResolver, RequestHeader... headers) { + return createService(serviceClass, connection, authorizationHeaderResolver, headers, null); + } + + /** + * 创建映射指定服务接口的 HTTP 服务代理; + * + * @param serviceClass + * 定义了服务的接口类型; + * @param serviceEndpoint + * 服务终结点; + * @param connectionManager + * 连接管理器; + * @param authorizationHeaderResolver + * 安全认证头部的解析器; + * @param headers + * 请求头部; + * @param bindingData + * 由调用者指定的绑定对象;
+ * 该对象将被关联到 HttpServiceContext 上;调用者可以通过此对象将某些数据对象传递到调用过程的一些处理组件上,例如 + * {@link ResponseConverter}; + * @return + */ + public static T createService(Class serviceClass, ServiceConnection connection, + AuthorizationHeaderResovler authorizationHeaderResolver, RequestHeader[] headers, Object bindingData) { + if (serviceClass == null) { + throw new IllegalArgumentException("Service class is null!"); + } + if (!(connection instanceof HttpServiceConnection)) { + throw new IllegalArgumentException( + "Illegal service connection! It must be created by the ServiceConnectionManager!"); + } + HttpServiceConnection httpConnection = (HttpServiceConnection) connection; + // 避免反复解析同一个服务类型; + HttpServiceAgent agent = serviceAgentMap.get(serviceClass); + if (agent == null) { + synchronized (serviceClass) { + agent = serviceAgentMap.get(serviceClass); + if (agent == null) { + agent = new HttpServiceAgent(serviceClass, authorizationHeaderResolver); + serviceAgentMap.put(serviceClass, agent); + } + } + } + + // CloseableHttpClient httpClient = createHttpClient(serviceEndpoint, + // connectionManager); + + ServiceInvocationHandler invocationHandler = new ServiceInvocationHandler(agent, httpConnection, headers, + bindingData); + + @SuppressWarnings("unchecked") + T serviceProxy = (T) Proxy.newProxyInstance(serviceClass.getClassLoader(), new Class[] { serviceClass }, + invocationHandler); + return serviceProxy; + } + + private void resolveService() { + // 处理服务路径; + HttpService serviceAnno = serviceClass.getAnnotation(HttpService.class); + if (serviceAnno == null) { + throw new IllegalHttpServiceDefinitionException( + "The specific service was not tag with HttpService annotation!"); + } + String servicePath = serviceAnno.path(); + servicePath = StringUtils.cleanPath(servicePath); + if (StringUtils.isEmpty(servicePath)) { + throw new IllegalHttpServiceDefinitionException( + "Illegal path or no path was specified for the HttpService!-- path=" + serviceAnno.path()); + } + + // 实例化服务的默认请求体参数转换器; + Class defaultRequestBodyConverterClazz = serviceAnno.defaultRequestBodyConverter(); + if (defaultRequestBodyConverterClazz != null && defaultRequestBodyConverterClazz != RequestBodyConverter.class) { + if (RequestBodyConverter.class.isAssignableFrom(defaultRequestBodyConverterClazz)) { + defaultRequestBodyConverter = (RequestBodyConverter) BeanUtils.instantiate(defaultRequestBodyConverterClazz); + } else { + throw new IllegalHttpServiceDefinitionException( + "The specified default request body converter of service doesn't implement the interface " + + RequestBodyConverter.class.getName() + "!"); + } + } + + // 实例化服务的默认回复转换器; + Class defaultResponseConverterClazz = serviceAnno.defaultResponseConverter(); + if (defaultResponseConverterClazz != null && defaultResponseConverterClazz != ResponseConverter.class) { + if (ResponseConverter.class.isAssignableFrom(defaultResponseConverterClazz)) { + defaultResponseConverter = (ResponseConverter) BeanUtils.instantiate(defaultResponseConverterClazz); + } else { + throw new IllegalHttpServiceDefinitionException( + "The specified default response converter of service doesn't implement the interface " + + ResponseConverter.class.getName() + "!"); + } + } + Class responseConverterFactoryClazz = serviceAnno.responseConverterFactory(); + if (responseConverterFactoryClazz != null && responseConverterFactoryClazz != ResponseBodyConverterFactory.class) { + if (ResponseBodyConverterFactory.class.isAssignableFrom(responseConverterFactoryClazz)) { + this.responseConverterFactory = (ResponseBodyConverterFactory) BeanUtils + .instantiate(responseConverterFactoryClazz); + } else { + throw new IllegalHttpServiceDefinitionException( + "The specified response converter factory of service doesn't implement the interface " + + ResponseBodyConverterFactory.class.getName() + "!"); + } + + } + + // 解析服务操作; +// Method[] mths = ReflectionUtils.getAllDeclaredMethods(serviceClass); + Method[] mths = serviceClass.getMethods(); + for (Method mth : mths) { + ServiceActionContext actionContext = resolveAction( mth, servicePath); + if (actionContext != null) { + actions.put(mth, actionContext); + } + } + } + + /** + * 解析指定的方法; + * + * 如果指定的方法不符合解析策略则返回 null; + * + * @param serviceEndpoint + * @param mth + * @param servicePath + * @return + */ + private ServiceActionContext resolveAction(Method mth, String servicePath) { + // 生成路径模板; + HttpAction actionAnno = mth.getAnnotation(HttpAction.class); + if (actionAnno == null) { + // 未声明的方法不做解析; + return null; + } + String actionPath = StringUtils.cleanPath(actionAnno.path()); + if (StringUtils.isEmpty(actionPath)) { + actionPath = mth.getName(); + } + RequestPathTemplate pathTemplate = new RequestPathTemplate(servicePath, actionPath); + + // 校验请求你方法; + if (actionAnno.method() == null) { + throw new IllegalHttpServiceDefinitionException("The http method of action was not specified!"); + } + + String contentType = actionAnno.contentType(); + if (contentType != null) { + contentType = contentType.trim(); + if (contentType.length() == 0) { + contentType = null; + } + } + + RequestParamFilter reqParamFilter = createRequestParamFilter(actionAnno); + ResponseConverter responseConverter = createResponseConverter(actionAnno, mth); + + // 获取参数定义; + // 参数列表中, RequestBody 最多只能定义一个; + RequestBodyResolverComposite bodyResolverComposite = new RequestBodyResolverComposite(); + Class[] paramTypes = mth.getParameterTypes(); + Annotation[][] paramAnnos = mth.getParameterAnnotations(); + + List> reqParamAnnos = new LinkedList>(); + List> reqParamMapAnnos = new LinkedList>(); + List> pathParamAnnos = new LinkedList>(); + for (int i = 0; i < paramTypes.length; i++) { + RequestBody reqBodyAnno = findAnnotation(RequestBody.class, paramAnnos[i]); + RequestParam reqParamAnno = findAnnotation(RequestParam.class, paramAnnos[i]); + RequestParamMap reqParamsAnno = findAnnotation(RequestParamMap.class, paramAnnos[i]); + PathParam pathParamAnno = findAnnotation(PathParam.class, paramAnnos[i]); + if (hasConflictiveAnnotation(reqBodyAnno, reqParamAnno, reqParamsAnno, pathParamAnno)) { + // 存在冲突的定义; + throw new IllegalHttpServiceDefinitionException( + "The argument[" + i + "] of action has conflictive definition!"); + } +// if (bodyResolver != null && reqBodyAnno != null) { +// throw new IllegalHttpServiceDefinitionException("Define more than one request body for the action!"); +// } + if (reqBodyAnno != null) { + RequestBodyResolver reqBodyResolver = createBodyResolver(new ArgDefEntry(i, paramTypes[i], reqBodyAnno)); + bodyResolverComposite.addRequestBodyResolver(reqBodyResolver); + } + if (reqParamAnno != null) { + reqParamAnnos.add(new ArgDefEntry(i, paramTypes[i], reqParamAnno)); + } + if (reqParamsAnno != null) { + reqParamMapAnnos.add(new ArgDefEntry(i, paramTypes[i], reqParamsAnno)); + } + if (pathParamAnno != null) { + pathParamAnnos.add(new ArgDefEntry(i, paramTypes[i], pathParamAnno)); + } + } + RequestParamResolver reqParamResolver = createRequestParamResolver(reqParamAnnos, reqParamMapAnnos); + PathParamResolver pathParamResolver = createPathParamResolver(pathParamAnnos); +// if (bodyResolverComposite == null) { +// bodyResolverComposite = RequestBodyResolvers.NULL_BODY_RESOLVER; +// } + + // 获取声明的异常列表; + Class[] thrownExceptionTypes = mth.getExceptionTypes(); + + ServiceActionContext actionContext = new ServiceActionContext(mth, actionAnno.method(), contentType, + pathTemplate, pathParamResolver, reqParamFilter, reqParamResolver, bodyResolverComposite, responseConverter, + thrownExceptionTypes, actionAnno.resolveContentOnHttpError()); + return actionContext; + } + + @SuppressWarnings("unchecked") + private static T findAnnotation(Class clazz, Annotation[] annos) { + for (Annotation annotation : annos) { + if (clazz.isAssignableFrom(annotation.getClass())) { + return (T) annotation; + } + } + return null; + } + + private RequestParamFilter createRequestParamFilter(HttpAction actionDef) { + Class reqParamFilterClass = actionDef.requestParamFilter(); + if (reqParamFilterClass == null || reqParamFilterClass == RequestParamFilter.class) { + return NullRequestParamFilter.INSTANCE; + } + if (RequestParamFilter.class.isAssignableFrom(reqParamFilterClass)) { + return (RequestParamFilter) BeanUtils.instantiate(reqParamFilterClass); + } else { + throw new IllegalHttpServiceDefinitionException( + "The specified RequestParamFilter doesn't implement the interface " + + RequestParamFilter.class.getName() + "!"); + } + } + + /** + * 创建回复结果转换器; + * + * @param actionDef + * @param retnClazz + * @return + */ + private ResponseConverter createResponseConverter(HttpAction actionDef, Method mth) { + Class retnClazz = mth.getReturnType(); + if (Void.class.equals(retnClazz)) { + return NullResponseConverter.INSTANCE; + } + Class respConverterClass = actionDef.responseConverter(); + if (respConverterClass == null || respConverterClass == ResponseConverter.class) { + // 未设置方法级别的回复转换器; + if (defaultResponseConverter != null) { + // 如果未设置方法级别的回复转换器,且设置了服务级别的默认回复转换器,则应用服务级别的默认回复转换器; + return defaultResponseConverter; + } + if (responseConverterFactory != null) { + return responseConverterFactory.createResponseConverter(actionDef, mth); + } + } + if (respConverterClass != null && respConverterClass != ResponseConverter.class) { + if (ResponseConverter.class.isAssignableFrom(respConverterClass)) { + return (ResponseConverter) BeanUtils.instantiate(respConverterClass); + } else { + throw new IllegalHttpServiceDefinitionException( + "The specified response converter doesn't implement the interface " + + ResponseConverter.class.getName() + "!"); + } + } + // create default response converter; + return DefaultResponseConverterFactory.INSTANCE.createResponseConverter(actionDef, mth); + + // if (byte[].class == retnClazz) { + // return ByteArrayResponseConverter.INSTANCE; + // } + // if (String.class == retnClazz) { + // return StringResponseConverter.INSTANCE; + // } + // // TODO:未处理 基本类型、输入输出流; + // return new JsonResponseConverter(retnClazz); + } + + /** + * 创建路径参数解析器; + * + * @param pathParamAnnos + * @return + */ + private PathParamResolver createPathParamResolver(List> pathParamAnnos) { + if (pathParamAnnos.size() == 0) { + return PathParamResolvers.NONE_PATH_PARAM_RESOLVER; + } + List> pathParamDefs = new LinkedList>(); + for (ArgDefEntry entry : pathParamAnnos) { + if (StringUtils.isEmpty(entry.getDefinition().name())) { + throw new IllegalHttpServiceDefinitionException("The name of path parameter is empty!"); + } + + Class converterClazz = entry.getDefinition().converter(); + StringConverter converter = StringConverterFactory.instantiateStringConverter(converterClazz); + ArgDefEntry argDefEntry = new ArgDefEntry(entry.getIndex(), + entry.getArgType(), new PathParamDefinition(entry.getDefinition().name(), converter)); + pathParamDefs.add(argDefEntry); + } + + return PathParamResolvers.createResolver(pathParamDefs); + } + + /** + * 创建请求参数解析器; + * + * @param reqParamAnnos + * @return + */ + private RequestParamResolver createRequestParamResolver(List> reqParamAnnos, + List> reqParamsAnnos) { + List> reqDefs = RequestParamDefinition + .resolveSingleParamDefinitions(reqParamAnnos); + List> reqMapDefs = RequestParamMapDefinition + .resolveParamMapDefinitions(reqParamsAnnos); + + return RequestParamResolvers.createParamMapResolver(reqDefs, reqMapDefs); + + } + + /** + * @param paramIndex + * @param parameter + * @param reqBodyAnnoEntry + * @return + */ + private RequestBodyResolver createBodyResolver(ArgDefEntry reqBodyAnnoEntry) { + Class converterClazz = reqBodyAnnoEntry.getDefinition().converter(); + RequestBodyConverter converter = null; + if (converterClazz == RequestBodyConverter.class || converterClazz == null) { + converter = defaultRequestBodyConverter; + if (converter == null) { + // create default body converter; + converter = new TypeAutoAdaptingRequestBodyConverter(reqBodyAnnoEntry.getArgType()); + } + } else { + if (!ClassUtils.isAssignable(RequestBodyConverter.class, converterClazz)) { + throw new IllegalHttpServiceDefinitionException( + "The specified body converter doesn't implement the interface " + + RequestBodyConverter.class.getName() + "!"); + } + converter = (RequestBodyConverter) BeanUtils.instantiate(converterClazz); + } + + RequestBodyDefinition reqBodyDef = new RequestBodyDefinition(reqBodyAnnoEntry.getDefinition().required(), + converter); + ArgDefEntry reqBodyDefEntry = new ArgDefEntry( + reqBodyAnnoEntry.getIndex(), reqBodyAnnoEntry.getArgType(), reqBodyDef); + return RequestBodyResolvers.createArgumentResolver(reqBodyDefEntry); + } + + /** + * 检查传入的三个参数中是否有两个或两个以上为非空; + * + * @param reqBodyAnno + * @param reqParamAnno + * @param pathParamAnno + * @return 有两个或两个以上为非空时返回 true; + * + * 全部为 null 或只有一个为 null 时,返回 false; + */ + private static boolean hasConflictiveAnnotation(RequestBody reqBodyAnno, RequestParam reqParamAnno, + RequestParamMap reqParamsAnno, PathParam pathParamAnno) { + return 1 < (reqBodyAnno == null ? 0 : 1) + (reqParamAnno == null ? 0 : 1) + (reqParamsAnno == null ? 0 : 1) + + (pathParamAnno == null ? 0 : 1); + } + + /** + * 解析被调用的方法,映射为 http 请求; + */ + private Object invoke(ServiceEndpoint serviceEndpoint, HttpServiceContext serviceContext, CloseableHttpClient httpClient, RequestHeader[] headers, + Method method, Object[] args) throws Throwable { + ServiceActionContext actionContext = actions.get(method); + if (actionContext == null) { + throw new UnsupportedOperationException("The invoked method was not a service action!"); + } + try { + HttpServiceRequest request = resolveRequest(serviceEndpoint, actionContext, args); + + HttpUriRequest httpRequest = buildRequest(request); + + // 设置预定义的头部; + setHeaders(httpRequest, headers); + // 设置解析请求生成的头部; + setHeaders(httpRequest, request.getHeaders()); + if (authorizationHeaderResolver != null) { + AuthorizationHeader auth = authorizationHeaderResolver.generateHeader(request); + // 设置认证属性; + buildAuthorization(httpRequest, auth); + } + + // 设置默认的 Content-Type; + Header[] contentTypeHeaders = httpRequest.getHeaders(HttpHeaders.CONTENT_TYPE); + if (contentTypeHeaders == null || contentTypeHeaders.length == 0) { + httpRequest.setHeader(HttpHeaders.CONTENT_TYPE, "application/json"); + } + CloseableHttpClient closeableHttpClient = HttpClientPool.getHttpClient(serviceEndpoint.getHost(), serviceEndpoint.getPort()); + + CloseableHttpResponse response = closeableHttpClient.execute(httpRequest); +// CloseableHttpResponse response = httpClient.execute(httpRequest); + try { + // 引发 http 异常; + if (response.getStatusLine().getStatusCode() >= 400) { + processAndThrowHttpException(actionContext, request, response); + // 注:上一步已抛出异常; + return null; + } + InputStream respStream = response.getEntity().getContent(); + Object respObject = actionContext.getResponseConverter().getResponse(request, respStream, + serviceContext); + return respObject; + } finally { + response.close(); + } + } catch (Exception e) { + if (isCustomThownException(e, actionContext)) { + throw e; + } + if (e instanceof HttpServiceException) { + throw (HttpServiceException) e; + } + throw new HttpServiceException(e.getMessage(), e); + } + } + + private void setHeaders(HttpUriRequest httpRequest, RequestHeader[] headers) { + if (headers == null) { + return; + } + for (RequestHeader header : headers) { + httpRequest.setHeader(header.getName(), header.getValue()); + } + } + + private void setHeaders(HttpUriRequest httpRequest, Properties customHeaders) { + Set names = customHeaders.stringPropertyNames(); + for (String name : names) { + httpRequest.setHeader(name, customHeaders.getProperty(name)); + } + } + + /** + * 判断指定的异常是否属于指定服务操作的接口方法通过 throws 声明的异常; + * + * @param e + * @param actionContext + * @return + */ + private boolean isCustomThownException(Exception e, ServiceActionContext actionContext) { + Class exType = e.getClass(); + Class[] thrownExTypes = actionContext.getThrownExceptionTypes(); + for (Class thrExType : thrownExTypes) { + if (thrExType.isAssignableFrom(exType)) { + return true; + } + } + return false; + } + + /** + * 处理 HTTP 错误,并抛出 HttpStatusException 异常; + * + * @param actionContext + * @param response + */ + private void processAndThrowHttpException(ServiceActionContext actionContext, ServiceRequest request, + CloseableHttpResponse response) throws HttpStatusException { + String content = null; + if (actionContext.isResolveContentOnHttpError()) { + try { + InputStream respStream = response.getEntity().getContent(); + content = (String) StringResponseConverter.INSTANCE.getResponse(request, respStream, null); + } catch (UnsupportedOperationException e) { + throw new HttpServiceException(e.getMessage(), e); + } catch (IOException e) { + throw new HttpServiceException(e.getMessage(), e); + } catch (Exception e) { + if (e instanceof HttpServiceException) { + throw (HttpServiceException) e; + } + throw new HttpServiceException(e.getMessage(), e); + } + } + String errMsg = String.format("[status=%s] %s", response.getStatusLine().getStatusCode(), content); + throw new HttpStatusException(response.getStatusLine().getStatusCode(), errMsg); + } + + private HttpServiceRequest resolveRequest(ServiceEndpoint serviceEndpoint, ServiceActionContext actionContext, Object[] args) throws IOException { + HttpServiceRequest request; + switch (actionContext.getRequestMethod()) { + case GET: + request = resolveGetRequest(serviceEndpoint, actionContext, args); + break; + case POST: + case PUT: + request = resolvePostOrPutRequest(serviceEndpoint, actionContext, args); + break; + case DELETE: + request = resolveDeleteRequest(serviceEndpoint, actionContext, args); + break; + default: + throw new UnsupportedOperationException( + "Unsupported http method '" + actionContext.getRequestMethod() + "'!"); + } + if (actionContext.getContentType() != null) { + request.setHeader(HttpHeaders.CONTENT_TYPE, actionContext.getContentType()); + } + return request; + } + + /** + * 创建请求; + * + * @param actionContext + * @param args + * @return + */ + private HttpUriRequest buildRequest(ServiceRequest request) { + ByteBuffer bodyBytes = null; + if (request.getBody() != null) { + // bodyStream = new ByteArrayInputStream(request.getBody().array()); + + bodyBytes = request.getBody(); + } + NamedParamMap reqParams = request.getRequestParams(); + switch (request.getHttpMethod()) { + case GET: + return new HttpGet(request.getUri()); + case POST: + HttpPost httppost = new HttpPost(request.getUri()); + + if (reqParams != null) { + // 以 form 表单提交; + NamedParam[] propNames = reqParams.getParams(); + List formParams = new ArrayList(); + for (NamedParam param : propNames) { + formParams.add(new BasicNameValuePair(param.getName(), param.getValue())); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formParams, Consts.UTF_8); + httppost.setEntity(formEntity); + // 设置默认的 Content-Type; + httppost.setHeader(formEntity.getContentType()); + } + if (bodyBytes != null) { + // 查询参数以 Stream body 方式提交; + ByteArrayEntity entity = new ByteArrayEntity(bodyBytes.array()); + // HttpEntity streamEntity = new InputStreamEntity(bodyStream); + httppost.setEntity(entity); + // 设置默认的 Content-Type; + httppost.setHeader(entity.getContentType()); + } + return httppost; + case PUT: + HttpPut httpput = new HttpPut(request.getUri()); + if (reqParams != null) { + // 以 form 表单提交; + NamedParam[] paramValues = reqParams.getParams(); + List formParams = new ArrayList(); + for (NamedParam param : paramValues) { + formParams.add(new BasicNameValuePair(param.getName(), param.getValue())); + } + UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formParams, Consts.UTF_8); + httpput.setEntity(formEntity); + } + if (bodyBytes != null) { + // 查询参数以 Stream body 方式提交; + ByteArrayEntity entity = new ByteArrayEntity(bodyBytes.array()); + // HttpEntity streamEntity = new InputStreamEntity(bodyStream); + httpput.setEntity(entity); + } + return httpput; + case DELETE: + // HttpDelete httpDelete = new HttpDelete(uri); + LocalHttpDelete httpDelete = new LocalHttpDelete(request.getUri()); + // 查询参数以 delete body 方式提交 + if (bodyBytes != null) { + ByteArrayEntity entity = new ByteArrayEntity(bodyBytes.array()); + // HttpEntity entity = new InputStreamEntity(bodyStream); + httpDelete.setEntity(entity); + } + // HttpEntity entity = new InputStreamEntity(bodyStream); + // httpDelete.setEntity(entity); + return httpDelete; + default: + throw new UnsupportedOperationException("Unsupported http method '" + request.getHttpMethod() + "'!"); + } + } + + /** + * 设置http请求头的Authorization属性 + * + * @param request + * @param setting + */ + private void buildAuthorization(HttpUriRequest request, RequestHeader setting) { + request.addHeader(setting.getName(), setting.getValue()); + } + + /** + * 创建 http post 请求; + * + * @param actionContext + * @param args + * @return + * @throws IOException + */ + // private HttpServiceRequest resolvePostRequest(ServiceActionContext + // actionContext, Object[] args) + // throws IOException { + // Map pathParams = + // actionContext.getPathParamResolver().resolve(args); + // Properties reqParams = + // actionContext.getRequestParamResolver().resolve(args); + // InputStream inputStream = + // actionContext.getRequestBodyResolver().resolve(args); + // URI uri = actionContext.getPathTemplate().generateRequestURI(pathParams, + // reqParams, + // ServiceActionContext.DEFAULT_CHARSET); + // byte[] bytes = BytesUtils.copyToBytes(inputStream); + // return new HttpServiceRequest(HttpMethod.POST, uri, + // ByteBuffer.wrap(bytes)); + // } + + /** + * 创建http put请求 + * + * @param actionContext + * @param args + * @return + * @throws IOException + */ + // private HttpServiceRequest resolvePutRequest(ServiceActionContext + // actionContext, Object[] args) throws IOException { + // Map pathParams = + // actionContext.getPathParamResolver().resolve(args); + // Properties reqParams = + // actionContext.getRequestParamResolver().resolve(args); + // InputStream inputStream = + // actionContext.getRequestBodyResolver().resolve(args); + // URI uri = actionContext.getPathTemplate().generateRequestURI(pathParams, + // reqParams, + // ServiceActionContext.DEFAULT_CHARSET); + // byte[] bytes = BytesUtils.copyToBytes(inputStream); + // return new HttpServiceRequest(HttpMethod.PUT, uri, + // ByteBuffer.wrap(bytes)); + // } + + private HttpServiceRequest resolvePostOrPutRequest(ServiceEndpoint serviceEndpoint, ServiceActionContext actionContext, Object[] args) + throws IOException { + // 解析路径参数; + Map pathParams = actionContext.getPathParamResolver().resolve(args); + HttpMethod httpMethod = actionContext.getRequestMethod(); + + // 解析 RequestBody; + ByteArrayOutputStream out = new ByteArrayOutputStream(); + actionContext.getRequestBodyResolver().resolve(args, out); + byte[] bodyBytes = out.toByteArray(); + + boolean noBody = bodyBytes.length == 0; + + // 解析 RequestParam; + NamedParamMap reqParams = actionContext.getRequestParamResolver().resolve(args); + boolean noReqParams = reqParams.isEmpty(); + actionContext.getRequestParamFilter().filter(httpMethod, reqParams); + + // 如果只有 RequestBody 标注的参数,则以 RequestBody 参数的序列化输出作为请求体; + if ((!noBody) && noReqParams) { + URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, new NamedParamMap(), + ServiceActionContext.DEFAULT_CHARSET); + ByteBuffer body = ByteBuffer.wrap(bodyBytes); + return new HttpServiceRequest(httpMethod, uri, null, body, args); + } + // 如果没有 RequestBody 标注的参数,只有 RequestParam ,则 RequestParam 通过请求体以表单格式提交; + if (noBody && (!noReqParams)) { + URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, new NamedParamMap(), + ServiceActionContext.DEFAULT_CHARSET); + return new HttpServiceRequest(httpMethod, uri, reqParams, null, args); + } + + // 如果同时有 RequestBody 标注的参数和 RequestParam 标注的参数,则以 RequestBody + // 参数的序列化输出作为请求体,RequestParam 作为 URL 参数; + if ((!noBody) && (!noReqParams)) { + URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, reqParams, + ServiceActionContext.DEFAULT_CHARSET); + ByteBuffer body = ByteBuffer.wrap(bodyBytes); + return new HttpServiceRequest(httpMethod, uri, null, body, args); + } + + // 既没有 RequestBody,也没有 RequestParam; + URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, new NamedParamMap(), + ServiceActionContext.DEFAULT_CHARSET); + return new HttpServiceRequest(httpMethod, uri, null, null, args); + } + + /** + * 创建http get请求 + * + * @param actionContext + * @param args + * @return + */ + private HttpServiceRequest resolveGetRequest(ServiceEndpoint serviceEndpoint, ServiceActionContext actionContext, Object[] args) { + Map pathParams = actionContext.getPathParamResolver().resolve(args); + NamedParamMap reqParams = actionContext.getRequestParamResolver().resolve(args); + URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, reqParams, + ServiceActionContext.DEFAULT_CHARSET); + // 对于 get 请求,请求参数已经编码到 URI 中,所以不必再传递出去进行处理; + return new HttpServiceRequest(HttpMethod.GET, uri, null, null, args); + } + + /** + * 创建http delete请求 + * + * @param actionContext + * @param args + * @return + * @throws IOException + */ + private HttpServiceRequest resolveDeleteRequest(ServiceEndpoint serviceEndpoint, ServiceActionContext actionContext, Object[] args) + throws IOException { + Map pathParams = actionContext.getPathParamResolver().resolve(args); + + NamedParamMap reqParams = actionContext.getRequestParamResolver().resolve(args); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + actionContext.getRequestBodyResolver().resolve(args, out); + byte[] bodyBytes = out.toByteArray(); + + URI uri = actionContext.getPathTemplate().generateRequestURI(serviceEndpoint, pathParams, reqParams, + ServiceActionContext.DEFAULT_CHARSET); + + ByteBuffer body = bodyBytes.length == 0 ? null : ByteBuffer.wrap(bodyBytes); + return new HttpServiceRequest(HttpMethod.DELETE, uri, null, body, args); + } + + private static class ServiceInvocationHandler implements InvocationHandler, HttpServiceContext { + + private HttpServiceAgent serviceAgent; + + private HttpServiceConnection connection; + + private RequestHeader[] headers; + + private Object bindingData; + + public ServiceInvocationHandler(HttpServiceAgent serviceAgent, HttpServiceConnection connection, + RequestHeader[] headers, Object bindingData) { + this.serviceAgent = serviceAgent; + this.connection = connection; + this.headers = headers; + this.bindingData = bindingData; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return serviceAgent.invoke(connection.getEndpoint(), this, connection.getHttpClient(), headers, method, args); + } + + @Override + public Class getServiceClasss() { + return serviceAgent.serviceClass; + } + + @Override + public Object getProxyBindingData() { + return bindingData; + } + + } + + private static class HttpServiceContextImpl implements HttpServiceContext { + + private Class serviceClass; + + private Object proxyBindingData; + + public HttpServiceContextImpl(Class serviceClass, Object proxyBindingData) { + this.serviceClass = serviceClass; + this.proxyBindingData = proxyBindingData; + } + + @Override + public Class getServiceClasss() { + return serviceClass; + } + + @Override + public Object getProxyBindingData() { + return proxyBindingData; + } + + } + + /** + * HttpServiceRequest 是对一次实际的服务调用转换生成的HTTP请求的模型; + * + * @author haiq + * + */ + private static class HttpServiceRequest implements ServiceRequest { + + private HttpMethod method; + + private URI uri; + + private ByteBuffer body; + + private Properties headers = new Properties(); + + private NamedParamMap requestParams; + + private Object[] args; + + public HttpServiceRequest(HttpMethod method, URI uri, NamedParamMap requestParams, ByteBuffer body, + Object[] args) { + this.method = method; + this.uri = uri; + this.requestParams = requestParams; + this.body = body; + this.args = args; + } + + /* + * (non-Javadoc) + * + * @see my.utils.http.agent.Request#getMethod() + */ + @Override + public HttpMethod getHttpMethod() { + return method; + } + + @Override + public NamedParamMap getRequestParams() { + return requestParams; + } + + /* + * (non-Javadoc) + * + * @see my.utils.http.agent.Request#getUri() + */ + @Override + public URI getUri() { + return uri; + } + + /* + * (non-Javadoc) + * + * @see my.utils.http.agent.Request#getBody() + */ + @Override + public ByteBuffer getBody() { + return body; + } + + @SuppressWarnings("unused") + public void setHeader(String name, String value) { + headers.setProperty(name, value); + } + + public Properties getHeaders() { + return headers; + } + + @Override + public Object[] getArgs() { + return args; + } + + } +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/HttpServiceConnection.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/HttpServiceConnection.java index 1fb2a219..1dbfac00 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/HttpServiceConnection.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/HttpServiceConnection.java @@ -1,43 +1,43 @@ -package com.jd.blockchain.utils.http.agent; - -import java.io.IOException; - -import org.apache.http.impl.client.CloseableHttpClient; - -class HttpServiceConnection implements ServiceConnection{ - - private ServiceEndpoint endpoint; - - private CloseableHttpClient httpClient; - - HttpServiceConnection(ServiceEndpoint endpoint, CloseableHttpClient httpClient) { - this.endpoint = endpoint; - this.httpClient = httpClient; - } - - CloseableHttpClient getHttpClient() { - CloseableHttpClient cli = httpClient; - if (cli == null) { - throw new IllegalArgumentException("HttpServiceConnection has been closed!"); - } - return cli; - } - - @Override - public void close() { - CloseableHttpClient cli = httpClient; - if (cli != null) { - httpClient = null; - try { - cli.close(); - } catch (IOException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - } - - @Override - public ServiceEndpoint getEndpoint() { - return endpoint; - } -} +package com.jd.blockchain.utils.http.agent; + +import java.io.IOException; + +import org.apache.http.impl.client.CloseableHttpClient; + +class HttpServiceConnection implements ServiceConnection{ + + private ServiceEndpoint endpoint; + + private CloseableHttpClient httpClient; + + HttpServiceConnection(ServiceEndpoint endpoint, CloseableHttpClient httpClient) { + this.endpoint = endpoint; + this.httpClient = httpClient; + } + + CloseableHttpClient getHttpClient() { + CloseableHttpClient cli = httpClient; + if (cli == null) { + throw new IllegalArgumentException("HttpServiceConnection has been closed!"); + } + return cli; + } + + @Override + public void close() { + CloseableHttpClient cli = httpClient; + if (cli != null) { + httpClient = null; + try { + cli.close(); + } catch (IOException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + } + + @Override + public ServiceEndpoint getEndpoint() { + return endpoint; + } +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/IllegalHttpServiceDefinitionException.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/IllegalHttpServiceDefinitionException.java index 4ea58bc6..3e11eebd 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/IllegalHttpServiceDefinitionException.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/IllegalHttpServiceDefinitionException.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.utils.http.agent; - -import com.jd.blockchain.utils.http.HttpServiceException; - -public class IllegalHttpServiceDefinitionException extends HttpServiceException{ - - private static final long serialVersionUID = -6866487415383367958L; - - public IllegalHttpServiceDefinitionException() { - } - - public IllegalHttpServiceDefinitionException(String message) { - super(message); - } - - public IllegalHttpServiceDefinitionException(String message, Throwable cause) { - super(message, cause); - } - - -} +package com.jd.blockchain.utils.http.agent; + +import com.jd.blockchain.utils.http.HttpServiceException; + +public class IllegalHttpServiceDefinitionException extends HttpServiceException{ + + private static final long serialVersionUID = -6866487415383367958L; + + public IllegalHttpServiceDefinitionException() { + } + + public IllegalHttpServiceDefinitionException(String message) { + super(message); + } + + public IllegalHttpServiceDefinitionException(String message, Throwable cause) { + super(message, cause); + } + + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/LocalHttpDelete.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/LocalHttpDelete.java index 1240123e..41e92e84 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/LocalHttpDelete.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/LocalHttpDelete.java @@ -1,33 +1,33 @@ -package com.jd.blockchain.utils.http.agent; - -import java.net.URI; - -import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; - -public class LocalHttpDelete extends HttpEntityEnclosingRequestBase { - - public final static String METHOD_NAME = "DELETE"; - - public LocalHttpDelete() { - super(); - } - - public LocalHttpDelete(final URI uri) { - super(); - setURI(uri); - } - - /** - * @throws IllegalArgumentException if the uri is invalid. - */ - public LocalHttpDelete(final String uri) { - super(); - setURI(URI.create(uri)); - } - - @Override - public String getMethod() { - return METHOD_NAME; - } - -} +package com.jd.blockchain.utils.http.agent; + +import java.net.URI; + +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; + +public class LocalHttpDelete extends HttpEntityEnclosingRequestBase { + + public final static String METHOD_NAME = "DELETE"; + + public LocalHttpDelete() { + super(); + } + + public LocalHttpDelete(final URI uri) { + super(); + setURI(uri); + } + + /** + * @throws IllegalArgumentException if the uri is invalid. + */ + public LocalHttpDelete(final String uri) { + super(); + setURI(URI.create(uri)); + } + + @Override + public String getMethod() { + return METHOD_NAME; + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/NullRequestParamFilter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/NullRequestParamFilter.java index b46b089b..d0ba8aed 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/NullRequestParamFilter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/NullRequestParamFilter.java @@ -1,18 +1,18 @@ -package com.jd.blockchain.utils.http.agent; - -import com.jd.blockchain.utils.http.HttpMethod; -import com.jd.blockchain.utils.http.NamedParamMap; -import com.jd.blockchain.utils.http.RequestParamFilter; - -public class NullRequestParamFilter implements RequestParamFilter{ - - public static RequestParamFilter INSTANCE = new NullRequestParamFilter(); - - private NullRequestParamFilter() { - } - - @Override - public void filter(HttpMethod requestMethod, NamedParamMap requestParams) { - } - -} +package com.jd.blockchain.utils.http.agent; + +import com.jd.blockchain.utils.http.HttpMethod; +import com.jd.blockchain.utils.http.NamedParamMap; +import com.jd.blockchain.utils.http.RequestParamFilter; + +public class NullRequestParamFilter implements RequestParamFilter{ + + public static RequestParamFilter INSTANCE = new NullRequestParamFilter(); + + private NullRequestParamFilter() { + } + + @Override + public void filter(HttpMethod requestMethod, NamedParamMap requestParams) { + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamDefinition.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamDefinition.java index 6f6adfef..1ab8afc9 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamDefinition.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamDefinition.java @@ -1,23 +1,23 @@ -package com.jd.blockchain.utils.http.agent; - -import com.jd.blockchain.utils.http.StringConverter; - -class PathParamDefinition { - - private String name; - - private StringConverter converter; - - public String getName() { - return name; - } - - public StringConverter getConverter() { - return converter; - } - - public PathParamDefinition(String name, StringConverter converter) { - this.name = name; - this.converter = converter; - } -} +package com.jd.blockchain.utils.http.agent; + +import com.jd.blockchain.utils.http.StringConverter; + +class PathParamDefinition { + + private String name; + + private StringConverter converter; + + public String getName() { + return name; + } + + public StringConverter getConverter() { + return converter; + } + + public PathParamDefinition(String name, StringConverter converter) { + this.name = name; + this.converter = converter; + } +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamResolver.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamResolver.java index 3f9ae4be..1e078889 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamResolver.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamResolver.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.utils.http.agent; - -import java.util.Map; - -/** - * 路径参数解析器; - * - * @author haiq - * - */ -interface PathParamResolver { - - /** - * 将方法参数列表解析为路径参数的变量表; - * - * @param args 方法参数列表; - * @return - */ - Map resolve(Object[] args); - -} +package com.jd.blockchain.utils.http.agent; + +import java.util.Map; + +/** + * 路径参数解析器; + * + * @author haiq + * + */ +interface PathParamResolver { + + /** + * 将方法参数列表解析为路径参数的变量表; + * + * @param args 方法参数列表; + * @return + */ + Map resolve(Object[] args); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamResolvers.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamResolvers.java index c5148bdd..859d784d 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamResolvers.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PathParamResolvers.java @@ -1,56 +1,56 @@ -package com.jd.blockchain.utils.http.agent; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -class PathParamResolvers { - - /** - * 空路径参数解析器; - */ - public static final PathParamResolver NONE_PATH_PARAM_RESOLVER = new NonePathParamResolver(); - - /** - * 根据指定的路径参数定义创建路径参数解析器; - * - * @param paramDefinitions - * @return - */ - public static PathParamResolver createResolver(List> paramDefinitions) { - return new ArgArrayPathParamResolver(paramDefinitions); - } - - private static class ArgArrayPathParamResolver implements PathParamResolver { - - private List> paramDefinitions; - - public ArgArrayPathParamResolver(List> paramDefinitions) { - this.paramDefinitions = paramDefinitions; - } - - @Override - public Map resolve(Object[] args) { - Map pathParams = new HashMap(); - String name; - String value; - for (ArgDefEntry paramDef : paramDefinitions) { - name = paramDef.getDefinition().getName(); - value = paramDef.getDefinition().getConverter().toString(args[paramDef.getIndex()]); - pathParams.put(name, value); - } - return pathParams; - } - } - - private static class NonePathParamResolver implements PathParamResolver { - - @SuppressWarnings("unchecked") - @Override - public Map resolve(Object[] args) { - return Collections.EMPTY_MAP; - } - - } -} +package com.jd.blockchain.utils.http.agent; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class PathParamResolvers { + + /** + * 空路径参数解析器; + */ + public static final PathParamResolver NONE_PATH_PARAM_RESOLVER = new NonePathParamResolver(); + + /** + * 根据指定的路径参数定义创建路径参数解析器; + * + * @param paramDefinitions + * @return + */ + public static PathParamResolver createResolver(List> paramDefinitions) { + return new ArgArrayPathParamResolver(paramDefinitions); + } + + private static class ArgArrayPathParamResolver implements PathParamResolver { + + private List> paramDefinitions; + + public ArgArrayPathParamResolver(List> paramDefinitions) { + this.paramDefinitions = paramDefinitions; + } + + @Override + public Map resolve(Object[] args) { + Map pathParams = new HashMap(); + String name; + String value; + for (ArgDefEntry paramDef : paramDefinitions) { + name = paramDef.getDefinition().getName(); + value = paramDef.getDefinition().getConverter().toString(args[paramDef.getIndex()]); + pathParams.put(name, value); + } + return pathParams; + } + } + + private static class NonePathParamResolver implements PathParamResolver { + + @SuppressWarnings("unchecked") + @Override + public Map resolve(Object[] args) { + return Collections.EMPTY_MAP; + } + + } +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PojoPropertiesConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PojoPropertiesConverter.java index 04e35415..5dc355c0 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PojoPropertiesConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PojoPropertiesConverter.java @@ -1,72 +1,72 @@ -package com.jd.blockchain.utils.http.agent; - -import java.beans.PropertyDescriptor; -import java.util.LinkedList; -import java.util.List; - -import org.springframework.beans.BeanWrapper; -import org.springframework.beans.BeanWrapperImpl; -import org.springframework.core.convert.TypeDescriptor; - -import com.jd.blockchain.utils.http.NamedParamMap; -import com.jd.blockchain.utils.http.PropertiesConverter; -import com.jd.blockchain.utils.http.RequestParam; - -/** - * 对 POJO 属性的转换器; - * - * @author haiq - * - */ -public class PojoPropertiesConverter implements PropertiesConverter { - - private List propNames = new LinkedList(); - - private RequestParamResolver paramResolver; - - private Class argType; - - public PojoPropertiesConverter(Class argType) { - this.argType = argType; - resolveParamProperties(); - } - - private void resolveParamProperties() { - BeanWrapperImpl beanWrapper = new BeanWrapperImpl(argType); - List> reqParamDefs = new LinkedList>(); - PropertyDescriptor[] propDescs = beanWrapper.getPropertyDescriptors(); - TypeDescriptor propTypeDesc; - for (PropertyDescriptor propDesc : propDescs) { - propTypeDesc = beanWrapper.getPropertyTypeDescriptor(propDesc.getName()); - - RequestParam reqParamAnno = propTypeDesc.getAnnotation(RequestParam.class); - if (reqParamAnno == null) { - // 忽略未标注 RequestParam 的属性; - continue; - } - RequestParamDefinition reqParamDef = RequestParamDefinition.resolveDefinition(reqParamAnno); - ArgDefEntry defEntry = new ArgDefEntry(reqParamDefs.size(), propTypeDesc.getType(), - reqParamDef); - reqParamDefs.add(defEntry); - propNames.add(propDesc.getName()); - } - paramResolver = RequestParamResolvers.createParamResolver(reqParamDefs); - } - - @Override - public NamedParamMap toProperties(Object arg) { - if (propNames.size() == 0) { - return new NamedParamMap(); - } - BeanWrapper beanWrapper = new BeanWrapperImpl(arg); - Object[] propValues = new Object[propNames.size()]; - int i = 0; - for (String propName : propNames) { - propValues[i] = beanWrapper.getPropertyValue(propName); - i++; - } - NamedParamMap params = paramResolver.resolve(propValues); - return params; - } - -} +package com.jd.blockchain.utils.http.agent; + +import java.beans.PropertyDescriptor; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.core.convert.TypeDescriptor; + +import com.jd.blockchain.utils.http.NamedParamMap; +import com.jd.blockchain.utils.http.PropertiesConverter; +import com.jd.blockchain.utils.http.RequestParam; + +/** + * 对 POJO 属性的转换器; + * + * @author haiq + * + */ +public class PojoPropertiesConverter implements PropertiesConverter { + + private List propNames = new LinkedList(); + + private RequestParamResolver paramResolver; + + private Class argType; + + public PojoPropertiesConverter(Class argType) { + this.argType = argType; + resolveParamProperties(); + } + + private void resolveParamProperties() { + BeanWrapperImpl beanWrapper = new BeanWrapperImpl(argType); + List> reqParamDefs = new LinkedList>(); + PropertyDescriptor[] propDescs = beanWrapper.getPropertyDescriptors(); + TypeDescriptor propTypeDesc; + for (PropertyDescriptor propDesc : propDescs) { + propTypeDesc = beanWrapper.getPropertyTypeDescriptor(propDesc.getName()); + + RequestParam reqParamAnno = propTypeDesc.getAnnotation(RequestParam.class); + if (reqParamAnno == null) { + // 忽略未标注 RequestParam 的属性; + continue; + } + RequestParamDefinition reqParamDef = RequestParamDefinition.resolveDefinition(reqParamAnno); + ArgDefEntry defEntry = new ArgDefEntry(reqParamDefs.size(), propTypeDesc.getType(), + reqParamDef); + reqParamDefs.add(defEntry); + propNames.add(propDesc.getName()); + } + paramResolver = RequestParamResolvers.createParamResolver(reqParamDefs); + } + + @Override + public NamedParamMap toProperties(Object arg) { + if (propNames.size() == 0) { + return new NamedParamMap(); + } + BeanWrapper beanWrapper = new BeanWrapperImpl(arg); + Object[] propValues = new Object[propNames.size()]; + int i = 0; + for (String propName : propNames) { + propValues[i] = beanWrapper.getPropertyValue(propName); + i++; + } + NamedParamMap params = paramResolver.resolve(propValues); + return params; + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PropertiesConverterFactory.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PropertiesConverterFactory.java index 00e8e474..7f62d058 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PropertiesConverterFactory.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/PropertiesConverterFactory.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.utils.http.agent; - -import org.springframework.beans.BeanUtils; - -import com.jd.blockchain.utils.http.PropertiesConverter; -import com.jd.blockchain.utils.http.StringConverter; - -public class PropertiesConverterFactory { - - public static PropertiesConverter instantiatePropertiesConverter(Class converterClazz, Class argType){ - if (converterClazz == null || PropertiesConverter.class == converterClazz || PojoPropertiesConverter.class == converterClazz) { - return new PojoPropertiesConverter(argType); - } - if (!PropertiesConverter.class.isAssignableFrom(converterClazz)) { - throw new IllegalHttpServiceDefinitionException( - "The specified converter of path param doesn't implement the interface " - + StringConverter.class.getName() + "!"); - } - - PropertiesConverter converter = (PropertiesConverter) BeanUtils.instantiate(converterClazz); - return converter; - } - -} +package com.jd.blockchain.utils.http.agent; + +import org.springframework.beans.BeanUtils; + +import com.jd.blockchain.utils.http.PropertiesConverter; +import com.jd.blockchain.utils.http.StringConverter; + +public class PropertiesConverterFactory { + + public static PropertiesConverter instantiatePropertiesConverter(Class converterClazz, Class argType){ + if (converterClazz == null || PropertiesConverter.class == converterClazz || PojoPropertiesConverter.class == converterClazz) { + return new PojoPropertiesConverter(argType); + } + if (!PropertiesConverter.class.isAssignableFrom(converterClazz)) { + throw new IllegalHttpServiceDefinitionException( + "The specified converter of path param doesn't implement the interface " + + StringConverter.class.getName() + "!"); + } + + PropertiesConverter converter = (PropertiesConverter) BeanUtils.instantiate(converterClazz); + return converter; + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyDefinition.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyDefinition.java index e30938e1..c5951272 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyDefinition.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyDefinition.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.utils.http.agent; - -import com.jd.blockchain.utils.http.RequestBodyConverter; - -class RequestBodyDefinition { - - private boolean required; - - private RequestBodyConverter converter; - - public RequestBodyDefinition(boolean required, RequestBodyConverter converter) { - this.required = required; - this.converter = converter; - } - - public RequestBodyConverter getConverter() { - return converter; - } - - public boolean isRequired() { - return required; - } - -} +package com.jd.blockchain.utils.http.agent; + +import com.jd.blockchain.utils.http.RequestBodyConverter; + +class RequestBodyDefinition { + + private boolean required; + + private RequestBodyConverter converter; + + public RequestBodyDefinition(boolean required, RequestBodyConverter converter) { + this.required = required; + this.converter = converter; + } + + public RequestBodyConverter getConverter() { + return converter; + } + + public boolean isRequired() { + return required; + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolver.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolver.java index c7dead00..d80d092d 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolver.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolver.java @@ -1,9 +1,9 @@ -package com.jd.blockchain.utils.http.agent; - -import java.io.OutputStream; - -interface RequestBodyResolver { - - void resolve(Object[] args, OutputStream out); - -} +package com.jd.blockchain.utils.http.agent; + +import java.io.OutputStream; + +interface RequestBodyResolver { + + void resolve(Object[] args, OutputStream out); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolverComposite.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolverComposite.java index 9b5ec9bb..8cc384d8 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolverComposite.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolverComposite.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.utils.http.agent; - -import java.io.OutputStream; -import java.util.LinkedList; -import java.util.List; - -class RequestBodyResolverComposite implements RequestBodyResolver { - - private List resolverList = new LinkedList(); - - @Override - public void resolve(Object[] args, OutputStream out) { - for (RequestBodyResolver resolver : resolverList) { - resolver.resolve(args, out); - } - } - - public void addRequestBodyResolver(RequestBodyResolver resolver) { - resolverList.add(resolver); - } -} +package com.jd.blockchain.utils.http.agent; + +import java.io.OutputStream; +import java.util.LinkedList; +import java.util.List; + +class RequestBodyResolverComposite implements RequestBodyResolver { + + private List resolverList = new LinkedList(); + + @Override + public void resolve(Object[] args, OutputStream out) { + for (RequestBodyResolver resolver : resolverList) { + resolver.resolve(args, out); + } + } + + public void addRequestBodyResolver(RequestBodyResolver resolver) { + resolverList.add(resolver); + } +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolvers.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolvers.java index e9ee9b8b..c649f0b8 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolvers.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestBodyResolvers.java @@ -1,63 +1,63 @@ -package com.jd.blockchain.utils.http.agent; - -import java.io.IOException; -import java.io.OutputStream; - -import com.jd.blockchain.utils.http.HttpServiceException; -import com.jd.blockchain.utils.io.RuntimeIOException; - -class RequestBodyResolvers { - - public static final RequestBodyResolver NULL_BODY_RESOLVER = new NullBodyResolver(); - - /** - * 创建基于参数列表的解析器; - * - * @param argIndex - * 要作为 body 输出的参数的位置; - * @param converter - * 参数值转换器; - * @return - */ - public static RequestBodyResolver createArgumentResolver(ArgDefEntry defEntry) { - return new ArgurmentResolver(defEntry); - } - - private static final class ArgurmentResolver implements RequestBodyResolver { - - private ArgDefEntry defEntry; - - public ArgurmentResolver(ArgDefEntry defEntry) { - this.defEntry = defEntry; - } - - @Override - public void resolve(Object[] args, OutputStream out) { - Object arg = args[defEntry.getIndex()]; - if (arg == null && defEntry.getDefinition().isRequired()) { - throw new HttpServiceException("The required body argument is null!"); - } - try { - defEntry.getDefinition().getConverter().write(arg, out); - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - } - - /** - * 空的 body 解析器; - * - * @author haiq - * - */ - private static final class NullBodyResolver implements RequestBodyResolver { - - @Override - public void resolve(Object[] args, OutputStream out) { - //Do nothing; - } - - } -} +package com.jd.blockchain.utils.http.agent; + +import java.io.IOException; +import java.io.OutputStream; + +import com.jd.blockchain.utils.http.HttpServiceException; +import com.jd.blockchain.utils.io.RuntimeIOException; + +class RequestBodyResolvers { + + public static final RequestBodyResolver NULL_BODY_RESOLVER = new NullBodyResolver(); + + /** + * 创建基于参数列表的解析器; + * + * @param argIndex + * 要作为 body 输出的参数的位置; + * @param converter + * 参数值转换器; + * @return + */ + public static RequestBodyResolver createArgumentResolver(ArgDefEntry defEntry) { + return new ArgurmentResolver(defEntry); + } + + private static final class ArgurmentResolver implements RequestBodyResolver { + + private ArgDefEntry defEntry; + + public ArgurmentResolver(ArgDefEntry defEntry) { + this.defEntry = defEntry; + } + + @Override + public void resolve(Object[] args, OutputStream out) { + Object arg = args[defEntry.getIndex()]; + if (arg == null && defEntry.getDefinition().isRequired()) { + throw new HttpServiceException("The required body argument is null!"); + } + try { + defEntry.getDefinition().getConverter().write(arg, out); + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + } + + /** + * 空的 body 解析器; + * + * @author haiq + * + */ + private static final class NullBodyResolver implements RequestBodyResolver { + + @Override + public void resolve(Object[] args, OutputStream out) { + //Do nothing; + } + + } +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestHeader.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestHeader.java index 4512da70..a4a3fdb2 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestHeader.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestHeader.java @@ -1,9 +1,9 @@ -package com.jd.blockchain.utils.http.agent; - -public interface RequestHeader { - - String getName(); - - String getValue(); - -} +package com.jd.blockchain.utils.http.agent; + +public interface RequestHeader { + + String getName(); + + String getValue(); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamDefinition.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamDefinition.java index 9a7d3033..864f2b51 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamDefinition.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamDefinition.java @@ -1,74 +1,74 @@ -package com.jd.blockchain.utils.http.agent; - -import java.util.LinkedList; -import java.util.List; - -import org.springframework.util.StringUtils; - -import com.jd.blockchain.utils.http.RequestParam; -import com.jd.blockchain.utils.http.StringConverter; - -class RequestParamDefinition { - - private String name; - - private boolean required; - - private boolean array; - - private String ignoreValue; - - private StringConverter converter; - - public RequestParamDefinition(String name, boolean required, boolean array, String ignoreValue, - StringConverter converter) { - this.name = name; - this.required = required; - this.array = array; - this.ignoreValue = ignoreValue; - this.converter = converter; - } - - public String getName() { - return name; - } - - public boolean isRequired() { - return required; - } - - public boolean isArray() { - return array; - } - - public String getIgnoreValue() { - return ignoreValue; - } - - public StringConverter getConverter() { - return converter; - } - - public static List> resolveSingleParamDefinitions( - List> reqParamAnnos) { - List> reqDefs = new LinkedList>(); - for (ArgDefEntry entry : reqParamAnnos) { - RequestParam reqParamAnno = entry.getDefinition(); - RequestParamDefinition reqDef = resolveDefinition(reqParamAnno); - reqDefs.add(new ArgDefEntry(entry.getIndex(), entry.getArgType(), reqDef)); - } - return reqDefs; - } - - public static RequestParamDefinition resolveDefinition(RequestParam reqParamAnno) { - if (StringUtils.isEmpty(reqParamAnno.name())) { - throw new IllegalHttpServiceDefinitionException("The name of request parameter is empty!"); - } - - Class converterClazz = reqParamAnno.converter(); - StringConverter converter = StringConverterFactory.instantiateStringConverter(converterClazz); - RequestParamDefinition reqDef = new RequestParamDefinition(reqParamAnno.name(), reqParamAnno.required(), - reqParamAnno.array(), reqParamAnno.ignoreValue(), converter); - return reqDef; - } -} +package com.jd.blockchain.utils.http.agent; + +import java.util.LinkedList; +import java.util.List; + +import org.springframework.util.StringUtils; + +import com.jd.blockchain.utils.http.RequestParam; +import com.jd.blockchain.utils.http.StringConverter; + +class RequestParamDefinition { + + private String name; + + private boolean required; + + private boolean array; + + private String ignoreValue; + + private StringConverter converter; + + public RequestParamDefinition(String name, boolean required, boolean array, String ignoreValue, + StringConverter converter) { + this.name = name; + this.required = required; + this.array = array; + this.ignoreValue = ignoreValue; + this.converter = converter; + } + + public String getName() { + return name; + } + + public boolean isRequired() { + return required; + } + + public boolean isArray() { + return array; + } + + public String getIgnoreValue() { + return ignoreValue; + } + + public StringConverter getConverter() { + return converter; + } + + public static List> resolveSingleParamDefinitions( + List> reqParamAnnos) { + List> reqDefs = new LinkedList>(); + for (ArgDefEntry entry : reqParamAnnos) { + RequestParam reqParamAnno = entry.getDefinition(); + RequestParamDefinition reqDef = resolveDefinition(reqParamAnno); + reqDefs.add(new ArgDefEntry(entry.getIndex(), entry.getArgType(), reqDef)); + } + return reqDefs; + } + + public static RequestParamDefinition resolveDefinition(RequestParam reqParamAnno) { + if (StringUtils.isEmpty(reqParamAnno.name())) { + throw new IllegalHttpServiceDefinitionException("The name of request parameter is empty!"); + } + + Class converterClazz = reqParamAnno.converter(); + StringConverter converter = StringConverterFactory.instantiateStringConverter(converterClazz); + RequestParamDefinition reqDef = new RequestParamDefinition(reqParamAnno.name(), reqParamAnno.required(), + reqParamAnno.array(), reqParamAnno.ignoreValue(), converter); + return reqDef; + } +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamMapDefinition.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamMapDefinition.java index 6ddfaf9e..37b176c8 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamMapDefinition.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamMapDefinition.java @@ -1,57 +1,57 @@ -package com.jd.blockchain.utils.http.agent; - -import java.util.LinkedList; -import java.util.List; - -import org.springframework.util.StringUtils; - -import com.jd.blockchain.utils.http.PropertiesConverter; -import com.jd.blockchain.utils.http.RequestParamMap; - -class RequestParamMapDefinition { - - private String prefix; - - private boolean required; - - private PropertiesConverter converter; - - public RequestParamMapDefinition(String prefix, String seperator, boolean required, PropertiesConverter converter) { - if (prefix == null || prefix.length() ==0) { - this.prefix = ""; - }else{ - this.prefix = prefix + seperator; - } - this.required = required; - this.converter = converter; - } - - public boolean isRequired() { - return required; - } - - public PropertiesConverter getConverter() { - return converter; - } - - public String getPrefix() { - return prefix; - } - - - public static List> resolveParamMapDefinitions(List> reqParamAnnos){ - List> reqDefs = new LinkedList>(); - for (ArgDefEntry entry : reqParamAnnos) { - RequestParamMap reqParamAnno = entry.getDefinition(); - String prefix = StringUtils.trimWhitespace(reqParamAnno.prefix()); - String seperator = StringUtils.trimWhitespace(reqParamAnno.seperator()); - - Class converterClazz = reqParamAnno.converter(); - PropertiesConverter converter = PropertiesConverterFactory.instantiatePropertiesConverter(converterClazz, entry.getArgType()); - RequestParamMapDefinition reqDef = new RequestParamMapDefinition(prefix, seperator, reqParamAnno.required(),converter); - reqDefs.add(new ArgDefEntry(entry.getIndex(), entry.getArgType(), reqDef)); - } - return reqDefs; - } - -} +package com.jd.blockchain.utils.http.agent; + +import java.util.LinkedList; +import java.util.List; + +import org.springframework.util.StringUtils; + +import com.jd.blockchain.utils.http.PropertiesConverter; +import com.jd.blockchain.utils.http.RequestParamMap; + +class RequestParamMapDefinition { + + private String prefix; + + private boolean required; + + private PropertiesConverter converter; + + public RequestParamMapDefinition(String prefix, String seperator, boolean required, PropertiesConverter converter) { + if (prefix == null || prefix.length() ==0) { + this.prefix = ""; + }else{ + this.prefix = prefix + seperator; + } + this.required = required; + this.converter = converter; + } + + public boolean isRequired() { + return required; + } + + public PropertiesConverter getConverter() { + return converter; + } + + public String getPrefix() { + return prefix; + } + + + public static List> resolveParamMapDefinitions(List> reqParamAnnos){ + List> reqDefs = new LinkedList>(); + for (ArgDefEntry entry : reqParamAnnos) { + RequestParamMap reqParamAnno = entry.getDefinition(); + String prefix = StringUtils.trimWhitespace(reqParamAnno.prefix()); + String seperator = StringUtils.trimWhitespace(reqParamAnno.seperator()); + + Class converterClazz = reqParamAnno.converter(); + PropertiesConverter converter = PropertiesConverterFactory.instantiatePropertiesConverter(converterClazz, entry.getArgType()); + RequestParamMapDefinition reqDef = new RequestParamMapDefinition(prefix, seperator, reqParamAnno.required(),converter); + reqDefs.add(new ArgDefEntry(entry.getIndex(), entry.getArgType(), reqDef)); + } + return reqDefs; + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamResolver.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamResolver.java index 3ac501bb..e405ed98 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamResolver.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamResolver.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.utils.http.agent; - -import com.jd.blockchain.utils.http.NamedParamMap; - -/** - * 请求参数解析器; - * - * @author haiq - * - */ -interface RequestParamResolver { - - /** - * 将方法参数列表解析为请求参数的变量表; - * - * @param args 方法参数列表; - * @return - */ - NamedParamMap resolve(Object[] args); - -} +package com.jd.blockchain.utils.http.agent; + +import com.jd.blockchain.utils.http.NamedParamMap; + +/** + * 请求参数解析器; + * + * @author haiq + * + */ +interface RequestParamResolver { + + /** + * 将方法参数列表解析为请求参数的变量表; + * + * @param args 方法参数列表; + * @return + */ + NamedParamMap resolve(Object[] args); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamResolvers.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamResolvers.java index be76a92d..515d014f 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamResolvers.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestParamResolvers.java @@ -1,220 +1,220 @@ -package com.jd.blockchain.utils.http.agent; - -import java.util.LinkedList; -import java.util.List; - -import org.springframework.util.CollectionUtils; - -import com.jd.blockchain.utils.http.HttpServiceException; -import com.jd.blockchain.utils.http.NamedParamMap; -import com.jd.blockchain.utils.http.StringConverter; - -/** - * 请求参数解析器; - * - * @author haiq - * - */ -abstract class RequestParamResolvers { - - public static final RequestParamResolver NONE_REQUEST_PARAM_RESOLVER = new NoneRequestParamResolver(); - - /** - * 创建解析器; - * - * @param definitions - * 方法参数定义; - * @return - */ - public static RequestParamResolver createParamMapResolver( - List> reqParamDefinitions, - List> reqParamMapDefinitions) { - if ((!CollectionUtils.isEmpty(reqParamDefinitions)) && (!CollectionUtils.isEmpty(reqParamMapDefinitions))) { - RequestParamResolver resolver1 = createParamResolver(reqParamDefinitions); - RequestParamResolver resolver2 = createParamMapResolver(reqParamMapDefinitions); - return new MultiRequestParamResolverWrapper(resolver1, resolver2); - } - if (!CollectionUtils.isEmpty(reqParamDefinitions)) { - return createParamResolver(reqParamDefinitions); - } - if (!CollectionUtils.isEmpty(reqParamMapDefinitions)) { - return createParamMapResolver(reqParamMapDefinitions); - } - return NONE_REQUEST_PARAM_RESOLVER; - } - - /** - * 创建解析器; - * - * @param definitions - * 方法参数定义; - * @return - */ - public static RequestParamResolver createParamMapResolver( - List> definitions) { - return new ArgArrayRequestParamMapResolver(definitions); - } - - /** - * 创建解析器; - * - * @param definitions - * 方法参数定义; - * @return - */ - public static RequestParamResolver createParamResolver(List> definitions) { - return new ArgArrayRequestParamResolver(definitions); - } - - /** - * 方法参数表解析器; - * - * @author haiq - * - */ - private static class ArgArrayRequestParamMapResolver implements RequestParamResolver { - - private List> definitions; - - /** - * @param definitions - */ - public ArgArrayRequestParamMapResolver(List> definitions) { - this.definitions = new LinkedList>(definitions); - } - - @Override - public NamedParamMap resolve(Object[] args) { - NamedParamMap params = new NamedParamMap(); - for (ArgDefEntry defEntry : definitions) { - RequestParamMapDefinition def = defEntry.getDefinition(); - Object argValue = args[defEntry.getIndex()]; - if (argValue == null && def.isRequired()) { - throw new HttpServiceException("The required argument object is null!"); - } - - NamedParamMap extParams = def.getConverter().toProperties(argValue); - if (extParams.isEmpty()) { - if (def.isRequired()) { - throw new HttpServiceException("The required request parameter map is empty!"); - } - // 非必需参数,忽略空值; - continue; - } - if (extParams != null) { - // 合并参数; - params.merge(extParams, def.getPrefix()); - } - } // End of for; - return params; - } - - } - - /** - * 方法参数解析器; - * - * @author haiq - * - */ - private static class ArgArrayRequestParamResolver implements RequestParamResolver { - - private List> paramDefinitions; - - /** - * @param paramDefinitions - */ - public ArgArrayRequestParamResolver(List> paramDefinitions) { - this.paramDefinitions = new LinkedList>(paramDefinitions); - } - - @Override - public NamedParamMap resolve(Object[] args) { - NamedParamMap params = new NamedParamMap(); - for (ArgDefEntry defEntry : paramDefinitions) { - RequestParamDefinition def = defEntry.getDefinition(); - Object arg = args[defEntry.getIndex()]; - if (arg == null && def.isRequired()) { - throw new HttpServiceException("The required argument object is null!"); - } - - resovleParams(params, def, arg); - } // End of for; - return params; - } - - private void resovleParams(NamedParamMap params, RequestParamDefinition def, Object arg) { - if (def.isArray() && arg != null) { - if (arg.getClass().isArray()) { - Object[] valObjs = (Object[]) arg; - for (Object val : valObjs) { - resovleParamValue(params, def, val); - } - } - }else { - resovleParamValue(params, def, arg); - } - } - - private void resovleParamValue(NamedParamMap params, RequestParamDefinition def, Object arg) { - String value = def.getConverter().toString(arg); - if (value == null) { - if (def.isRequired()) { - throw new HttpServiceException("The required argument value is null!"); - } - // not required, and ignore null value; - return; - } - if (value.equals(def.getIgnoreValue())) { - // ignore ; - return; - } - params.addParam(def.getName(), value); - } - - } - - /** - * 将多个请求参数解析器的解析结果组合在一起的包装器; - * - * @author haiq - * - */ - private static class MultiRequestParamResolverWrapper implements RequestParamResolver { - - private RequestParamResolver[] resolvers; - - public MultiRequestParamResolverWrapper(RequestParamResolver... resolvers) { - this.resolvers = resolvers; - } - - @Override - public NamedParamMap resolve(Object[] args) { - NamedParamMap params = new NamedParamMap(); - for (RequestParamResolver resolver : resolvers) { - NamedParamMap extParams = resolver.resolve(args); - params.merge(extParams); - } - return params; - } - - } - - /** - * 空的请求参数解析器; - * - * 总是返回空的请求参数; - * - * @author haiq - * - */ - private static class NoneRequestParamResolver implements RequestParamResolver { - - @Override - public NamedParamMap resolve(Object[] args) { - return new NamedParamMap(); - } - - } - -} +package com.jd.blockchain.utils.http.agent; + +import java.util.LinkedList; +import java.util.List; + +import org.springframework.util.CollectionUtils; + +import com.jd.blockchain.utils.http.HttpServiceException; +import com.jd.blockchain.utils.http.NamedParamMap; +import com.jd.blockchain.utils.http.StringConverter; + +/** + * 请求参数解析器; + * + * @author haiq + * + */ +abstract class RequestParamResolvers { + + public static final RequestParamResolver NONE_REQUEST_PARAM_RESOLVER = new NoneRequestParamResolver(); + + /** + * 创建解析器; + * + * @param definitions + * 方法参数定义; + * @return + */ + public static RequestParamResolver createParamMapResolver( + List> reqParamDefinitions, + List> reqParamMapDefinitions) { + if ((!CollectionUtils.isEmpty(reqParamDefinitions)) && (!CollectionUtils.isEmpty(reqParamMapDefinitions))) { + RequestParamResolver resolver1 = createParamResolver(reqParamDefinitions); + RequestParamResolver resolver2 = createParamMapResolver(reqParamMapDefinitions); + return new MultiRequestParamResolverWrapper(resolver1, resolver2); + } + if (!CollectionUtils.isEmpty(reqParamDefinitions)) { + return createParamResolver(reqParamDefinitions); + } + if (!CollectionUtils.isEmpty(reqParamMapDefinitions)) { + return createParamMapResolver(reqParamMapDefinitions); + } + return NONE_REQUEST_PARAM_RESOLVER; + } + + /** + * 创建解析器; + * + * @param definitions + * 方法参数定义; + * @return + */ + public static RequestParamResolver createParamMapResolver( + List> definitions) { + return new ArgArrayRequestParamMapResolver(definitions); + } + + /** + * 创建解析器; + * + * @param definitions + * 方法参数定义; + * @return + */ + public static RequestParamResolver createParamResolver(List> definitions) { + return new ArgArrayRequestParamResolver(definitions); + } + + /** + * 方法参数表解析器; + * + * @author haiq + * + */ + private static class ArgArrayRequestParamMapResolver implements RequestParamResolver { + + private List> definitions; + + /** + * @param definitions + */ + public ArgArrayRequestParamMapResolver(List> definitions) { + this.definitions = new LinkedList>(definitions); + } + + @Override + public NamedParamMap resolve(Object[] args) { + NamedParamMap params = new NamedParamMap(); + for (ArgDefEntry defEntry : definitions) { + RequestParamMapDefinition def = defEntry.getDefinition(); + Object argValue = args[defEntry.getIndex()]; + if (argValue == null && def.isRequired()) { + throw new HttpServiceException("The required argument object is null!"); + } + + NamedParamMap extParams = def.getConverter().toProperties(argValue); + if (extParams.isEmpty()) { + if (def.isRequired()) { + throw new HttpServiceException("The required request parameter map is empty!"); + } + // 非必需参数,忽略空值; + continue; + } + if (extParams != null) { + // 合并参数; + params.merge(extParams, def.getPrefix()); + } + } // End of for; + return params; + } + + } + + /** + * 方法参数解析器; + * + * @author haiq + * + */ + private static class ArgArrayRequestParamResolver implements RequestParamResolver { + + private List> paramDefinitions; + + /** + * @param paramDefinitions + */ + public ArgArrayRequestParamResolver(List> paramDefinitions) { + this.paramDefinitions = new LinkedList>(paramDefinitions); + } + + @Override + public NamedParamMap resolve(Object[] args) { + NamedParamMap params = new NamedParamMap(); + for (ArgDefEntry defEntry : paramDefinitions) { + RequestParamDefinition def = defEntry.getDefinition(); + Object arg = args[defEntry.getIndex()]; + if (arg == null && def.isRequired()) { + throw new HttpServiceException("The required argument object is null!"); + } + + resovleParams(params, def, arg); + } // End of for; + return params; + } + + private void resovleParams(NamedParamMap params, RequestParamDefinition def, Object arg) { + if (def.isArray() && arg != null) { + if (arg.getClass().isArray()) { + Object[] valObjs = (Object[]) arg; + for (Object val : valObjs) { + resovleParamValue(params, def, val); + } + } + }else { + resovleParamValue(params, def, arg); + } + } + + private void resovleParamValue(NamedParamMap params, RequestParamDefinition def, Object arg) { + String value = def.getConverter().toString(arg); + if (value == null) { + if (def.isRequired()) { + throw new HttpServiceException("The required argument value is null!"); + } + // not required, and ignore null value; + return; + } + if (value.equals(def.getIgnoreValue())) { + // ignore ; + return; + } + params.addParam(def.getName(), value); + } + + } + + /** + * 将多个请求参数解析器的解析结果组合在一起的包装器; + * + * @author haiq + * + */ + private static class MultiRequestParamResolverWrapper implements RequestParamResolver { + + private RequestParamResolver[] resolvers; + + public MultiRequestParamResolverWrapper(RequestParamResolver... resolvers) { + this.resolvers = resolvers; + } + + @Override + public NamedParamMap resolve(Object[] args) { + NamedParamMap params = new NamedParamMap(); + for (RequestParamResolver resolver : resolvers) { + NamedParamMap extParams = resolver.resolve(args); + params.merge(extParams); + } + return params; + } + + } + + /** + * 空的请求参数解析器; + * + * 总是返回空的请求参数; + * + * @author haiq + * + */ + private static class NoneRequestParamResolver implements RequestParamResolver { + + @Override + public NamedParamMap resolve(Object[] args) { + return new NamedParamMap(); + } + + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestPathTemplate.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestPathTemplate.java index 3d021af7..137bea9e 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestPathTemplate.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestPathTemplate.java @@ -1,87 +1,87 @@ -package com.jd.blockchain.utils.http.agent; - -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.http.NameValuePair; -import org.apache.http.client.utils.URIBuilder; - -import com.jd.blockchain.utils.PathUtils; -import com.jd.blockchain.utils.http.NamedParamMap; - -class RequestPathTemplate { -// private ServiceEndpoint serviceEndpoint; - private String servicePath; - private String actionPath; - - public RequestPathTemplate(String servicePath, String actionPath) { -// this.serviceEndpoint = serviceEndpoint; - this.servicePath = PathUtils.standardize(servicePath); - this.actionPath = PathUtils.standardize(actionPath); - } - - - /** - * 更新请求路径; - * - * @param pathVariableName - * @param value - */ - private static String updateActionPath(String actionPath, String pathVariableName, String value) { - String pathVarName = String.format("{%s}", pathVariableName); - actionPath = actionPath.replace(pathVarName, value); - return actionPath; - } - - /** - * 返回完整的请求URL; - * - * @param pathParams - * 路径参数; - * @param queryParams - * 查询参数; - * @return - */ - public URI generateRequestURI(ServiceEndpoint serviceEndpoint, Map pathParams, NamedParamMap queryParams, - Charset encodingCharset) { - // 生成路径; - String reallyActionPath = createActionPath(pathParams); - String path = PathUtils.concatPaths(serviceEndpoint.getContextPath(), servicePath, reallyActionPath); - path = PathUtils.absolute(path); - - // 生成查询字符串; - URIBuilder uriBuilder = new URIBuilder(); - uriBuilder.setCharset(encodingCharset); - if (serviceEndpoint.isSecure()) { - uriBuilder.setScheme("https"); - }else{ - uriBuilder.setScheme("http"); - } - - uriBuilder.setHost(serviceEndpoint.getHost()); - uriBuilder.setPort(serviceEndpoint.getPort()); - uriBuilder.setPath(path.toString()); - List queryParameters = RequestUtils.createQueryParameters(queryParams); - uriBuilder.setParameters(queryParameters); - try { - return uriBuilder.build(); - } catch (URISyntaxException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } - } - - private String createActionPath(Map pathParams) { - String reallyActionPath = actionPath; - if (pathParams != null) { - for (Entry pathParam : pathParams.entrySet()) { - reallyActionPath = updateActionPath(reallyActionPath, pathParam.getKey(), pathParam.getValue()); - } - } - return reallyActionPath; - } - -} +package com.jd.blockchain.utils.http.agent; + +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URIBuilder; + +import com.jd.blockchain.utils.PathUtils; +import com.jd.blockchain.utils.http.NamedParamMap; + +class RequestPathTemplate { +// private ServiceEndpoint serviceEndpoint; + private String servicePath; + private String actionPath; + + public RequestPathTemplate(String servicePath, String actionPath) { +// this.serviceEndpoint = serviceEndpoint; + this.servicePath = PathUtils.standardize(servicePath); + this.actionPath = PathUtils.standardize(actionPath); + } + + + /** + * 更新请求路径; + * + * @param pathVariableName + * @param value + */ + private static String updateActionPath(String actionPath, String pathVariableName, String value) { + String pathVarName = String.format("{%s}", pathVariableName); + actionPath = actionPath.replace(pathVarName, value); + return actionPath; + } + + /** + * 返回完整的请求URL; + * + * @param pathParams + * 路径参数; + * @param queryParams + * 查询参数; + * @return + */ + public URI generateRequestURI(ServiceEndpoint serviceEndpoint, Map pathParams, NamedParamMap queryParams, + Charset encodingCharset) { + // 生成路径; + String reallyActionPath = createActionPath(pathParams); + String path = PathUtils.concatPaths(serviceEndpoint.getContextPath(), servicePath, reallyActionPath); + path = PathUtils.absolute(path); + + // 生成查询字符串; + URIBuilder uriBuilder = new URIBuilder(); + uriBuilder.setCharset(encodingCharset); + if (serviceEndpoint.isSecure()) { + uriBuilder.setScheme("https"); + }else{ + uriBuilder.setScheme("http"); + } + + uriBuilder.setHost(serviceEndpoint.getHost()); + uriBuilder.setPort(serviceEndpoint.getPort()); + uriBuilder.setPath(path.toString()); + List queryParameters = RequestUtils.createQueryParameters(queryParams); + uriBuilder.setParameters(queryParameters); + try { + return uriBuilder.build(); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + + private String createActionPath(Map pathParams) { + String reallyActionPath = actionPath; + if (pathParams != null) { + for (Entry pathParam : pathParams.entrySet()) { + reallyActionPath = updateActionPath(reallyActionPath, pathParam.getKey(), pathParam.getValue()); + } + } + return reallyActionPath; + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestUtils.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestUtils.java index c47e0a81..205beeb9 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestUtils.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/RequestUtils.java @@ -1,27 +1,27 @@ -package com.jd.blockchain.utils.http.agent; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.apache.http.NameValuePair; -import org.apache.http.message.BasicNameValuePair; - -import com.jd.blockchain.utils.http.NamedParam; -import com.jd.blockchain.utils.http.NamedParamMap; - -public abstract class RequestUtils { - - @SuppressWarnings("unchecked") - public static List createQueryParameters(NamedParamMap queryParams) { - if (queryParams == null || queryParams.isEmpty()) { - return Collections.EMPTY_LIST; - } - List params = new ArrayList(); - NamedParam[] paramValues = queryParams.getParams(); - for (NamedParam param : paramValues) { - params.add(new BasicNameValuePair(param.getName(), param.getValue())); - } - return params; - } -} +package com.jd.blockchain.utils.http.agent; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; + +import com.jd.blockchain.utils.http.NamedParam; +import com.jd.blockchain.utils.http.NamedParamMap; + +public abstract class RequestUtils { + + @SuppressWarnings("unchecked") + public static List createQueryParameters(NamedParamMap queryParams) { + if (queryParams == null || queryParams.isEmpty()) { + return Collections.EMPTY_LIST; + } + List params = new ArrayList(); + NamedParam[] paramValues = queryParams.getParams(); + for (NamedParam param : paramValues) { + params.add(new BasicNameValuePair(param.getName(), param.getValue())); + } + return params; + } +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceActionContext.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceActionContext.java index 8635557d..fa70d5be 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceActionContext.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceActionContext.java @@ -1,148 +1,148 @@ -package com.jd.blockchain.utils.http.agent; - -import java.lang.reflect.Method; -import java.nio.charset.Charset; - -import com.jd.blockchain.utils.http.HttpMethod; -import com.jd.blockchain.utils.http.RequestParamFilter; -import com.jd.blockchain.utils.http.ResponseConverter; - -/** - * 服务操作上下文; - * - * 维持了一个特定的服务操作相关的参数定义; - * - * @author haiq - * - */ -class ServiceActionContext { - - public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); - - private Method serviceMethod; - - private HttpMethod requestMethod; - - private RequestPathTemplate pathTemplate; - - private PathParamResolver pathParamResolver; - - private RequestParamFilter requestParamFilter; - - private RequestParamResolver requestParamResolver; - - private RequestBodyResolver requestBodyResolver; - - private ResponseConverter responseConverter; - - private Class[] thrownExceptionTypes; - - private String contentType; - - private boolean resolveContentOnHttpError; - - /** - * 创建服务操作上下文; - * - * @param serviceMethod - * 服务接口的方法; - * @param requestMethod - * 服务操作调用所采用的 HTTP 方法; - * @param pathTemplate - * 服务操作的 HTTP 路径模板; - * @param pathParamResolver - * 服务操作的 HTTP URL 路径参数解析器; - * @param requestParamResolver - * 服务操作的 HTTP URL 查询参数解析器; - * @param requestBodyResolver - * 服务操作的 HTTP 请求体解析器; - * @param responseConverter - * 服务操作的 HTTP 成功回复结果转换器; - * @param thrownExceptionTypes - * 服务接口的方法通过 throws 关键字声明的异常的类型列表; - * @param resolveContentOnHttpError - * 是否在 HTTP 错误中包含回复的 HTTP 内容; - */ - public ServiceActionContext(Method serviceMethod, HttpMethod requestMethod, String contentType, RequestPathTemplate pathTemplate, - PathParamResolver pathParamResolver, RequestParamFilter requestParamFilter, - RequestParamResolver requestParamResolver, RequestBodyResolver requestBodyResolver, - ResponseConverter responseConverter, Class[] thrownExceptionTypes, - boolean resolveContentOnHttpError) { - this.serviceMethod = serviceMethod; - this.requestMethod = requestMethod; - this.contentType = contentType; - this.pathTemplate = pathTemplate; - this.pathParamResolver = pathParamResolver; - this.requestParamFilter = requestParamFilter; - this.requestParamResolver = requestParamResolver; - this.requestBodyResolver = requestBodyResolver; - this.responseConverter = responseConverter; - this.thrownExceptionTypes = thrownExceptionTypes; - this.resolveContentOnHttpError = resolveContentOnHttpError; - } - - /** - * 请求路径模板; - * - * @return - */ - public RequestPathTemplate getPathTemplate() { - return pathTemplate; - } - - /** - * 路径参数解析器; - * - * @return - */ - public PathParamResolver getPathParamResolver() { - return pathParamResolver; - } - - /** - * 请求参数解析器; - * - * @return - */ - public RequestParamResolver getRequestParamResolver() { - return requestParamResolver; - } - - /** - * 回复结果转换器; - * - * @return - */ - public ResponseConverter getResponseConverter() { - return responseConverter; - } - - public Method getServiceMethod() { - return serviceMethod; - } - - public HttpMethod getRequestMethod() { - return requestMethod; - } - - public RequestBodyResolver getRequestBodyResolver() { - return requestBodyResolver; - } - - public boolean isResolveContentOnHttpError() { - return resolveContentOnHttpError; - } - - public Class[] getThrownExceptionTypes() { - return thrownExceptionTypes; - } - - public RequestParamFilter getRequestParamFilter() { - return requestParamFilter; - } - - public String getContentType() { - return contentType; - } - -} +package com.jd.blockchain.utils.http.agent; + +import java.lang.reflect.Method; +import java.nio.charset.Charset; + +import com.jd.blockchain.utils.http.HttpMethod; +import com.jd.blockchain.utils.http.RequestParamFilter; +import com.jd.blockchain.utils.http.ResponseConverter; + +/** + * 服务操作上下文; + * + * 维持了一个特定的服务操作相关的参数定义; + * + * @author haiq + * + */ +class ServiceActionContext { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Method serviceMethod; + + private HttpMethod requestMethod; + + private RequestPathTemplate pathTemplate; + + private PathParamResolver pathParamResolver; + + private RequestParamFilter requestParamFilter; + + private RequestParamResolver requestParamResolver; + + private RequestBodyResolver requestBodyResolver; + + private ResponseConverter responseConverter; + + private Class[] thrownExceptionTypes; + + private String contentType; + + private boolean resolveContentOnHttpError; + + /** + * 创建服务操作上下文; + * + * @param serviceMethod + * 服务接口的方法; + * @param requestMethod + * 服务操作调用所采用的 HTTP 方法; + * @param pathTemplate + * 服务操作的 HTTP 路径模板; + * @param pathParamResolver + * 服务操作的 HTTP URL 路径参数解析器; + * @param requestParamResolver + * 服务操作的 HTTP URL 查询参数解析器; + * @param requestBodyResolver + * 服务操作的 HTTP 请求体解析器; + * @param responseConverter + * 服务操作的 HTTP 成功回复结果转换器; + * @param thrownExceptionTypes + * 服务接口的方法通过 throws 关键字声明的异常的类型列表; + * @param resolveContentOnHttpError + * 是否在 HTTP 错误中包含回复的 HTTP 内容; + */ + public ServiceActionContext(Method serviceMethod, HttpMethod requestMethod, String contentType, RequestPathTemplate pathTemplate, + PathParamResolver pathParamResolver, RequestParamFilter requestParamFilter, + RequestParamResolver requestParamResolver, RequestBodyResolver requestBodyResolver, + ResponseConverter responseConverter, Class[] thrownExceptionTypes, + boolean resolveContentOnHttpError) { + this.serviceMethod = serviceMethod; + this.requestMethod = requestMethod; + this.contentType = contentType; + this.pathTemplate = pathTemplate; + this.pathParamResolver = pathParamResolver; + this.requestParamFilter = requestParamFilter; + this.requestParamResolver = requestParamResolver; + this.requestBodyResolver = requestBodyResolver; + this.responseConverter = responseConverter; + this.thrownExceptionTypes = thrownExceptionTypes; + this.resolveContentOnHttpError = resolveContentOnHttpError; + } + + /** + * 请求路径模板; + * + * @return + */ + public RequestPathTemplate getPathTemplate() { + return pathTemplate; + } + + /** + * 路径参数解析器; + * + * @return + */ + public PathParamResolver getPathParamResolver() { + return pathParamResolver; + } + + /** + * 请求参数解析器; + * + * @return + */ + public RequestParamResolver getRequestParamResolver() { + return requestParamResolver; + } + + /** + * 回复结果转换器; + * + * @return + */ + public ResponseConverter getResponseConverter() { + return responseConverter; + } + + public Method getServiceMethod() { + return serviceMethod; + } + + public HttpMethod getRequestMethod() { + return requestMethod; + } + + public RequestBodyResolver getRequestBodyResolver() { + return requestBodyResolver; + } + + public boolean isResolveContentOnHttpError() { + return resolveContentOnHttpError; + } + + public Class[] getThrownExceptionTypes() { + return thrownExceptionTypes; + } + + public RequestParamFilter getRequestParamFilter() { + return requestParamFilter; + } + + public String getContentType() { + return contentType; + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceConnection.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceConnection.java index 04f9d611..8530b335 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceConnection.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceConnection.java @@ -1,12 +1,12 @@ -package com.jd.blockchain.utils.http.agent; - -import java.io.Closeable; - -public interface ServiceConnection extends Closeable { - - ServiceEndpoint getEndpoint(); - - @Override - void close(); - -} +package com.jd.blockchain.utils.http.agent; + +import java.io.Closeable; + +public interface ServiceConnection extends Closeable { + + ServiceEndpoint getEndpoint(); + + @Override + void close(); + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceConnectionManager.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceConnectionManager.java index f676fdc6..014b32cd 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceConnectionManager.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceConnectionManager.java @@ -1,137 +1,137 @@ -package com.jd.blockchain.utils.http.agent; - -import java.io.Closeable; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - -import org.apache.http.conn.HttpClientConnectionManager; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; - -public class ServiceConnectionManager implements Closeable { - - private PoolingHttpClientConnectionManager connectionMananeger; - - public ServiceConnectionManager() { - this.connectionMananeger = new PoolingHttpClientConnectionManager(); - setMaxTotal(100).setDefaultMaxPerRoute(20); - } - - public ServiceConnectionManager setMaxTotal(int maxConn) { - connectionMananeger.setMaxTotal(maxConn); - return this; - } - - public ServiceConnectionManager setDefaultMaxPerRoute(int maxConnPerRoute) { - connectionMananeger.setDefaultMaxPerRoute(maxConnPerRoute); - return this; - } - - HttpClientConnectionManager getHttpConnectionManager() { - return connectionMananeger; - } - - /** - * 创建一个受此连接管理器管理的连接; - * - * @param endpoint - * @return - */ - public ServiceConnection create(ServiceEndpoint serviceEndpoint) { - CloseableHttpClient httpClient = createHttpClient(serviceEndpoint, this); - return new HttpServiceConnection(serviceEndpoint, httpClient); - } - - /** - * 创建一个不受管理的连接; - * - * @param serviceEndpoint - * @return - */ - public static ServiceConnection connect(ServiceEndpoint serviceEndpoint) { - CloseableHttpClient httpClient = createHttpClient(serviceEndpoint, null); - return new HttpServiceConnection(serviceEndpoint, httpClient); - } - - @Override - public void close() { - PoolingHttpClientConnectionManager cm = connectionMananeger; - if (cm != null) { - connectionMananeger = null; - cm.close(); - } - } - - private static CloseableHttpClient createHttpClient(ServiceEndpoint serviceEndpoint, - ServiceConnectionManager connectionManager) { - try { - HttpClientBuilder httpClientBuilder = HttpClients.custom(); - - if (connectionManager != null) { - HttpClientConnectionManager httpConnMng = connectionManager.getHttpConnectionManager(); - httpClientBuilder.setConnectionManager(httpConnMng).setConnectionManagerShared(true); - } - - if (serviceEndpoint.isSecure()) { - httpClientBuilder.setSSLSocketFactory(createSSLConnectionSocketFactory()); - } - - return httpClientBuilder.build(); - } catch (KeyManagementException e) { - throw new IllegalStateException(e.getMessage(), e); - } catch (NoSuchAlgorithmException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - /** - * 创建SSL安全连接 - * - * @return - * @throws NoSuchAlgorithmException - * @throws KeyManagementException - */ - private static SSLConnectionSocketFactory createSSLConnectionSocketFactory() - throws NoSuchAlgorithmException, KeyManagementException { - SSLConnectionSocketFactory sslsf = null; - SSLContext context = SSLContext.getInstance("TLS"); - context.init(null, new TrustManager[] { trustManager }, null); - sslsf = new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE); - return sslsf; - } - - /** - * 重新验证方法,取消SSL验证(信任所有证书) - */ - private static TrustManager trustManager = new X509TrustManager() { - - @Override - public void checkClientTrusted(X509Certificate[] ax509certificate, String s) throws CertificateException { - // TODO Auto-generated method stub - - } - - @Override - public void checkServerTrusted(X509Certificate[] ax509certificate, String s) throws CertificateException { - // TODO Auto-generated method stub - - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return null; - } - - }; - -} +package com.jd.blockchain.utils.http.agent; + +import java.io.Closeable; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.apache.http.conn.HttpClientConnectionManager; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; + +public class ServiceConnectionManager implements Closeable { + + private PoolingHttpClientConnectionManager connectionMananeger; + + public ServiceConnectionManager() { + this.connectionMananeger = new PoolingHttpClientConnectionManager(); + setMaxTotal(100).setDefaultMaxPerRoute(20); + } + + public ServiceConnectionManager setMaxTotal(int maxConn) { + connectionMananeger.setMaxTotal(maxConn); + return this; + } + + public ServiceConnectionManager setDefaultMaxPerRoute(int maxConnPerRoute) { + connectionMananeger.setDefaultMaxPerRoute(maxConnPerRoute); + return this; + } + + HttpClientConnectionManager getHttpConnectionManager() { + return connectionMananeger; + } + + /** + * 创建一个受此连接管理器管理的连接; + * + * @param endpoint + * @return + */ + public ServiceConnection create(ServiceEndpoint serviceEndpoint) { + CloseableHttpClient httpClient = createHttpClient(serviceEndpoint, this); + return new HttpServiceConnection(serviceEndpoint, httpClient); + } + + /** + * 创建一个不受管理的连接; + * + * @param serviceEndpoint + * @return + */ + public static ServiceConnection connect(ServiceEndpoint serviceEndpoint) { + CloseableHttpClient httpClient = createHttpClient(serviceEndpoint, null); + return new HttpServiceConnection(serviceEndpoint, httpClient); + } + + @Override + public void close() { + PoolingHttpClientConnectionManager cm = connectionMananeger; + if (cm != null) { + connectionMananeger = null; + cm.close(); + } + } + + private static CloseableHttpClient createHttpClient(ServiceEndpoint serviceEndpoint, + ServiceConnectionManager connectionManager) { + try { + HttpClientBuilder httpClientBuilder = HttpClients.custom(); + + if (connectionManager != null) { + HttpClientConnectionManager httpConnMng = connectionManager.getHttpConnectionManager(); + httpClientBuilder.setConnectionManager(httpConnMng).setConnectionManagerShared(true); + } + + if (serviceEndpoint.isSecure()) { + httpClientBuilder.setSSLSocketFactory(createSSLConnectionSocketFactory()); + } + + return httpClientBuilder.build(); + } catch (KeyManagementException e) { + throw new IllegalStateException(e.getMessage(), e); + } catch (NoSuchAlgorithmException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + /** + * 创建SSL安全连接 + * + * @return + * @throws NoSuchAlgorithmException + * @throws KeyManagementException + */ + private static SSLConnectionSocketFactory createSSLConnectionSocketFactory() + throws NoSuchAlgorithmException, KeyManagementException { + SSLConnectionSocketFactory sslsf = null; + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, new TrustManager[] { trustManager }, null); + sslsf = new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE); + return sslsf; + } + + /** + * 重新验证方法,取消SSL验证(信任所有证书) + */ + private static TrustManager trustManager = new X509TrustManager() { + + @Override + public void checkClientTrusted(X509Certificate[] ax509certificate, String s) throws CertificateException { + // TODO Auto-generated method stub + + } + + @Override + public void checkServerTrusted(X509Certificate[] ax509certificate, String s) throws CertificateException { + // TODO Auto-generated method stub + + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + }; + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceEndpoint.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceEndpoint.java index 5baf60bf..4772ce69 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceEndpoint.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceEndpoint.java @@ -1,50 +1,50 @@ -package com.jd.blockchain.utils.http.agent; - -import org.springframework.util.StringUtils; - -import com.jd.blockchain.utils.net.NetworkAddress; - -/** - * 服务器设置; - * - * @author haiq - * - */ -public class ServiceEndpoint extends NetworkAddress implements Cloneable { - - private static final long serialVersionUID = 128018335830143965L; - - private String contextPath; - - public ServiceEndpoint(String host, int port, boolean secure) { - this(host, port, secure, null); - } - - public ServiceEndpoint(NetworkAddress networkAddress) { - this(networkAddress.getHost(), networkAddress.getPort(), networkAddress.isSecure(), null); - } - - public ServiceEndpoint(String host, int port, boolean secure, String contextPath) { - super(host, port, secure); - contextPath = StringUtils.cleanPath(contextPath); - if (StringUtils.isEmpty(contextPath)) { - this.contextPath = "/"; - }else{ - this.contextPath = contextPath; - } - } - - public String getContextPath() { - return contextPath; - } - - @Override - public ServiceEndpoint clone() { - try { - return (ServiceEndpoint) super.clone(); - } catch (CloneNotSupportedException e) { - throw new UnsupportedOperationException(e.getMessage(), e); - } - } - -} +package com.jd.blockchain.utils.http.agent; + +import org.springframework.util.StringUtils; + +import com.jd.blockchain.utils.net.NetworkAddress; + +/** + * 服务器设置; + * + * @author haiq + * + */ +public class ServiceEndpoint extends NetworkAddress implements Cloneable { + + private static final long serialVersionUID = 128018335830143965L; + + private String contextPath; + + public ServiceEndpoint(String host, int port, boolean secure) { + this(host, port, secure, null); + } + + public ServiceEndpoint(NetworkAddress networkAddress) { + this(networkAddress.getHost(), networkAddress.getPort(), networkAddress.isSecure(), null); + } + + public ServiceEndpoint(String host, int port, boolean secure, String contextPath) { + super(host, port, secure); + contextPath = StringUtils.cleanPath(contextPath); + if (StringUtils.isEmpty(contextPath)) { + this.contextPath = "/"; + }else{ + this.contextPath = contextPath; + } + } + + public String getContextPath() { + return contextPath; + } + + @Override + public ServiceEndpoint clone() { + try { + return (ServiceEndpoint) super.clone(); + } catch (CloneNotSupportedException e) { + throw new UnsupportedOperationException(e.getMessage(), e); + } + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceRequest.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceRequest.java index 16a00aab..a584eb82 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceRequest.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/ServiceRequest.java @@ -1,26 +1,26 @@ -package com.jd.blockchain.utils.http.agent; - -import java.net.URI; -import java.nio.ByteBuffer; - -import com.jd.blockchain.utils.http.HttpMethod; -import com.jd.blockchain.utils.http.NamedParamMap; - -public interface ServiceRequest { - - HttpMethod getHttpMethod(); - - URI getUri(); - - ByteBuffer getBody(); - - NamedParamMap getRequestParams(); - - /** - * 返回服务方法的参数值列表; - * - * @return - */ - Object[] getArgs(); - +package com.jd.blockchain.utils.http.agent; + +import java.net.URI; +import java.nio.ByteBuffer; + +import com.jd.blockchain.utils.http.HttpMethod; +import com.jd.blockchain.utils.http.NamedParamMap; + +public interface ServiceRequest { + + HttpMethod getHttpMethod(); + + URI getUri(); + + ByteBuffer getBody(); + + NamedParamMap getRequestParams(); + + /** + * 返回服务方法的参数值列表; + * + * @return + */ + Object[] getArgs(); + } \ No newline at end of file diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/StringConverterFactory.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/StringConverterFactory.java index 3d209d61..f6cbb2b0 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/StringConverterFactory.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/StringConverterFactory.java @@ -1,28 +1,28 @@ -package com.jd.blockchain.utils.http.agent; - -import org.springframework.beans.BeanUtils; - -import com.jd.blockchain.utils.http.StringConverter; -import com.jd.blockchain.utils.http.converters.ObjectToStringConverter; - -abstract class StringConverterFactory { - - public static final StringConverter DEFAULT_PARAM_CONVERTER = new ObjectToStringConverter(); - - public static StringConverter instantiateStringConverter(Class converterClazz) { - StringConverter converter = null; - if (converterClazz != null) { - if (!StringConverter.class.isAssignableFrom(converterClazz)) { - throw new IllegalHttpServiceDefinitionException( - "The specified converter of path param doesn't implement the interface " - + StringConverter.class.getName() + "!"); - } - - converter = (StringConverter) BeanUtils.instantiate(converterClazz); - } else { - // create default converter; - converter = DEFAULT_PARAM_CONVERTER; - } - return converter; - } -} +package com.jd.blockchain.utils.http.agent; + +import org.springframework.beans.BeanUtils; + +import com.jd.blockchain.utils.http.StringConverter; +import com.jd.blockchain.utils.http.converters.ObjectToStringConverter; + +abstract class StringConverterFactory { + + public static final StringConverter DEFAULT_PARAM_CONVERTER = new ObjectToStringConverter(); + + public static StringConverter instantiateStringConverter(Class converterClazz) { + StringConverter converter = null; + if (converterClazz != null) { + if (!StringConverter.class.isAssignableFrom(converterClazz)) { + throw new IllegalHttpServiceDefinitionException( + "The specified converter of path param doesn't implement the interface " + + StringConverter.class.getName() + "!"); + } + + converter = (StringConverter) BeanUtils.instantiate(converterClazz); + } else { + // create default converter; + converter = DEFAULT_PARAM_CONVERTER; + } + return converter; + } +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/TypeAutoAdaptingRequestBodyConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/TypeAutoAdaptingRequestBodyConverter.java index c847cb88..56a8129f 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/TypeAutoAdaptingRequestBodyConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/agent/TypeAutoAdaptingRequestBodyConverter.java @@ -1,62 +1,62 @@ -package com.jd.blockchain.utils.http.agent; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import org.springframework.util.ClassUtils; - -import com.jd.blockchain.utils.http.RequestBodyConverter; -import com.jd.blockchain.utils.http.converters.ByteArrayBodyConverter; -import com.jd.blockchain.utils.http.converters.InputStreamBodyConverter; -import com.jd.blockchain.utils.http.converters.JsonBodyConverter; -import com.jd.blockchain.utils.http.converters.ObjectToStringBodyConverter; - -/** - * 类型自动匹配的 RequestBody 转换器; - * @author haiq - * - */ -class TypeAutoAdaptingRequestBodyConverter implements RequestBodyConverter{ - - private static final RequestBodyConverter OBJECT_TO_STRING_CONVERTER = new ObjectToStringBodyConverter(); - private static final RequestBodyConverter INPUT_STREAM_CONVERTER = new InputStreamBodyConverter(); - private static final RequestBodyConverter BYTES_CONVERTER = new ByteArrayBodyConverter(); -// private static final RequestBodyConverter JSON_CONVERTER = new JsonBodyConverter(); - - private RequestBodyConverter converter; - - public TypeAutoAdaptingRequestBodyConverter(Class argType) { - converter = createConverter(argType); - } - - private RequestBodyConverter createConverter(Class argType){ - if (ClassUtils.isAssignable(InputStream.class, argType)) { - return INPUT_STREAM_CONVERTER; - } - if (ClassUtils.isAssignable(String.class, argType)) { - return OBJECT_TO_STRING_CONVERTER; - } - if (ClassUtils.isAssignable(byte[].class, argType)) { - return BYTES_CONVERTER; - } - if (ClassUtils.isPrimitiveOrWrapper(argType)) { - return OBJECT_TO_STRING_CONVERTER; - } - if (ClassUtils.isAssignable(OutputStream.class, argType)) { - throw new IllegalHttpServiceDefinitionException("Unsupported type for the request body argument!"); - } - //默认按照 JSON 方式返回; - return new JsonBodyConverter(argType); -// return JSON_CONVERTER; - } - - @Override - public void write(Object param, OutputStream out) throws IOException{ - if (param == null) { - return; - } - converter.write(param, out); - } - -} +package com.jd.blockchain.utils.http.agent; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.springframework.util.ClassUtils; + +import com.jd.blockchain.utils.http.RequestBodyConverter; +import com.jd.blockchain.utils.http.converters.ByteArrayBodyConverter; +import com.jd.blockchain.utils.http.converters.InputStreamBodyConverter; +import com.jd.blockchain.utils.http.converters.JsonBodyConverter; +import com.jd.blockchain.utils.http.converters.ObjectToStringBodyConverter; + +/** + * 类型自动匹配的 RequestBody 转换器; + * @author haiq + * + */ +class TypeAutoAdaptingRequestBodyConverter implements RequestBodyConverter{ + + private static final RequestBodyConverter OBJECT_TO_STRING_CONVERTER = new ObjectToStringBodyConverter(); + private static final RequestBodyConverter INPUT_STREAM_CONVERTER = new InputStreamBodyConverter(); + private static final RequestBodyConverter BYTES_CONVERTER = new ByteArrayBodyConverter(); +// private static final RequestBodyConverter JSON_CONVERTER = new JsonBodyConverter(); + + private RequestBodyConverter converter; + + public TypeAutoAdaptingRequestBodyConverter(Class argType) { + converter = createConverter(argType); + } + + private RequestBodyConverter createConverter(Class argType){ + if (ClassUtils.isAssignable(InputStream.class, argType)) { + return INPUT_STREAM_CONVERTER; + } + if (ClassUtils.isAssignable(String.class, argType)) { + return OBJECT_TO_STRING_CONVERTER; + } + if (ClassUtils.isAssignable(byte[].class, argType)) { + return BYTES_CONVERTER; + } + if (ClassUtils.isPrimitiveOrWrapper(argType)) { + return OBJECT_TO_STRING_CONVERTER; + } + if (ClassUtils.isAssignable(OutputStream.class, argType)) { + throw new IllegalHttpServiceDefinitionException("Unsupported type for the request body argument!"); + } + //默认按照 JSON 方式返回; + return new JsonBodyConverter(argType); +// return JSON_CONVERTER; + } + + @Override + public void write(Object param, OutputStream out) throws IOException{ + if (param == null) { + return; + } + converter.write(param, out); + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/auth/Securities.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/auth/Securities.java index 0bf8c444..945b3f53 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/auth/Securities.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/auth/Securities.java @@ -1,8 +1,8 @@ -package com.jd.blockchain.utils.http.auth; - -import com.jd.blockchain.utils.security.ShaUtils; - -public class Securities { - - -} +package com.jd.blockchain.utils.http.auth; + +import com.jd.blockchain.utils.security.ShaUtils; + +public class Securities { + + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ByteArrayBodyConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ByteArrayBodyConverter.java index c0daae22..6ffcbb79 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ByteArrayBodyConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ByteArrayBodyConverter.java @@ -1,15 +1,15 @@ -package com.jd.blockchain.utils.http.converters; - -import java.io.IOException; -import java.io.OutputStream; - -import com.jd.blockchain.utils.http.RequestBodyConverter; - -public class ByteArrayBodyConverter implements RequestBodyConverter{ - - @Override - public void write(Object param, OutputStream out) throws IOException{ - out.write((byte[])param); - } - -} +package com.jd.blockchain.utils.http.converters; + +import java.io.IOException; +import java.io.OutputStream; + +import com.jd.blockchain.utils.http.RequestBodyConverter; + +public class ByteArrayBodyConverter implements RequestBodyConverter{ + + @Override + public void write(Object param, OutputStream out) throws IOException{ + out.write((byte[])param); + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ByteArrayResponseConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ByteArrayResponseConverter.java index dfa25ad3..0df52ec4 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ByteArrayResponseConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ByteArrayResponseConverter.java @@ -1,31 +1,31 @@ -package com.jd.blockchain.utils.http.converters; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -import org.springframework.util.StreamUtils; - -import com.jd.blockchain.utils.http.HttpServiceContext; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.agent.ServiceRequest; - -public class ByteArrayResponseConverter implements ResponseConverter { - - public static final ByteArrayResponseConverter INSTANCE = new ByteArrayResponseConverter(); - - private ByteArrayResponseConverter() { - } - - @Override - public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) { - try { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - StreamUtils.copy(responseStream, out); - return out.toByteArray(); - } catch (IOException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - -} +package com.jd.blockchain.utils.http.converters; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.springframework.util.StreamUtils; + +import com.jd.blockchain.utils.http.HttpServiceContext; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.agent.ServiceRequest; + +public class ByteArrayResponseConverter implements ResponseConverter { + + public static final ByteArrayResponseConverter INSTANCE = new ByteArrayResponseConverter(); + + private ByteArrayResponseConverter() { + } + + @Override + public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) { + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + StreamUtils.copy(responseStream, out); + return out.toByteArray(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/EmptyBodyConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/EmptyBodyConverter.java index acbb91e9..b3b4a825 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/EmptyBodyConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/EmptyBodyConverter.java @@ -1,15 +1,15 @@ -package com.jd.blockchain.utils.http.converters; - -import java.io.IOException; -import java.io.OutputStream; - -import com.jd.blockchain.utils.http.RequestBodyConverter; - -public class EmptyBodyConverter implements RequestBodyConverter{ - - @Override - public void write(Object param, OutputStream out) throws IOException{ - //Do nothing; - } - -} +package com.jd.blockchain.utils.http.converters; + +import java.io.IOException; +import java.io.OutputStream; + +import com.jd.blockchain.utils.http.RequestBodyConverter; + +public class EmptyBodyConverter implements RequestBodyConverter{ + + @Override + public void write(Object param, OutputStream out) throws IOException{ + //Do nothing; + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/InputStreamBodyConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/InputStreamBodyConverter.java index fe6928d6..7954bf1c 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/InputStreamBodyConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/InputStreamBodyConverter.java @@ -1,17 +1,17 @@ -package com.jd.blockchain.utils.http.converters; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import com.jd.blockchain.utils.http.RequestBodyConverter; -import com.jd.blockchain.utils.io.BytesUtils; - -public class InputStreamBodyConverter implements RequestBodyConverter{ - - @Override - public void write(Object param, OutputStream out) throws IOException{ - BytesUtils.copy((InputStream)param, out); - } - -} +package com.jd.blockchain.utils.http.converters; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import com.jd.blockchain.utils.http.RequestBodyConverter; +import com.jd.blockchain.utils.io.BytesUtils; + +public class InputStreamBodyConverter implements RequestBodyConverter{ + + @Override + public void write(Object param, OutputStream out) throws IOException{ + BytesUtils.copy((InputStream)param, out); + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonBodyConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonBodyConverter.java index c6416935..53369f4a 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonBodyConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonBodyConverter.java @@ -1,29 +1,29 @@ -package com.jd.blockchain.utils.http.converters; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; - -import com.jd.blockchain.utils.http.HttpServiceConsts; -import com.jd.blockchain.utils.http.RequestBodyConverter; -import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; - -public class JsonBodyConverter implements RequestBodyConverter { - - private Class dataType; - - public JsonBodyConverter(Class dataType) { - this.dataType = dataType; - } - - @Override - public void write(Object param, OutputStream out) throws IOException{ - String jsonString = JSONSerializeUtils.serializeToJSON(param, dataType); - try { - out.write(jsonString.getBytes(HttpServiceConsts.CHARSET)); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - -} +package com.jd.blockchain.utils.http.converters; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import com.jd.blockchain.utils.http.HttpServiceConsts; +import com.jd.blockchain.utils.http.RequestBodyConverter; +import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; + +public class JsonBodyConverter implements RequestBodyConverter { + + private Class dataType; + + public JsonBodyConverter(Class dataType) { + this.dataType = dataType; + } + + @Override + public void write(Object param, OutputStream out) throws IOException{ + String jsonString = JSONSerializeUtils.serializeToJSON(param, dataType); + try { + out.write(jsonString.getBytes(HttpServiceConsts.CHARSET)); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonConverter.java index 217ee4a1..436f51bc 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonConverter.java @@ -1,27 +1,27 @@ -package com.jd.blockchain.utils.http.converters; - -import com.jd.blockchain.utils.http.StringConverter; -import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; - -/** - * JSON 格式的参数转换器; - * - * @author haiq - * - */ -public class JsonConverter implements StringConverter { - - private Class dataType; - - public JsonConverter(Class dataType) { - this.dataType = dataType; - } - - @Override - public String toString(Object obj) { - // TODO:未定义“日期时间”的输出格式 ; - return JSONSerializeUtils.serializeToJSON(obj, dataType); - // return JSON.toJSONString(obj); - } - -} +package com.jd.blockchain.utils.http.converters; + +import com.jd.blockchain.utils.http.StringConverter; +import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; + +/** + * JSON 格式的参数转换器; + * + * @author haiq + * + */ +public class JsonConverter implements StringConverter { + + private Class dataType; + + public JsonConverter(Class dataType) { + this.dataType = dataType; + } + + @Override + public String toString(Object obj) { + // TODO:未定义“日期时间”的输出格式 ; + return JSONSerializeUtils.serializeToJSON(obj, dataType); + // return JSON.toJSONString(obj); + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonResponseConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonResponseConverter.java index 04195133..6396f0b2 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonResponseConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/JsonResponseConverter.java @@ -1,30 +1,30 @@ -package com.jd.blockchain.utils.http.converters; - -import java.io.InputStream; - -import com.jd.blockchain.utils.http.HttpServiceContext; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.agent.ServiceRequest; -import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; - -public class JsonResponseConverter implements ResponseConverter { - - private Class clazz; - - public JsonResponseConverter(Class clazz) { - this.clazz = clazz; - } - - @Override - public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) throws Exception { - String jsonResponse = (String) StringResponseConverter.INSTANCE.getResponse(request, responseStream, null); - if (jsonResponse == null) { - return null; - } - jsonResponse = jsonResponse.trim(); - // TODO: 未指定“日期时间”格式的策略; - return JSONSerializeUtils.deserializeAs(jsonResponse, clazz); -// return JSON.toJavaObject(JSONObject.parseObject(jsonResponse), clazz); - } - -} +package com.jd.blockchain.utils.http.converters; + +import java.io.InputStream; + +import com.jd.blockchain.utils.http.HttpServiceContext; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.agent.ServiceRequest; +import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; + +public class JsonResponseConverter implements ResponseConverter { + + private Class clazz; + + public JsonResponseConverter(Class clazz) { + this.clazz = clazz; + } + + @Override + public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) throws Exception { + String jsonResponse = (String) StringResponseConverter.INSTANCE.getResponse(request, responseStream, null); + if (jsonResponse == null) { + return null; + } + jsonResponse = jsonResponse.trim(); + // TODO: 未指定“日期时间”格式的策略; + return JSONSerializeUtils.deserializeAs(jsonResponse, clazz); +// return JSON.toJavaObject(JSONObject.parseObject(jsonResponse), clazz); + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/NullResponseConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/NullResponseConverter.java index 71b06042..5fe8a79e 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/NullResponseConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/NullResponseConverter.java @@ -1,21 +1,21 @@ -package com.jd.blockchain.utils.http.converters; - -import java.io.InputStream; - -import com.jd.blockchain.utils.http.HttpServiceContext; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.agent.ServiceRequest; - -public class NullResponseConverter implements ResponseConverter { - - public static final ResponseConverter INSTANCE = new NullResponseConverter(); - - private NullResponseConverter() { - } - - @Override - public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) { - return null; - } - -} +package com.jd.blockchain.utils.http.converters; + +import java.io.InputStream; + +import com.jd.blockchain.utils.http.HttpServiceContext; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.agent.ServiceRequest; + +public class NullResponseConverter implements ResponseConverter { + + public static final ResponseConverter INSTANCE = new NullResponseConverter(); + + private NullResponseConverter() { + } + + @Override + public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) { + return null; + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ObjectToStringBodyConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ObjectToStringBodyConverter.java index cdea2d27..c0e4a87f 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ObjectToStringBodyConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ObjectToStringBodyConverter.java @@ -1,23 +1,23 @@ -package com.jd.blockchain.utils.http.converters; - -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; - -import com.jd.blockchain.utils.http.HttpServiceConsts; -import com.jd.blockchain.utils.http.RequestBodyConverter; - -public class ObjectToStringBodyConverter implements RequestBodyConverter { - - @Override - public void write(Object param, OutputStream out) throws IOException{ - try { - String text = param.toString(); - byte[] bytes = text.getBytes(HttpServiceConsts.CHARSET); - out.write(bytes); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - -} +package com.jd.blockchain.utils.http.converters; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import com.jd.blockchain.utils.http.HttpServiceConsts; +import com.jd.blockchain.utils.http.RequestBodyConverter; + +public class ObjectToStringBodyConverter implements RequestBodyConverter { + + @Override + public void write(Object param, OutputStream out) throws IOException{ + try { + String text = param.toString(); + byte[] bytes = text.getBytes(HttpServiceConsts.CHARSET); + out.write(bytes); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ObjectToStringConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ObjectToStringConverter.java index 21e12d4e..0c110b3e 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ObjectToStringConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/ObjectToStringConverter.java @@ -1,12 +1,12 @@ -package com.jd.blockchain.utils.http.converters; - -import com.jd.blockchain.utils.http.StringConverter; - -public class ObjectToStringConverter implements StringConverter { - - @Override - public String toString(Object param) { - return param == null ? null : param.toString(); - } - -} +package com.jd.blockchain.utils.http.converters; + +import com.jd.blockchain.utils.http.StringConverter; + +public class ObjectToStringConverter implements StringConverter { + + @Override + public String toString(Object param) { + return param == null ? null : param.toString(); + } + +} diff --git a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/StringResponseConverter.java b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/StringResponseConverter.java index a5858295..3053b323 100644 --- a/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/StringResponseConverter.java +++ b/source/utils/utils-http/src/main/java/com/jd/blockchain/utils/http/converters/StringResponseConverter.java @@ -1,60 +1,60 @@ -package com.jd.blockchain.utils.http.converters; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; - -import com.jd.blockchain.utils.http.HttpServiceConsts; -import com.jd.blockchain.utils.http.HttpServiceContext; -import com.jd.blockchain.utils.http.HttpServiceException; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.agent.ServiceRequest; - -/** - * 返回字符的转换器; - * - * @author haiq - * - */ -public class StringResponseConverter implements ResponseConverter { - - public static final ResponseConverter INSTANCE = new StringResponseConverter(); - - private StringResponseConverter() { - } - - @Override - public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) { - String responseText = readString(responseStream); - return responseText; - } - - private String readString(InputStream in) { - InputStreamReader reader = null; - try { - reader = new InputStreamReader(in, HttpServiceConsts.CHARSET); - - StringBuilder text = new StringBuilder(); - char[] buffer = new char[256]; - int len = 0; - while((len = reader.read(buffer)) > 0){ - text.append(buffer, 0, len); - } - return text.toString(); - } catch (UnsupportedEncodingException e) { - throw new IllegalArgumentException(e.getMessage(), e); - } catch (IOException e) { - throw new HttpServiceException(e.getMessage(), e); - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - // ignore exception thrown again; - } - } - } - } - -} +package com.jd.blockchain.utils.http.converters; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; + +import com.jd.blockchain.utils.http.HttpServiceConsts; +import com.jd.blockchain.utils.http.HttpServiceContext; +import com.jd.blockchain.utils.http.HttpServiceException; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.agent.ServiceRequest; + +/** + * 返回字符的转换器; + * + * @author haiq + * + */ +public class StringResponseConverter implements ResponseConverter { + + public static final ResponseConverter INSTANCE = new StringResponseConverter(); + + private StringResponseConverter() { + } + + @Override + public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) { + String responseText = readString(responseStream); + return responseText; + } + + private String readString(InputStream in) { + InputStreamReader reader = null; + try { + reader = new InputStreamReader(in, HttpServiceConsts.CHARSET); + + StringBuilder text = new StringBuilder(); + char[] buffer = new char[256]; + int len = 0; + while((len = reader.read(buffer)) > 0){ + text.append(buffer, 0, len); + } + return text.toString(); + } catch (UnsupportedEncodingException e) { + throw new IllegalArgumentException(e.getMessage(), e); + } catch (IOException e) { + throw new HttpServiceException(e.getMessage(), e); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + // ignore exception thrown again; + } + } + } + } + +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/BaseRequestSetting.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/BaseRequestSetting.java index 07a343ab..817a3704 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/BaseRequestSetting.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/BaseRequestSetting.java @@ -1,31 +1,31 @@ -package test.my.utils.http.agent; - -import com.jd.blockchain.utils.http.RequestParam; - -public abstract class BaseRequestSetting { - - @RequestParam(name = "id") - private String id; - - @RequestParam(name = "type") - public final OpType type = OpType.TYPE2; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public abstract int getValue(); - - /** - * 只读属性; - * - * @return - */ - public OpType getType() { - return type; - } -} +package test.my.utils.http.agent; + +import com.jd.blockchain.utils.http.RequestParam; + +public abstract class BaseRequestSetting { + + @RequestParam(name = "id") + private String id; + + @RequestParam(name = "type") + public final OpType type = OpType.TYPE2; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public abstract int getValue(); + + /** + * 只读属性; + * + * @return + */ + public OpType getType() { + return type; + } +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/ContentRequestSetting.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/ContentRequestSetting.java index c0ff6cbe..be778ad1 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/ContentRequestSetting.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/ContentRequestSetting.java @@ -1,48 +1,48 @@ -package test.my.utils.http.agent; - -import com.jd.blockchain.utils.http.RequestParam; - -/** - * ContentRequestSetting 用于测试以 POJO 方式定义请求参数; - * - * 并且通过继承 BaseRequestSetting 用于测试通过继承 POJO 的方式继承请求参数的定义; - * - * @author haiq - * - */ -public class ContentRequestSetting extends BaseRequestSetting { - - @RequestParam(name = "permited") - private boolean permited; - @RequestParam(name = "male", converter = CustomBooleanConverter.class) - private boolean male; - - - @RequestParam(name = "value", required = false, ignoreValue = "-1") - private int value; - - public boolean isPermited() { - return permited; - } - - public void setPermited(boolean permited) { - this.permited = permited; - } - - public boolean isMale() { - return male; - } - - public void setMale(boolean male) { - this.male = male; - } - - @Override - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } -} +package test.my.utils.http.agent; + +import com.jd.blockchain.utils.http.RequestParam; + +/** + * ContentRequestSetting 用于测试以 POJO 方式定义请求参数; + * + * 并且通过继承 BaseRequestSetting 用于测试通过继承 POJO 的方式继承请求参数的定义; + * + * @author haiq + * + */ +public class ContentRequestSetting extends BaseRequestSetting { + + @RequestParam(name = "permited") + private boolean permited; + @RequestParam(name = "male", converter = CustomBooleanConverter.class) + private boolean male; + + + @RequestParam(name = "value", required = false, ignoreValue = "-1") + private int value; + + public boolean isPermited() { + return permited; + } + + public void setPermited(boolean permited) { + this.permited = permited; + } + + public boolean isMale() { + return male; + } + + public void setMale(boolean male) { + this.male = male; + } + + @Override + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/CustomBooleanConverter.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/CustomBooleanConverter.java index 44593cfe..6029ac18 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/CustomBooleanConverter.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/CustomBooleanConverter.java @@ -1,13 +1,13 @@ -package test.my.utils.http.agent; - -import com.jd.blockchain.utils.http.StringConverter; - -public class CustomBooleanConverter implements StringConverter { - - @Override - public String toString(Object obj) { - Boolean value = (Boolean) obj; - return value.booleanValue() ? "1" : "0"; - } - -} +package test.my.utils.http.agent; + +import com.jd.blockchain.utils.http.StringConverter; + +public class CustomBooleanConverter implements StringConverter { + + @Override + public String toString(Object obj) { + Boolean value = (Boolean) obj; + return value.booleanValue() ? "1" : "0"; + } + +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/DataResponse.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/DataResponse.java index 9c31b93a..7e01173c 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/DataResponse.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/DataResponse.java @@ -1,44 +1,44 @@ -package test.my.utils.http.agent; - -public class DataResponse { - - private boolean success; - - private String error; - - private String content; - - public void setSuccess(boolean success) { - this.success = success; - } - - public void setError(String error) { - this.error = error; - } - - public void setContent(String content) { - this.content = content; - } - - public DataResponse() { - } - - public DataResponse(boolean success, String error, String content) { - this.success = success; - this.error = error; - this.content = content; - } - - public boolean isSuccess() { - return success; - } - - public String getError() { - return error; - } - - public String getContent() { - return content; - } - -} +package test.my.utils.http.agent; + +public class DataResponse { + + private boolean success; + + private String error; + + private String content; + + public void setSuccess(boolean success) { + this.success = success; + } + + public void setError(String error) { + this.error = error; + } + + public void setContent(String content) { + this.content = content; + } + + public DataResponse() { + } + + public DataResponse(boolean success, String error, String content) { + this.success = success; + this.error = error; + this.content = content; + } + + public boolean isSuccess() { + return success; + } + + public String getError() { + return error; + } + + public String getContent() { + return content; + } + +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentException.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentException.java index bd133402..9855e43c 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentException.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentException.java @@ -1,15 +1,15 @@ -package test.my.utils.http.agent; - -public class GetContentException extends Exception{ - - private static final long serialVersionUID = 8896491616375068614L; - - public GetContentException() { - } - - - public GetContentException(String message) { - super(message); - } - -} +package test.my.utils.http.agent; + +public class GetContentException extends Exception{ + + private static final long serialVersionUID = 8896491616375068614L; + + public GetContentException() { + } + + + public GetContentException(String message) { + super(message); + } + +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentResponseConverter.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentResponseConverter.java index 77ed4fbe..424c3145 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentResponseConverter.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentResponseConverter.java @@ -1,20 +1,20 @@ -package test.my.utils.http.agent; - -import java.io.InputStream; - -import com.jd.blockchain.utils.http.HttpServiceContext; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.agent.ServiceRequest; -import com.jd.blockchain.utils.http.converters.JsonResponseConverter; - -public class GetContentResponseConverter implements ResponseConverter { - - private JsonResponseConverter jsonResponseConverter = new JsonResponseConverter(DataResponse.class); - - @Override - public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) throws Exception { - DataResponse data = (DataResponse) jsonResponseConverter.getResponse(request, responseStream, null); - return data.getContent(); - } - -} +package test.my.utils.http.agent; + +import java.io.InputStream; + +import com.jd.blockchain.utils.http.HttpServiceContext; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.agent.ServiceRequest; +import com.jd.blockchain.utils.http.converters.JsonResponseConverter; + +public class GetContentResponseConverter implements ResponseConverter { + + private JsonResponseConverter jsonResponseConverter = new JsonResponseConverter(DataResponse.class); + + @Override + public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) throws Exception { + DataResponse data = (DataResponse) jsonResponseConverter.getResponse(request, responseStream, null); + return data.getContent(); + } + +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentResponseConverterWithException.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentResponseConverterWithException.java index 9d05f92f..3da1429e 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentResponseConverterWithException.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/GetContentResponseConverterWithException.java @@ -1,23 +1,23 @@ -package test.my.utils.http.agent; - -import java.io.InputStream; - -import com.jd.blockchain.utils.http.HttpServiceContext; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.agent.ServiceRequest; -import com.jd.blockchain.utils.http.converters.JsonResponseConverter; - -public class GetContentResponseConverterWithException implements ResponseConverter { - - private JsonResponseConverter jsonResponseConverter = new JsonResponseConverter(DataResponse.class); - - @Override - public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) throws Exception { - DataResponse data = (DataResponse) jsonResponseConverter.getResponse(request, responseStream, null); - if (data.isSuccess()) { - return data.getContent(); - } - throw new GetContentException(data.getError()); - } - -} +package test.my.utils.http.agent; + +import java.io.InputStream; + +import com.jd.blockchain.utils.http.HttpServiceContext; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.agent.ServiceRequest; +import com.jd.blockchain.utils.http.converters.JsonResponseConverter; + +public class GetContentResponseConverterWithException implements ResponseConverter { + + private JsonResponseConverter jsonResponseConverter = new JsonResponseConverter(DataResponse.class); + + @Override + public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) throws Exception { + DataResponse data = (DataResponse) jsonResponseConverter.getResponse(request, responseStream, null); + if (data.isSuccess()) { + return data.getContent(); + } + throw new GetContentException(data.getError()); + } + +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpRequestCollector.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpRequestCollector.java index e16b5a80..00a4e431 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpRequestCollector.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpRequestCollector.java @@ -1,149 +1,149 @@ -package test.my.utils.http.agent; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import com.jd.blockchain.utils.http.HttpMethod; -import com.jd.blockchain.utils.io.ByteArray; -import com.jd.blockchain.utils.io.BytesUtils; - -public class HttpRequestCollector extends HttpServlet{ - - private static final long serialVersionUID = -8014615357825392276L; - - private List reqRecords = new LinkedList(); - - private String requestPath = null; - - private String authorization = null; - - private String responseText = null; - - private byte[] responseBytes = null; - - private String requestMethod = null; - - private ByteArray requestBody = null; - - public HttpRequestCollector(String responseText) { - this.responseText = responseText; - } - - public HttpRequestCollector(byte[] responseBytes) { - this.responseBytes = responseBytes; - } - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - reqRecords.add(new HttpRequestInfo(HttpMethod.GET, req.getParameterMap())); - requestPath = req.getRequestURI(); - authorization = req.getHeader("Authorization"); - requestMethod = req.getMethod(); - - if (responseText != null) { - resp.getWriter().print(responseText); - resp.getWriter().flush(); - }else if(responseBytes != null) { - resp.getOutputStream().write(responseBytes, 0, responseBytes.length); - resp.getOutputStream().flush(); - } - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - reqRecords.add(new HttpRequestInfo(HttpMethod.POST, req.getParameterMap())); - requestPath = req.getRequestURI(); - authorization = req.getHeader("Authorization"); - requestMethod = req.getMethod(); - requestBody = readRequestBody(req); - - if (responseText != null) { - resp.getWriter().print(responseText); - resp.getWriter().flush(); - }else if(responseBytes != null) { - resp.getOutputStream().write(responseBytes, 0, responseBytes.length); - resp.getOutputStream().flush(); - } - } - - @Override - protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ - reqRecords.add(new HttpRequestInfo(HttpMethod.PUT, req.getParameterMap())); - requestPath = req.getRequestURI(); - authorization = req.getHeader("Authorization"); - requestMethod = req.getMethod(); - requestBody = readRequestBody(req); - - if (responseText != null) { - resp.getWriter().print(responseText); - resp.getWriter().flush(); - }else if(responseBytes != null) { - resp.getOutputStream().write(responseBytes, 0, responseBytes.length); - resp.getOutputStream().flush(); - } - } - - @Override - protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ - reqRecords.add(new HttpRequestInfo(HttpMethod.DELETE, req.getParameterMap())); - requestPath = req.getRequestURI(); - authorization = req.getHeader("Authorization"); - requestMethod = req.getMethod(); - - if (responseText != null) { - resp.getWriter().print(responseText); - resp.getWriter().flush(); - }else if(responseBytes != null) { - resp.getOutputStream().write(responseBytes, 0, responseBytes.length); - resp.getOutputStream().flush(); - } - } - - private ByteArray readRequestBody(HttpServletRequest request) throws UnsupportedEncodingException, IOException{ - byte[] bodyBytes = BytesUtils.copyToBytes(request.getInputStream()); - return ByteArray.wrap(bodyBytes); - -// BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8")); -// String line = null; -// StringBuilder builder = new StringBuilder(); -// while((line = reader.readLine()) != null){ -// builder.append(line); -// } -// return builder.toString(); - } - - - - public Iterator getRequestRecords(){ - return reqRecords.iterator(); - } - - public String getRequestPath(){ - return requestPath; - } - - public String getAuthorization(){ - return authorization; - } - - public String getRequestMethod(){ - return requestMethod; - } - - public ByteArray getRequestBody(){ - return requestBody; - } - - public void clearRequestRecords(){ - reqRecords.clear(); - requestPath = null; - } -} +package test.my.utils.http.agent; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.jd.blockchain.utils.http.HttpMethod; +import com.jd.blockchain.utils.io.ByteArray; +import com.jd.blockchain.utils.io.BytesUtils; + +public class HttpRequestCollector extends HttpServlet{ + + private static final long serialVersionUID = -8014615357825392276L; + + private List reqRecords = new LinkedList(); + + private String requestPath = null; + + private String authorization = null; + + private String responseText = null; + + private byte[] responseBytes = null; + + private String requestMethod = null; + + private ByteArray requestBody = null; + + public HttpRequestCollector(String responseText) { + this.responseText = responseText; + } + + public HttpRequestCollector(byte[] responseBytes) { + this.responseBytes = responseBytes; + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + reqRecords.add(new HttpRequestInfo(HttpMethod.GET, req.getParameterMap())); + requestPath = req.getRequestURI(); + authorization = req.getHeader("Authorization"); + requestMethod = req.getMethod(); + + if (responseText != null) { + resp.getWriter().print(responseText); + resp.getWriter().flush(); + }else if(responseBytes != null) { + resp.getOutputStream().write(responseBytes, 0, responseBytes.length); + resp.getOutputStream().flush(); + } + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + reqRecords.add(new HttpRequestInfo(HttpMethod.POST, req.getParameterMap())); + requestPath = req.getRequestURI(); + authorization = req.getHeader("Authorization"); + requestMethod = req.getMethod(); + requestBody = readRequestBody(req); + + if (responseText != null) { + resp.getWriter().print(responseText); + resp.getWriter().flush(); + }else if(responseBytes != null) { + resp.getOutputStream().write(responseBytes, 0, responseBytes.length); + resp.getOutputStream().flush(); + } + } + + @Override + protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ + reqRecords.add(new HttpRequestInfo(HttpMethod.PUT, req.getParameterMap())); + requestPath = req.getRequestURI(); + authorization = req.getHeader("Authorization"); + requestMethod = req.getMethod(); + requestBody = readRequestBody(req); + + if (responseText != null) { + resp.getWriter().print(responseText); + resp.getWriter().flush(); + }else if(responseBytes != null) { + resp.getOutputStream().write(responseBytes, 0, responseBytes.length); + resp.getOutputStream().flush(); + } + } + + @Override + protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ + reqRecords.add(new HttpRequestInfo(HttpMethod.DELETE, req.getParameterMap())); + requestPath = req.getRequestURI(); + authorization = req.getHeader("Authorization"); + requestMethod = req.getMethod(); + + if (responseText != null) { + resp.getWriter().print(responseText); + resp.getWriter().flush(); + }else if(responseBytes != null) { + resp.getOutputStream().write(responseBytes, 0, responseBytes.length); + resp.getOutputStream().flush(); + } + } + + private ByteArray readRequestBody(HttpServletRequest request) throws UnsupportedEncodingException, IOException{ + byte[] bodyBytes = BytesUtils.copyToBytes(request.getInputStream()); + return ByteArray.wrap(bodyBytes); + +// BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8")); +// String line = null; +// StringBuilder builder = new StringBuilder(); +// while((line = reader.readLine()) != null){ +// builder.append(line); +// } +// return builder.toString(); + } + + + + public Iterator getRequestRecords(){ + return reqRecords.iterator(); + } + + public String getRequestPath(){ + return requestPath; + } + + public String getAuthorization(){ + return authorization; + } + + public String getRequestMethod(){ + return requestMethod; + } + + public ByteArray getRequestBody(){ + return requestBody; + } + + public void clearRequestRecords(){ + reqRecords.clear(); + requestPath = null; + } +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpRequestInfo.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpRequestInfo.java index bcada3cf..b7294e62 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpRequestInfo.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpRequestInfo.java @@ -1,28 +1,28 @@ -package test.my.utils.http.agent; - -import java.util.HashMap; -import java.util.Map; - -import com.jd.blockchain.utils.http.HttpMethod; - -public class HttpRequestInfo { - - private HttpMethod method; - - private Map parameters; - - - public HttpMethod getMethod() { - return method; - } - - public Map getParameters() { - return parameters; - } - - public HttpRequestInfo(HttpMethod method, Map parameters) { - this.method = method; - this.parameters = new HashMap(parameters); - } - -} +package test.my.utils.http.agent; + +import java.util.HashMap; +import java.util.Map; + +import com.jd.blockchain.utils.http.HttpMethod; + +public class HttpRequestInfo { + + private HttpMethod method; + + private Map parameters; + + + public HttpMethod getMethod() { + return method; + } + + public Map getParameters() { + return parameters; + } + + public HttpRequestInfo(HttpMethod method, Map parameters) { + this.method = method; + this.parameters = new HashMap(parameters); + } + +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpServiceAgentTest.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpServiceAgentTest.java index 3bed4a46..3adbaa58 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpServiceAgentTest.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpServiceAgentTest.java @@ -1,576 +1,576 @@ -package test.my.utils.http.agent; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.io.InputStream; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; - -import javax.servlet.http.HttpServlet; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.jd.blockchain.utils.http.HttpMethod; -import com.jd.blockchain.utils.http.agent.AuthorizationAlgs; -import com.jd.blockchain.utils.http.agent.AuthorizationHeader; -import com.jd.blockchain.utils.http.agent.HttpServiceAgent; -import com.jd.blockchain.utils.http.agent.ServiceEndpoint; -import com.jd.blockchain.utils.io.BytesUtils; -import com.jd.blockchain.utils.security.ShaUtils; -import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; -import com.jd.blockchain.utils.web.server.WebServer; - -public class HttpServiceAgentTest { - - private static final String host = "127.0.0.1"; - -// private static final int port = 10809; - - private static final String SENDER_NAME = "upush_test"; - - private static final String SECRET_KEY = "123abc"; - - private WebServer server; - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - if (server != null) { - server.stop(); - } - } - - private int getRandomPort() { - byte[] nanoTime = BytesUtils.toBytes(System.nanoTime()); - byte[] hash = ShaUtils.hash_256(nanoTime); - return hash[0]; - } - - private int prepareEnvironment(String contextPath, HttpServlet servlet, String servletMapping) { - //随机化端口,避免测试用例的端口冲突 - int port = 11000 + getRandomPort(); - server = new WebServer(host, port); - server.registServlet("test-servlet", servlet, servletMapping); - server.setContextPath(contextPath); - server.start(); - - return port; - } - - @Test - public void testRequestParam() { - String contextPath = "/testserver"; - String servicePath = "/test/content"; - DataResponse expectedResponse = new DataResponse(true, null, "TestContent\r\nabckkk\r\n1"); - String expectedResponseText = JSON.toJSONString(expectedResponse); - HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); - - // 准备环境; - int port = prepareEnvironment(contextPath, servlet, servicePath); - - ServiceEndpoint endpoint = new ServiceEndpoint(host, port, false, contextPath); - AuthorizationHeader authorization = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); - // setting.setContextPath(contextPath); - HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, endpoint, authorization); - - // 主要路径; - String expectedId = "001"; - boolean expectedPermited = true; - boolean origMale = false; - String expectedMaleStr = (new CustomBooleanConverter()).toString(origMale); - int expectedValue = 10; - // 发起请求; - String actualResponseText = testService.content(expectedId, expectedPermited, origMale, expectedValue); - // 验证结果; - assertEquals(expectedResponseText, actualResponseText); - Iterator reqRecords = servlet.getRequestRecords(); - assertTrue(reqRecords.hasNext()); - HttpRequestInfo reqRecord = reqRecords.next(); - assertEquals(HttpMethod.GET, reqRecord.getMethod()); - Map params = reqRecord.getParameters(); - assertEquals(4, params.size()); - assertTrue(params.containsKey("id")); - assertTrue(params.containsKey("permited")); - assertTrue(params.containsKey("male")); - assertTrue(params.containsKey("value")); - assertEquals(expectedId, params.get("id")[0]); - assertEquals(Boolean.toString(expectedPermited), params.get("permited")[0]); - assertEquals(expectedMaleStr, params.get("male")[0]); - assertEquals(expectedValue + "", params.get("value")[0]); - // 清理数据; - servlet.clearRequestRecords(); - - // 在主要路径的基础上验证标注的请求路径名,忽略特定值的参数; - expectedId = "001"; - expectedPermited = true; - origMale = false; - expectedMaleStr = (new CustomBooleanConverter()).toString(origMale); - int expectedIgnoreValue = -1; - // 发起请求; - DataResponse actualResponse = testService.getContent(expectedId, expectedPermited, origMale, - expectedIgnoreValue, "other values"); - // 验证结果; - assertEquals(expectedResponse.getContent(), actualResponse.getContent()); - assertEquals(expectedResponse.getError(), actualResponse.getError()); - assertEquals(expectedResponse.isSuccess(), actualResponse.isSuccess()); - - reqRecords = servlet.getRequestRecords(); - assertTrue(reqRecords.hasNext()); - reqRecord = reqRecords.next(); - assertEquals(HttpMethod.GET, reqRecord.getMethod()); - params = reqRecord.getParameters(); - assertEquals(3, params.size()); - assertTrue(params.containsKey("id")); - assertTrue(params.containsKey("permited")); - assertTrue(params.containsKey("male")); - assertTrue(!params.containsKey("value"));// 不包含应被忽略的值; - assertEquals(expectedId, params.get("id")[0]); - assertEquals(Boolean.toString(expectedPermited), params.get("permited")[0]); - assertEquals(expectedMaleStr, params.get("male")[0]); - servlet.clearRequestRecords(); - - // 在前面的测试路径的基础上验证 http post 方法发送请求,以及自定义的回复转换器; - expectedId = "001"; - expectedPermited = true; - boolean expectedMale = false; - expectedValue = 188; - // 发起请求; - String actualResponseText2 = testService.fetchContent(expectedId, expectedPermited, expectedMale, - expectedValue); - // 验证结果; - assertEquals(expectedResponse.getContent(), actualResponseText2); - reqRecords = servlet.getRequestRecords(); - assertTrue(reqRecords.hasNext()); - reqRecord = reqRecords.next(); - assertEquals(HttpMethod.POST, reqRecord.getMethod()); - params = reqRecord.getParameters(); - assertEquals(4, params.size()); - assertTrue(params.containsKey("id")); - assertTrue(params.containsKey("permited")); - assertTrue(params.containsKey("male")); - assertTrue(params.containsKey("value")); - assertEquals(expectedId, params.get("id")[0]); - assertEquals(Boolean.toString(expectedPermited), params.get("permited")[0]); - assertEquals(expectedMaleStr, params.get("male")[0]); - assertEquals(expectedValue + "", params.get("value")[0]); - - } - - /** - * 测试自定义的 ResponseConverter 以及服务方法声明异常的处理机制; - */ - public void testResponseConverterWithException_Success() { - String contextPath = "/testserver"; - String servicePath = "/test/content"; - boolean success = true; - String expectedError = ""; - DataResponse expectedResponse = new DataResponse(success, expectedError, "TestContent\r\nabckkk\r\n1"); - String expectedResponseText = JSON.toJSONString(expectedResponse); - HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); - - // 准备环境; - int port = prepareEnvironment(contextPath, servlet, servicePath); - ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); - AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); - HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); - - // 准备数据; - String expectedId = "001"; - boolean expectedPermited = true; - boolean origMale = false; - int expectedValue = 10; - - // 主要路径:测试自定义的回复转换器返回正常时的回复结果; - expectedId = "001"; - expectedPermited = true; - boolean expectedMale = false; - String expectedMaleStr = (new CustomBooleanConverter()).toString(origMale); - expectedValue = 188; - // 发起请求; - GetContentException expectedException = null; - String actualResponseText2 = null; - try { - actualResponseText2 = testService.fetchContentWithError(expectedId, expectedPermited, expectedMale, - expectedValue); - } catch (GetContentException e) { - expectedException = e; - } - // 验证结果; - assertTrue(expectedException == null);// 预期没有异常; - - assertEquals(expectedResponse.getContent(), actualResponseText2); - Iterator reqRecords = servlet.getRequestRecords(); - assertTrue(reqRecords.hasNext()); - HttpRequestInfo reqRecord = reqRecords.next(); - assertEquals(HttpMethod.POST, reqRecord.getMethod()); - Map params = reqRecord.getParameters(); - assertEquals(4, params.size()); - assertTrue(params.containsKey("id")); - assertTrue(params.containsKey("permited")); - assertTrue(params.containsKey("male")); - assertTrue(params.containsKey("value")); - assertEquals(expectedId, params.get("id")[0]); - assertEquals(Boolean.toString(expectedPermited), params.get("permited")[0]); - assertEquals(expectedMaleStr, params.get("male")[0]); - assertEquals(expectedValue + "", params.get("value")[0]); - - } - - /** - * 测试自定义的 ResponseConverter 以及服务方法声明异常的处理机制; - */ - public void testResponseConverterWithException_Error() { - String contextPath = "/testserver"; - String servicePath = "/test/content"; - boolean success = false; - String expectedError = "test error message"; - DataResponse expectedResponse = new DataResponse(success, expectedError, "TestContent\r\nabckkk\r\n1"); - String expectedResponseText = JSON.toJSONString(expectedResponse); - HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); - - // 准备环境; - int port = prepareEnvironment(contextPath, servlet, servicePath); - - ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); - AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); - HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); - - // 准备数据; - String expectedId = "001"; - boolean expectedPermited = true; - int expectedValue = 10; - - // 主要路径:测试自定义的回复转换器返回正常时的回复结果; - expectedId = "001"; - expectedPermited = true; - boolean expectedMale = false; - expectedValue = 188; - // 发起请求; - GetContentException expectedException = null; - try { - String actualResponseText2 = testService.fetchContentWithError(expectedId, expectedPermited, expectedMale, - expectedValue); - } catch (GetContentException e) { - expectedException = e; - } - // 验证结果; - assertTrue(expectedException != null);// 预期没有异常; - assertEquals(expectedError, expectedException.getMessage()); - } - - @Test - public void testRequestParamMap() { - String contextPath = "/testserver"; - String servicePath = "/test/content"; - DataResponse expectedResponse = new DataResponse(true, null, "TestContent\r\nabckkk\r\n1"); - String expectedResponseText = JSON.toJSONString(expectedResponse); - HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); - - // 准备环境; - int port = prepareEnvironment(contextPath, servlet, servicePath); - - ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); - AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); - HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); - - // 主要路径; - String expectedId = "001"; - boolean expectedPermited = true; - boolean origMale = false; - String expectedMaleStr = (new CustomBooleanConverter()).toString(origMale); - int expectedValue = 10; - - ContentRequestSetting expected = new ContentRequestSetting(); - expected.setId(expectedId); - expected.setMale(origMale); - expected.setPermited(expectedPermited); - expected.setValue(expectedValue); - - // 发起请求; - String actualResponseText = testService.content(expected); - // 验证结果; - assertEquals(expectedResponseText, actualResponseText); - Iterator reqRecords = servlet.getRequestRecords(); - assertTrue(reqRecords.hasNext()); - HttpRequestInfo reqRecord = reqRecords.next(); - assertEquals(HttpMethod.GET, reqRecord.getMethod()); - Map params = reqRecord.getParameters(); - assertEquals(5, params.size()); - assertTrue(params.containsKey("id")); - assertTrue(params.containsKey("permited")); - assertTrue(params.containsKey("male")); - assertTrue(params.containsKey("value")); - assertEquals(expectedId, params.get("id")[0]); - assertEquals(Boolean.toString(expectedPermited), params.get("permited")[0]); - assertEquals(expectedMaleStr, params.get("male")[0]); - assertEquals(expectedValue + "", params.get("value")[0]); - - assertTrue(params.containsKey("type"));// 验证只读常量字段也可以映射为请求参数; - assertEquals(expected.getType().toString(), params.get("type")[0]); - // 清理数据; - servlet.clearRequestRecords(); - } - - @Test - public void testRequestParam_Map() { - // TODO implemented; - } - - @Test - public void testMultiRequestParamMap() { - // TODO implemented; - } - - /** - * 测试多行文本的发送和获取; - */ - @Test - public void testMultilineTextSendAndGet() { - String contextPath = "/testserver"; - String servicePath = "/test/content/update"; - String expectedResponseText = "TestContent\r\nline2:testcontent.......\r\nline3::::"; - HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); - - // 准备环境; - int port = prepareEnvironment(contextPath, servlet, servicePath); - - ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); - AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); - HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); - - // 发起请求; - String actualResponseText = testService.updateAndGetContent(expectedResponseText); - // 验证结果; - assertEquals(expectedResponseText, actualResponseText); - - Iterator reqRecords = servlet.getRequestRecords(); - assertTrue(reqRecords.hasNext()); - HttpRequestInfo reqRecord = reqRecords.next(); - assertEquals(HttpMethod.GET, reqRecord.getMethod()); - Map params = reqRecord.getParameters(); - assertEquals(1, params.size()); - assertTrue(params.containsKey("content")); - assertEquals(expectedResponseText, params.get("content")[0]); - - // 清理数据; - servlet.clearRequestRecords(); - } - - @Test - public void testRequestParam_Map_Body() { - // TODO implemented; - } - - /** - * 测试PathParam - */ - @Test - public void testPathParam() { - String contextPath = "/testserver"; - String servicePath = "/test/content/*"; - DataResponse expectedResponse = new DataResponse(true, null, "TestContent\r\nabckkk\r\n001"); - String expectedResponseText = JSON.toJSONString(expectedResponse); - HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); - - // 准备环境; - int port = prepareEnvironment(contextPath, servlet, servicePath); - - ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); - AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); - HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); - - // 主要路径; - String expectedId = "001"; - // 发起请求; - String actualResponseText = testService.contentById(expectedId); - // 验证结果; - assertEquals(expectedResponseText, actualResponseText); - assertEquals("/testserver/test/content/001", servlet.getRequestPath()); - assertEquals(AuthorizationAlgs.DEFAULT + " upush_test:123abc", servlet.getAuthorization()); - // 清理数据; - servlet.clearRequestRecords(); - - /** - * - * 测试put请求 - * - */ - String expectedContent = "Hello World!"; - // 发起请求; - actualResponseText = testService.contentByPut(expectedId, expectedContent); - // 验证结果; - assertEquals(expectedResponseText, actualResponseText); - assertEquals("PUT", servlet.getRequestMethod()); - // 清理数据; - servlet.clearRequestRecords(); - } - - @Test - public void testRequestBody() { - String contextPath = "/testserver"; - String servicePath = "/test/content/*"; - DataResponse expectedResponse = new DataResponse(true, null, "TestContent\r\nabckkk\r\n001"); - String expectedResponseText = JSON.toJSONString(expectedResponse); - HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); - - // 准备环境; - int port = prepareEnvironment(contextPath, servlet, servicePath); - - ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); - AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); - HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); - - // 主要路径; - String expectedId = "001"; - String expectedName = "liuxrb"; - RequestContent expectedRequestContent = new RequestContent(100, "Hello, World!"); - // 发起请求; - String actualResponseText = testService.contentBody(expectedId, expectedName, expectedRequestContent); - // 验证结果; - assertEquals(expectedResponseText, actualResponseText); - assertEquals("/testserver/test/content/001", servlet.getRequestPath()); - assertEquals(AuthorizationAlgs.DEFAULT + " upush_test:123abc", servlet.getAuthorization()); - - JSONObject jsonReqBody = JSONObject.parseObject(servlet.getRequestBody().toString("utf-8")); - JSONObject expectedJsonReqBody = (JSONObject) JSONObject.toJSON(expectedRequestContent); - assertJSONEqual(jsonReqBody, expectedJsonReqBody); - // assertEquals(JSONObject.toJSONString(expectedRequestContent), - // servlet.getRequestBody()); - // 清理数据; - servlet.clearRequestRecords(); - - } - - @Test - public void testMultiRequestBodies() { - String contextPath = "/testserver"; - String servicePath = "/test/content/*"; - - TestData expectedResponseData = new TestData(); - expectedResponseData.setId(99); - expectedResponseData.setValue(UUID.randomUUID().toString()); - byte[] expectedResponseBytes = BinarySerializeUtils.serialize(expectedResponseData); - HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseBytes); - - // 准备环境; - int port = prepareEnvironment(contextPath, servlet, servicePath); - - ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); - AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); - HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); - - // 主要路径; - String expectedId = "001"; - String expectedName = "liuxrb"; - - TestData data1 = new TestData(); - data1.setId(1); - data1.setValue(UUID.randomUUID().toString()); - TestData data2 = new TestData(); - data2.setId(1); - data2.setValue(UUID.randomUUID().toString()); - // 发起请求; - TestData actualResponseData = testService.multiContentBodies(expectedId, expectedName, data1, data2); - // 验证结果; - assertEquals(expectedResponseData.getId(), actualResponseData.getId()); - assertEquals(expectedResponseData.getValue(), actualResponseData.getValue()); - - assertEquals("/testserver/test/content/001/multi", servlet.getRequestPath()); - assertEquals(AuthorizationAlgs.DEFAULT + " upush_test:123abc", servlet.getAuthorization()); - - InputStream in = servlet.getRequestBody().asInputStream(); - TestData actualData1 = BinarySerializeUtils.deserialize(in); - TestData actualData2 = BinarySerializeUtils.deserialize(in); - - assertEquals(data1.getId(), actualData1.getId()); - assertEquals(data1.getValue(), actualData1.getValue()); - assertEquals(data2.getId(), actualData2.getId()); - assertEquals(data2.getValue(), actualData2.getValue()); - // assertEquals(JSONObject.toJSONString(expectedRequestContent), - // servlet.getRequestBody()); - // 清理数据; - servlet.clearRequestRecords(); - - } - - - @Test - public void testMultiRequestBodiesWithDefaultConverter() { - String contextPath = "/testserver"; - String servicePath = "/test/content/*"; - - TestData expectedResponseData = new TestData(); - expectedResponseData.setId(99); - expectedResponseData.setValue(UUID.randomUUID().toString()); - byte[] expectedResponseBytes = BinarySerializeUtils.serialize(expectedResponseData); - HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseBytes); - - // 准备环境; - int port = prepareEnvironment(contextPath, servlet, servicePath); - - ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); - AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); - - // 创建测试对象; - MultiRequestBodiesWithDefaultConverterTestService testService = HttpServiceAgent.createService(MultiRequestBodiesWithDefaultConverterTestService.class, setting, authSetting); - - // 主要路径; - String expectedId = "001"; - String expectedName = "liuxrb"; - - TestData data1 = new TestData(); - data1.setId(1); - data1.setValue(UUID.randomUUID().toString()); - TestData data2 = new TestData(); - data2.setId(1); - data2.setValue(UUID.randomUUID().toString()); - // 发起请求; - TestData actualResponseData = testService.multiContentBodies(expectedId, expectedName, data1, data2); - // 验证结果; - assertEquals(expectedResponseData.getId(), actualResponseData.getId()); - assertEquals(expectedResponseData.getValue(), actualResponseData.getValue()); - - assertEquals("/testserver/test/content/001/multi", servlet.getRequestPath()); - assertEquals(AuthorizationAlgs.DEFAULT + " upush_test:123abc", servlet.getAuthorization()); - - InputStream in = servlet.getRequestBody().asInputStream(); - TestData actualData1 = BinarySerializeUtils.deserialize(in); - TestData actualData2 = BinarySerializeUtils.deserialize(in); - - assertEquals(data1.getId(), actualData1.getId()); - assertEquals(data1.getValue(), actualData1.getValue()); - assertEquals(data2.getId(), actualData2.getId()); - assertEquals(data2.getValue(), actualData2.getValue()); - // assertEquals(JSONObject.toJSONString(expectedRequestContent), - // servlet.getRequestBody()); - // 清理数据; - servlet.clearRequestRecords(); - - } - - private void assertJSONEqual(JSONObject jsonObj1, JSONObject jsonObj2) { - Set> fields = jsonObj1.entrySet(); - for (Entry field : fields) { - assertTrue(jsonObj2.containsKey(field.getKey())); - Object value1 = field.getValue(); - Object value2 = jsonObj2.get(field.getKey()); - if (value1 != null && value2 != null && value1 instanceof JSONObject && value2 instanceof JSONObject) { - assertJSONEqual((JSONObject) value1, (JSONObject) value2); - } else { - assertEquals(value1, value2); - } - } - } -} - +package test.my.utils.http.agent; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.InputStream; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.UUID; + +import javax.servlet.http.HttpServlet; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.jd.blockchain.utils.http.HttpMethod; +import com.jd.blockchain.utils.http.agent.AuthorizationAlgs; +import com.jd.blockchain.utils.http.agent.AuthorizationHeader; +import com.jd.blockchain.utils.http.agent.HttpServiceAgent; +import com.jd.blockchain.utils.http.agent.ServiceEndpoint; +import com.jd.blockchain.utils.io.BytesUtils; +import com.jd.blockchain.utils.security.ShaUtils; +import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; +import com.jd.blockchain.utils.web.server.WebServer; + +public class HttpServiceAgentTest { + + private static final String host = "127.0.0.1"; + +// private static final int port = 10809; + + private static final String SENDER_NAME = "upush_test"; + + private static final String SECRET_KEY = "123abc"; + + private WebServer server; + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + if (server != null) { + server.stop(); + } + } + + private int getRandomPort() { + byte[] nanoTime = BytesUtils.toBytes(System.nanoTime()); + byte[] hash = ShaUtils.hash_256(nanoTime); + return hash[0]; + } + + private int prepareEnvironment(String contextPath, HttpServlet servlet, String servletMapping) { + //随机化端口,避免测试用例的端口冲突 + int port = 11000 + getRandomPort(); + server = new WebServer(host, port); + server.registServlet("test-servlet", servlet, servletMapping); + server.setContextPath(contextPath); + server.start(); + + return port; + } + + @Test + public void testRequestParam() { + String contextPath = "/testserver"; + String servicePath = "/test/content"; + DataResponse expectedResponse = new DataResponse(true, null, "TestContent\r\nabckkk\r\n1"); + String expectedResponseText = JSON.toJSONString(expectedResponse); + HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); + + // 准备环境; + int port = prepareEnvironment(contextPath, servlet, servicePath); + + ServiceEndpoint endpoint = new ServiceEndpoint(host, port, false, contextPath); + AuthorizationHeader authorization = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); + // setting.setContextPath(contextPath); + HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, endpoint, authorization); + + // 主要路径; + String expectedId = "001"; + boolean expectedPermited = true; + boolean origMale = false; + String expectedMaleStr = (new CustomBooleanConverter()).toString(origMale); + int expectedValue = 10; + // 发起请求; + String actualResponseText = testService.content(expectedId, expectedPermited, origMale, expectedValue); + // 验证结果; + assertEquals(expectedResponseText, actualResponseText); + Iterator reqRecords = servlet.getRequestRecords(); + assertTrue(reqRecords.hasNext()); + HttpRequestInfo reqRecord = reqRecords.next(); + assertEquals(HttpMethod.GET, reqRecord.getMethod()); + Map params = reqRecord.getParameters(); + assertEquals(4, params.size()); + assertTrue(params.containsKey("id")); + assertTrue(params.containsKey("permited")); + assertTrue(params.containsKey("male")); + assertTrue(params.containsKey("value")); + assertEquals(expectedId, params.get("id")[0]); + assertEquals(Boolean.toString(expectedPermited), params.get("permited")[0]); + assertEquals(expectedMaleStr, params.get("male")[0]); + assertEquals(expectedValue + "", params.get("value")[0]); + // 清理数据; + servlet.clearRequestRecords(); + + // 在主要路径的基础上验证标注的请求路径名,忽略特定值的参数; + expectedId = "001"; + expectedPermited = true; + origMale = false; + expectedMaleStr = (new CustomBooleanConverter()).toString(origMale); + int expectedIgnoreValue = -1; + // 发起请求; + DataResponse actualResponse = testService.getContent(expectedId, expectedPermited, origMale, + expectedIgnoreValue, "other values"); + // 验证结果; + assertEquals(expectedResponse.getContent(), actualResponse.getContent()); + assertEquals(expectedResponse.getError(), actualResponse.getError()); + assertEquals(expectedResponse.isSuccess(), actualResponse.isSuccess()); + + reqRecords = servlet.getRequestRecords(); + assertTrue(reqRecords.hasNext()); + reqRecord = reqRecords.next(); + assertEquals(HttpMethod.GET, reqRecord.getMethod()); + params = reqRecord.getParameters(); + assertEquals(3, params.size()); + assertTrue(params.containsKey("id")); + assertTrue(params.containsKey("permited")); + assertTrue(params.containsKey("male")); + assertTrue(!params.containsKey("value"));// 不包含应被忽略的值; + assertEquals(expectedId, params.get("id")[0]); + assertEquals(Boolean.toString(expectedPermited), params.get("permited")[0]); + assertEquals(expectedMaleStr, params.get("male")[0]); + servlet.clearRequestRecords(); + + // 在前面的测试路径的基础上验证 http post 方法发送请求,以及自定义的回复转换器; + expectedId = "001"; + expectedPermited = true; + boolean expectedMale = false; + expectedValue = 188; + // 发起请求; + String actualResponseText2 = testService.fetchContent(expectedId, expectedPermited, expectedMale, + expectedValue); + // 验证结果; + assertEquals(expectedResponse.getContent(), actualResponseText2); + reqRecords = servlet.getRequestRecords(); + assertTrue(reqRecords.hasNext()); + reqRecord = reqRecords.next(); + assertEquals(HttpMethod.POST, reqRecord.getMethod()); + params = reqRecord.getParameters(); + assertEquals(4, params.size()); + assertTrue(params.containsKey("id")); + assertTrue(params.containsKey("permited")); + assertTrue(params.containsKey("male")); + assertTrue(params.containsKey("value")); + assertEquals(expectedId, params.get("id")[0]); + assertEquals(Boolean.toString(expectedPermited), params.get("permited")[0]); + assertEquals(expectedMaleStr, params.get("male")[0]); + assertEquals(expectedValue + "", params.get("value")[0]); + + } + + /** + * 测试自定义的 ResponseConverter 以及服务方法声明异常的处理机制; + */ + public void testResponseConverterWithException_Success() { + String contextPath = "/testserver"; + String servicePath = "/test/content"; + boolean success = true; + String expectedError = ""; + DataResponse expectedResponse = new DataResponse(success, expectedError, "TestContent\r\nabckkk\r\n1"); + String expectedResponseText = JSON.toJSONString(expectedResponse); + HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); + + // 准备环境; + int port = prepareEnvironment(contextPath, servlet, servicePath); + ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); + AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); + HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); + + // 准备数据; + String expectedId = "001"; + boolean expectedPermited = true; + boolean origMale = false; + int expectedValue = 10; + + // 主要路径:测试自定义的回复转换器返回正常时的回复结果; + expectedId = "001"; + expectedPermited = true; + boolean expectedMale = false; + String expectedMaleStr = (new CustomBooleanConverter()).toString(origMale); + expectedValue = 188; + // 发起请求; + GetContentException expectedException = null; + String actualResponseText2 = null; + try { + actualResponseText2 = testService.fetchContentWithError(expectedId, expectedPermited, expectedMale, + expectedValue); + } catch (GetContentException e) { + expectedException = e; + } + // 验证结果; + assertTrue(expectedException == null);// 预期没有异常; + + assertEquals(expectedResponse.getContent(), actualResponseText2); + Iterator reqRecords = servlet.getRequestRecords(); + assertTrue(reqRecords.hasNext()); + HttpRequestInfo reqRecord = reqRecords.next(); + assertEquals(HttpMethod.POST, reqRecord.getMethod()); + Map params = reqRecord.getParameters(); + assertEquals(4, params.size()); + assertTrue(params.containsKey("id")); + assertTrue(params.containsKey("permited")); + assertTrue(params.containsKey("male")); + assertTrue(params.containsKey("value")); + assertEquals(expectedId, params.get("id")[0]); + assertEquals(Boolean.toString(expectedPermited), params.get("permited")[0]); + assertEquals(expectedMaleStr, params.get("male")[0]); + assertEquals(expectedValue + "", params.get("value")[0]); + + } + + /** + * 测试自定义的 ResponseConverter 以及服务方法声明异常的处理机制; + */ + public void testResponseConverterWithException_Error() { + String contextPath = "/testserver"; + String servicePath = "/test/content"; + boolean success = false; + String expectedError = "test error message"; + DataResponse expectedResponse = new DataResponse(success, expectedError, "TestContent\r\nabckkk\r\n1"); + String expectedResponseText = JSON.toJSONString(expectedResponse); + HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); + + // 准备环境; + int port = prepareEnvironment(contextPath, servlet, servicePath); + + ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); + AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); + HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); + + // 准备数据; + String expectedId = "001"; + boolean expectedPermited = true; + int expectedValue = 10; + + // 主要路径:测试自定义的回复转换器返回正常时的回复结果; + expectedId = "001"; + expectedPermited = true; + boolean expectedMale = false; + expectedValue = 188; + // 发起请求; + GetContentException expectedException = null; + try { + String actualResponseText2 = testService.fetchContentWithError(expectedId, expectedPermited, expectedMale, + expectedValue); + } catch (GetContentException e) { + expectedException = e; + } + // 验证结果; + assertTrue(expectedException != null);// 预期没有异常; + assertEquals(expectedError, expectedException.getMessage()); + } + + @Test + public void testRequestParamMap() { + String contextPath = "/testserver"; + String servicePath = "/test/content"; + DataResponse expectedResponse = new DataResponse(true, null, "TestContent\r\nabckkk\r\n1"); + String expectedResponseText = JSON.toJSONString(expectedResponse); + HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); + + // 准备环境; + int port = prepareEnvironment(contextPath, servlet, servicePath); + + ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); + AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); + HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); + + // 主要路径; + String expectedId = "001"; + boolean expectedPermited = true; + boolean origMale = false; + String expectedMaleStr = (new CustomBooleanConverter()).toString(origMale); + int expectedValue = 10; + + ContentRequestSetting expected = new ContentRequestSetting(); + expected.setId(expectedId); + expected.setMale(origMale); + expected.setPermited(expectedPermited); + expected.setValue(expectedValue); + + // 发起请求; + String actualResponseText = testService.content(expected); + // 验证结果; + assertEquals(expectedResponseText, actualResponseText); + Iterator reqRecords = servlet.getRequestRecords(); + assertTrue(reqRecords.hasNext()); + HttpRequestInfo reqRecord = reqRecords.next(); + assertEquals(HttpMethod.GET, reqRecord.getMethod()); + Map params = reqRecord.getParameters(); + assertEquals(5, params.size()); + assertTrue(params.containsKey("id")); + assertTrue(params.containsKey("permited")); + assertTrue(params.containsKey("male")); + assertTrue(params.containsKey("value")); + assertEquals(expectedId, params.get("id")[0]); + assertEquals(Boolean.toString(expectedPermited), params.get("permited")[0]); + assertEquals(expectedMaleStr, params.get("male")[0]); + assertEquals(expectedValue + "", params.get("value")[0]); + + assertTrue(params.containsKey("type"));// 验证只读常量字段也可以映射为请求参数; + assertEquals(expected.getType().toString(), params.get("type")[0]); + // 清理数据; + servlet.clearRequestRecords(); + } + + @Test + public void testRequestParam_Map() { + // TODO implemented; + } + + @Test + public void testMultiRequestParamMap() { + // TODO implemented; + } + + /** + * 测试多行文本的发送和获取; + */ + @Test + public void testMultilineTextSendAndGet() { + String contextPath = "/testserver"; + String servicePath = "/test/content/update"; + String expectedResponseText = "TestContent\r\nline2:testcontent.......\r\nline3::::"; + HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); + + // 准备环境; + int port = prepareEnvironment(contextPath, servlet, servicePath); + + ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); + AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); + HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); + + // 发起请求; + String actualResponseText = testService.updateAndGetContent(expectedResponseText); + // 验证结果; + assertEquals(expectedResponseText, actualResponseText); + + Iterator reqRecords = servlet.getRequestRecords(); + assertTrue(reqRecords.hasNext()); + HttpRequestInfo reqRecord = reqRecords.next(); + assertEquals(HttpMethod.GET, reqRecord.getMethod()); + Map params = reqRecord.getParameters(); + assertEquals(1, params.size()); + assertTrue(params.containsKey("content")); + assertEquals(expectedResponseText, params.get("content")[0]); + + // 清理数据; + servlet.clearRequestRecords(); + } + + @Test + public void testRequestParam_Map_Body() { + // TODO implemented; + } + + /** + * 测试PathParam + */ + @Test + public void testPathParam() { + String contextPath = "/testserver"; + String servicePath = "/test/content/*"; + DataResponse expectedResponse = new DataResponse(true, null, "TestContent\r\nabckkk\r\n001"); + String expectedResponseText = JSON.toJSONString(expectedResponse); + HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); + + // 准备环境; + int port = prepareEnvironment(contextPath, servlet, servicePath); + + ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); + AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); + HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); + + // 主要路径; + String expectedId = "001"; + // 发起请求; + String actualResponseText = testService.contentById(expectedId); + // 验证结果; + assertEquals(expectedResponseText, actualResponseText); + assertEquals("/testserver/test/content/001", servlet.getRequestPath()); + assertEquals(AuthorizationAlgs.DEFAULT + " upush_test:123abc", servlet.getAuthorization()); + // 清理数据; + servlet.clearRequestRecords(); + + /** + * + * 测试put请求 + * + */ + String expectedContent = "Hello World!"; + // 发起请求; + actualResponseText = testService.contentByPut(expectedId, expectedContent); + // 验证结果; + assertEquals(expectedResponseText, actualResponseText); + assertEquals("PUT", servlet.getRequestMethod()); + // 清理数据; + servlet.clearRequestRecords(); + } + + @Test + public void testRequestBody() { + String contextPath = "/testserver"; + String servicePath = "/test/content/*"; + DataResponse expectedResponse = new DataResponse(true, null, "TestContent\r\nabckkk\r\n001"); + String expectedResponseText = JSON.toJSONString(expectedResponse); + HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseText); + + // 准备环境; + int port = prepareEnvironment(contextPath, servlet, servicePath); + + ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); + AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); + HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); + + // 主要路径; + String expectedId = "001"; + String expectedName = "liuxrb"; + RequestContent expectedRequestContent = new RequestContent(100, "Hello, World!"); + // 发起请求; + String actualResponseText = testService.contentBody(expectedId, expectedName, expectedRequestContent); + // 验证结果; + assertEquals(expectedResponseText, actualResponseText); + assertEquals("/testserver/test/content/001", servlet.getRequestPath()); + assertEquals(AuthorizationAlgs.DEFAULT + " upush_test:123abc", servlet.getAuthorization()); + + JSONObject jsonReqBody = JSONObject.parseObject(servlet.getRequestBody().toString("utf-8")); + JSONObject expectedJsonReqBody = (JSONObject) JSONObject.toJSON(expectedRequestContent); + assertJSONEqual(jsonReqBody, expectedJsonReqBody); + // assertEquals(JSONObject.toJSONString(expectedRequestContent), + // servlet.getRequestBody()); + // 清理数据; + servlet.clearRequestRecords(); + + } + + @Test + public void testMultiRequestBodies() { + String contextPath = "/testserver"; + String servicePath = "/test/content/*"; + + TestData expectedResponseData = new TestData(); + expectedResponseData.setId(99); + expectedResponseData.setValue(UUID.randomUUID().toString()); + byte[] expectedResponseBytes = BinarySerializeUtils.serialize(expectedResponseData); + HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseBytes); + + // 准备环境; + int port = prepareEnvironment(contextPath, servlet, servicePath); + + ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); + AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); + HttpTestService testService = HttpServiceAgent.createService(HttpTestService.class, setting, authSetting); + + // 主要路径; + String expectedId = "001"; + String expectedName = "liuxrb"; + + TestData data1 = new TestData(); + data1.setId(1); + data1.setValue(UUID.randomUUID().toString()); + TestData data2 = new TestData(); + data2.setId(1); + data2.setValue(UUID.randomUUID().toString()); + // 发起请求; + TestData actualResponseData = testService.multiContentBodies(expectedId, expectedName, data1, data2); + // 验证结果; + assertEquals(expectedResponseData.getId(), actualResponseData.getId()); + assertEquals(expectedResponseData.getValue(), actualResponseData.getValue()); + + assertEquals("/testserver/test/content/001/multi", servlet.getRequestPath()); + assertEquals(AuthorizationAlgs.DEFAULT + " upush_test:123abc", servlet.getAuthorization()); + + InputStream in = servlet.getRequestBody().asInputStream(); + TestData actualData1 = BinarySerializeUtils.deserialize(in); + TestData actualData2 = BinarySerializeUtils.deserialize(in); + + assertEquals(data1.getId(), actualData1.getId()); + assertEquals(data1.getValue(), actualData1.getValue()); + assertEquals(data2.getId(), actualData2.getId()); + assertEquals(data2.getValue(), actualData2.getValue()); + // assertEquals(JSONObject.toJSONString(expectedRequestContent), + // servlet.getRequestBody()); + // 清理数据; + servlet.clearRequestRecords(); + + } + + + @Test + public void testMultiRequestBodiesWithDefaultConverter() { + String contextPath = "/testserver"; + String servicePath = "/test/content/*"; + + TestData expectedResponseData = new TestData(); + expectedResponseData.setId(99); + expectedResponseData.setValue(UUID.randomUUID().toString()); + byte[] expectedResponseBytes = BinarySerializeUtils.serialize(expectedResponseData); + HttpRequestCollector servlet = new HttpRequestCollector(expectedResponseBytes); + + // 准备环境; + int port = prepareEnvironment(contextPath, servlet, servicePath); + + ServiceEndpoint setting = new ServiceEndpoint(host, port, false, contextPath); + AuthorizationHeader authSetting = new AuthorizationHeader(AuthorizationAlgs.DEFAULT, SENDER_NAME, SECRET_KEY); + + // 创建测试对象; + MultiRequestBodiesWithDefaultConverterTestService testService = HttpServiceAgent.createService(MultiRequestBodiesWithDefaultConverterTestService.class, setting, authSetting); + + // 主要路径; + String expectedId = "001"; + String expectedName = "liuxrb"; + + TestData data1 = new TestData(); + data1.setId(1); + data1.setValue(UUID.randomUUID().toString()); + TestData data2 = new TestData(); + data2.setId(1); + data2.setValue(UUID.randomUUID().toString()); + // 发起请求; + TestData actualResponseData = testService.multiContentBodies(expectedId, expectedName, data1, data2); + // 验证结果; + assertEquals(expectedResponseData.getId(), actualResponseData.getId()); + assertEquals(expectedResponseData.getValue(), actualResponseData.getValue()); + + assertEquals("/testserver/test/content/001/multi", servlet.getRequestPath()); + assertEquals(AuthorizationAlgs.DEFAULT + " upush_test:123abc", servlet.getAuthorization()); + + InputStream in = servlet.getRequestBody().asInputStream(); + TestData actualData1 = BinarySerializeUtils.deserialize(in); + TestData actualData2 = BinarySerializeUtils.deserialize(in); + + assertEquals(data1.getId(), actualData1.getId()); + assertEquals(data1.getValue(), actualData1.getValue()); + assertEquals(data2.getId(), actualData2.getId()); + assertEquals(data2.getValue(), actualData2.getValue()); + // assertEquals(JSONObject.toJSONString(expectedRequestContent), + // servlet.getRequestBody()); + // 清理数据; + servlet.clearRequestRecords(); + + } + + private void assertJSONEqual(JSONObject jsonObj1, JSONObject jsonObj2) { + Set> fields = jsonObj1.entrySet(); + for (Entry field : fields) { + assertTrue(jsonObj2.containsKey(field.getKey())); + Object value1 = field.getValue(); + Object value2 = jsonObj2.get(field.getKey()); + if (value1 != null && value2 != null && value1 instanceof JSONObject && value2 instanceof JSONObject) { + assertJSONEqual((JSONObject) value1, (JSONObject) value2); + } else { + assertEquals(value1, value2); + } + } + } +} + diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpTestService.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpTestService.java index a8414ace..fa06c839 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpTestService.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/HttpTestService.java @@ -1,131 +1,131 @@ -package test.my.utils.http.agent; - -import com.jd.blockchain.utils.http.HttpAction; -import com.jd.blockchain.utils.http.HttpMethod; -import com.jd.blockchain.utils.http.HttpService; -import com.jd.blockchain.utils.http.PathParam; -import com.jd.blockchain.utils.http.RequestBody; -import com.jd.blockchain.utils.http.RequestParam; -import com.jd.blockchain.utils.http.RequestParamMap; -import com.jd.blockchain.utils.http.converters.BinarySerializeRequestBodyConverter; -import com.jd.blockchain.utils.http.converters.BinarySerializeResponseConverter; - -@HttpService(path = "/test") -public interface HttpTestService { - - /** - * 通过 HTTP GET 方法获取文本内容; - * - * @param id - * @param permited - * @param male - * 性别;作为请求参数,设置了自定义的转换器将布尔值转换为 0/1 ; - * @param value - * 值;定义为非必须的请求参数,如果值为 -1 时被忽略; - * @return 返回结果是包含了请求处理状态、错误信息、成功的数据内容在内的 JSON 字符串; - */ - @HttpAction(method = HttpMethod.GET) - public String content(@RequestParam(name = "id") String id, @RequestParam(name = "permited") boolean permited, - @RequestParam(name = "male", converter = CustomBooleanConverter.class) boolean male, - @RequestParam(name = "value", required = false, ignoreValue = "-1") int value); - - /** - * 通过 HTTP GET 方法获取文本内容; - * - * @param setting - * 请求参数 - * @return - */ - @HttpAction(method = HttpMethod.GET) - public String content(@RequestParamMap ContentRequestSetting setting); - - /** - * 通过 HTTP GET 方法获取文本内容; - * - * @param id - * @param permited - * @param male - * @param value - * @param otherArg - * 定义一个额外的方法参数,但该参数的内容不会包含在 http 请求中; - * @return - */ - @HttpAction(path = "/content", method = HttpMethod.GET) - public DataResponse getContent(@RequestParam(name = "id") String id, - @RequestParam(name = "permited") boolean permited, - @RequestParam(name = "male", converter = CustomBooleanConverter.class) boolean male, - @RequestParam(name = "value", required = false, ignoreValue = "-1") int value, String otherArg); - - /** - * 以 HTTP POST 方式获取内容; - * - * @param id - * @param permited - * @param male - * @param value - * @return 指定了自定义的返回结果转换器,使返回结果仅包含数据内容,而不包含成功状态及错误信息; - */ - @HttpAction(path = "/content", method = HttpMethod.POST, responseConverter = GetContentResponseConverter.class) - public String fetchContent(@RequestParam(name = "id") String id, @RequestParam(name = "permited") boolean permited, - @RequestParam(name = "male", converter = CustomBooleanConverter.class) boolean male, - @RequestParam(name = "value", required = false, ignoreValue = "-1") int value); - - /** - * 以 HTTP POST 方式获取内容; - * - * @param id - * @param permited - * @param male - * @param value - * @return 指定了自定义的返回结果转换器,使返回结果仅包含成功时数据内容,而不包含成功状态及错误信息,并且失败时抛出声明的异常; - * @throws GetContentException - */ - @HttpAction(path = "/content", method = HttpMethod.POST, responseConverter = GetContentResponseConverterWithException.class) - public String fetchContentWithError(@RequestParam(name = "id") String id, - @RequestParam(name = "permited") boolean permited, - @RequestParam(name = "male", converter = CustomBooleanConverter.class) boolean male, - @RequestParam(name = "value", required = false, ignoreValue = "-1") int value) throws GetContentException; - - @HttpAction(path = "/content/update", method = HttpMethod.GET) - public String updateAndGetContent(@RequestParam(name = "content") String content); - - @HttpAction(path = "/content/{id}", method = HttpMethod.POST) - public String contentById(@PathParam(name = "id") String id); - - @HttpAction(path = "/content/ids", method = HttpMethod.POST) - public String contentByIds(@RequestParam(name = "ids", array=true) String[] ids); - - /** - * 以Http put 请求 - * - * @param id - * @return - */ - @HttpAction(path = "/content/{id}", method = HttpMethod.PUT) - public String contentByPut(@PathParam(name = "id") String id, @RequestParam(name = "content") String content); - - /** - * http delete 请求 - * - * @param id - * @return - */ - @HttpAction(path = "/content/{id}", method = HttpMethod.DELETE) - public String contentByDelete(@PathParam(name = "id") String id); - - @HttpAction(path = "/content/{id}", method = HttpMethod.POST) - public String contentBody(@PathParam(name = "id") String id, @RequestParam(name = "name") String name, - @RequestBody RequestContent requestContent); - - @HttpAction(path = "/content/{id}/multi", method = HttpMethod.POST, responseConverter = BinarySerializeResponseConverter.class) - public TestData multiContentBodies(@PathParam(name = "id") String id, @RequestParam(name = "name") String name, - @RequestBody(converter = BinarySerializeRequestBodyConverter.class) TestData data1, - @RequestBody(converter = BinarySerializeRequestBodyConverter.class) TestData data2); - - /** - * 测试https请求 - */ - @HttpAction(path = "/", method = HttpMethod.GET) - public String testHttps(); - -} +package test.my.utils.http.agent; + +import com.jd.blockchain.utils.http.HttpAction; +import com.jd.blockchain.utils.http.HttpMethod; +import com.jd.blockchain.utils.http.HttpService; +import com.jd.blockchain.utils.http.PathParam; +import com.jd.blockchain.utils.http.RequestBody; +import com.jd.blockchain.utils.http.RequestParam; +import com.jd.blockchain.utils.http.RequestParamMap; +import com.jd.blockchain.utils.http.converters.BinarySerializeRequestBodyConverter; +import com.jd.blockchain.utils.http.converters.BinarySerializeResponseConverter; + +@HttpService(path = "/test") +public interface HttpTestService { + + /** + * 通过 HTTP GET 方法获取文本内容; + * + * @param id + * @param permited + * @param male + * 性别;作为请求参数,设置了自定义的转换器将布尔值转换为 0/1 ; + * @param value + * 值;定义为非必须的请求参数,如果值为 -1 时被忽略; + * @return 返回结果是包含了请求处理状态、错误信息、成功的数据内容在内的 JSON 字符串; + */ + @HttpAction(method = HttpMethod.GET) + public String content(@RequestParam(name = "id") String id, @RequestParam(name = "permited") boolean permited, + @RequestParam(name = "male", converter = CustomBooleanConverter.class) boolean male, + @RequestParam(name = "value", required = false, ignoreValue = "-1") int value); + + /** + * 通过 HTTP GET 方法获取文本内容; + * + * @param setting + * 请求参数 + * @return + */ + @HttpAction(method = HttpMethod.GET) + public String content(@RequestParamMap ContentRequestSetting setting); + + /** + * 通过 HTTP GET 方法获取文本内容; + * + * @param id + * @param permited + * @param male + * @param value + * @param otherArg + * 定义一个额外的方法参数,但该参数的内容不会包含在 http 请求中; + * @return + */ + @HttpAction(path = "/content", method = HttpMethod.GET) + public DataResponse getContent(@RequestParam(name = "id") String id, + @RequestParam(name = "permited") boolean permited, + @RequestParam(name = "male", converter = CustomBooleanConverter.class) boolean male, + @RequestParam(name = "value", required = false, ignoreValue = "-1") int value, String otherArg); + + /** + * 以 HTTP POST 方式获取内容; + * + * @param id + * @param permited + * @param male + * @param value + * @return 指定了自定义的返回结果转换器,使返回结果仅包含数据内容,而不包含成功状态及错误信息; + */ + @HttpAction(path = "/content", method = HttpMethod.POST, responseConverter = GetContentResponseConverter.class) + public String fetchContent(@RequestParam(name = "id") String id, @RequestParam(name = "permited") boolean permited, + @RequestParam(name = "male", converter = CustomBooleanConverter.class) boolean male, + @RequestParam(name = "value", required = false, ignoreValue = "-1") int value); + + /** + * 以 HTTP POST 方式获取内容; + * + * @param id + * @param permited + * @param male + * @param value + * @return 指定了自定义的返回结果转换器,使返回结果仅包含成功时数据内容,而不包含成功状态及错误信息,并且失败时抛出声明的异常; + * @throws GetContentException + */ + @HttpAction(path = "/content", method = HttpMethod.POST, responseConverter = GetContentResponseConverterWithException.class) + public String fetchContentWithError(@RequestParam(name = "id") String id, + @RequestParam(name = "permited") boolean permited, + @RequestParam(name = "male", converter = CustomBooleanConverter.class) boolean male, + @RequestParam(name = "value", required = false, ignoreValue = "-1") int value) throws GetContentException; + + @HttpAction(path = "/content/update", method = HttpMethod.GET) + public String updateAndGetContent(@RequestParam(name = "content") String content); + + @HttpAction(path = "/content/{id}", method = HttpMethod.POST) + public String contentById(@PathParam(name = "id") String id); + + @HttpAction(path = "/content/ids", method = HttpMethod.POST) + public String contentByIds(@RequestParam(name = "ids", array=true) String[] ids); + + /** + * 以Http put 请求 + * + * @param id + * @return + */ + @HttpAction(path = "/content/{id}", method = HttpMethod.PUT) + public String contentByPut(@PathParam(name = "id") String id, @RequestParam(name = "content") String content); + + /** + * http delete 请求 + * + * @param id + * @return + */ + @HttpAction(path = "/content/{id}", method = HttpMethod.DELETE) + public String contentByDelete(@PathParam(name = "id") String id); + + @HttpAction(path = "/content/{id}", method = HttpMethod.POST) + public String contentBody(@PathParam(name = "id") String id, @RequestParam(name = "name") String name, + @RequestBody RequestContent requestContent); + + @HttpAction(path = "/content/{id}/multi", method = HttpMethod.POST, responseConverter = BinarySerializeResponseConverter.class) + public TestData multiContentBodies(@PathParam(name = "id") String id, @RequestParam(name = "name") String name, + @RequestBody(converter = BinarySerializeRequestBodyConverter.class) TestData data1, + @RequestBody(converter = BinarySerializeRequestBodyConverter.class) TestData data2); + + /** + * 测试https请求 + */ + @HttpAction(path = "/", method = HttpMethod.GET) + public String testHttps(); + +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/MultiRequestBodiesWithDefaultConverterTestService.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/MultiRequestBodiesWithDefaultConverterTestService.java index 618b7dcf..7c9a45e5 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/MultiRequestBodiesWithDefaultConverterTestService.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/MultiRequestBodiesWithDefaultConverterTestService.java @@ -1,18 +1,18 @@ -package test.my.utils.http.agent; - -import com.jd.blockchain.utils.http.HttpAction; -import com.jd.blockchain.utils.http.HttpMethod; -import com.jd.blockchain.utils.http.HttpService; -import com.jd.blockchain.utils.http.PathParam; -import com.jd.blockchain.utils.http.RequestBody; -import com.jd.blockchain.utils.http.RequestParam; -import com.jd.blockchain.utils.http.converters.BinarySerializeRequestBodyConverter; -import com.jd.blockchain.utils.http.converters.BinarySerializeResponseConverter; - -@HttpService(path = "/test", defaultRequestBodyConverter = BinarySerializeRequestBodyConverter.class, defaultResponseConverter = BinarySerializeResponseConverter.class) -public interface MultiRequestBodiesWithDefaultConverterTestService { - @HttpAction(path = "/content/{id}/multi", method = HttpMethod.POST) - public TestData multiContentBodies(@PathParam(name = "id") String id, @RequestParam(name = "name") String name, - @RequestBody TestData data1, @RequestBody TestData data2); - -} +package test.my.utils.http.agent; + +import com.jd.blockchain.utils.http.HttpAction; +import com.jd.blockchain.utils.http.HttpMethod; +import com.jd.blockchain.utils.http.HttpService; +import com.jd.blockchain.utils.http.PathParam; +import com.jd.blockchain.utils.http.RequestBody; +import com.jd.blockchain.utils.http.RequestParam; +import com.jd.blockchain.utils.http.converters.BinarySerializeRequestBodyConverter; +import com.jd.blockchain.utils.http.converters.BinarySerializeResponseConverter; + +@HttpService(path = "/test", defaultRequestBodyConverter = BinarySerializeRequestBodyConverter.class, defaultResponseConverter = BinarySerializeResponseConverter.class) +public interface MultiRequestBodiesWithDefaultConverterTestService { + @HttpAction(path = "/content/{id}/multi", method = HttpMethod.POST) + public TestData multiContentBodies(@PathParam(name = "id") String id, @RequestParam(name = "name") String name, + @RequestBody TestData data1, @RequestBody TestData data2); + +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/OpType.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/OpType.java index 6932e798..af746ec0 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/OpType.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/OpType.java @@ -1,25 +1,25 @@ -package test.my.utils.http.agent; - -/** - * 用于验证将枚举类型的 POJO 字段映射为请求参数时,默认情况下通过 toString 方法取得参数值; - * - * @author haiq - * - */ -public enum OpType { - - TYPE1(1), - - TYPE2(2); - - private int value; - - private OpType(int value) { - this.value = value; - } - - @Override - public String toString() { - return String.valueOf(this.value); - } -} +package test.my.utils.http.agent; + +/** + * 用于验证将枚举类型的 POJO 字段映射为请求参数时,默认情况下通过 toString 方法取得参数值; + * + * @author haiq + * + */ +public enum OpType { + + TYPE1(1), + + TYPE2(2); + + private int value; + + private OpType(int value) { + this.value = value; + } + + @Override + public String toString() { + return String.valueOf(this.value); + } +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/RequestContent.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/RequestContent.java index e35a223e..1f1f0b18 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/RequestContent.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/RequestContent.java @@ -1,37 +1,37 @@ -package test.my.utils.http.agent; - -public class RequestContent { - - private int requestId; - - private String requestContent; - - public RequestContent(){ - - } - - public RequestContent(int requestId, String requestContent){ - this.requestId = requestId; - this.requestContent = requestContent; - } - - - - public int getRequestId() { - return requestId; - } - - public void setRequestId(int requestId) { - this.requestId = requestId; - } - - public String getRequestContent() { - return requestContent; - } - - public void setRequestContent(String requestContent) { - this.requestContent = requestContent; - } - - -} +package test.my.utils.http.agent; + +public class RequestContent { + + private int requestId; + + private String requestContent; + + public RequestContent(){ + + } + + public RequestContent(int requestId, String requestContent){ + this.requestId = requestId; + this.requestContent = requestContent; + } + + + + public int getRequestId() { + return requestId; + } + + public void setRequestId(int requestId) { + this.requestId = requestId; + } + + public String getRequestContent() { + return requestContent; + } + + public void setRequestContent(String requestContent) { + this.requestContent = requestContent; + } + + +} diff --git a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/TestData.java b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/TestData.java index 585a8a0f..699f7532 100644 --- a/source/utils/utils-http/src/test/java/test/my/utils/http/agent/TestData.java +++ b/source/utils/utils-http/src/test/java/test/my/utils/http/agent/TestData.java @@ -1,29 +1,29 @@ -package test.my.utils.http.agent; - -import java.io.Serializable; - -public class TestData implements Serializable { - - private static final long serialVersionUID = -4339820200060895807L; - - private int id; - - private String value; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - -} +package test.my.utils.http.agent; + +import java.io.Serializable; + +public class TestData implements Serializable { + + private static final long serialVersionUID = -4339820200060895807L; + + private int id; + + private String value; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/source/utils/utils-serialize/pom.xml b/source/utils/utils-serialize/pom.xml index acdd4ed2..83bd2409 100644 --- a/source/utils/utils-serialize/pom.xml +++ b/source/utils/utils-serialize/pom.xml @@ -1,22 +1,22 @@ - - 4.0.0 - - com.jd.blockchain - utils - 1.1.2.RELEASE - - utils-serialize - - - - com.jd.blockchain - utils-common - ${project.version} - - - com.alibaba - fastjson - - + + 4.0.0 + + com.jd.blockchain + utils + 1.1.2.RELEASE + + utils-serialize + + + + com.jd.blockchain + utils-common + ${project.version} + + + com.alibaba + fastjson + + \ No newline at end of file diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/BinarySerializeUtils.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/BinarySerializeUtils.java index d1b1439d..24997f48 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/BinarySerializeUtils.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/binary/BinarySerializeUtils.java @@ -1,63 +1,63 @@ -package com.jd.blockchain.utils.serialize.binary; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.ObjectOutputStream; -import java.io.OutputStream; - -import com.jd.blockchain.utils.io.BytesUtils; -import com.jd.blockchain.utils.io.RuntimeIOException; - -public class BinarySerializeUtils { - - public static byte[] serialize(Object object) { - if (object == null) { - return BytesUtils.EMPTY_BYTES; - } - ByteArrayOutputStream out = new ByteArrayOutputStream(); - serialize(object, out); - return out.toByteArray(); - } - - public static void serialize(Object object, OutputStream out) { - if (object == null) { - return; - } - try { - ObjectOutputStream objOut = new ObjectOutputStream(out); - objOut.writeObject(object); - objOut.flush(); - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } - } - - public static T deserialize(byte[] bytes) { - if (bytes == null || bytes.length == 0) { - return null; - } - ByteArrayInputStream in = new ByteArrayInputStream(bytes); - return deserialize(in); - } - - @SuppressWarnings("unchecked") - public static T deserialize(InputStream in) { - try { - try(FilteredObjectInputStream objIn = new FilteredObjectInputStream(in)){ - Object obj = objIn.readObject(); - return (T) obj; - } - } catch (IOException e) { - throw new RuntimeIOException(e.getMessage(), e); - } catch (ClassNotFoundException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - public static T copyOf(T obj) { - byte[] bts = serialize(obj); - return deserialize(bts); - } -} +package com.jd.blockchain.utils.serialize.binary; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; + +import com.jd.blockchain.utils.io.BytesUtils; +import com.jd.blockchain.utils.io.RuntimeIOException; + +public class BinarySerializeUtils { + + public static byte[] serialize(Object object) { + if (object == null) { + return BytesUtils.EMPTY_BYTES; + } + ByteArrayOutputStream out = new ByteArrayOutputStream(); + serialize(object, out); + return out.toByteArray(); + } + + public static void serialize(Object object, OutputStream out) { + if (object == null) { + return; + } + try { + ObjectOutputStream objOut = new ObjectOutputStream(out); + objOut.writeObject(object); + objOut.flush(); + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } + } + + public static T deserialize(byte[] bytes) { + if (bytes == null || bytes.length == 0) { + return null; + } + ByteArrayInputStream in = new ByteArrayInputStream(bytes); + return deserialize(in); + } + + @SuppressWarnings("unchecked") + public static T deserialize(InputStream in) { + try { + try(FilteredObjectInputStream objIn = new FilteredObjectInputStream(in)){ + Object obj = objIn.readObject(); + return (T) obj; + } + } catch (IOException e) { + throw new RuntimeIOException(e.getMessage(), e); + } catch (ClassNotFoundException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + public static T copyOf(T obj) { + byte[] bts = serialize(obj); + return deserialize(bts); + } +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/ArrayMergeStrategy.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/ArrayMergeStrategy.java index c631c55a..42788c01 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/ArrayMergeStrategy.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/ArrayMergeStrategy.java @@ -1,26 +1,26 @@ -package com.jd.blockchain.utils.serialize.json; - -/** - * 数组的合并策略; - * - * @author haiq - * - */ -public enum ArrayMergeStrategy { - - /** - * 替换策略:用新的数组替换掉原来的数组; - */ - REPLACE, - - /** - * 追加策略:把新数组的元素追加到原来的数组元素之后; - */ - APPEND, - - /** - * 深度合并策略:对于相同位置的元素,如果是原生值则进行替换,如果是JSON对象,则进行递归合并;新数组多出的元素则追加到原数组后面; - */ - DEEP_MERGE - -} +package com.jd.blockchain.utils.serialize.json; + +/** + * 数组的合并策略; + * + * @author haiq + * + */ +public enum ArrayMergeStrategy { + + /** + * 替换策略:用新的数组替换掉原来的数组; + */ + REPLACE, + + /** + * 追加策略:把新数组的元素追加到原来的数组元素之后; + */ + APPEND, + + /** + * 深度合并策略:对于相同位置的元素,如果是原生值则进行替换,如果是JSON对象,则进行递归合并;新数组多出的元素则追加到原数组后面; + */ + DEEP_MERGE + +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/GenericType.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/GenericType.java index 0220cad8..86a847a9 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/GenericType.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/GenericType.java @@ -1,20 +1,20 @@ -package com.jd.blockchain.utils.serialize.json; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - -public class GenericType { - - private final Type firstTypeArgument; - - protected GenericType(){ - Type superClass = getClass().getGenericSuperclass(); - - firstTypeArgument = ((ParameterizedType) superClass).getActualTypeArguments()[0]; - } - - public Type getTypeArgument() { - return firstTypeArgument; - } - -} +package com.jd.blockchain.utils.serialize.json; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +public class GenericType { + + private final Type firstTypeArgument; + + protected GenericType(){ + Type superClass = getClass().getGenericSuperclass(); + + firstTypeArgument = ((ParameterizedType) superClass).getActualTypeArguments()[0]; + } + + public Type getTypeArgument() { + return firstTypeArgument; + } + +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBean.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBean.java index 995070be..f9f470f1 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBean.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBean.java @@ -1,552 +1,552 @@ -package com.jd.blockchain.utils.serialize.json; - -import static com.alibaba.fastjson.util.TypeUtils.castToBigDecimal; -import static com.alibaba.fastjson.util.TypeUtils.castToBigInteger; -import static com.alibaba.fastjson.util.TypeUtils.castToBoolean; -import static com.alibaba.fastjson.util.TypeUtils.castToByte; -import static com.alibaba.fastjson.util.TypeUtils.castToBytes; -import static com.alibaba.fastjson.util.TypeUtils.castToDate; -import static com.alibaba.fastjson.util.TypeUtils.castToDouble; -import static com.alibaba.fastjson.util.TypeUtils.castToFloat; -import static com.alibaba.fastjson.util.TypeUtils.castToInt; -import static com.alibaba.fastjson.util.TypeUtils.castToLong; -import static com.alibaba.fastjson.util.TypeUtils.castToShort; -import static com.alibaba.fastjson.util.TypeUtils.castToSqlDate; -import static com.alibaba.fastjson.util.TypeUtils.castToTimestamp; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Collection; -import java.util.Date; -import java.util.Map; -import java.util.regex.Pattern; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.annotation.JSONType; -import com.alibaba.fastjson.util.TypeUtils; - -@JSONType(serializer=JSONBeanSerializer.class,deserializer =JSONBeanDeserializer.class) -public class JSONBean { - - /** - * JSON Bean 的属性路径的正则表达式;
- * - * 属性路径由“字段名”,加上可选的数组下标索引“[位置]”,加上句点“.”构成;
- * - * 如: contract.addresses[1].telephone ; - */ - private static final String KEY_PATH_REGEX = "\\A([\\w\\$]+(\\[\\d+\\])?\\.)*[\\w\\$]+\\z"; - - private static final Pattern KEY_PATH_PATTERN = Pattern.compile(KEY_PATH_REGEX); - - private JSONObject jsonObject; - - public JSONBean() { - this(new JSONObject()); - } - - protected JSONBean(JSONObject jsonObj) { - this.jsonObject = jsonObj; - } - - - public JSONObject getJsonObject() { - return jsonObject; - } - - public void setJsonObject(JSONObject jsonObject) { - this.jsonObject = jsonObject; - } - - public boolean isEmpty(){ - return jsonObject.isEmpty(); - } - - /** - * 合并指定的 JSON Bean 的全部属性到当前对象;
- * - * 对数组类型的属性采取“替换”策略 {@link ArrayMergeStrategy.REPLACE}进行合并; - * - * @param jsonBean - * 要合并的 JSON 对象; - * @return - */ - public JSONBean merge(JSONBean jsonBean) { - if (jsonBean == this) { - return this; - } - return merge(jsonBean, ArrayMergeStrategy.REPLACE); - } - - protected Object get(String keyPath) { - if (!KEY_PATH_PATTERN.matcher(keyPath).matches()) { - throw new IllegalArgumentException("Illegal key path! --keyPath=[" + keyPath + "]"); - } - int startInx = 0; - int endIdx = -1; - Object value = null; - do { - // 逐段分解属性; - endIdx = keyPath.indexOf('.', startInx); - String key; - if (endIdx > startInx) { - key = keyPath.substring(startInx, endIdx); - - startInx = endIdx + 1;// 更新下一次搜索的起始索引; - } else { - //最后一项; - key = keyPath.substring(startInx); - } - String field = key; - int leftIdx = key.indexOf('['); - int position = -1; - if (leftIdx > 0) { - field = key.substring(0, leftIdx); - position = Integer.parseInt(key.substring(leftIdx + 1, key.length() - 1)); - // 注:KeyPath 的正则表达式限制了数组下标的数字不可能为负数,否则不能通过校验; - } - - // 解析对象属性; - if (value == null) { - value = jsonObject.get(field); - } else { - if (value instanceof JSONObject) { - value = ((JSONObject) value).get(field); - } else if (value instanceof JSONArray) { - throw new IllegalArgumentException("Array cann't be accessed by field[" + field + "]!"); - } else { - throw new IllegalArgumentException( - "JSON primitive value cann't be accessed by field[" + field + "]!"); - } - } - if (value == null) { - return null; -// throw new IllegalArgumentException("The field[" + field + "] not exist!"); - } - // 解析数组元素; - if (position > -1) { - if (value instanceof JSONArray) { - JSONArray arrayValue = (JSONArray) value; - if (position < arrayValue.size()) { - value = arrayValue.get(position); - } else { - throw new IndexOutOfBoundsException( - "Index[" + position + "] out of the size of array field[" + field + "]!"); - } - } else if (value instanceof JSONObject) { - throw new IllegalArgumentException( - "JSON object field[" + field + "] cann't be accessed by array index!"); - } else { - throw new IllegalArgumentException( - "JSON primitive value field[" + field + "] cann't be accessed by array index!"); - } - } - } while (endIdx > -1); - - return value; - } - - - /** - * 设置属性; - * - * 注:未实现对 key path 进行解析; - * - * @param key - * @param value - */ - protected void set(String key, Object value){ - //TODO: 未实现对 key path 进行解析; - jsonObject.put(key, value); - } - - - public T getObject(String key, Class clazz) { - Object obj = get(key); - return TypeUtils.castToJavaBean(obj, clazz); - } - - public Boolean getBoolean(String key) { - Object value = get(key); - - if (value == null) { - return null; - } - - return castToBoolean(value); - } - - public byte[] getBytes(String key) { - Object value = get(key); - - if (value == null) { - return null; - } - - return castToBytes(value); - } - - public boolean getBooleanValue(String key) { - Object value = get(key); - - if (value == null) { - return false; - } - - return castToBoolean(value).booleanValue(); - } - - public Byte getByte(String key) { - Object value = get(key); - - return castToByte(value); - } - - public byte getByteValue(String key) { - Object value = get(key); - - if (value == null) { - return 0; - } - - return castToByte(value).byteValue(); // TODO 如果 value - // 是""、"null"或"NULL",可能会存在报空指针的情况,是否需要加以处理? - // 其他转换也存在类似情况 - } - - public Short getShort(String key) { - Object value = get(key); - - return castToShort(value); - } - - public short getShortValue(String key) { - Object value = get(key); - - if (value == null) { - return 0; - } - - return castToShort(value).shortValue(); - } - - public Integer getInteger(String key) { - Object value = get(key); - - return castToInt(value); - } - - public int getIntValue(String key) { - Object value = get(key); - - if (value == null) { - return 0; - } - - return castToInt(value).intValue(); - } - - public Long getLong(String key) { - Object value = get(key); - - return castToLong(value); - } - - public long getLongValue(String key) { - Object value = get(key); - - if (value == null) { - return 0L; - } - - return castToLong(value).longValue(); - } - - public Float getFloat(String key) { - Object value = get(key); - - return castToFloat(value); - } - - public float getFloatValue(String key) { - Object value = get(key); - - if (value == null) { - return 0F; - } - - return castToFloat(value).floatValue(); - } - - public Double getDouble(String key) { - Object value = get(key); - - return castToDouble(value); - } - - public double getDoubleValue(String key) { - Object value = get(key); - - if (value == null) { - return 0D; - } - - return castToDouble(value); - } - - public BigDecimal getBigDecimal(String key) { - Object value = get(key); - - return castToBigDecimal(value); - } - - public BigInteger getBigInteger(String key) { - Object value = get(key); - - return castToBigInteger(value); - } - - public String getString(String key) { - Object value = get(key); - - if (value == null) { - return null; - } - - return value.toString(); - } - - public Date getDate(String key) { - Object value = get(key); - - return castToDate(value); - } - - public java.sql.Date getSqlDate(String key) { - Object value = get(key); - - return castToSqlDate(value); - } - - public java.sql.Timestamp getTimestamp(String key) { - Object value = get(key); - - return castToTimestamp(value); - } - - @Override - public String toString() { - return jsonObject.toJSONString(); - } - - public T toJavaBean(Class beanClass){ - return jsonObject.toJavaObject(beanClass); - } - - /** - * 合并指定的 JSON Bean 的全部属性到当前对象; - * - * @param jsonBean - * 要合并的 JSON 对象; - * @param arrayMergeStrategy - * 对数组类型的属性采取的合并策略; - * @return - */ - public JSONBean merge(JSONBean jsonBean, ArrayMergeStrategy arrayMergeStrategy) { - mergeJSONObject(this.jsonObject, jsonBean.jsonObject, arrayMergeStrategy); - return this; - } - - private static void mergeJSONObject(JSONObject target, JSONObject from, ArrayMergeStrategy arrayMergeStrategy) { - for (Map.Entry field : from.entrySet()) { - if (target.containsKey(field.getKey())) { - Object targetFieldValue = target.get(field.getKey()); - Object fromFieldValue = field.getValue(); - if ((targetFieldValue instanceof JSONObject) && (fromFieldValue instanceof JSONObject)) { - // 都是 JSON 对象,进行深度合并; - mergeJSONObject((JSONObject) targetFieldValue, (JSONObject) fromFieldValue, arrayMergeStrategy); - } else if ((targetFieldValue instanceof JSONArray) && (fromFieldValue instanceof JSONArray)) { - // 都是 JSON 数组,进行数组合并; - mergeJSONArray((JSONArray) targetFieldValue, (JSONArray) fromFieldValue, arrayMergeStrategy); - } else { - // 类型不同,直接替换; - target.put(field.getKey(), field.getValue()); - } - } else { - target.put(field.getKey(), field.getValue()); - } - } - } - - private static void mergeJSONArray(JSONArray target, JSONArray from, ArrayMergeStrategy strategy) { - switch (strategy) { - case REPLACE: - if (target.size() > from.size()) { - for (int i = 0; i < from.size(); i++) { - target.set(i, from.get(i)); - } - } else { - target.clear(); - target.addAll(from); - } - break; - case APPEND: - target.addAll(from); - break; - case DEEP_MERGE: - // 对位置相同的元素进行合并; - int mergeCount = Math.min(target.size(), from.size()); - Object targetFieldValue; - Object fromFieldValue; - for (int i = 0; i < mergeCount; i++) { - targetFieldValue = target.get(i); - fromFieldValue = from.get(i); - if ((targetFieldValue instanceof JSONObject) && (fromFieldValue instanceof JSONObject)) { - // 都是 JSON 对象,进行深度合并; - mergeJSONObject((JSONObject) targetFieldValue, (JSONObject) fromFieldValue, strategy); - } else if ((targetFieldValue instanceof JSONArray) && (fromFieldValue instanceof JSONArray)) { - // 都是 JSON 数组,进行数组合并; - mergeJSONArray((JSONArray) targetFieldValue, (JSONArray) fromFieldValue, strategy); - } else { - // 类型不同,直接替换; - target.set(i, fromFieldValue); - } - } - // 对多出来的元素进行追加; - if (from.size() > target.size()) { - for (int i = target.size(); i < from.size(); i++) { - target.add(from.get(i)); - } - } - break; - default: - throw new IllegalStateException("Unsupported strategy[" + strategy + "] for merging json array!"); - } - } - - public static JSONBean parse(String json){ - JSONObject jsonObj = parseJSONObject(json); - return new JSONBean(jsonObj); - } - - public static JSONBean wrap(Object object) { - if (object == null) { - throw new IllegalArgumentException("Null object!"); - } - if (object instanceof JSONBean) { - return (JSONBean) object; - } - JSONObject jsonObj = toJSONObject(object); - return new JSONBean(jsonObj); - } - - public static JSONBean tryWrap(Object object) { - if (object == null) { - return null; - } - if (object instanceof JSONBean) { - return (JSONBean) object; - } - JSONObject jsonObj = tryToJSONObject(object); - if (jsonObj == null) { - return null; - } - return new JSONBean(jsonObj); - } - - public static JSONObject tryToJSONObject(Object javaObject){ - if (javaObject == null) { - return null; - } - - if (javaObject instanceof JSONObject) { - return (JSONObject) javaObject; - } - - if (javaObject instanceof Collection) { - return null; - } - Class cls = javaObject.getClass(); - if (cls.isArray()) { - return null; - } - if (cls.isEnum()) { - return null; - } - if (isPrimitive(cls)) { - return null; - } - - Object obj = JSONObject.toJSON(javaObject); - if (obj instanceof JSONObject) { - return (JSONObject) obj; - } - - return null; - } - - private static JSONObject parseJSONObject(String json){ - Object obj = JSON.parse(json); - if (obj instanceof JSONObject) { - return (JSONObject) obj; - } - throw new IllegalArgumentException("The specified json string is not a JSON Object!"); - } - - private static JSONObject toJSONObject(Object javaObject) { - if (javaObject == null) { - throw new IllegalArgumentException("The wrapped java object is null!"); - } - - if (javaObject instanceof JSONObject) { - return (JSONObject) javaObject; - } - - if (javaObject instanceof Collection) { - throw new IllegalArgumentException("The wrapped java object is a collection!"); - } - Class cls = javaObject.getClass(); - if (cls.isArray()) { - throw new IllegalArgumentException("The wrapped java object is a array!"); - } - if (cls.isEnum()) { - throw new IllegalArgumentException("The wrapped java object is a enum!"); - } - if (isPrimitive(cls)) { - throw new IllegalArgumentException("The wrapped java object is a primitive value!"); - } - - Object obj = JSONObject.toJSON(javaObject); - if (obj instanceof JSONObject) { - return (JSONObject) obj; - } - - throw new IllegalArgumentException("The wrapped java object cann't be converted to a JSON Object!"); - } - - - - private static boolean isPrimitive(Class clazz) { - return clazz.isPrimitive() // - || clazz == Boolean.class // - || clazz == Character.class // - || clazz == Byte.class // - || clazz == Short.class // - || clazz == Integer.class // - || clazz == Long.class // - || clazz == Float.class // - || clazz == Double.class // - || clazz == BigInteger.class // - || clazz == BigDecimal.class // - || clazz == String.class // - || clazz == java.util.Date.class // - || clazz == java.sql.Date.class // - || clazz == java.sql.Time.class // - || clazz == java.sql.Timestamp.class // - || clazz.isEnum() // - ; - } - -} +package com.jd.blockchain.utils.serialize.json; + +import static com.alibaba.fastjson.util.TypeUtils.castToBigDecimal; +import static com.alibaba.fastjson.util.TypeUtils.castToBigInteger; +import static com.alibaba.fastjson.util.TypeUtils.castToBoolean; +import static com.alibaba.fastjson.util.TypeUtils.castToByte; +import static com.alibaba.fastjson.util.TypeUtils.castToBytes; +import static com.alibaba.fastjson.util.TypeUtils.castToDate; +import static com.alibaba.fastjson.util.TypeUtils.castToDouble; +import static com.alibaba.fastjson.util.TypeUtils.castToFloat; +import static com.alibaba.fastjson.util.TypeUtils.castToInt; +import static com.alibaba.fastjson.util.TypeUtils.castToLong; +import static com.alibaba.fastjson.util.TypeUtils.castToShort; +import static com.alibaba.fastjson.util.TypeUtils.castToSqlDate; +import static com.alibaba.fastjson.util.TypeUtils.castToTimestamp; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Collection; +import java.util.Date; +import java.util.Map; +import java.util.regex.Pattern; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.annotation.JSONType; +import com.alibaba.fastjson.util.TypeUtils; + +@JSONType(serializer=JSONBeanSerializer.class,deserializer =JSONBeanDeserializer.class) +public class JSONBean { + + /** + * JSON Bean 的属性路径的正则表达式;
+ * + * 属性路径由“字段名”,加上可选的数组下标索引“[位置]”,加上句点“.”构成;
+ * + * 如: contract.addresses[1].telephone ; + */ + private static final String KEY_PATH_REGEX = "\\A([\\w\\$]+(\\[\\d+\\])?\\.)*[\\w\\$]+\\z"; + + private static final Pattern KEY_PATH_PATTERN = Pattern.compile(KEY_PATH_REGEX); + + private JSONObject jsonObject; + + public JSONBean() { + this(new JSONObject()); + } + + protected JSONBean(JSONObject jsonObj) { + this.jsonObject = jsonObj; + } + + + public JSONObject getJsonObject() { + return jsonObject; + } + + public void setJsonObject(JSONObject jsonObject) { + this.jsonObject = jsonObject; + } + + public boolean isEmpty(){ + return jsonObject.isEmpty(); + } + + /** + * 合并指定的 JSON Bean 的全部属性到当前对象;
+ * + * 对数组类型的属性采取“替换”策略 {@link ArrayMergeStrategy.REPLACE}进行合并; + * + * @param jsonBean + * 要合并的 JSON 对象; + * @return + */ + public JSONBean merge(JSONBean jsonBean) { + if (jsonBean == this) { + return this; + } + return merge(jsonBean, ArrayMergeStrategy.REPLACE); + } + + protected Object get(String keyPath) { + if (!KEY_PATH_PATTERN.matcher(keyPath).matches()) { + throw new IllegalArgumentException("Illegal key path! --keyPath=[" + keyPath + "]"); + } + int startInx = 0; + int endIdx = -1; + Object value = null; + do { + // 逐段分解属性; + endIdx = keyPath.indexOf('.', startInx); + String key; + if (endIdx > startInx) { + key = keyPath.substring(startInx, endIdx); + + startInx = endIdx + 1;// 更新下一次搜索的起始索引; + } else { + //最后一项; + key = keyPath.substring(startInx); + } + String field = key; + int leftIdx = key.indexOf('['); + int position = -1; + if (leftIdx > 0) { + field = key.substring(0, leftIdx); + position = Integer.parseInt(key.substring(leftIdx + 1, key.length() - 1)); + // 注:KeyPath 的正则表达式限制了数组下标的数字不可能为负数,否则不能通过校验; + } + + // 解析对象属性; + if (value == null) { + value = jsonObject.get(field); + } else { + if (value instanceof JSONObject) { + value = ((JSONObject) value).get(field); + } else if (value instanceof JSONArray) { + throw new IllegalArgumentException("Array cann't be accessed by field[" + field + "]!"); + } else { + throw new IllegalArgumentException( + "JSON primitive value cann't be accessed by field[" + field + "]!"); + } + } + if (value == null) { + return null; +// throw new IllegalArgumentException("The field[" + field + "] not exist!"); + } + // 解析数组元素; + if (position > -1) { + if (value instanceof JSONArray) { + JSONArray arrayValue = (JSONArray) value; + if (position < arrayValue.size()) { + value = arrayValue.get(position); + } else { + throw new IndexOutOfBoundsException( + "Index[" + position + "] out of the size of array field[" + field + "]!"); + } + } else if (value instanceof JSONObject) { + throw new IllegalArgumentException( + "JSON object field[" + field + "] cann't be accessed by array index!"); + } else { + throw new IllegalArgumentException( + "JSON primitive value field[" + field + "] cann't be accessed by array index!"); + } + } + } while (endIdx > -1); + + return value; + } + + + /** + * 设置属性; + * + * 注:未实现对 key path 进行解析; + * + * @param key + * @param value + */ + protected void set(String key, Object value){ + //TODO: 未实现对 key path 进行解析; + jsonObject.put(key, value); + } + + + public T getObject(String key, Class clazz) { + Object obj = get(key); + return TypeUtils.castToJavaBean(obj, clazz); + } + + public Boolean getBoolean(String key) { + Object value = get(key); + + if (value == null) { + return null; + } + + return castToBoolean(value); + } + + public byte[] getBytes(String key) { + Object value = get(key); + + if (value == null) { + return null; + } + + return castToBytes(value); + } + + public boolean getBooleanValue(String key) { + Object value = get(key); + + if (value == null) { + return false; + } + + return castToBoolean(value).booleanValue(); + } + + public Byte getByte(String key) { + Object value = get(key); + + return castToByte(value); + } + + public byte getByteValue(String key) { + Object value = get(key); + + if (value == null) { + return 0; + } + + return castToByte(value).byteValue(); // TODO 如果 value + // 是""、"null"或"NULL",可能会存在报空指针的情况,是否需要加以处理? + // 其他转换也存在类似情况 + } + + public Short getShort(String key) { + Object value = get(key); + + return castToShort(value); + } + + public short getShortValue(String key) { + Object value = get(key); + + if (value == null) { + return 0; + } + + return castToShort(value).shortValue(); + } + + public Integer getInteger(String key) { + Object value = get(key); + + return castToInt(value); + } + + public int getIntValue(String key) { + Object value = get(key); + + if (value == null) { + return 0; + } + + return castToInt(value).intValue(); + } + + public Long getLong(String key) { + Object value = get(key); + + return castToLong(value); + } + + public long getLongValue(String key) { + Object value = get(key); + + if (value == null) { + return 0L; + } + + return castToLong(value).longValue(); + } + + public Float getFloat(String key) { + Object value = get(key); + + return castToFloat(value); + } + + public float getFloatValue(String key) { + Object value = get(key); + + if (value == null) { + return 0F; + } + + return castToFloat(value).floatValue(); + } + + public Double getDouble(String key) { + Object value = get(key); + + return castToDouble(value); + } + + public double getDoubleValue(String key) { + Object value = get(key); + + if (value == null) { + return 0D; + } + + return castToDouble(value); + } + + public BigDecimal getBigDecimal(String key) { + Object value = get(key); + + return castToBigDecimal(value); + } + + public BigInteger getBigInteger(String key) { + Object value = get(key); + + return castToBigInteger(value); + } + + public String getString(String key) { + Object value = get(key); + + if (value == null) { + return null; + } + + return value.toString(); + } + + public Date getDate(String key) { + Object value = get(key); + + return castToDate(value); + } + + public java.sql.Date getSqlDate(String key) { + Object value = get(key); + + return castToSqlDate(value); + } + + public java.sql.Timestamp getTimestamp(String key) { + Object value = get(key); + + return castToTimestamp(value); + } + + @Override + public String toString() { + return jsonObject.toJSONString(); + } + + public T toJavaBean(Class beanClass){ + return jsonObject.toJavaObject(beanClass); + } + + /** + * 合并指定的 JSON Bean 的全部属性到当前对象; + * + * @param jsonBean + * 要合并的 JSON 对象; + * @param arrayMergeStrategy + * 对数组类型的属性采取的合并策略; + * @return + */ + public JSONBean merge(JSONBean jsonBean, ArrayMergeStrategy arrayMergeStrategy) { + mergeJSONObject(this.jsonObject, jsonBean.jsonObject, arrayMergeStrategy); + return this; + } + + private static void mergeJSONObject(JSONObject target, JSONObject from, ArrayMergeStrategy arrayMergeStrategy) { + for (Map.Entry field : from.entrySet()) { + if (target.containsKey(field.getKey())) { + Object targetFieldValue = target.get(field.getKey()); + Object fromFieldValue = field.getValue(); + if ((targetFieldValue instanceof JSONObject) && (fromFieldValue instanceof JSONObject)) { + // 都是 JSON 对象,进行深度合并; + mergeJSONObject((JSONObject) targetFieldValue, (JSONObject) fromFieldValue, arrayMergeStrategy); + } else if ((targetFieldValue instanceof JSONArray) && (fromFieldValue instanceof JSONArray)) { + // 都是 JSON 数组,进行数组合并; + mergeJSONArray((JSONArray) targetFieldValue, (JSONArray) fromFieldValue, arrayMergeStrategy); + } else { + // 类型不同,直接替换; + target.put(field.getKey(), field.getValue()); + } + } else { + target.put(field.getKey(), field.getValue()); + } + } + } + + private static void mergeJSONArray(JSONArray target, JSONArray from, ArrayMergeStrategy strategy) { + switch (strategy) { + case REPLACE: + if (target.size() > from.size()) { + for (int i = 0; i < from.size(); i++) { + target.set(i, from.get(i)); + } + } else { + target.clear(); + target.addAll(from); + } + break; + case APPEND: + target.addAll(from); + break; + case DEEP_MERGE: + // 对位置相同的元素进行合并; + int mergeCount = Math.min(target.size(), from.size()); + Object targetFieldValue; + Object fromFieldValue; + for (int i = 0; i < mergeCount; i++) { + targetFieldValue = target.get(i); + fromFieldValue = from.get(i); + if ((targetFieldValue instanceof JSONObject) && (fromFieldValue instanceof JSONObject)) { + // 都是 JSON 对象,进行深度合并; + mergeJSONObject((JSONObject) targetFieldValue, (JSONObject) fromFieldValue, strategy); + } else if ((targetFieldValue instanceof JSONArray) && (fromFieldValue instanceof JSONArray)) { + // 都是 JSON 数组,进行数组合并; + mergeJSONArray((JSONArray) targetFieldValue, (JSONArray) fromFieldValue, strategy); + } else { + // 类型不同,直接替换; + target.set(i, fromFieldValue); + } + } + // 对多出来的元素进行追加; + if (from.size() > target.size()) { + for (int i = target.size(); i < from.size(); i++) { + target.add(from.get(i)); + } + } + break; + default: + throw new IllegalStateException("Unsupported strategy[" + strategy + "] for merging json array!"); + } + } + + public static JSONBean parse(String json){ + JSONObject jsonObj = parseJSONObject(json); + return new JSONBean(jsonObj); + } + + public static JSONBean wrap(Object object) { + if (object == null) { + throw new IllegalArgumentException("Null object!"); + } + if (object instanceof JSONBean) { + return (JSONBean) object; + } + JSONObject jsonObj = toJSONObject(object); + return new JSONBean(jsonObj); + } + + public static JSONBean tryWrap(Object object) { + if (object == null) { + return null; + } + if (object instanceof JSONBean) { + return (JSONBean) object; + } + JSONObject jsonObj = tryToJSONObject(object); + if (jsonObj == null) { + return null; + } + return new JSONBean(jsonObj); + } + + public static JSONObject tryToJSONObject(Object javaObject){ + if (javaObject == null) { + return null; + } + + if (javaObject instanceof JSONObject) { + return (JSONObject) javaObject; + } + + if (javaObject instanceof Collection) { + return null; + } + Class cls = javaObject.getClass(); + if (cls.isArray()) { + return null; + } + if (cls.isEnum()) { + return null; + } + if (isPrimitive(cls)) { + return null; + } + + Object obj = JSONObject.toJSON(javaObject); + if (obj instanceof JSONObject) { + return (JSONObject) obj; + } + + return null; + } + + private static JSONObject parseJSONObject(String json){ + Object obj = JSON.parse(json); + if (obj instanceof JSONObject) { + return (JSONObject) obj; + } + throw new IllegalArgumentException("The specified json string is not a JSON Object!"); + } + + private static JSONObject toJSONObject(Object javaObject) { + if (javaObject == null) { + throw new IllegalArgumentException("The wrapped java object is null!"); + } + + if (javaObject instanceof JSONObject) { + return (JSONObject) javaObject; + } + + if (javaObject instanceof Collection) { + throw new IllegalArgumentException("The wrapped java object is a collection!"); + } + Class cls = javaObject.getClass(); + if (cls.isArray()) { + throw new IllegalArgumentException("The wrapped java object is a array!"); + } + if (cls.isEnum()) { + throw new IllegalArgumentException("The wrapped java object is a enum!"); + } + if (isPrimitive(cls)) { + throw new IllegalArgumentException("The wrapped java object is a primitive value!"); + } + + Object obj = JSONObject.toJSON(javaObject); + if (obj instanceof JSONObject) { + return (JSONObject) obj; + } + + throw new IllegalArgumentException("The wrapped java object cann't be converted to a JSON Object!"); + } + + + + private static boolean isPrimitive(Class clazz) { + return clazz.isPrimitive() // + || clazz == Boolean.class // + || clazz == Character.class // + || clazz == Byte.class // + || clazz == Short.class // + || clazz == Integer.class // + || clazz == Long.class // + || clazz == Float.class // + || clazz == Double.class // + || clazz == BigInteger.class // + || clazz == BigDecimal.class // + || clazz == String.class // + || clazz == java.util.Date.class // + || clazz == java.sql.Date.class // + || clazz == java.sql.Time.class // + || clazz == java.sql.Timestamp.class // + || clazz.isEnum() // + ; + } + +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBeanDeserializer.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBeanDeserializer.java index 834480ce..6fd64f3c 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBeanDeserializer.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBeanDeserializer.java @@ -1,38 +1,38 @@ -package com.jd.blockchain.utils.serialize.json; - -import java.lang.reflect.Type; - -import com.alibaba.fastjson.JSONException; -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.parser.DefaultJSONParser; -import com.alibaba.fastjson.parser.JSONToken; -import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; - -public class JSONBeanDeserializer implements ObjectDeserializer { - - @SuppressWarnings("unchecked") - @Override - public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { - if (type instanceof Class && JSONBean.class.isAssignableFrom((Class) type)) { - Class clazz = (Class) type; - try { - JSONBean jsonBean = (JSONBean) clazz.newInstance(); - JSONObject jsonObj = (JSONObject) parser.parseObject(jsonBean.getJsonObject()); - jsonBean.setJsonObject(jsonObj); - - return (T) jsonBean; - } catch (InstantiationException e) { - throw new JSONException(e.getMessage(), e); - } catch (IllegalAccessException e) { - throw new JSONException(e.getMessage(), e); - } - } - return (T) parser.parse(fieldName); - } - - @Override - public int getFastMatchToken() { - return JSONToken.LBRACE; - } - -} +package com.jd.blockchain.utils.serialize.json; + +import java.lang.reflect.Type; + +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.parser.DefaultJSONParser; +import com.alibaba.fastjson.parser.JSONToken; +import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; + +public class JSONBeanDeserializer implements ObjectDeserializer { + + @SuppressWarnings("unchecked") + @Override + public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { + if (type instanceof Class && JSONBean.class.isAssignableFrom((Class) type)) { + Class clazz = (Class) type; + try { + JSONBean jsonBean = (JSONBean) clazz.newInstance(); + JSONObject jsonObj = (JSONObject) parser.parseObject(jsonBean.getJsonObject()); + jsonBean.setJsonObject(jsonObj); + + return (T) jsonBean; + } catch (InstantiationException e) { + throw new JSONException(e.getMessage(), e); + } catch (IllegalAccessException e) { + throw new JSONException(e.getMessage(), e); + } + } + return (T) parser.parse(fieldName); + } + + @Override + public int getFastMatchToken() { + return JSONToken.LBRACE; + } + +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBeanSerializer.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBeanSerializer.java index 06afeeb5..d50b0c83 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBeanSerializer.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONBeanSerializer.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.utils.serialize.json; - -import java.io.IOException; -import java.lang.reflect.Type; - -import com.alibaba.fastjson.serializer.JSONSerializer; -import com.alibaba.fastjson.serializer.ObjectSerializer; -import com.alibaba.fastjson.serializer.SerializeWriter; - -public class JSONBeanSerializer implements ObjectSerializer { - - @Override - public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) - throws IOException { - SerializeWriter out = serializer.out; - if (object == null) { - out.writeNull(); - return; - } - JSONBean jsonBean = (JSONBean) object; - out.write(jsonBean.toString()); - } - -} +package com.jd.blockchain.utils.serialize.json; + +import java.io.IOException; +import java.lang.reflect.Type; + +import com.alibaba.fastjson.serializer.JSONSerializer; +import com.alibaba.fastjson.serializer.ObjectSerializer; +import com.alibaba.fastjson.serializer.SerializeWriter; + +public class JSONBeanSerializer implements ObjectSerializer { + + @Override + public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) + throws IOException { + SerializeWriter out = serializer.out; + if (object == null) { + out.writeNull(); + return; + } + JSONBean jsonBean = (JSONBean) object; + out.write(jsonBean.toString()); + } + +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONSerializeUtils.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONSerializeUtils.java index 1d88796f..d26fa440 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONSerializeUtils.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONSerializeUtils.java @@ -1,359 +1,359 @@ -package com.jd.blockchain.utils.serialize.json; - -import java.io.IOException; -import java.io.Writer; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Proxy; -import java.lang.reflect.Type; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.parser.ParserConfig; -import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; -import com.alibaba.fastjson.serializer.JSONSerializer; -import com.alibaba.fastjson.serializer.ObjectSerializer; -import com.alibaba.fastjson.serializer.SerializeConfig; -import com.alibaba.fastjson.serializer.SerializeWriter; -import com.alibaba.fastjson.serializer.SerializerFeature; -import com.jd.blockchain.utils.PrimitiveUtils; - -/** - * SerializeUtils 提供统一的序列化反序列化操作实现; - * - * @author haiq - * - */ -public abstract class JSONSerializeUtils { - - private static final ToStringSerializer TO_STRING_SERIALIZER = new ToStringSerializer(); - - private static final RuntimeDeserializer RUNTIME_DESERIALIZER = new RuntimeDeserializer(); - - public static void addTypeMap(Class fromClazz, Class toClazz) { - RUNTIME_DESERIALIZER.addTypeMap(fromClazz, toClazz); - ParserConfig.getGlobalInstance().putDeserializer(fromClazz, RUNTIME_DESERIALIZER); - } - - public static void configSerialization(Class clazz, ObjectSerializer serializer, ObjectDeserializer deserializer) { - SerializeConfig.globalInstance.put(clazz, serializer); - ParserConfig.getGlobalInstance().putDeserializer(clazz, deserializer); - } - - /** - * 配置指定的类型在序列化时总是输出 {@link Object#toString()} 方法的结果 ; - * - * @param type - */ - public static void configStringSerializer(Class type) { - SerializeConfig.globalInstance.put(type, TO_STRING_SERIALIZER); - } - - /** - * 禁用循环引用检测; - * - *
- * 默认是开启的; - * - * @param type - */ - public static void disableCircularReferenceDetect() { - JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask(); - } - - // /** - // * 禁用循环引用检测; - // * - // *
- // * 默认是开启的; - // * - // * @param type - // */ - // public static void disableCircularReferenceDetect(Class type) { - // SerializeConfig.globalInstance.config(type, - // SerializerFeature.DisableCircularReferenceDetect, true); - // } - - // public static void addSerialzedType(Class objectType, Class - // serialzedType) { - // if (!serialzedType.isAssignableFrom(objectType)) { - // throw new IllegalArgumentException("The filteredType[" + - // serialzedType.getName() - // + "] isn't assignable from the objectType[" + objectType.getName() + - // "]!"); - // } - // JavaBeanSerializer serializer = new JavaBeanSerializer(serialzedType); - // SerializeConfig.globalInstance.put(objectType, serializer); - // } - - private JSONSerializeUtils() { - } - - public static Type getGenericType(Object obj) { - return getGenericTypes(obj)[0]; - } - - public static Type[] getGenericTypes(Object obj) { - Type superClass = obj.getClass().getGenericSuperclass(); - - Type[] types = ((ParameterizedType) superClass).getActualTypeArguments(); - return types; - } - - /** - * 判断是否是 JSON 字符; - *

- * - * 此方法判断的JSON 字符的方法是检查指定的字符是否由花括号 { } 或者方括号 [ ] 或者双引号 ""包围; - *

- * - * 这只是一种简化但不严谨的方法,检查通过返回 true 也不代表在花括号 { } 或者方括号 [ ] 或者双引号 "" 之间的内容符合 JSON 语法; - * - * @param str - * @return - */ - public static boolean isJSON(String str) { - return isJSONObject(str) || isJSONOArray(str) || isJSONOValue(str); - } - - /** - * 判断是否是 JSON 对象; - *

- * - * 此方法判断的JSON 对象的方法是检查指定的字符是否由花括号 { } 包围; - *

- * - * 这只是一种简化但不严谨的方法,检查通过返回 true 也不代表在花括号 { } 之间的内容符合 JSON 语法; - * - * @param str - * @return - */ - public static boolean isJSONObject(String str) { - return str.startsWith("{") && str.endsWith("}"); - } - - /** - * 判断是否是 JSON 数组; - *

- * - * 此方法判断的JSON 数组的方法是检查指定的字符是否由方括号 [ ] 包围; - *

- * - * 这只是一种简化但不严谨的方法,检查通过返回 true 也不代表在方括号 [ ] 之间的内容符合 JSON 语法; - * - * @param str - * @return - */ - public static boolean isJSONOArray(String str) { - return str.startsWith("[") && str.endsWith("]"); - } - - /** - * 判断是否是 JSON 值; - *

- * - * 此方法判断的JSON 字符的方法是检查指定的字符是否由双引号 "" 包围; - *

- * - * 这只是一种简化但不严谨的方法,检查通过返回 true 也不代表在双引号 "" 之间的内容符合 JSON 语法; - * - * @param str - * @return - */ - public static boolean isJSONOValue(String str) { - return str.startsWith("\"") && str.endsWith("\""); - } - - /** - * 将对象序列化为 JSON 字符串;(紧凑格式) - * - * @param data - * @return - */ - public static String serializeToJSON(Object data) { - // if (data instanceof JSONObject) { - // return ((JSONObject) data).toJSONString(); - // } - return serializeToJSON(data, null, false); - } - - /** - * 将对象序列化为 JSON 字符串;(紧凑格式) - * - * @param data - * @return - */ - public static String serializeToJSON(Object data, Class serializedType) { - return serializeToJSON(data, serializedType, false); - } - - /** - * 将对象序列化为 JSON 字符串; - * - * @param data - * 要序列化的对象; - * @param prettyFormat - * 是否以包含换行和缩进的良好格式输出 JSON; - * @return - */ - public static String serializeToJSON(Object data, boolean prettyFormat) { - return serializeToJSON(data, null, prettyFormat); - } - - /** - * 将对象序列化为 JSON 字符串; - * - * @param data - * 要序列化的对象; - * @param serializedType - * 要序列化的对象的输出的类型;
- * 指定该对象的父类或者某一个实现的接口类型,序列化输出的 JSON 将只包含该类型的属性;
- * 如果指定为 null, 则按对象本身的类型进行序列化; - * @param prettyFormat - * 是否以包含换行和缩进的良好格式输出 JSON; - * @return - */ - public static String serializeToJSON(Object data, Class serializedType, boolean prettyFormat) { - return serializeToJSON(data, serializedType, null, prettyFormat); - } - - /** - * 将对象序列化为 JSON 字符串; - * - * @param data - * 要序列化的对象; - * @param serializedType - * 要序列化的对象的输出的类型;
- * 指定该对象的父类或者某一个实现的接口类型,序列化输出的 JSON 将只包含该类型的属性;
- * 如果指定为 null, 则按对象本身的类型进行序列化; - * @param dateFormat - * 日期格式; - * @param prettyFormat - * 是否以包含换行和缩进的良好格式输出 JSON; - * @return - */ - public static String serializeToJSON(Object data, Class serializedType, String dateFormat, - boolean prettyFormat) { - SerializeWriter out; - - if (prettyFormat) { - out = new SerializeWriter((Writer) null, JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.PrettyFormat); - } else { - out = new SerializeWriter((Writer) null, JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.EMPTY); - } - - try { - if (data == null) { - return null; - // out.writeNull(); - } else { - // 确定要序列化的类型; - if (serializedType == null) { - serializedType = data.getClass(); - } else if ((!PrimitiveUtils.isPrimitiveType(serializedType)) - && (!PrimitiveUtils.isPrimitiveType(data.getClass())) - && (!serializedType.isAssignableFrom(data.getClass()))) { - throw new IllegalArgumentException("The serialized type[" + serializedType.getName() - + "] isn't assignable from the data type[" + data.getClass().getName() + "]!"); - } - - if (PrimitiveUtils.isWrapping(data.getClass(), serializedType)) { - // 避免 serializedType 原生的值类型时引发 fastjson 的序列化异常; - serializedType = data.getClass(); - } - - JSONSerializer serializer = new JSONSerializer(out, SerializeConfig.globalInstance); - - // 配置日期格式; - if (dateFormat != null && dateFormat.length() != 0) { - serializer.setDateFormat(dateFormat); - serializer.config(SerializerFeature.WriteDateUseDateFormat, true); - } - - // 序列化; - ObjectSerializer writer = serializer.getObjectWriter(serializedType); - - writer.write(serializer, data, null, null, JSON.DEFAULT_GENERATE_FEATURE); - } - return out.toString(); - } catch (IOException e) { - throw new IllegalStateException( - "Error occurred on serializing type[" + serializedType.getName() + "]! --" + e.getMessage(), e); - } finally { - out.close(); - } - } - - /** - * - * @param json - * @param dataClazz - * @return - */ - public static T deserializeFromJSON(String json, Class dataClazz) { - return JSON.parseObject(json, dataClazz); - } - - /** - * - * - * @param jsonObj - * @param dataClazz - * @param - * @return - */ - public static T deserializeFromJSONObject(JSONObject jsonObj, Class dataClazz) { - return (T)Proxy.newProxyInstance(dataClazz.getClassLoader(), new Class[] {dataClazz}, jsonObj); - } - - /** - * - * @param json - * @param dataClazz - * @return - */ - public static T deserializeFromJSON(String json, GenericType type) { - return JSON.parseObject(json, type.getTypeArgument()); - } - - @SuppressWarnings("unchecked") - public static T deserializeAs(Object data, Class clazz) { - if (data == null) { - return null; - } - if (data instanceof JSON) { - return ((JSON) data).toJavaObject(clazz); - } - if (data instanceof JSONBean) { - return ((JSONBean) data).toJavaBean(clazz); - } - if (data instanceof String) { - if (clazz.isInterface()) { - JSONObject jsonObj = JSONSerializeUtils.deserializeAs(data, JSONObject.class); - return deserializeFromJSONObject(jsonObj, clazz); - } - if (isJSON((String) data)) { - return deserializeFromJSON((String) data, clazz); - } - } - if (data instanceof JSONString) { - String jsonStr = ((JSONString) data).toString(); - if (isJSON(jsonStr)) { - return deserializeFromJSON(jsonStr, clazz); - } else { - data = jsonStr; - } - } - if (PrimitiveUtils.isPrimitiveType(clazz)) { - return PrimitiveUtils.castTo(data, clazz); - } - if (clazz.isAssignableFrom(data.getClass())) { - return (T) data; - } - if (clazz.isAssignableFrom(String.class)) { - return (T) data.toString(); - } - throw new IllegalArgumentException("Unsupported deserialization from type[" + data.getClass().toString() - + "] to type[" + clazz.toString() + "]!"); - } - -} +package com.jd.blockchain.utils.serialize.json; + +import java.io.IOException; +import java.io.Writer; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Proxy; +import java.lang.reflect.Type; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; +import com.alibaba.fastjson.serializer.JSONSerializer; +import com.alibaba.fastjson.serializer.ObjectSerializer; +import com.alibaba.fastjson.serializer.SerializeConfig; +import com.alibaba.fastjson.serializer.SerializeWriter; +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.jd.blockchain.utils.PrimitiveUtils; + +/** + * SerializeUtils 提供统一的序列化反序列化操作实现; + * + * @author haiq + * + */ +public abstract class JSONSerializeUtils { + + private static final ToStringSerializer TO_STRING_SERIALIZER = new ToStringSerializer(); + + private static final RuntimeDeserializer RUNTIME_DESERIALIZER = new RuntimeDeserializer(); + + public static void addTypeMap(Class fromClazz, Class toClazz) { + RUNTIME_DESERIALIZER.addTypeMap(fromClazz, toClazz); + ParserConfig.getGlobalInstance().putDeserializer(fromClazz, RUNTIME_DESERIALIZER); + } + + public static void configSerialization(Class clazz, ObjectSerializer serializer, ObjectDeserializer deserializer) { + SerializeConfig.globalInstance.put(clazz, serializer); + ParserConfig.getGlobalInstance().putDeserializer(clazz, deserializer); + } + + /** + * 配置指定的类型在序列化时总是输出 {@link Object#toString()} 方法的结果 ; + * + * @param type + */ + public static void configStringSerializer(Class type) { + SerializeConfig.globalInstance.put(type, TO_STRING_SERIALIZER); + } + + /** + * 禁用循环引用检测; + * + *
+ * 默认是开启的; + * + * @param type + */ + public static void disableCircularReferenceDetect() { + JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask(); + } + + // /** + // * 禁用循环引用检测; + // * + // *
+ // * 默认是开启的; + // * + // * @param type + // */ + // public static void disableCircularReferenceDetect(Class type) { + // SerializeConfig.globalInstance.config(type, + // SerializerFeature.DisableCircularReferenceDetect, true); + // } + + // public static void addSerialzedType(Class objectType, Class + // serialzedType) { + // if (!serialzedType.isAssignableFrom(objectType)) { + // throw new IllegalArgumentException("The filteredType[" + + // serialzedType.getName() + // + "] isn't assignable from the objectType[" + objectType.getName() + + // "]!"); + // } + // JavaBeanSerializer serializer = new JavaBeanSerializer(serialzedType); + // SerializeConfig.globalInstance.put(objectType, serializer); + // } + + private JSONSerializeUtils() { + } + + public static Type getGenericType(Object obj) { + return getGenericTypes(obj)[0]; + } + + public static Type[] getGenericTypes(Object obj) { + Type superClass = obj.getClass().getGenericSuperclass(); + + Type[] types = ((ParameterizedType) superClass).getActualTypeArguments(); + return types; + } + + /** + * 判断是否是 JSON 字符; + *

+ * + * 此方法判断的JSON 字符的方法是检查指定的字符是否由花括号 { } 或者方括号 [ ] 或者双引号 ""包围; + *

+ * + * 这只是一种简化但不严谨的方法,检查通过返回 true 也不代表在花括号 { } 或者方括号 [ ] 或者双引号 "" 之间的内容符合 JSON 语法; + * + * @param str + * @return + */ + public static boolean isJSON(String str) { + return isJSONObject(str) || isJSONOArray(str) || isJSONOValue(str); + } + + /** + * 判断是否是 JSON 对象; + *

+ * + * 此方法判断的JSON 对象的方法是检查指定的字符是否由花括号 { } 包围; + *

+ * + * 这只是一种简化但不严谨的方法,检查通过返回 true 也不代表在花括号 { } 之间的内容符合 JSON 语法; + * + * @param str + * @return + */ + public static boolean isJSONObject(String str) { + return str.startsWith("{") && str.endsWith("}"); + } + + /** + * 判断是否是 JSON 数组; + *

+ * + * 此方法判断的JSON 数组的方法是检查指定的字符是否由方括号 [ ] 包围; + *

+ * + * 这只是一种简化但不严谨的方法,检查通过返回 true 也不代表在方括号 [ ] 之间的内容符合 JSON 语法; + * + * @param str + * @return + */ + public static boolean isJSONOArray(String str) { + return str.startsWith("[") && str.endsWith("]"); + } + + /** + * 判断是否是 JSON 值; + *

+ * + * 此方法判断的JSON 字符的方法是检查指定的字符是否由双引号 "" 包围; + *

+ * + * 这只是一种简化但不严谨的方法,检查通过返回 true 也不代表在双引号 "" 之间的内容符合 JSON 语法; + * + * @param str + * @return + */ + public static boolean isJSONOValue(String str) { + return str.startsWith("\"") && str.endsWith("\""); + } + + /** + * 将对象序列化为 JSON 字符串;(紧凑格式) + * + * @param data + * @return + */ + public static String serializeToJSON(Object data) { + // if (data instanceof JSONObject) { + // return ((JSONObject) data).toJSONString(); + // } + return serializeToJSON(data, null, false); + } + + /** + * 将对象序列化为 JSON 字符串;(紧凑格式) + * + * @param data + * @return + */ + public static String serializeToJSON(Object data, Class serializedType) { + return serializeToJSON(data, serializedType, false); + } + + /** + * 将对象序列化为 JSON 字符串; + * + * @param data + * 要序列化的对象; + * @param prettyFormat + * 是否以包含换行和缩进的良好格式输出 JSON; + * @return + */ + public static String serializeToJSON(Object data, boolean prettyFormat) { + return serializeToJSON(data, null, prettyFormat); + } + + /** + * 将对象序列化为 JSON 字符串; + * + * @param data + * 要序列化的对象; + * @param serializedType + * 要序列化的对象的输出的类型;
+ * 指定该对象的父类或者某一个实现的接口类型,序列化输出的 JSON 将只包含该类型的属性;
+ * 如果指定为 null, 则按对象本身的类型进行序列化; + * @param prettyFormat + * 是否以包含换行和缩进的良好格式输出 JSON; + * @return + */ + public static String serializeToJSON(Object data, Class serializedType, boolean prettyFormat) { + return serializeToJSON(data, serializedType, null, prettyFormat); + } + + /** + * 将对象序列化为 JSON 字符串; + * + * @param data + * 要序列化的对象; + * @param serializedType + * 要序列化的对象的输出的类型;
+ * 指定该对象的父类或者某一个实现的接口类型,序列化输出的 JSON 将只包含该类型的属性;
+ * 如果指定为 null, 则按对象本身的类型进行序列化; + * @param dateFormat + * 日期格式; + * @param prettyFormat + * 是否以包含换行和缩进的良好格式输出 JSON; + * @return + */ + public static String serializeToJSON(Object data, Class serializedType, String dateFormat, + boolean prettyFormat) { + SerializeWriter out; + + if (prettyFormat) { + out = new SerializeWriter((Writer) null, JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.PrettyFormat); + } else { + out = new SerializeWriter((Writer) null, JSON.DEFAULT_GENERATE_FEATURE, SerializerFeature.EMPTY); + } + + try { + if (data == null) { + return null; + // out.writeNull(); + } else { + // 确定要序列化的类型; + if (serializedType == null) { + serializedType = data.getClass(); + } else if ((!PrimitiveUtils.isPrimitiveType(serializedType)) + && (!PrimitiveUtils.isPrimitiveType(data.getClass())) + && (!serializedType.isAssignableFrom(data.getClass()))) { + throw new IllegalArgumentException("The serialized type[" + serializedType.getName() + + "] isn't assignable from the data type[" + data.getClass().getName() + "]!"); + } + + if (PrimitiveUtils.isWrapping(data.getClass(), serializedType)) { + // 避免 serializedType 原生的值类型时引发 fastjson 的序列化异常; + serializedType = data.getClass(); + } + + JSONSerializer serializer = new JSONSerializer(out, SerializeConfig.globalInstance); + + // 配置日期格式; + if (dateFormat != null && dateFormat.length() != 0) { + serializer.setDateFormat(dateFormat); + serializer.config(SerializerFeature.WriteDateUseDateFormat, true); + } + + // 序列化; + ObjectSerializer writer = serializer.getObjectWriter(serializedType); + + writer.write(serializer, data, null, null, JSON.DEFAULT_GENERATE_FEATURE); + } + return out.toString(); + } catch (IOException e) { + throw new IllegalStateException( + "Error occurred on serializing type[" + serializedType.getName() + "]! --" + e.getMessage(), e); + } finally { + out.close(); + } + } + + /** + * + * @param json + * @param dataClazz + * @return + */ + public static T deserializeFromJSON(String json, Class dataClazz) { + return JSON.parseObject(json, dataClazz); + } + + /** + * + * + * @param jsonObj + * @param dataClazz + * @param + * @return + */ + public static T deserializeFromJSONObject(JSONObject jsonObj, Class dataClazz) { + return (T)Proxy.newProxyInstance(dataClazz.getClassLoader(), new Class[] {dataClazz}, jsonObj); + } + + /** + * + * @param json + * @param dataClazz + * @return + */ + public static T deserializeFromJSON(String json, GenericType type) { + return JSON.parseObject(json, type.getTypeArgument()); + } + + @SuppressWarnings("unchecked") + public static T deserializeAs(Object data, Class clazz) { + if (data == null) { + return null; + } + if (data instanceof JSON) { + return ((JSON) data).toJavaObject(clazz); + } + if (data instanceof JSONBean) { + return ((JSONBean) data).toJavaBean(clazz); + } + if (data instanceof String) { + if (clazz.isInterface()) { + JSONObject jsonObj = JSONSerializeUtils.deserializeAs(data, JSONObject.class); + return deserializeFromJSONObject(jsonObj, clazz); + } + if (isJSON((String) data)) { + return deserializeFromJSON((String) data, clazz); + } + } + if (data instanceof JSONString) { + String jsonStr = ((JSONString) data).toString(); + if (isJSON(jsonStr)) { + return deserializeFromJSON(jsonStr, clazz); + } else { + data = jsonStr; + } + } + if (PrimitiveUtils.isPrimitiveType(clazz)) { + return PrimitiveUtils.castTo(data, clazz); + } + if (clazz.isAssignableFrom(data.getClass())) { + return (T) data; + } + if (clazz.isAssignableFrom(String.class)) { + return (T) data.toString(); + } + throw new IllegalArgumentException("Unsupported deserialization from type[" + data.getClass().toString() + + "] to type[" + clazz.toString() + "]!"); + } + +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONString.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONString.java index 873e09f3..ef905bfa 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONString.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONString.java @@ -1,42 +1,42 @@ -package com.jd.blockchain.utils.serialize.json; - -import com.alibaba.fastjson.annotation.JSONType; - -/** - * JSONString 用于包装不需要执行 JSON 序列化而直接输出的字符串; - * @author haiq - * - */ -@JSONType(serializer=JSONStringSerializer.class,deserializer =JSONStringDeserializer.class) -public final class JSONString { - - private String jsonString; - - public JSONString(String jsonString) { - if (jsonString == null) { - throw new IllegalArgumentException("Null json string!"); - } -// if (!SerializeUtils.isJSON(jsonString)) { -// throw new IllegalArgumentException("The arg is not a JSON string!"); -// } - this.jsonString = jsonString; - } - - private JSONString() { - } - - @Override - public String toString() { - return jsonString; - } - - public static JSONString toJSONString(Object data){ - if (data == null) { - return null; - } - String jsonString = JSONSerializeUtils.serializeToJSON(data); - JSONString retn = new JSONString(); - retn.jsonString = jsonString; - return retn; - } -} +package com.jd.blockchain.utils.serialize.json; + +import com.alibaba.fastjson.annotation.JSONType; + +/** + * JSONString 用于包装不需要执行 JSON 序列化而直接输出的字符串; + * @author haiq + * + */ +@JSONType(serializer=JSONStringSerializer.class,deserializer =JSONStringDeserializer.class) +public final class JSONString { + + private String jsonString; + + public JSONString(String jsonString) { + if (jsonString == null) { + throw new IllegalArgumentException("Null json string!"); + } +// if (!SerializeUtils.isJSON(jsonString)) { +// throw new IllegalArgumentException("The arg is not a JSON string!"); +// } + this.jsonString = jsonString; + } + + private JSONString() { + } + + @Override + public String toString() { + return jsonString; + } + + public static JSONString toJSONString(Object data){ + if (data == null) { + return null; + } + String jsonString = JSONSerializeUtils.serializeToJSON(data); + JSONString retn = new JSONString(); + retn.jsonString = jsonString; + return retn; + } +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONStringDeserializer.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONStringDeserializer.java index 671b61c1..0cae1e98 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONStringDeserializer.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONStringDeserializer.java @@ -1,26 +1,26 @@ -package com.jd.blockchain.utils.serialize.json; - -import java.lang.reflect.Type; - -import com.alibaba.fastjson.parser.DefaultJSONParser; -import com.alibaba.fastjson.parser.JSONToken; -import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; - -public class JSONStringDeserializer implements ObjectDeserializer{ - - @SuppressWarnings("unchecked") - @Override - public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { - if (type instanceof Class && JSONString.class.isAssignableFrom((Class) type)) { - String jsonString = parser.parseObject(String.class); - return (T) new JSONString(jsonString); - } - return (T) parser.parse(fieldName); - } - - @Override - public int getFastMatchToken() { - return JSONToken.LBRACE; - } - -} +package com.jd.blockchain.utils.serialize.json; + +import java.lang.reflect.Type; + +import com.alibaba.fastjson.parser.DefaultJSONParser; +import com.alibaba.fastjson.parser.JSONToken; +import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; + +public class JSONStringDeserializer implements ObjectDeserializer{ + + @SuppressWarnings("unchecked") + @Override + public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { + if (type instanceof Class && JSONString.class.isAssignableFrom((Class) type)) { + String jsonString = parser.parseObject(String.class); + return (T) new JSONString(jsonString); + } + return (T) parser.parse(fieldName); + } + + @Override + public int getFastMatchToken() { + return JSONToken.LBRACE; + } + +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONStringSerializer.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONStringSerializer.java index 6752e072..eadd2ea3 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONStringSerializer.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/JSONStringSerializer.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.utils.serialize.json; - -import java.io.IOException; -import java.lang.reflect.Type; - -import com.alibaba.fastjson.serializer.JSONSerializer; -import com.alibaba.fastjson.serializer.ObjectSerializer; -import com.alibaba.fastjson.serializer.SerializeWriter; - -public class JSONStringSerializer implements ObjectSerializer { - - @Override - public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) - throws IOException { - SerializeWriter out = serializer.out; - if (object == null) { - out.writeNull(); - return; - } - JSONString jsonString = (JSONString) object; - out.write(jsonString.toString()); - } - -} +package com.jd.blockchain.utils.serialize.json; + +import java.io.IOException; +import java.lang.reflect.Type; + +import com.alibaba.fastjson.serializer.JSONSerializer; +import com.alibaba.fastjson.serializer.ObjectSerializer; +import com.alibaba.fastjson.serializer.SerializeWriter; + +public class JSONStringSerializer implements ObjectSerializer { + + @Override + public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) + throws IOException { + SerializeWriter out = serializer.out; + if (object == null) { + out.writeNull(); + return; + } + JSONString jsonString = (JSONString) object; + out.write(jsonString.toString()); + } + +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/RuntimeDeserializer.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/RuntimeDeserializer.java index 2ebc7543..4fe6c8e5 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/RuntimeDeserializer.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/RuntimeDeserializer.java @@ -1,36 +1,36 @@ -package com.jd.blockchain.utils.serialize.json; - -import java.lang.reflect.Type; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import com.alibaba.fastjson.parser.DefaultJSONParser; -import com.alibaba.fastjson.parser.JSONToken; -import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; - -public class RuntimeDeserializer implements ObjectDeserializer { - - private Map, Class> typeMap = new ConcurrentHashMap, Class>(); - - synchronized void addTypeMap(Class fromClazz, Class toClazz){ - typeMap.put(fromClazz, toClazz); - } - - @SuppressWarnings("unchecked") - @Override - public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { - if (type instanceof Class) { - Class toClazz = typeMap.get((Class) type); - if (toClazz != null) { - return (T) parser.parseObject(toClazz); - } - } - return (T) parser.parse(fieldName); - } - - @Override - public int getFastMatchToken() { - return JSONToken.LBRACE; - } - -} +package com.jd.blockchain.utils.serialize.json; + +import java.lang.reflect.Type; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.alibaba.fastjson.parser.DefaultJSONParser; +import com.alibaba.fastjson.parser.JSONToken; +import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; + +public class RuntimeDeserializer implements ObjectDeserializer { + + private Map, Class> typeMap = new ConcurrentHashMap, Class>(); + + synchronized void addTypeMap(Class fromClazz, Class toClazz){ + typeMap.put(fromClazz, toClazz); + } + + @SuppressWarnings("unchecked") + @Override + public T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { + if (type instanceof Class) { + Class toClazz = typeMap.get((Class) type); + if (toClazz != null) { + return (T) parser.parseObject(toClazz); + } + } + return (T) parser.parse(fieldName); + } + + @Override + public int getFastMatchToken() { + return JSONToken.LBRACE; + } + +} diff --git a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/ToStringSerializer.java b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/ToStringSerializer.java index b66b160a..abc4b478 100644 --- a/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/ToStringSerializer.java +++ b/source/utils/utils-serialize/src/main/java/com/jd/blockchain/utils/serialize/json/ToStringSerializer.java @@ -1,24 +1,24 @@ -package com.jd.blockchain.utils.serialize.json; - -import java.io.IOException; -import java.lang.reflect.Type; - -import com.alibaba.fastjson.serializer.JSONSerializer; -import com.alibaba.fastjson.serializer.ObjectSerializer; -import com.alibaba.fastjson.serializer.SerializeWriter; - -public class ToStringSerializer implements ObjectSerializer { - - @Override - public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) - throws IOException { - SerializeWriter out = serializer.out; - if (object == null) { - out.writeNull(); - return; - } - - out.writeString(object.toString()); - } - -} +package com.jd.blockchain.utils.serialize.json; + +import java.io.IOException; +import java.lang.reflect.Type; + +import com.alibaba.fastjson.serializer.JSONSerializer; +import com.alibaba.fastjson.serializer.ObjectSerializer; +import com.alibaba.fastjson.serializer.SerializeWriter; + +public class ToStringSerializer implements ObjectSerializer { + + @Override + public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) + throws IOException { + SerializeWriter out = serializer.out; + if (object == null) { + out.writeNull(); + return; + } + + out.writeString(object.toString()); + } + +} diff --git a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/BinarySerializeUtilsTest.java b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/BinarySerializeUtilsTest.java index e10ff2c0..3fa99ae9 100644 --- a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/BinarySerializeUtilsTest.java +++ b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/BinarySerializeUtilsTest.java @@ -1,97 +1,97 @@ -package test.my.utils.serialize; - -import static org.junit.Assert.assertEquals; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.Serializable; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; - -public class BinarySerializeUtilsTest { - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - @Test - public void testSerializePrimitive() { - int v = 5; - byte[] bytes = BinarySerializeUtils.serialize(v); - Object desV = BinarySerializeUtils.deserialize(bytes); - - int v2 = (int) desV; - - assertEquals(v, v2); - } - - @Test - public void testSerializeMultiValues() { - String str = "kkkjijfekwejwe"; - int v = 5; - Data data = new Data(); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - BinarySerializeUtils.serialize(str, out); - BinarySerializeUtils.serialize(v, out); - BinarySerializeUtils.serialize(data, out); - - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - - String deStr = BinarySerializeUtils.deserialize(in); - int deV = BinarySerializeUtils.deserialize(in); - Data deData = BinarySerializeUtils.deserialize(in); - - assertEquals(str, deStr); - assertEquals(v, deV); - assertEquals(data.getId(), deData.getId()); - assertEquals(data.getName(), deData.getName()); - assertEquals(data.isMale(), deData.isMale()); - } - - - public static class Data implements Serializable{ - - private static final long serialVersionUID = -3168475060300920369L; - - private int id = 12; - private boolean male = false; - - private String name = "John"; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public boolean isMale() { - return male; - } - - public void setMale(boolean male) { - this.male = male; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - - - } -} +package test.my.utils.serialize; + +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Serializable; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; + +public class BinarySerializeUtilsTest { + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Test + public void testSerializePrimitive() { + int v = 5; + byte[] bytes = BinarySerializeUtils.serialize(v); + Object desV = BinarySerializeUtils.deserialize(bytes); + + int v2 = (int) desV; + + assertEquals(v, v2); + } + + @Test + public void testSerializeMultiValues() { + String str = "kkkjijfekwejwe"; + int v = 5; + Data data = new Data(); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + BinarySerializeUtils.serialize(str, out); + BinarySerializeUtils.serialize(v, out); + BinarySerializeUtils.serialize(data, out); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + + String deStr = BinarySerializeUtils.deserialize(in); + int deV = BinarySerializeUtils.deserialize(in); + Data deData = BinarySerializeUtils.deserialize(in); + + assertEquals(str, deStr); + assertEquals(v, deV); + assertEquals(data.getId(), deData.getId()); + assertEquals(data.getName(), deData.getName()); + assertEquals(data.isMale(), deData.isMale()); + } + + + public static class Data implements Serializable{ + + private static final long serialVersionUID = -3168475060300920369L; + + private int id = 12; + private boolean male = false; + + private String name = "John"; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public boolean isMale() { + return male; + } + + public void setMale(boolean male) { + this.male = male; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + + } +} diff --git a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Car.java b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Car.java index 99dfe2c7..7dc1d600 100644 --- a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Car.java +++ b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Car.java @@ -1,46 +1,46 @@ -package test.my.utils.serialize; - -public class Car implements ICar{ - private int weight; - - private int cost; - - private Wheel wheel; - - /* (non-Javadoc) - * @see test.my.utils.serialize.ICar#getWeight() - */ - @Override - public int getWeight() { - return weight; - } - - public void setWeight(int weight) { - this.weight = weight; - } - - /* (non-Javadoc) - * @see test.my.utils.serialize.ICar#getCost() - */ - @Override - public int getCost() { - return cost; - } - - public void setCost(int cost) { - this.cost = cost; - } - - public Wheel getWheel() { - return wheel; - } - - public void setWheel(Wheel wheel) { - this.wheel = wheel; - } - - public boolean test(Car car) { - return this.weight == car.weight; - } - +package test.my.utils.serialize; + +public class Car implements ICar{ + private int weight; + + private int cost; + + private Wheel wheel; + + /* (non-Javadoc) + * @see test.my.utils.serialize.ICar#getWeight() + */ + @Override + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + /* (non-Javadoc) + * @see test.my.utils.serialize.ICar#getCost() + */ + @Override + public int getCost() { + return cost; + } + + public void setCost(int cost) { + this.cost = cost; + } + + public Wheel getWheel() { + return wheel; + } + + public void setWheel(Wheel wheel) { + this.wheel = wheel; + } + + public boolean test(Car car) { + return this.weight == car.weight; + } + } \ No newline at end of file diff --git a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Entity.java b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Entity.java index 3f142549..57a6a361 100644 --- a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Entity.java +++ b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Entity.java @@ -1,65 +1,65 @@ -package test.my.utils.serialize; - -import java.lang.reflect.Type; - -public class Entity { - private String name; - - private int value; - - private Level level; - - private String data; - - private T header; - - private transient Type type; - - public Entity() { - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - public String getData() { - return data; - } - - public void setData(String data) { - this.data = data; - } - - public T getHeader() { - return header; - } - - public void setHeader(T header) { - this.header = header; - } - - public Type getType() { - return type; - } - - public Level getLevel() { - return level; - } - - public void setLevel(Level level) { - this.level = level; - } - +package test.my.utils.serialize; + +import java.lang.reflect.Type; + +public class Entity { + private String name; + + private int value; + + private Level level; + + private String data; + + private T header; + + private transient Type type; + + public Entity() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + public T getHeader() { + return header; + } + + public void setHeader(T header) { + this.header = header; + } + + public Type getType() { + return type; + } + + public Level getLevel() { + return level; + } + + public void setLevel(Level level) { + this.level = level; + } + } \ No newline at end of file diff --git a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/JSONBeanTest.java b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/JSONBeanTest.java index e32e7bed..db5f3349 100644 --- a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/JSONBeanTest.java +++ b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/JSONBeanTest.java @@ -1,327 +1,327 @@ -package test.my.utils.serialize; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.util.Date; -import java.util.UUID; - -import org.junit.Test; - -import com.jd.blockchain.utils.serialize.json.JSONBean; -import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; - -public class JSONBeanTest { - - @Test - public void testGet() { - CompositData compositeData = new CompositData(); - compositeData.setTelNo("18800101234"); - compositeData.setTime(new Date()); - - Score[] scores = new Score[2]; - scores[0] = new Score(); - scores[0].setId("A"); - scores[0].setValue(10); - scores[1] = new Score(); - scores[1].setId("B"); - scores[1].setValue(20); - - ExtData extdata = new ExtData(); - extdata.setCode("ext-00012"); - extdata.setAmount(1000); - extdata.setAddress("mvsekkjfdsafie932kjkasfdas"); - extdata.setEnable(true); - extdata.setCompositeData(compositeData); - extdata.setScores(scores); - - JSONBean jsonBean = JSONBean.wrap(extdata); - - String telNo = jsonBean.getString("compositeData.telNo"); - assertEquals(compositeData.getTelNo(), telNo); - - Date time = jsonBean.getDate("compositeData.time"); - assertEquals(compositeData.getTime(), time); - - int score2 = jsonBean.getIntValue("scores[1].value"); - assertEquals(scores[1].getValue(), score2); - } - - @Test - public void testMergeJSONBeanArrayMergeStrategy() { - // 准备初始数据; - CompositData compositeData = new CompositData(); - compositeData.setTelNo("18800101234"); - compositeData.setTime(new Date()); - - Score[] scores = new Score[2]; - scores[0] = new Score(); - scores[0].setId("A"); - scores[0].setValue(10); - scores[1] = new Score(); - scores[1].setId("B"); - scores[1].setValue(20); - - ExtData extdata = new ExtData(); - extdata.setCode("ext-00012"); - extdata.setAmount(1000); - extdata.setAddress("mvsekkjfdsafie932kjkasfdas"); - extdata.setEnable(true); - extdata.setCompositeData(compositeData); - extdata.setScores(scores); - - JSONBean jsonBean = JSONBean.wrap(extdata); - - String telNo = jsonBean.getString("compositeData.telNo"); - assertEquals(compositeData.getTelNo(), telNo); - - int score2 = jsonBean.getIntValue("scores[1].value"); - assertEquals(scores[1].getValue(), score2); - - // 准备合并数据; - Score[] scores2 = new Score[3]; - scores2[0] = new Score(); - scores2[0].setId("c"); - scores2[0].setValue(28); - scores2[1] = new Score(); - scores2[1].setId("d"); - scores2[1].setValue(50); - scores2[2] = new Score(); - scores2[2].setId("e"); - scores2[2].setValue(66); - - SubData subdata2 = new SubData(); - subdata2.setCode("sub-00018"); - subdata2.setAmount(180); - subdata2.setScores(scores2); - - JSONBean jsonBean2 = JSONBean.wrap(subdata2); - - jsonBean.merge(jsonBean2); - String code = jsonBean.getString("code"); - assertEquals(subdata2.getCode(), code); - telNo = jsonBean.getString("compositeData.telNo"); - assertEquals(compositeData.getTelNo(), telNo); - - score2 = jsonBean.getIntValue("scores[1].value"); - assertEquals(scores2[1].getValue(), score2); - - int score3 = jsonBean.getIntValue("scores[2].value"); - assertEquals(scores2[2].getValue(), score3); - } - - @Test - public void testSerializeAndDeserialize1(){ - CompositData compositeData = new CompositData(); - compositeData.setTelNo("18800101234"); - compositeData.setTime(new Date()); - - Score[] scores = new Score[2]; - scores[0] = new Score(); - scores[0].setId("A"); - scores[0].setValue(10); - scores[1] = new Score(); - scores[1].setId("B"); - scores[1].setValue(20); - - ExtData extdata = new ExtData(); - extdata.setCode("ext-00012"); - extdata.setAmount(1000); - extdata.setAddress("mvsekkjfdsafie932kjkasfdas"); - extdata.setEnable(true); - extdata.setCompositeData(compositeData); - extdata.setScores(scores); - - JSONBean jsonBean = JSONBean.wrap(extdata); - - String json = JSONSerializeUtils.serializeToJSON(jsonBean); - System.out.println("--------- serialize ----------"); - System.out.println(json); - - JSONBean jsonBean2 = JSONSerializeUtils.deserializeFromJSON(json, JSONBean.class); - System.out.println("--------- deserialize ----------"); - assertNotNull(jsonBean2); - assertEquals(extdata.getCode(), jsonBean2.getString("code")); - assertEquals(extdata.getAmount(), jsonBean2.getIntValue("amount")); - assertEquals(extdata.isEnable(), jsonBean2.getBooleanValue("enable")); - } - @Test - public void testSerializeAndDeserialize2(){ - CompositData compositeData = new CompositData(); - compositeData.setTelNo("18800101234"); - compositeData.setTime(new Date()); - - Score[] scores = new Score[2]; - scores[0] = new Score(); - scores[0].setId("A"); - scores[0].setValue(10); - scores[1] = new Score(); - scores[1].setId("B"); - scores[1].setValue(20); - - ExtData extdata = new ExtData(); - extdata.setCode("ext-00012"); - extdata.setAmount(1000); - extdata.setAddress("mvsekkjfdsafie932kjkasfdas"); - extdata.setEnable(true); - extdata.setCompositeData(compositeData); - extdata.setScores(scores); - - JSONBean jsonBean = JSONBean.wrap(extdata); - - TopMetadata meta = new TopMetadata(); - meta.setId(UUID.randomUUID().toString()); - meta.setHeader(jsonBean); - - String json = JSONSerializeUtils.serializeToJSON(meta); - System.out.println("--------- serialize ----------"); - System.out.println(json); - - TopMetadata meta2 = JSONSerializeUtils.deserializeFromJSON(json, TopMetadata.class); - System.out.println("--------- deserialize ----------"); - System.out.println("id="+ meta2.getId()); - assertNotNull(meta2.getHeader()); - assertEquals(extdata.getCode(), meta2.getHeader().getString("code")); - assertEquals(extdata.getAmount(), meta2.getHeader().getIntValue("amount")); - assertEquals(extdata.isEnable(), meta2.getHeader().getBooleanValue("enable")); - } - - public static class TopMetadata{ - - private String id; - - private JSONBean header; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public JSONBean getHeader() { - return header; - } - - public void setHeader(JSONBean header) { - this.header = header; - } - - } - - public static class SubData { - - private String code; - - private int amount; - - private Score[] scores; - - public Score[] getScores() { - return scores; - } - - public void setScores(Score[] scores) { - this.scores = scores; - } - - public String getCode() { - return code; - } - - public int getAmount() { - return amount; - } - - public void setCode(String code) { - this.code = code; - } - - public void setAmount(int amount) { - this.amount = amount; - } - - } - - public static class Score { - private String id; - - private int value; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public int getValue() { - return value; - } - - public void setValue(int value) { - this.value = value; - } - - } - - public static class ExtData extends SubData { - - private String address; - - private boolean enable; - - private CompositData compositeData; - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public boolean isEnable() { - return enable; - } - - public void setEnable(boolean enable) { - this.enable = enable; - } - - public CompositData getCompositeData() { - return compositeData; - } - - public void setCompositeData(CompositData compositeData) { - this.compositeData = compositeData; - } - } - - public static class CompositData { - - private String telNo; - - private Date time; - - public String getTelNo() { - return telNo; - } - - public void setTelNo(String telNo) { - this.telNo = telNo; - } - - public Date getTime() { - return time; - } - - public void setTime(Date time) { - this.time = time; - } - - } - -} +package test.my.utils.serialize; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Date; +import java.util.UUID; + +import org.junit.Test; + +import com.jd.blockchain.utils.serialize.json.JSONBean; +import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; + +public class JSONBeanTest { + + @Test + public void testGet() { + CompositData compositeData = new CompositData(); + compositeData.setTelNo("18800101234"); + compositeData.setTime(new Date()); + + Score[] scores = new Score[2]; + scores[0] = new Score(); + scores[0].setId("A"); + scores[0].setValue(10); + scores[1] = new Score(); + scores[1].setId("B"); + scores[1].setValue(20); + + ExtData extdata = new ExtData(); + extdata.setCode("ext-00012"); + extdata.setAmount(1000); + extdata.setAddress("mvsekkjfdsafie932kjkasfdas"); + extdata.setEnable(true); + extdata.setCompositeData(compositeData); + extdata.setScores(scores); + + JSONBean jsonBean = JSONBean.wrap(extdata); + + String telNo = jsonBean.getString("compositeData.telNo"); + assertEquals(compositeData.getTelNo(), telNo); + + Date time = jsonBean.getDate("compositeData.time"); + assertEquals(compositeData.getTime(), time); + + int score2 = jsonBean.getIntValue("scores[1].value"); + assertEquals(scores[1].getValue(), score2); + } + + @Test + public void testMergeJSONBeanArrayMergeStrategy() { + // 准备初始数据; + CompositData compositeData = new CompositData(); + compositeData.setTelNo("18800101234"); + compositeData.setTime(new Date()); + + Score[] scores = new Score[2]; + scores[0] = new Score(); + scores[0].setId("A"); + scores[0].setValue(10); + scores[1] = new Score(); + scores[1].setId("B"); + scores[1].setValue(20); + + ExtData extdata = new ExtData(); + extdata.setCode("ext-00012"); + extdata.setAmount(1000); + extdata.setAddress("mvsekkjfdsafie932kjkasfdas"); + extdata.setEnable(true); + extdata.setCompositeData(compositeData); + extdata.setScores(scores); + + JSONBean jsonBean = JSONBean.wrap(extdata); + + String telNo = jsonBean.getString("compositeData.telNo"); + assertEquals(compositeData.getTelNo(), telNo); + + int score2 = jsonBean.getIntValue("scores[1].value"); + assertEquals(scores[1].getValue(), score2); + + // 准备合并数据; + Score[] scores2 = new Score[3]; + scores2[0] = new Score(); + scores2[0].setId("c"); + scores2[0].setValue(28); + scores2[1] = new Score(); + scores2[1].setId("d"); + scores2[1].setValue(50); + scores2[2] = new Score(); + scores2[2].setId("e"); + scores2[2].setValue(66); + + SubData subdata2 = new SubData(); + subdata2.setCode("sub-00018"); + subdata2.setAmount(180); + subdata2.setScores(scores2); + + JSONBean jsonBean2 = JSONBean.wrap(subdata2); + + jsonBean.merge(jsonBean2); + String code = jsonBean.getString("code"); + assertEquals(subdata2.getCode(), code); + telNo = jsonBean.getString("compositeData.telNo"); + assertEquals(compositeData.getTelNo(), telNo); + + score2 = jsonBean.getIntValue("scores[1].value"); + assertEquals(scores2[1].getValue(), score2); + + int score3 = jsonBean.getIntValue("scores[2].value"); + assertEquals(scores2[2].getValue(), score3); + } + + @Test + public void testSerializeAndDeserialize1(){ + CompositData compositeData = new CompositData(); + compositeData.setTelNo("18800101234"); + compositeData.setTime(new Date()); + + Score[] scores = new Score[2]; + scores[0] = new Score(); + scores[0].setId("A"); + scores[0].setValue(10); + scores[1] = new Score(); + scores[1].setId("B"); + scores[1].setValue(20); + + ExtData extdata = new ExtData(); + extdata.setCode("ext-00012"); + extdata.setAmount(1000); + extdata.setAddress("mvsekkjfdsafie932kjkasfdas"); + extdata.setEnable(true); + extdata.setCompositeData(compositeData); + extdata.setScores(scores); + + JSONBean jsonBean = JSONBean.wrap(extdata); + + String json = JSONSerializeUtils.serializeToJSON(jsonBean); + System.out.println("--------- serialize ----------"); + System.out.println(json); + + JSONBean jsonBean2 = JSONSerializeUtils.deserializeFromJSON(json, JSONBean.class); + System.out.println("--------- deserialize ----------"); + assertNotNull(jsonBean2); + assertEquals(extdata.getCode(), jsonBean2.getString("code")); + assertEquals(extdata.getAmount(), jsonBean2.getIntValue("amount")); + assertEquals(extdata.isEnable(), jsonBean2.getBooleanValue("enable")); + } + @Test + public void testSerializeAndDeserialize2(){ + CompositData compositeData = new CompositData(); + compositeData.setTelNo("18800101234"); + compositeData.setTime(new Date()); + + Score[] scores = new Score[2]; + scores[0] = new Score(); + scores[0].setId("A"); + scores[0].setValue(10); + scores[1] = new Score(); + scores[1].setId("B"); + scores[1].setValue(20); + + ExtData extdata = new ExtData(); + extdata.setCode("ext-00012"); + extdata.setAmount(1000); + extdata.setAddress("mvsekkjfdsafie932kjkasfdas"); + extdata.setEnable(true); + extdata.setCompositeData(compositeData); + extdata.setScores(scores); + + JSONBean jsonBean = JSONBean.wrap(extdata); + + TopMetadata meta = new TopMetadata(); + meta.setId(UUID.randomUUID().toString()); + meta.setHeader(jsonBean); + + String json = JSONSerializeUtils.serializeToJSON(meta); + System.out.println("--------- serialize ----------"); + System.out.println(json); + + TopMetadata meta2 = JSONSerializeUtils.deserializeFromJSON(json, TopMetadata.class); + System.out.println("--------- deserialize ----------"); + System.out.println("id="+ meta2.getId()); + assertNotNull(meta2.getHeader()); + assertEquals(extdata.getCode(), meta2.getHeader().getString("code")); + assertEquals(extdata.getAmount(), meta2.getHeader().getIntValue("amount")); + assertEquals(extdata.isEnable(), meta2.getHeader().getBooleanValue("enable")); + } + + public static class TopMetadata{ + + private String id; + + private JSONBean header; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public JSONBean getHeader() { + return header; + } + + public void setHeader(JSONBean header) { + this.header = header; + } + + } + + public static class SubData { + + private String code; + + private int amount; + + private Score[] scores; + + public Score[] getScores() { + return scores; + } + + public void setScores(Score[] scores) { + this.scores = scores; + } + + public String getCode() { + return code; + } + + public int getAmount() { + return amount; + } + + public void setCode(String code) { + this.code = code; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + } + + public static class Score { + private String id; + + private int value; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + } + + public static class ExtData extends SubData { + + private String address; + + private boolean enable; + + private CompositData compositeData; + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public boolean isEnable() { + return enable; + } + + public void setEnable(boolean enable) { + this.enable = enable; + } + + public CompositData getCompositeData() { + return compositeData; + } + + public void setCompositeData(CompositData compositeData) { + this.compositeData = compositeData; + } + } + + public static class CompositData { + + private String telNo; + + private Date time; + + public String getTelNo() { + return telNo; + } + + public void setTelNo(String telNo) { + this.telNo = telNo; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } + + } + +} diff --git a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/JSONSerializeUtilsTest.java b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/JSONSerializeUtilsTest.java index 3550f353..4a41d8dc 100644 --- a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/JSONSerializeUtilsTest.java +++ b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/JSONSerializeUtilsTest.java @@ -1,262 +1,262 @@ -package test.my.utils.serialize; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.lang.reflect.Proxy; -import java.util.Date; -import java.util.UUID; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.parser.ParserConfig; -import com.jd.blockchain.utils.serialize.json.GenericType; -import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; -import com.jd.blockchain.utils.serialize.json.JSONString; - -public class JSONSerializeUtilsTest { - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - } - - @Before - public void setUp() throws Exception { - } - - @After - public void tearDown() throws Exception { - } - - - @Test - public void testInterface() { - Car car = new Car(); - car.setCost(10); - car.setWeight(1000); - Wheel wheel = new Wheel(); - wheel.setBlack("Black"); - car.setWheel(wheel); - - String json = JSONSerializeUtils.serializeToJSON(car); - - ParserConfig.global.setAutoTypeSupport(true); - - JSONObject jsonObj = JSONSerializeUtils.deserializeAs(json, JSONObject.class); - ICar decar = (ICar) Proxy.newProxyInstance(ICar.class.getClassLoader(), new Class[] {ICar.class}, jsonObj); - System.out.println("Class of decar :" + decar.getClass().getName()); - assertNotNull(decar); - assertEquals(car.getCost(), decar.getCost()); - assertEquals(car.getWeight(), decar.getWeight()); - Wheel deWheel = decar.getWheel(); - assertEquals(wheel.getBlack(), deWheel.getBlack()); - } - - @Test - public void tempTest() { - Car car = new Car(); - car.setCost(10); - car.setWeight(1000); - - String name = "john"; - boolean enable = true; - - Object[] dataArrays = new Object[] { name, car, enable, null, new Date() }; - String json = JSON.toJSONString(dataArrays); - System.out.println("--------- json ---------"); - System.out.println(json); - - System.out.println("--------- deserialize ---------"); - Object deObj = JSON.parse(json); - assertTrue(deObj instanceof JSONArray); - System.out.println("deObj.type=" + deObj.getClass().getName()); - JSONArray jsonArray = (JSONArray) deObj; - assertEquals(5, jsonArray.size()); - - assertTrue(jsonArray.get(0) instanceof String); - assertTrue(jsonArray.get(1) instanceof JSONObject); - assertTrue(jsonArray.get(2) instanceof Boolean); - assertNull(jsonArray.get(3)); - assertTrue(jsonArray.get(4) instanceof Long); - System.out.println("[0]--" + jsonArray.get(0).getClass().getName()); - System.out.println("[1]--" + jsonArray.get(1).getClass().getName()); - System.out.println("[2]--" + jsonArray.get(2).getClass().getName()); - System.out.println("[3]--" + jsonArray.get(3)); - System.out.println("[4]--" + jsonArray.get(4).getClass().getName()); - - System.out.println("--------- get specified type --------"); - assertTrue(jsonArray.getObject(1, Car.class) instanceof Car); - assertTrue(jsonArray.getDate(4) instanceof Date); - assertTrue(jsonArray.getObject(4, Date.class) instanceof Date); - System.out.println("[1]--" + jsonArray.getObject(1, Car.class).getClass().getName()); - System.out.println("[4]--" + jsonArray.getObject(4, Date.class).getClass().getName()); - } - - @Test - public void testSerialize() { - Car car = new Car(); - car.setCost(10000); - car.setWeight(600); - - String jsonCar = JSONSerializeUtils.serializeToJSON(car); - - Entity entity = new Entity(); - entity.setName("test-entity"); - entity.setValue(80); - entity.setData(jsonCar); - entity.setHeader(car); - entity.setLevel(Level.LOW); - - String jsonEntity = JSONSerializeUtils.serializeToJSON(entity); - GenericType> type = new GenericType>() { - }; - Entity deEntity = JSONSerializeUtils.deserializeFromJSON(jsonEntity, type); - assertEquals(entity.getName(), deEntity.getName()); - assertEquals(entity.getValue(), deEntity.getValue()); - assertEquals(entity.getData(), deEntity.getData()); - assertEquals(entity.getLevel(), deEntity.getLevel()); - assertSame(entity.getLevel(), deEntity.getLevel()); - assertNotNull(deEntity.getHeader()); - assertTrue(deEntity.getHeader() instanceof Car); - assertEquals(car.getCost(), deEntity.getHeader().getCost()); - - testGereric(entity, jsonEntity); - - Entity deEntity2 = JSONSerializeUtils.deserializeFromJSON(jsonEntity, Entity.class); - assertNotNull(deEntity2); - assertTrue(deEntity2.getHeader() instanceof JSONObject); - test(deEntity2, JSONObject.class); - - Entity entityStr = new Entity(); - entityStr.setName("test-entity"); - entityStr.setValue(80); - entityStr.setData("StringCarData"); - entityStr.setHeader("StringCar"); - entityStr.setLevel(Level.LOW); - String jsonEntityStr = JSONSerializeUtils.serializeToJSON(entityStr); - - Entity deEntity3 = JSONSerializeUtils.deserializeFromJSON(jsonEntityStr, Entity.class); - assertNotNull(deEntity3); - assertTrue(deEntity3.getHeader() instanceof String); - - test(deEntity3, String.class); - } - - private void test(Entity entity, Class type) { - assertNotNull(entity); - assertNotNull(entity.getHeader()); - assertTrue(type.isAssignableFrom(entity.getHeader().getClass())); - } - - @SuppressWarnings("unchecked") - private void testGereric(Entity expectedEntity, String jsonEntity) { - Entity deEntity = JSONSerializeUtils.deserializeFromJSON(jsonEntity, Entity.class); - assertEquals(expectedEntity.getName(), deEntity.getName()); - assertEquals(expectedEntity.getValue(), deEntity.getValue()); - assertEquals(expectedEntity.getData(), deEntity.getData()); - assertEquals(expectedEntity.getLevel(), deEntity.getLevel()); - assertSame(expectedEntity.getLevel(), deEntity.getLevel()); - assertNotNull(deEntity.getHeader()); - assertTrue(deEntity.getHeader() instanceof JSONObject); - } - - @Test - public void testJSONArray() { - Car[] cars = new Car[2]; - - cars[0] = new Car(); - cars[0].setCost(10); - cars[0].setWeight(1000); - - cars[1] = new Car(); - cars[1].setCost(10); - cars[1].setWeight(1000); - - String jsonString = JSONSerializeUtils.serializeToJSON(cars); - Object json = JSON.parse(jsonString); - assertTrue(json instanceof JSONArray); - - Car[] deCars = JSONSerializeUtils.deserializeAs(json, Car[].class); - assertNotNull(deCars); - assertEquals(cars.length, deCars.length); - for (int i = 0; i < deCars.length; i++) { - assertNotNull(cars[i]); - assertEquals(cars[i].getCost(), deCars[i].getCost()); - assertEquals(cars[i].getWeight(), deCars[i].getWeight()); - } - } - - @Test - public void testSerializeString() { - String origString = "test string"; - String json = JSONSerializeUtils.serializeToJSON(origString, String.class); - - String desString = JSON.parseObject(json, String.class); - assertEquals(origString, desString); - - String desString1 = JSONSerializeUtils.deserializeAs(json, String.class); - assertEquals(origString, desString1); - - String desString2 = JSONSerializeUtils.deserializeAs(origString, String.class); - assertEquals(origString, desString2); - - Car car = new Car(); - car.setCost(10); - car.setWeight(1000); - - String carJSON = JSONSerializeUtils.serializeToJSON(car); - String carJSON1 = JSON.toJSONString(car, false); - assertEquals(carJSON, carJSON1); - - String carString = JSON.parseObject(carJSON, String.class); - assertEquals(carJSON, carString); - String carString2 = JSONSerializeUtils.deserializeAs(carJSON, String.class); - assertEquals(carJSON, carString2); - } - - @Test - public void testJSONString(){ - Car car = new Car(); - car.setCost(10); - car.setWeight(1000); - - String carJSON = JSONSerializeUtils.serializeToJSON(car); - JSONString jsonString = new JSONString(carJSON); - System.out.println("1:--\r\n" + carJSON ); - - String newJSONString = JSONSerializeUtils.serializeToJSON(jsonString); - assertEquals(carJSON, newJSONString); - System.out.println("2:--\r\n" + newJSONString ); - - JSONString newJSONString2 = JSONSerializeUtils.deserializeAs(newJSONString, JSONString.class); - assertEquals(carJSON, newJSONString2.toString()); - - String address = UUID.randomUUID().toString(); - JSONString jsonAddress = new JSONString(JSONSerializeUtils.serializeToJSON(address)); - String desAddress = JSONSerializeUtils.deserializeAs(jsonAddress, String.class); - assertEquals(address, desAddress); - - String emptyStr = ""; - JSONString emptyJsonStr = new JSONString(JSONSerializeUtils.serializeToJSON(emptyStr)); - String desEmptyStr = JSONSerializeUtils.deserializeAs(emptyJsonStr, String.class); - assertEquals(emptyStr, desEmptyStr); - - String nullStr = null; - String nullJson = JSONSerializeUtils.serializeToJSON(nullStr); - assertNull(nullJson); - } -} +package test.my.utils.serialize; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Proxy; +import java.util.Date; +import java.util.UUID; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.parser.ParserConfig; +import com.jd.blockchain.utils.serialize.json.GenericType; +import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; +import com.jd.blockchain.utils.serialize.json.JSONString; + +public class JSONSerializeUtilsTest { + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + } + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testInterface() { + Car car = new Car(); + car.setCost(10); + car.setWeight(1000); + Wheel wheel = new Wheel(); + wheel.setBlack("Black"); + car.setWheel(wheel); + + String json = JSONSerializeUtils.serializeToJSON(car); + + ParserConfig.global.setAutoTypeSupport(true); + + JSONObject jsonObj = JSONSerializeUtils.deserializeAs(json, JSONObject.class); + ICar decar = (ICar) Proxy.newProxyInstance(ICar.class.getClassLoader(), new Class[] {ICar.class}, jsonObj); + System.out.println("Class of decar :" + decar.getClass().getName()); + assertNotNull(decar); + assertEquals(car.getCost(), decar.getCost()); + assertEquals(car.getWeight(), decar.getWeight()); + Wheel deWheel = decar.getWheel(); + assertEquals(wheel.getBlack(), deWheel.getBlack()); + } + + @Test + public void tempTest() { + Car car = new Car(); + car.setCost(10); + car.setWeight(1000); + + String name = "john"; + boolean enable = true; + + Object[] dataArrays = new Object[] { name, car, enable, null, new Date() }; + String json = JSON.toJSONString(dataArrays); + System.out.println("--------- json ---------"); + System.out.println(json); + + System.out.println("--------- deserialize ---------"); + Object deObj = JSON.parse(json); + assertTrue(deObj instanceof JSONArray); + System.out.println("deObj.type=" + deObj.getClass().getName()); + JSONArray jsonArray = (JSONArray) deObj; + assertEquals(5, jsonArray.size()); + + assertTrue(jsonArray.get(0) instanceof String); + assertTrue(jsonArray.get(1) instanceof JSONObject); + assertTrue(jsonArray.get(2) instanceof Boolean); + assertNull(jsonArray.get(3)); + assertTrue(jsonArray.get(4) instanceof Long); + System.out.println("[0]--" + jsonArray.get(0).getClass().getName()); + System.out.println("[1]--" + jsonArray.get(1).getClass().getName()); + System.out.println("[2]--" + jsonArray.get(2).getClass().getName()); + System.out.println("[3]--" + jsonArray.get(3)); + System.out.println("[4]--" + jsonArray.get(4).getClass().getName()); + + System.out.println("--------- get specified type --------"); + assertTrue(jsonArray.getObject(1, Car.class) instanceof Car); + assertTrue(jsonArray.getDate(4) instanceof Date); + assertTrue(jsonArray.getObject(4, Date.class) instanceof Date); + System.out.println("[1]--" + jsonArray.getObject(1, Car.class).getClass().getName()); + System.out.println("[4]--" + jsonArray.getObject(4, Date.class).getClass().getName()); + } + + @Test + public void testSerialize() { + Car car = new Car(); + car.setCost(10000); + car.setWeight(600); + + String jsonCar = JSONSerializeUtils.serializeToJSON(car); + + Entity entity = new Entity(); + entity.setName("test-entity"); + entity.setValue(80); + entity.setData(jsonCar); + entity.setHeader(car); + entity.setLevel(Level.LOW); + + String jsonEntity = JSONSerializeUtils.serializeToJSON(entity); + GenericType> type = new GenericType>() { + }; + Entity deEntity = JSONSerializeUtils.deserializeFromJSON(jsonEntity, type); + assertEquals(entity.getName(), deEntity.getName()); + assertEquals(entity.getValue(), deEntity.getValue()); + assertEquals(entity.getData(), deEntity.getData()); + assertEquals(entity.getLevel(), deEntity.getLevel()); + assertSame(entity.getLevel(), deEntity.getLevel()); + assertNotNull(deEntity.getHeader()); + assertTrue(deEntity.getHeader() instanceof Car); + assertEquals(car.getCost(), deEntity.getHeader().getCost()); + + testGereric(entity, jsonEntity); + + Entity deEntity2 = JSONSerializeUtils.deserializeFromJSON(jsonEntity, Entity.class); + assertNotNull(deEntity2); + assertTrue(deEntity2.getHeader() instanceof JSONObject); + test(deEntity2, JSONObject.class); + + Entity entityStr = new Entity(); + entityStr.setName("test-entity"); + entityStr.setValue(80); + entityStr.setData("StringCarData"); + entityStr.setHeader("StringCar"); + entityStr.setLevel(Level.LOW); + String jsonEntityStr = JSONSerializeUtils.serializeToJSON(entityStr); + + Entity deEntity3 = JSONSerializeUtils.deserializeFromJSON(jsonEntityStr, Entity.class); + assertNotNull(deEntity3); + assertTrue(deEntity3.getHeader() instanceof String); + + test(deEntity3, String.class); + } + + private void test(Entity entity, Class type) { + assertNotNull(entity); + assertNotNull(entity.getHeader()); + assertTrue(type.isAssignableFrom(entity.getHeader().getClass())); + } + + @SuppressWarnings("unchecked") + private void testGereric(Entity expectedEntity, String jsonEntity) { + Entity deEntity = JSONSerializeUtils.deserializeFromJSON(jsonEntity, Entity.class); + assertEquals(expectedEntity.getName(), deEntity.getName()); + assertEquals(expectedEntity.getValue(), deEntity.getValue()); + assertEquals(expectedEntity.getData(), deEntity.getData()); + assertEquals(expectedEntity.getLevel(), deEntity.getLevel()); + assertSame(expectedEntity.getLevel(), deEntity.getLevel()); + assertNotNull(deEntity.getHeader()); + assertTrue(deEntity.getHeader() instanceof JSONObject); + } + + @Test + public void testJSONArray() { + Car[] cars = new Car[2]; + + cars[0] = new Car(); + cars[0].setCost(10); + cars[0].setWeight(1000); + + cars[1] = new Car(); + cars[1].setCost(10); + cars[1].setWeight(1000); + + String jsonString = JSONSerializeUtils.serializeToJSON(cars); + Object json = JSON.parse(jsonString); + assertTrue(json instanceof JSONArray); + + Car[] deCars = JSONSerializeUtils.deserializeAs(json, Car[].class); + assertNotNull(deCars); + assertEquals(cars.length, deCars.length); + for (int i = 0; i < deCars.length; i++) { + assertNotNull(cars[i]); + assertEquals(cars[i].getCost(), deCars[i].getCost()); + assertEquals(cars[i].getWeight(), deCars[i].getWeight()); + } + } + + @Test + public void testSerializeString() { + String origString = "test string"; + String json = JSONSerializeUtils.serializeToJSON(origString, String.class); + + String desString = JSON.parseObject(json, String.class); + assertEquals(origString, desString); + + String desString1 = JSONSerializeUtils.deserializeAs(json, String.class); + assertEquals(origString, desString1); + + String desString2 = JSONSerializeUtils.deserializeAs(origString, String.class); + assertEquals(origString, desString2); + + Car car = new Car(); + car.setCost(10); + car.setWeight(1000); + + String carJSON = JSONSerializeUtils.serializeToJSON(car); + String carJSON1 = JSON.toJSONString(car, false); + assertEquals(carJSON, carJSON1); + + String carString = JSON.parseObject(carJSON, String.class); + assertEquals(carJSON, carString); + String carString2 = JSONSerializeUtils.deserializeAs(carJSON, String.class); + assertEquals(carJSON, carString2); + } + + @Test + public void testJSONString(){ + Car car = new Car(); + car.setCost(10); + car.setWeight(1000); + + String carJSON = JSONSerializeUtils.serializeToJSON(car); + JSONString jsonString = new JSONString(carJSON); + System.out.println("1:--\r\n" + carJSON ); + + String newJSONString = JSONSerializeUtils.serializeToJSON(jsonString); + assertEquals(carJSON, newJSONString); + System.out.println("2:--\r\n" + newJSONString ); + + JSONString newJSONString2 = JSONSerializeUtils.deserializeAs(newJSONString, JSONString.class); + assertEquals(carJSON, newJSONString2.toString()); + + String address = UUID.randomUUID().toString(); + JSONString jsonAddress = new JSONString(JSONSerializeUtils.serializeToJSON(address)); + String desAddress = JSONSerializeUtils.deserializeAs(jsonAddress, String.class); + assertEquals(address, desAddress); + + String emptyStr = ""; + JSONString emptyJsonStr = new JSONString(JSONSerializeUtils.serializeToJSON(emptyStr)); + String desEmptyStr = JSONSerializeUtils.deserializeAs(emptyJsonStr, String.class); + assertEquals(emptyStr, desEmptyStr); + + String nullStr = null; + String nullJson = JSONSerializeUtils.serializeToJSON(nullStr); + assertNull(nullJson); + } +} diff --git a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Level.java b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Level.java index d960b4ed..f5cd98cb 100644 --- a/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Level.java +++ b/source/utils/utils-serialize/src/test/java/test/my/utils/serialize/Level.java @@ -1,18 +1,18 @@ -package test.my.utils.serialize; - -public enum Level { - - HIGH(10), - - LOW(1); - - private final int value; - - private Level(int value) { - this.value = value; - } - - public int getValue() { - return value; - } -} +package test.my.utils.serialize; + +public enum Level { + + HIGH(10), + + LOW(1); + + private final int value; + + private Level(int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} diff --git a/source/utils/utils-test/.gitignore b/source/utils/utils-test/.gitignore index 24d64373..b83d2226 100644 --- a/source/utils/utils-test/.gitignore +++ b/source/utils/utils-test/.gitignore @@ -1 +1 @@ -/target/ +/target/ diff --git a/source/utils/utils-test/pom.xml b/source/utils/utils-test/pom.xml index 0fce0b58..b56d6c80 100644 --- a/source/utils/utils-test/pom.xml +++ b/source/utils/utils-test/pom.xml @@ -1,75 +1,75 @@ - - 4.0.0 - - com.jd.blockchain - utils - 1.1.2.RELEASE - - utils-test - - - - org.slf4j - slf4j-api - - - com.jd.blockchain - utils-serialize - ${project.version} - - - - javax.servlet - javax.servlet-api - - - - org.eclipse.jetty - jetty-server - - - org.eclipse.jetty - jetty-servlet - - - - - org.springframework - spring-web - - - org.springframework - spring-webmvc - - - org.springframework - spring-beans - - - org.springframework - spring-test - - - junit - junit - - - org.mockito - mockito-core - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - true - - - - + + 4.0.0 + + com.jd.blockchain + utils + 1.1.2.RELEASE + + utils-test + + + + org.slf4j + slf4j-api + + + com.jd.blockchain + utils-serialize + ${project.version} + + + + javax.servlet + javax.servlet-api + + + + org.eclipse.jetty + jetty-server + + + org.eclipse.jetty + jetty-servlet + + + + + org.springframework + spring-web + + + org.springframework + spring-webmvc + + + org.springframework + spring-beans + + + org.springframework + spring-test + + + junit + junit + + + org.mockito + mockito-core + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + \ No newline at end of file diff --git a/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/JunitAssertMatcher.java b/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/JunitAssertMatcher.java index 7febfc1d..9ebeaee5 100644 --- a/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/JunitAssertMatcher.java +++ b/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/JunitAssertMatcher.java @@ -1,34 +1,34 @@ -package com.jd.blockchain.utils.test; - -import static org.junit.Assert.*; - -import org.hamcrest.CustomMatcher; - -import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; - -public class JunitAssertMatcher { - - public static CustomMatcher assertEqualsMatch(final T expected){ - return new CustomMatcher("expected arg equals the value [" + expected + "].") { - @Override - public boolean matches(Object item) { - assertEquals(expected, item); - return true; - } - }; - } - - public static CustomMatcher assertJsonEqualMatch(final T expected){ - return new CustomMatcher("expected arg equals the value [" + expected + "].") { - @Override - public boolean matches(Object item) { - assertNotNull(item); - String actualJSON = JSONSerializeUtils.serializeToJSON(item); - String expectedJSON = JSONSerializeUtils.serializeToJSON(expected); - assertEquals(expectedJSON, actualJSON); - return true; - } - }; - } - -} +package com.jd.blockchain.utils.test; + +import static org.junit.Assert.*; + +import org.hamcrest.CustomMatcher; + +import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; + +public class JunitAssertMatcher { + + public static CustomMatcher assertEqualsMatch(final T expected){ + return new CustomMatcher("expected arg equals the value [" + expected + "].") { + @Override + public boolean matches(Object item) { + assertEquals(expected, item); + return true; + } + }; + } + + public static CustomMatcher assertJsonEqualMatch(final T expected){ + return new CustomMatcher("expected arg equals the value [" + expected + "].") { + @Override + public boolean matches(Object item) { + assertNotNull(item); + String actualJSON = JSONSerializeUtils.serializeToJSON(item); + String expectedJSON = JSONSerializeUtils.serializeToJSON(expected); + assertEquals(expectedJSON, actualJSON); + return true; + } + }; + } + +} diff --git a/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/ServletRegister.java b/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/ServletRegister.java index 09f8f703..7a24a4da 100644 --- a/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/ServletRegister.java +++ b/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/ServletRegister.java @@ -1,44 +1,44 @@ -package com.jd.blockchain.utils.test; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; - -import javax.servlet.Servlet; -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.ServletRegistration; - -public class ServletRegister implements ServletContextListener { - - private Map servlets = new LinkedHashMap(); - - public ServletRegister() { - } - - public void addServlet(String mapping, Servlet servlet){ - if (servlets.containsKey(mapping)) { - throw new IllegalArgumentException("The same mapping already exist! --[mapping="+mapping+"]"); - } - servlets.put(mapping, servlet); - } - - @Override - public void contextInitialized(ServletContextEvent event) { - ServletContext servletContext = event.getServletContext(); - int i=1; - for (Entry entry : servlets.entrySet()) { - ServletRegistration.Dynamic serviceDispatcherServlet = servletContext.addServlet("servlet-" + i, entry.getValue()); - serviceDispatcherServlet.addMapping(entry.getKey()); - serviceDispatcherServlet.setLoadOnStartup(1); - serviceDispatcherServlet.setAsyncSupported(true); - i++; - } - } - - @Override - public void contextDestroyed(ServletContextEvent sce) { - } - -} +package com.jd.blockchain.utils.test; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; + +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.ServletRegistration; + +public class ServletRegister implements ServletContextListener { + + private Map servlets = new LinkedHashMap(); + + public ServletRegister() { + } + + public void addServlet(String mapping, Servlet servlet){ + if (servlets.containsKey(mapping)) { + throw new IllegalArgumentException("The same mapping already exist! --[mapping="+mapping+"]"); + } + servlets.put(mapping, servlet); + } + + @Override + public void contextInitialized(ServletContextEvent event) { + ServletContext servletContext = event.getServletContext(); + int i=1; + for (Entry entry : servlets.entrySet()) { + ServletRegistration.Dynamic serviceDispatcherServlet = servletContext.addServlet("servlet-" + i, entry.getValue()); + serviceDispatcherServlet.addMapping(entry.getKey()); + serviceDispatcherServlet.setLoadOnStartup(1); + serviceDispatcherServlet.setAsyncSupported(true); + i++; + } + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + } + +} diff --git a/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/WebBoot.java b/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/WebBoot.java index 4068e561..ab61908e 100644 --- a/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/WebBoot.java +++ b/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/WebBoot.java @@ -1,122 +1,122 @@ -package com.jd.blockchain.utils.test; - -import java.net.InetSocketAddress; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.servlet.ServletContextListener; - -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.session.SessionHandler; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class WebBoot { - - private static final Logger LOGGER = LoggerFactory.getLogger(WebBoot.class); - - private static final AtomicInteger PORT_POOL; - - static { - int seed = 10000; - int time = (int) (System.nanoTime() & 0xFFF); - PORT_POOL = new AtomicInteger(seed + time); - } - - private Server server; - - private InetSocketAddress hostAddr; - - public int getPort() { - return hostAddr.getPort(); - } - - public WebBoot(InetSocketAddress hostAddr) { - this(hostAddr, null); - } - - public WebBoot(InetSocketAddress hostAddr, ServletContextListener contextListener) { - this.server = new Server(hostAddr); - this.hostAddr = hostAddr; - init(contextListener); - } - - /** - * 以本地IP和随机端口创建服务器; - */ - public WebBoot() { - this(new InetSocketAddress(PORT_POOL.getAndIncrement()), null); - } - - /** - * 以本地IP和随机端口创建服务器; - */ - public WebBoot(ServletContextListener contextListener) { - this(new InetSocketAddress(PORT_POOL.getAndIncrement()), contextListener); - } - - public static WebBoot startWithRandomPort(ServletContextListener contextListener) { - WebBoot server = null; - RuntimeException error = null; - for (int i = 0; i < 100; i++) { - WebBoot serverTemp = new WebBoot(contextListener); - try { - serverTemp.start(); - server = serverTemp; - break; - } catch (RuntimeException e) { - // retry; - error = e; - LOGGER.warn("Server starting exception! And retry again! --[" + e.getClass().toGenericString() + "] " - + e.getMessage()); - } - } - if (server != null) { - return server; - } - throw error; - } - - public WebBoot(int port) { - this(new InetSocketAddress(port), null); - } - - public WebBoot(int port, ServletContextListener contextListener) { - this(new InetSocketAddress(port), contextListener); - } - - public WebBoot(String host, int port, ServletContextListener contextListener) { - this(host == null ? new InetSocketAddress(port) : new InetSocketAddress(host, port), contextListener); - } - - private void init(ServletContextListener contextListener) { - ServletContextHandler contextHandler = new ServletContextHandler(); - contextHandler.addEventListener(contextListener); - - // Create the SessionHandler (wrapper) to handle the sessions -// HashSessionManager manager = new HashSessionManager(); -// SessionHandler sessions = new SessionHandler(manager); - SessionHandler sessions = new SessionHandler(); - contextHandler.setHandler(sessions); - - server.setHandler(contextHandler); - } - - public void start() { - try { - server.start(); - } catch (Exception e) { - LOGGER.error("Server start error! ---[" + e.getClass().toString() + "] " + e.getMessage()); - throw new RuntimeException(e.getMessage(), e); - } - } - - public void stop() { - try { - server.stop(); - } catch (Exception e) { - LOGGER.error("Server stop error! ---[" + e.getClass().toString() + "] " + e.getMessage()); - throw new RuntimeException(e.getMessage(), e); - } - } -} +package com.jd.blockchain.utils.test; + +import java.net.InetSocketAddress; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.servlet.ServletContextListener; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.session.SessionHandler; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class WebBoot { + + private static final Logger LOGGER = LoggerFactory.getLogger(WebBoot.class); + + private static final AtomicInteger PORT_POOL; + + static { + int seed = 10000; + int time = (int) (System.nanoTime() & 0xFFF); + PORT_POOL = new AtomicInteger(seed + time); + } + + private Server server; + + private InetSocketAddress hostAddr; + + public int getPort() { + return hostAddr.getPort(); + } + + public WebBoot(InetSocketAddress hostAddr) { + this(hostAddr, null); + } + + public WebBoot(InetSocketAddress hostAddr, ServletContextListener contextListener) { + this.server = new Server(hostAddr); + this.hostAddr = hostAddr; + init(contextListener); + } + + /** + * 以本地IP和随机端口创建服务器; + */ + public WebBoot() { + this(new InetSocketAddress(PORT_POOL.getAndIncrement()), null); + } + + /** + * 以本地IP和随机端口创建服务器; + */ + public WebBoot(ServletContextListener contextListener) { + this(new InetSocketAddress(PORT_POOL.getAndIncrement()), contextListener); + } + + public static WebBoot startWithRandomPort(ServletContextListener contextListener) { + WebBoot server = null; + RuntimeException error = null; + for (int i = 0; i < 100; i++) { + WebBoot serverTemp = new WebBoot(contextListener); + try { + serverTemp.start(); + server = serverTemp; + break; + } catch (RuntimeException e) { + // retry; + error = e; + LOGGER.warn("Server starting exception! And retry again! --[" + e.getClass().toGenericString() + "] " + + e.getMessage()); + } + } + if (server != null) { + return server; + } + throw error; + } + + public WebBoot(int port) { + this(new InetSocketAddress(port), null); + } + + public WebBoot(int port, ServletContextListener contextListener) { + this(new InetSocketAddress(port), contextListener); + } + + public WebBoot(String host, int port, ServletContextListener contextListener) { + this(host == null ? new InetSocketAddress(port) : new InetSocketAddress(host, port), contextListener); + } + + private void init(ServletContextListener contextListener) { + ServletContextHandler contextHandler = new ServletContextHandler(); + contextHandler.addEventListener(contextListener); + + // Create the SessionHandler (wrapper) to handle the sessions +// HashSessionManager manager = new HashSessionManager(); +// SessionHandler sessions = new SessionHandler(manager); + SessionHandler sessions = new SessionHandler(); + contextHandler.setHandler(sessions); + + server.setHandler(contextHandler); + } + + public void start() { + try { + server.start(); + } catch (Exception e) { + LOGGER.error("Server start error! ---[" + e.getClass().toString() + "] " + e.getMessage()); + throw new RuntimeException(e.getMessage(), e); + } + } + + public void stop() { + try { + server.stop(); + } catch (Exception e) { + LOGGER.error("Server stop error! ---[" + e.getClass().toString() + "] " + e.getMessage()); + throw new RuntimeException(e.getMessage(), e); + } + } +} diff --git a/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/WebTest.java b/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/WebTest.java index d2a917a8..9eb48d9b 100644 --- a/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/WebTest.java +++ b/source/utils/utils-test/src/main/java/com/jd/blockchain/utils/test/WebTest.java @@ -1,57 +1,57 @@ -package com.jd.blockchain.utils.test; - -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; - -@RunWith(SpringJUnit4ClassRunner.class) -@WebAppConfiguration -public class WebTest { - - protected static WebBoot server; - - @Autowired - protected WebApplicationContext wac; - - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - WebBoot booter = server; - server = null; - if (booter != null) { - booter.stop(); - } - } - - @Before - public void setUp() throws Exception { - // 启动 JETTY; - if (server == null) { - ServletRegister servletRegister = new ServletRegister(); - DispatcherServlet dispachterServlet = new DispatcherServlet(wac); - servletRegister.addServlet("/service/*", dispachterServlet); - WebBoot booter = WebBoot.startWithRandomPort(servletRegister); - - server = booter; - afterWebStarted(booter.getPort()); - } - } - - protected void afterWebStarted(int port){ - } - - @After - public void tearDown() throws Exception { - } -} +package com.jd.blockchain.utils.test; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.DispatcherServlet; + +@RunWith(SpringJUnit4ClassRunner.class) +@WebAppConfiguration +public class WebTest { + + protected static WebBoot server; + + @Autowired + protected WebApplicationContext wac; + + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + WebBoot booter = server; + server = null; + if (booter != null) { + booter.stop(); + } + } + + @Before + public void setUp() throws Exception { + // 启动 JETTY; + if (server == null) { + ServletRegister servletRegister = new ServletRegister(); + DispatcherServlet dispachterServlet = new DispatcherServlet(wac); + servletRegister.addServlet("/service/*", dispachterServlet); + WebBoot booter = WebBoot.startWithRandomPort(servletRegister); + + server = booter; + afterWebStarted(booter.getPort()); + } + } + + protected void afterWebStarted(int port){ + } + + @After + public void tearDown() throws Exception { + } +} diff --git a/source/utils/utils-web-server/.gitignore b/source/utils/utils-web-server/.gitignore index 24d64373..b83d2226 100644 --- a/source/utils/utils-web-server/.gitignore +++ b/source/utils/utils-web-server/.gitignore @@ -1 +1 @@ -/target/ +/target/ diff --git a/source/utils/utils-web-server/pom.xml b/source/utils/utils-web-server/pom.xml index 109fd82e..aa32a705 100644 --- a/source/utils/utils-web-server/pom.xml +++ b/source/utils/utils-web-server/pom.xml @@ -1,34 +1,34 @@ - - 4.0.0 - - com.jd.blockchain - utils - 1.1.2.RELEASE - - utils-web-server - - - - org.eclipse.jetty - jetty-server - - - org.eclipse.jetty - jetty-servlet - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - true - - - - + + 4.0.0 + + com.jd.blockchain + utils + 1.1.2.RELEASE + + utils-web-server + + + + org.eclipse.jetty + jetty-server + + + org.eclipse.jetty + jetty-servlet + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + true + + + + \ No newline at end of file diff --git a/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/ServletSetting.java b/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/ServletSetting.java index 68436162..7b3aa74c 100644 --- a/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/ServletSetting.java +++ b/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/ServletSetting.java @@ -1,40 +1,40 @@ -package com.jd.blockchain.utils.web.server; - -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; - -public class ServletSetting { - - private Set mappings = new LinkedHashSet(); - - private Integer loadOnStartup; - - private Boolean asyncSupported; - - - public Set getMappings() { - return Collections.unmodifiableSet(mappings); - } - - public void addMapping(String mapping) { - this.mappings.add(mapping); - } - - public Integer getLoadOnStartup() { - return loadOnStartup; - } - - public void setLoadOnStartup(Integer loadOnStartup) { - this.loadOnStartup = loadOnStartup; - } - - public Boolean getAsyncSupported() { - return asyncSupported; - } - - public void setAsyncSupported(Boolean asyncSupported) { - this.asyncSupported = asyncSupported; - } - -} +package com.jd.blockchain.utils.web.server; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +public class ServletSetting { + + private Set mappings = new LinkedHashSet(); + + private Integer loadOnStartup; + + private Boolean asyncSupported; + + + public Set getMappings() { + return Collections.unmodifiableSet(mappings); + } + + public void addMapping(String mapping) { + this.mappings.add(mapping); + } + + public Integer getLoadOnStartup() { + return loadOnStartup; + } + + public void setLoadOnStartup(Integer loadOnStartup) { + this.loadOnStartup = loadOnStartup; + } + + public Boolean getAsyncSupported() { + return asyncSupported; + } + + public void setAsyncSupported(Boolean asyncSupported) { + this.asyncSupported = asyncSupported; + } + +} diff --git a/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServer.java b/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServer.java index 908d2b82..9da5d7bc 100644 --- a/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServer.java +++ b/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServer.java @@ -1,254 +1,254 @@ -package com.jd.blockchain.utils.web.server; - -import java.io.File; -import java.net.InetSocketAddress; - -import javax.servlet.ServletContextAttributeListener; -import javax.servlet.ServletContextListener; -import javax.servlet.ServletRequestAttributeListener; -import javax.servlet.ServletRequestListener; -import javax.servlet.http.HttpServlet; - -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.session.SessionHandler; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.servlet.ServletMapping; -//import org.eclipse.jetty.util.resource.EmptyResource; -import org.eclipse.jetty.util.resource.EmptyResource; - -/** - * WebServer 实现为一个可以通过内嵌方式启动的 web 容器; - * - * @author haiq - * - */ -public class WebServer { - private Server server; - - - protected String resourceRootDir; - - private ServletContextHandler contextHandler; - -// private ServletRegisterManager servletRegisterManager = new ServletRegisterManager(); - - /** - * 创建一个 WebServer 实例; - * - * @param hostAddress - * @param resourceRootDir - * 资源根目录; - */ - public WebServer(InetSocketAddress hostAddress, String resourceRootDir) { - this.resourceRootDir = resourceRootDir; - this.server = new Server(hostAddress); - init(); - } - - /** - * 创建一个 WebServer 实例; - * - * @param host - * 主机地址; - * @param port - * 端口; - * @param resourceRootDir - * 资源根目录; - */ - public WebServer(String host, int port, String resourceRootDir) { - this(new InetSocketAddress(host, port), resourceRootDir); - } - - - /** - * 创建一个 WebServer 实例; - * - * @param port - * 端口 - */ - public WebServer(String host, int port) { - this(new InetSocketAddress(host, port), null); - } - - /** - * 创建一个 WebServer 实例; - * - * @param port - * 端口 - * @param resourceRootDir - * 资源根目录; - */ - public WebServer(int port, String resourceRootDir) { - this(new InetSocketAddress(port), resourceRootDir); - } - - - /** - * 创建一个 WebServer 实例; - * - * @param port - * 端口 - */ - public WebServer(int port) { - this(new InetSocketAddress(port), null); - } - - public void setContextPath(String contextPath){ - this.contextHandler.setContextPath(contextPath); - } - - private void init() { - contextHandler = new ServletContextHandler(); - - if (resourceRootDir != null) { - File resRootDir = new File(resourceRootDir); - if (!resRootDir.isDirectory()) { - throw new IllegalArgumentException( - "The path specified as the resource root directory does not exist or isn't a directory!"); - } - contextHandler.setResourceBase(resourceRootDir); - }else{ - contextHandler.setBaseResource(EmptyResource.INSTANCE); - } - - server.setHandler(contextHandler); - } - - /** - * 增加 ServletContextListener; - * - * @param listener - */ - public void addListener(ServletContextListener listener) { - contextHandler.addEventListener(listener); - } - - /** - * 增加 ServletContextAttributeListener; - * - * @param listener - */ - public void addListener(ServletContextAttributeListener listener) { - contextHandler.addEventListener(listener); - } - - /** - * 增加 ServletRequestListener; - * - * @param listener - */ - public void addListener(ServletRequestListener listener) { - contextHandler.addEventListener(listener); - } - - /** - * 增加 ServletRequestListener; - * - * @param listener - */ - public void addListener(ServletRequestAttributeListener listener) { - contextHandler.addEventListener(listener); - } - - /** - * 注册 Servlet; - * - * @param name - * @param servlet - * @param mapping - */ -// public void registServlet(String name, HttpServlet servlet, String mapping) { -// ServletSetting setting = new ServletSetting(); -// setting.addMapping(mapping); -// registServlet(name, servlet, setting); -// } - - public void registServlet(String name, HttpServlet servlet, String... mappings) { - ServletHolder servletHolder = new ServletHolder(name, servlet); - contextHandler.getServletHandler().addServlet(servletHolder); - ServletMapping servletMapping = new ServletMapping(); - servletMapping.setServletName(name); - servletMapping.setPathSpecs(mappings); - - contextHandler.getServletHandler().addServletMapping(servletMapping); -// for (String mapping : setting.getMappings()) { -// contextHandler.addServlet(servletHolder, mapping); -// } - } - - public void start() { - try { - server.start(); - } catch (Exception e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - public void stop() { - try { - server.stop(); - } catch (Exception e) { - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } - throw new RuntimeException(e.getMessage(), e); - } - } - -// private static class ServletRegisterManager implements ServletContextListener { -// private Map servletRegisterMap = new LinkedHashMap(); -// -// public void register(String name, Servlet servlet, ServletSetting setting) { -// servletRegisterMap.put(name, new ServletRegisterInfo(name, servlet, setting)); -// } -// -// @Override -// public void contextInitialized(ServletContextEvent sce) { -// ServletContext context = sce.getServletContext(); -// for (ServletRegisterInfo regInfo : servletRegisterMap.values()) { -// ServletRegistration.Dynamic registration = context.addServlet(regInfo.getName(), regInfo.getServlet()); -// registration.addMapping(regInfo.getSetting().getMappings().toArray(new String[0])); -// if (regInfo.getSetting().getLoadOnStartup() != null) { -// registration.setLoadOnStartup(regInfo.getSetting().getLoadOnStartup()); -// } -// if (regInfo.getSetting().getAsyncSupported() != null) { -// registration.setAsyncSupported(regInfo.getSetting().getAsyncSupported()); -// } -// } -// } -// -// @Override -// public void contextDestroyed(ServletContextEvent sce) { -// } -// -// } - -// private static class ServletRegisterInfo { -// -// private String name; -// -// private Servlet servlet; -// -// private ServletSetting setting; -// -// public ServletRegisterInfo(String name, Servlet servlet, ServletSetting setting) { -// this.name = name; -// this.servlet = servlet; -// this.setting = setting; -// } -// -// public String getName() { -// return name; -// } -// -// public Servlet getServlet() { -// return servlet; -// } -// -// public ServletSetting getSetting() { -// return setting; -// } -// -// } -} +package com.jd.blockchain.utils.web.server; + +import java.io.File; +import java.net.InetSocketAddress; + +import javax.servlet.ServletContextAttributeListener; +import javax.servlet.ServletContextListener; +import javax.servlet.ServletRequestAttributeListener; +import javax.servlet.ServletRequestListener; +import javax.servlet.http.HttpServlet; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.session.SessionHandler; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.servlet.ServletMapping; +//import org.eclipse.jetty.util.resource.EmptyResource; +import org.eclipse.jetty.util.resource.EmptyResource; + +/** + * WebServer 实现为一个可以通过内嵌方式启动的 web 容器; + * + * @author haiq + * + */ +public class WebServer { + private Server server; + + + protected String resourceRootDir; + + private ServletContextHandler contextHandler; + +// private ServletRegisterManager servletRegisterManager = new ServletRegisterManager(); + + /** + * 创建一个 WebServer 实例; + * + * @param hostAddress + * @param resourceRootDir + * 资源根目录; + */ + public WebServer(InetSocketAddress hostAddress, String resourceRootDir) { + this.resourceRootDir = resourceRootDir; + this.server = new Server(hostAddress); + init(); + } + + /** + * 创建一个 WebServer 实例; + * + * @param host + * 主机地址; + * @param port + * 端口; + * @param resourceRootDir + * 资源根目录; + */ + public WebServer(String host, int port, String resourceRootDir) { + this(new InetSocketAddress(host, port), resourceRootDir); + } + + + /** + * 创建一个 WebServer 实例; + * + * @param port + * 端口 + */ + public WebServer(String host, int port) { + this(new InetSocketAddress(host, port), null); + } + + /** + * 创建一个 WebServer 实例; + * + * @param port + * 端口 + * @param resourceRootDir + * 资源根目录; + */ + public WebServer(int port, String resourceRootDir) { + this(new InetSocketAddress(port), resourceRootDir); + } + + + /** + * 创建一个 WebServer 实例; + * + * @param port + * 端口 + */ + public WebServer(int port) { + this(new InetSocketAddress(port), null); + } + + public void setContextPath(String contextPath){ + this.contextHandler.setContextPath(contextPath); + } + + private void init() { + contextHandler = new ServletContextHandler(); + + if (resourceRootDir != null) { + File resRootDir = new File(resourceRootDir); + if (!resRootDir.isDirectory()) { + throw new IllegalArgumentException( + "The path specified as the resource root directory does not exist or isn't a directory!"); + } + contextHandler.setResourceBase(resourceRootDir); + }else{ + contextHandler.setBaseResource(EmptyResource.INSTANCE); + } + + server.setHandler(contextHandler); + } + + /** + * 增加 ServletContextListener; + * + * @param listener + */ + public void addListener(ServletContextListener listener) { + contextHandler.addEventListener(listener); + } + + /** + * 增加 ServletContextAttributeListener; + * + * @param listener + */ + public void addListener(ServletContextAttributeListener listener) { + contextHandler.addEventListener(listener); + } + + /** + * 增加 ServletRequestListener; + * + * @param listener + */ + public void addListener(ServletRequestListener listener) { + contextHandler.addEventListener(listener); + } + + /** + * 增加 ServletRequestListener; + * + * @param listener + */ + public void addListener(ServletRequestAttributeListener listener) { + contextHandler.addEventListener(listener); + } + + /** + * 注册 Servlet; + * + * @param name + * @param servlet + * @param mapping + */ +// public void registServlet(String name, HttpServlet servlet, String mapping) { +// ServletSetting setting = new ServletSetting(); +// setting.addMapping(mapping); +// registServlet(name, servlet, setting); +// } + + public void registServlet(String name, HttpServlet servlet, String... mappings) { + ServletHolder servletHolder = new ServletHolder(name, servlet); + contextHandler.getServletHandler().addServlet(servletHolder); + ServletMapping servletMapping = new ServletMapping(); + servletMapping.setServletName(name); + servletMapping.setPathSpecs(mappings); + + contextHandler.getServletHandler().addServletMapping(servletMapping); +// for (String mapping : setting.getMappings()) { +// contextHandler.addServlet(servletHolder, mapping); +// } + } + + public void start() { + try { + server.start(); + } catch (Exception e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public void stop() { + try { + server.stop(); + } catch (Exception e) { + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + throw new RuntimeException(e.getMessage(), e); + } + } + +// private static class ServletRegisterManager implements ServletContextListener { +// private Map servletRegisterMap = new LinkedHashMap(); +// +// public void register(String name, Servlet servlet, ServletSetting setting) { +// servletRegisterMap.put(name, new ServletRegisterInfo(name, servlet, setting)); +// } +// +// @Override +// public void contextInitialized(ServletContextEvent sce) { +// ServletContext context = sce.getServletContext(); +// for (ServletRegisterInfo regInfo : servletRegisterMap.values()) { +// ServletRegistration.Dynamic registration = context.addServlet(regInfo.getName(), regInfo.getServlet()); +// registration.addMapping(regInfo.getSetting().getMappings().toArray(new String[0])); +// if (regInfo.getSetting().getLoadOnStartup() != null) { +// registration.setLoadOnStartup(regInfo.getSetting().getLoadOnStartup()); +// } +// if (regInfo.getSetting().getAsyncSupported() != null) { +// registration.setAsyncSupported(regInfo.getSetting().getAsyncSupported()); +// } +// } +// } +// +// @Override +// public void contextDestroyed(ServletContextEvent sce) { +// } +// +// } + +// private static class ServletRegisterInfo { +// +// private String name; +// +// private Servlet servlet; +// +// private ServletSetting setting; +// +// public ServletRegisterInfo(String name, Servlet servlet, ServletSetting setting) { +// this.name = name; +// this.servlet = servlet; +// this.setting = setting; +// } +// +// public String getName() { +// return name; +// } +// +// public Servlet getServlet() { +// return servlet; +// } +// +// public ServletSetting getSetting() { +// return setting; +// } +// +// } +} diff --git a/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServerDemo.java b/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServerDemo.java index 078aae55..afad2241 100644 --- a/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServerDemo.java +++ b/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServerDemo.java @@ -1,61 +1,61 @@ -package com.jd.blockchain.utils.web.server; - -import java.io.File; -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -public class WebServerDemo { - - public static void main(String[] args) { - WebServer server = new WebServer("127.0.0.1", 8899, new File("./").getAbsolutePath()); - server.setContextPath("/test"); - - server.registServlet("ts", new TestServlet(), "/a"); - -// server.addListener(new ServletContextListener() { -// @Override -// public void contextInitialized(ServletContextEvent sce) { -// ServletRegistration.Dynamic registration = sce.getServletContext().addServlet("ts", new TestServlet()); -// registration.addMapping("/a"); -// registration.setAsyncSupported(true); -// registration.setLoadOnStartup(1);; -// } -// -// @Override -// public void contextDestroyed(ServletContextEvent sce) { -// } -// }); - - server.start(); - } - - - private static class TestServlet extends HttpServlet{ - - private static final long serialVersionUID = 6723790617689867229L; - - @Override - protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - System.out.println("service..."); - super.service(req, resp); - } - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - System.out.println("do get..."); - resp.getWriter().write("test response "+ System.currentTimeMillis()); - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - System.out.println("do post..."); - resp.getWriter().write("test response "+ System.currentTimeMillis()); - } - - } - -} +package com.jd.blockchain.utils.web.server; + +import java.io.File; +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +public class WebServerDemo { + + public static void main(String[] args) { + WebServer server = new WebServer("127.0.0.1", 8899, new File("./").getAbsolutePath()); + server.setContextPath("/test"); + + server.registServlet("ts", new TestServlet(), "/a"); + +// server.addListener(new ServletContextListener() { +// @Override +// public void contextInitialized(ServletContextEvent sce) { +// ServletRegistration.Dynamic registration = sce.getServletContext().addServlet("ts", new TestServlet()); +// registration.addMapping("/a"); +// registration.setAsyncSupported(true); +// registration.setLoadOnStartup(1);; +// } +// +// @Override +// public void contextDestroyed(ServletContextEvent sce) { +// } +// }); + + server.start(); + } + + + private static class TestServlet extends HttpServlet{ + + private static final long serialVersionUID = 6723790617689867229L; + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + System.out.println("service..."); + super.service(req, resp); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + System.out.println("do get..."); + resp.getWriter().write("test response "+ System.currentTimeMillis()); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + System.out.println("do post..."); + resp.getWriter().write("test response "+ System.currentTimeMillis()); + } + + } + +} diff --git a/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServerException.java b/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServerException.java index a0f432f5..e51fa2a3 100644 --- a/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServerException.java +++ b/source/utils/utils-web-server/src/main/java/com/jd/blockchain/utils/web/server/WebServerException.java @@ -1,18 +1,18 @@ -package com.jd.blockchain.utils.web.server; - -public class WebServerException extends RuntimeException{ - - private static final long serialVersionUID = -9177534295689026560L; - - public WebServerException() { - } - - public WebServerException(String message) { - super(message); - } - - public WebServerException(String message, Throwable cause) { - super(message, cause); - } - -} +package com.jd.blockchain.utils.web.server; + +public class WebServerException extends RuntimeException{ + + private static final long serialVersionUID = -9177534295689026560L; + + public WebServerException() { + } + + public WebServerException(String message) { + super(message); + } + + public WebServerException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/source/utils/utils-web/.gitignore b/source/utils/utils-web/.gitignore index 24d64373..b83d2226 100644 --- a/source/utils/utils-web/.gitignore +++ b/source/utils/utils-web/.gitignore @@ -1 +1 @@ -/target/ +/target/ diff --git a/source/utils/utils-web/pom.xml b/source/utils/utils-web/pom.xml index b635dfb0..964451f3 100644 --- a/source/utils/utils-web/pom.xml +++ b/source/utils/utils-web/pom.xml @@ -1,25 +1,25 @@ - - 4.0.0 - - com.jd.blockchain - utils - 1.1.2.RELEASE - - utils-web - - - com.jd.blockchain - utils-http - ${project.version} - - - org.springframework - spring-web - - - com.alibaba - fastjson - - + + 4.0.0 + + com.jd.blockchain + utils + 1.1.2.RELEASE + + utils-web + + + com.jd.blockchain + utils-http + ${project.version} + + + org.springframework + spring-web + + + com.alibaba + fastjson + + \ No newline at end of file diff --git a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebResponseConverter.java b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebResponseConverter.java index 3b45fc58..e4940337 100644 --- a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebResponseConverter.java +++ b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebResponseConverter.java @@ -1,73 +1,73 @@ -package com.jd.blockchain.utils.web.client; - -import java.io.InputStream; -import java.lang.reflect.Proxy; - -import com.alibaba.fastjson.JSONObject; -import com.jd.blockchain.utils.PrimitiveUtils; -import com.jd.blockchain.utils.http.HttpServiceContext; -import com.jd.blockchain.utils.http.ResponseConverter; -import com.jd.blockchain.utils.http.agent.ServiceRequest; -import com.jd.blockchain.utils.http.converters.JsonResponseConverter; -import com.jd.blockchain.utils.http.converters.StringResponseConverter; -import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; -import com.jd.blockchain.utils.web.model.WebResponse; - -public class WebResponseConverter implements ResponseConverter { - - private JsonResponseConverter jsonConverter = new JsonResponseConverter(WebResponse.class); - - private Class dataClazz; - - public WebResponseConverter(Class dataClazz) { - this.dataClazz = dataClazz; - } - - @Override - public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) throws Exception { -// if (dataClazz.isInterface()) { -// String json = (String) StringResponseConverter.INSTANCE.getResponse(request, responseStream, null); -// if (json == null) { -// return null; -// } -// JSONObject jsonObj = JSONSerializeUtils.deserializeAs(json, JSONObject.class); -// return Proxy.newProxyInstance(dataClazz.getClassLoader(), new Class[] {dataClazz}, jsonObj); -// } - WebResponse response = (WebResponse) jsonConverter.getResponse(request, responseStream, null); - if (response == null) { - return null; - } - if (response.getError() != null) { - throw new WebServiceException(response.getError().getErrorCode(), response.getError().getErrorMessage()); - } - if (response.getData() == null) { - return null; - } - if (dataClazz.isAssignableFrom(response.getData().getClass())) { - return response.getData(); - } - if (dataClazz.isAssignableFrom(String.class)) { - return response.getData().toString(); - } - if (PrimitiveUtils.isPrimitiveType(dataClazz)) { - return PrimitiveUtils.castTo(response.getData(), dataClazz); - } - return JSONSerializeUtils.deserializeAs(response.getData(), dataClazz); -// return response.getData(); - -// JSONString jsonData = response.getData(); -// Object data = SerializeUtils.deserializeAs(jsonData, dataClazz); -// return data; - -// if (response.getData() instanceof JSONObject) { -// JSONObject jsonObj = (JSONObject) response.getData(); -// data = jsonObj.toJavaObject(dataClazz); -// }else if (response.getData() instanceof JSONArray) { -// JSONArray jsonObj = (JSONArray) response.getData(); -// data = jsonObj.toJavaObject(dataClazz); -// }else{ -// data = response.getData(); -// } -// return data; - } -} +package com.jd.blockchain.utils.web.client; + +import java.io.InputStream; +import java.lang.reflect.Proxy; + +import com.alibaba.fastjson.JSONObject; +import com.jd.blockchain.utils.PrimitiveUtils; +import com.jd.blockchain.utils.http.HttpServiceContext; +import com.jd.blockchain.utils.http.ResponseConverter; +import com.jd.blockchain.utils.http.agent.ServiceRequest; +import com.jd.blockchain.utils.http.converters.JsonResponseConverter; +import com.jd.blockchain.utils.http.converters.StringResponseConverter; +import com.jd.blockchain.utils.serialize.json.JSONSerializeUtils; +import com.jd.blockchain.utils.web.model.WebResponse; + +public class WebResponseConverter implements ResponseConverter { + + private JsonResponseConverter jsonConverter = new JsonResponseConverter(WebResponse.class); + + private Class dataClazz; + + public WebResponseConverter(Class dataClazz) { + this.dataClazz = dataClazz; + } + + @Override + public Object getResponse(ServiceRequest request, InputStream responseStream, HttpServiceContext serviceContext) throws Exception { +// if (dataClazz.isInterface()) { +// String json = (String) StringResponseConverter.INSTANCE.getResponse(request, responseStream, null); +// if (json == null) { +// return null; +// } +// JSONObject jsonObj = JSONSerializeUtils.deserializeAs(json, JSONObject.class); +// return Proxy.newProxyInstance(dataClazz.getClassLoader(), new Class[] {dataClazz}, jsonObj); +// } + WebResponse response = (WebResponse) jsonConverter.getResponse(request, responseStream, null); + if (response == null) { + return null; + } + if (response.getError() != null) { + throw new WebServiceException(response.getError().getErrorCode(), response.getError().getErrorMessage()); + } + if (response.getData() == null) { + return null; + } + if (dataClazz.isAssignableFrom(response.getData().getClass())) { + return response.getData(); + } + if (dataClazz.isAssignableFrom(String.class)) { + return response.getData().toString(); + } + if (PrimitiveUtils.isPrimitiveType(dataClazz)) { + return PrimitiveUtils.castTo(response.getData(), dataClazz); + } + return JSONSerializeUtils.deserializeAs(response.getData(), dataClazz); +// return response.getData(); + +// JSONString jsonData = response.getData(); +// Object data = SerializeUtils.deserializeAs(jsonData, dataClazz); +// return data; + +// if (response.getData() instanceof JSONObject) { +// JSONObject jsonObj = (JSONObject) response.getData(); +// data = jsonObj.toJavaObject(dataClazz); +// }else if (response.getData() instanceof JSONArray) { +// JSONArray jsonObj = (JSONArray) response.getData(); +// data = jsonObj.toJavaObject(dataClazz); +// }else{ +// data = response.getData(); +// } +// return data; + } +} diff --git a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebResponseConverterFactory.java b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebResponseConverterFactory.java index 932622d3..4d0d770d 100644 --- a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebResponseConverterFactory.java +++ b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebResponseConverterFactory.java @@ -1,16 +1,16 @@ -package com.jd.blockchain.utils.web.client; - -import java.lang.reflect.Method; - -import com.jd.blockchain.utils.http.HttpAction; -import com.jd.blockchain.utils.http.ResponseBodyConverterFactory; -import com.jd.blockchain.utils.http.ResponseConverter; - -public class WebResponseConverterFactory implements ResponseBodyConverterFactory{ - - @Override - public ResponseConverter createResponseConverter(HttpAction actionDef, Method mth) { - return new WebResponseConverter(mth.getReturnType()); - } - -} +package com.jd.blockchain.utils.web.client; + +import java.lang.reflect.Method; + +import com.jd.blockchain.utils.http.HttpAction; +import com.jd.blockchain.utils.http.ResponseBodyConverterFactory; +import com.jd.blockchain.utils.http.ResponseConverter; + +public class WebResponseConverterFactory implements ResponseBodyConverterFactory{ + + @Override + public ResponseConverter createResponseConverter(HttpAction actionDef, Method mth) { + return new WebResponseConverter(mth.getReturnType()); + } + +} diff --git a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebServiceException.java b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebServiceException.java index 9a5d83b0..9fc54420 100644 --- a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebServiceException.java +++ b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/client/WebServiceException.java @@ -1,33 +1,33 @@ -package com.jd.blockchain.utils.web.client; - -import com.jd.blockchain.utils.http.HttpServiceException; - -public class WebServiceException extends HttpServiceException { - - private static final long serialVersionUID = -4869903115201215122L; - - private int errorCode; - - public int getErrorCode() { - return errorCode; - } - - public WebServiceException() { - } - - public WebServiceException(int errorCode) { - super("Error code[" + errorCode + "]!"); - this.errorCode = errorCode; - } - - public WebServiceException(int errorCode, String message) { - super(message); - this.errorCode = errorCode; - } - - public WebServiceException(int errorCode, String message, Throwable cause) { - super(message, cause); - this.errorCode = errorCode; - } - -} +package com.jd.blockchain.utils.web.client; + +import com.jd.blockchain.utils.http.HttpServiceException; + +public class WebServiceException extends HttpServiceException { + + private static final long serialVersionUID = -4869903115201215122L; + + private int errorCode; + + public int getErrorCode() { + return errorCode; + } + + public WebServiceException() { + } + + public WebServiceException(int errorCode) { + super("Error code[" + errorCode + "]!"); + this.errorCode = errorCode; + } + + public WebServiceException(int errorCode, String message) { + super(message); + this.errorCode = errorCode; + } + + public WebServiceException(int errorCode, String message, Throwable cause) { + super(message, cause); + this.errorCode = errorCode; + } + +} diff --git a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/BinaryMessageConverter.java b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/BinaryMessageConverter.java index 108c481b..dd501708 100644 --- a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/BinaryMessageConverter.java +++ b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/BinaryMessageConverter.java @@ -1,61 +1,61 @@ -package com.jd.blockchain.utils.web.model; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.Serializable; -import java.util.Collections; -import java.util.List; - -import org.springframework.http.HttpInputMessage; -import org.springframework.http.HttpOutputMessage; -import org.springframework.http.MediaType; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.http.converter.HttpMessageNotWritableException; - -import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; - -/** - * 针对二进制对象的序列化和反序列化的 HTTP 消息转换器; - * - * @author huanghaiquan - * - */ -public class BinaryMessageConverter implements HttpMessageConverter { - - public static final String CONTENT_TYPE_VALUE = "application/bin-obj"; - - public static final MediaType CONTENT_TYPE = MediaType.valueOf(CONTENT_TYPE_VALUE); - - private static final List SUPPORTED_MEDIA_TYPES = Collections.singletonList(CONTENT_TYPE); - - @Override - public boolean canRead(Class clazz, MediaType mediaType) { - return CONTENT_TYPE.includes(mediaType) - && (clazz.isPrimitive() || Serializable.class.isAssignableFrom(clazz) || Externalizable.class.isAssignableFrom(clazz)); - } - - @Override - public boolean canWrite(Class clazz, MediaType mediaType) { - return CONTENT_TYPE.includes(mediaType) - && (clazz.isPrimitive() || Serializable.class.isAssignableFrom(clazz) || Externalizable.class.isAssignableFrom(clazz)); - } - - @Override - public List getSupportedMediaTypes() { - return SUPPORTED_MEDIA_TYPES; - } - - @Override - public Object read(Class clazz, HttpInputMessage inputMessage) - throws IOException, HttpMessageNotReadableException { - return BinarySerializeUtils.deserialize(inputMessage.getBody()); - } - - @Override - public void write(Object t, MediaType contentType, HttpOutputMessage outputMessage) - throws IOException, HttpMessageNotWritableException { - BinarySerializeUtils.serialize(t, outputMessage.getBody()); - } - -} +package com.jd.blockchain.utils.web.model; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.Serializable; +import java.util.Collections; +import java.util.List; + +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; + +import com.jd.blockchain.utils.serialize.binary.BinarySerializeUtils; + +/** + * 针对二进制对象的序列化和反序列化的 HTTP 消息转换器; + * + * @author huanghaiquan + * + */ +public class BinaryMessageConverter implements HttpMessageConverter { + + public static final String CONTENT_TYPE_VALUE = "application/bin-obj"; + + public static final MediaType CONTENT_TYPE = MediaType.valueOf(CONTENT_TYPE_VALUE); + + private static final List SUPPORTED_MEDIA_TYPES = Collections.singletonList(CONTENT_TYPE); + + @Override + public boolean canRead(Class clazz, MediaType mediaType) { + return CONTENT_TYPE.includes(mediaType) + && (clazz.isPrimitive() || Serializable.class.isAssignableFrom(clazz) || Externalizable.class.isAssignableFrom(clazz)); + } + + @Override + public boolean canWrite(Class clazz, MediaType mediaType) { + return CONTENT_TYPE.includes(mediaType) + && (clazz.isPrimitive() || Serializable.class.isAssignableFrom(clazz) || Externalizable.class.isAssignableFrom(clazz)); + } + + @Override + public List getSupportedMediaTypes() { + return SUPPORTED_MEDIA_TYPES; + } + + @Override + public Object read(Class clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + return BinarySerializeUtils.deserialize(inputMessage.getBody()); + } + + @Override + public void write(Object t, MediaType contentType, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + BinarySerializeUtils.serialize(t, outputMessage.getBody()); + } + +} diff --git a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/ErrorCode.java b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/ErrorCode.java index 3f24b0ac..b83eb799 100644 --- a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/ErrorCode.java +++ b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/ErrorCode.java @@ -1,46 +1,46 @@ -package com.jd.blockchain.utils.web.model; - -/** - * 错误代码; - */ -public enum ErrorCode { - - /** 参数格式不正确 */ - ILLEGAL_PARAMETE(1001, "参数格式不正确![parma=%s]"), - - /** 缺少必要参数 */ - MISSING_REQUIRED_PARAMETE(1002, "缺少必要参数![param=%s]"), - - /** 没有操作权限 */ - PERFORM_FORBIDDEN(1003, "没有该操作权限!"), - - UNEXPECTED(5000, "未预期的异常!"), - - REQUEST_PARAM_FORMAT_ILLEGAL(12001, "请求体格式不正确"), - - NULL_VALUE(4001, "空值!"), - - NULL_VALUE_PARAM(4001, "参数%s不能为空值!"); - - private int value; - - private String description; - - private ErrorCode(int value, String description) { - this.value = value; - this.description = description; - } - - public int getValue() { - return value; - } - - public String getDescription() { - return description; - } - - public String getDescription(String details) { - return details == null ? description : new StringBuilder(description).append(" --").append(details).toString(); - } - +package com.jd.blockchain.utils.web.model; + +/** + * 错误代码; + */ +public enum ErrorCode { + + /** 参数格式不正确 */ + ILLEGAL_PARAMETE(1001, "参数格式不正确![parma=%s]"), + + /** 缺少必要参数 */ + MISSING_REQUIRED_PARAMETE(1002, "缺少必要参数![param=%s]"), + + /** 没有操作权限 */ + PERFORM_FORBIDDEN(1003, "没有该操作权限!"), + + UNEXPECTED(5000, "未预期的异常!"), + + REQUEST_PARAM_FORMAT_ILLEGAL(12001, "请求体格式不正确"), + + NULL_VALUE(4001, "空值!"), + + NULL_VALUE_PARAM(4001, "参数%s不能为空值!"); + + private int value; + + private String description; + + private ErrorCode(int value, String description) { + this.value = value; + this.description = description; + } + + public int getValue() { + return value; + } + + public String getDescription() { + return description; + } + + public String getDescription(String details) { + return details == null ? description : new StringBuilder(description).append(" --").append(details).toString(); + } + } \ No newline at end of file diff --git a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/JsonWebResponseMessageConverter.java b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/JsonWebResponseMessageConverter.java index c8921e1e..4791bb28 100644 --- a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/JsonWebResponseMessageConverter.java +++ b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/JsonWebResponseMessageConverter.java @@ -1,72 +1,72 @@ -package com.jd.blockchain.utils.web.model; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Proxy; - -import org.springframework.http.HttpOutputMessage; -import org.springframework.http.converter.HttpMessageNotWritableException; - -import com.alibaba.fastjson.serializer.SerializerFeature; -import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; - -public class JsonWebResponseMessageConverter extends FastJsonHttpMessageConverter{ - - public JsonWebResponseMessageConverter() { - this(false); - } - - public JsonWebResponseMessageConverter(boolean jsonPretty) { - if (jsonPretty) { - getFastJsonConfig().setSerializerFeatures(SerializerFeature.PrettyFormat); - } - } - - @Override - protected void writeInternal(Object obj, HttpOutputMessage outputMessage) - throws IOException, HttpMessageNotWritableException { - //把返回结果自动转换为 WebResponse; - if (obj instanceof WebResponse) { - super.writeInternal(obj, outputMessage); - return; - } else if (obj.getClass().isArray()) { - // 数组类型需要判断是否为代理对象 - Object[] objects = (Object[])obj; - if (objects != null && objects.length > 0) { - Object[] results = new Object[objects.length]; - for (int i = 0; i < objects.length; i++) { - Object o = objects[i]; - if (o instanceof Proxy) { - try { - results[i] = proxy2Obj(o); - } catch (Exception e) { - super.writeInternal(WebResponse.createSuccessResult(obj), outputMessage); - return; - } - } else { - results[i] = o; - } - } - super.writeInternal(WebResponse.createSuccessResult(results), outputMessage); - return; - } - } else if (obj instanceof Proxy) { - try { - Object result = proxy2Obj(obj); //获取Proxy对象进行转换 - super.writeInternal(WebResponse.createSuccessResult(result), outputMessage); - return; - } catch (Exception e) { - super.writeInternal(WebResponse.createSuccessResult(obj), outputMessage); - return; - } - } - super.writeInternal(WebResponse.createSuccessResult(obj), outputMessage); - } - - private Object proxy2Obj(Object obj) throws Exception { - Field field = obj.getClass().getSuperclass().getDeclaredField("h"); - field.setAccessible(true); - //获取指定对象中此字段的值 - return field.get(obj); //获取Proxy对象中的此字段的值 - } -} +package com.jd.blockchain.utils.web.model; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Proxy; + +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.converter.HttpMessageNotWritableException; + +import com.alibaba.fastjson.serializer.SerializerFeature; +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; + +public class JsonWebResponseMessageConverter extends FastJsonHttpMessageConverter{ + + public JsonWebResponseMessageConverter() { + this(false); + } + + public JsonWebResponseMessageConverter(boolean jsonPretty) { + if (jsonPretty) { + getFastJsonConfig().setSerializerFeatures(SerializerFeature.PrettyFormat); + } + } + + @Override + protected void writeInternal(Object obj, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + //把返回结果自动转换为 WebResponse; + if (obj instanceof WebResponse) { + super.writeInternal(obj, outputMessage); + return; + } else if (obj.getClass().isArray()) { + // 数组类型需要判断是否为代理对象 + Object[] objects = (Object[])obj; + if (objects != null && objects.length > 0) { + Object[] results = new Object[objects.length]; + for (int i = 0; i < objects.length; i++) { + Object o = objects[i]; + if (o instanceof Proxy) { + try { + results[i] = proxy2Obj(o); + } catch (Exception e) { + super.writeInternal(WebResponse.createSuccessResult(obj), outputMessage); + return; + } + } else { + results[i] = o; + } + } + super.writeInternal(WebResponse.createSuccessResult(results), outputMessage); + return; + } + } else if (obj instanceof Proxy) { + try { + Object result = proxy2Obj(obj); //获取Proxy对象进行转换 + super.writeInternal(WebResponse.createSuccessResult(result), outputMessage); + return; + } catch (Exception e) { + super.writeInternal(WebResponse.createSuccessResult(obj), outputMessage); + return; + } + } + super.writeInternal(WebResponse.createSuccessResult(obj), outputMessage); + } + + private Object proxy2Obj(Object obj) throws Exception { + Field field = obj.getClass().getSuperclass().getDeclaredField("h"); + field.setAccessible(true); + //获取指定对象中此字段的值 + return field.get(obj); //获取Proxy对象中的此字段的值 + } +} diff --git a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/WebResponse.java b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/WebResponse.java index 97eaccd9..da08493f 100644 --- a/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/WebResponse.java +++ b/source/utils/utils-web/src/main/java/com/jd/blockchain/utils/web/model/WebResponse.java @@ -1,103 +1,103 @@ -package com.jd.blockchain.utils.web.model; - -import com.jd.blockchain.utils.serialize.json.JSONString; - -public class WebResponse { - - private boolean success; - - private Object data; - - private ErrorMessage error; - - private WebResponse(){ - - } - - public boolean isSuccess() { - return success; - } - - public void setSuccess(boolean success) { - this.success = success; - } - - public Object getData() { - return data; - } - - public void setData(Object data) { - this.data = data; - } - - public ErrorMessage getError() { - return error; - } - - public void setError(ErrorMessage error) { - this.error = error; - } - - public static WebResponse createSuccessResult(Object data){ - WebResponse resonseResult = new WebResponse(); - resonseResult.setSuccess(true); -// if (data != null) { -// JSONString jsonData = JSONString.toJSONString(data); -// resonseResult.setData(jsonData); -// } - resonseResult.setData(data); - return resonseResult; - } - - public static WebResponse createFailureResult(int code, String message){ - ErrorMessage errorMessage = new ErrorMessage(code, message); - return createFailureResult(errorMessage); - } - - public static WebResponse createFailureResult(ErrorMessage errorMessage){ - WebResponse resonseResult = new WebResponse(); - resonseResult.setSuccess(false); - resonseResult.setError(errorMessage); - return resonseResult; - } - - - - /** - * 错误消息实体 - * - * @author liuxrb - * - */ - public static class ErrorMessage { - - private int errorCode; - - private String errorMessage; - - public ErrorMessage() { - - } - - public ErrorMessage(int errorCode, String errorMessage) { - this.errorCode = errorCode; - this.errorMessage = errorMessage; - } - - public int getErrorCode() { - return errorCode; - } - - public void setErrorCode(int errorCode) { - this.errorCode = errorCode; - } - - public String getErrorMessage() { - return errorMessage; - } - - public void setErrorMessage(String errorMessage) { - this.errorMessage = errorMessage; - } - } -} +package com.jd.blockchain.utils.web.model; + +import com.jd.blockchain.utils.serialize.json.JSONString; + +public class WebResponse { + + private boolean success; + + private Object data; + + private ErrorMessage error; + + private WebResponse(){ + + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + public ErrorMessage getError() { + return error; + } + + public void setError(ErrorMessage error) { + this.error = error; + } + + public static WebResponse createSuccessResult(Object data){ + WebResponse resonseResult = new WebResponse(); + resonseResult.setSuccess(true); +// if (data != null) { +// JSONString jsonData = JSONString.toJSONString(data); +// resonseResult.setData(jsonData); +// } + resonseResult.setData(data); + return resonseResult; + } + + public static WebResponse createFailureResult(int code, String message){ + ErrorMessage errorMessage = new ErrorMessage(code, message); + return createFailureResult(errorMessage); + } + + public static WebResponse createFailureResult(ErrorMessage errorMessage){ + WebResponse resonseResult = new WebResponse(); + resonseResult.setSuccess(false); + resonseResult.setError(errorMessage); + return resonseResult; + } + + + + /** + * 错误消息实体 + * + * @author liuxrb + * + */ + public static class ErrorMessage { + + private int errorCode; + + private String errorMessage; + + public ErrorMessage() { + + } + + public ErrorMessage(int errorCode, String errorMessage) { + this.errorCode = errorCode; + this.errorMessage = errorMessage; + } + + public int getErrorCode() { + return errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + } +}