From 6b86651ee731b68e8caaf304336e80abdfc3dd59 Mon Sep 17 00:00:00 2001 From: "ken.lj" Date: Tue, 17 Sep 2019 15:50:18 +0800 Subject: [PATCH] Protobuf service definition and serialization support --- .gitignore | 4 +- LICENSE | 2 +- .../.gradle/4.3/fileChanges/last-build.bin | Bin .../4.3/fileContent/annotation-processors.bin | Bin .../.gradle/4.3/fileContent/fileContent.lock | Bin .../.gradle/4.3/fileHashes/fileHashes.bin | Bin .../.gradle/4.3/fileHashes/fileHashes.lock | Bin .../4.3/fileHashes/resourceHashesCache.bin | Bin .../4.3/nativeCompile/nativeCompile.bin | Bin .../4.3/nativeCompile/nativeCompile.lock | Bin .../.gradle/4.3/taskHistory/taskHistory.bin | Bin .../.gradle/4.3/taskHistory/taskHistory.lock | Bin .../.gradle/4.9/fileChanges/last-build.bin | Bin .../4.9/fileContent/annotation-processors.bin | Bin .../.gradle/4.9/fileContent/fileContent.lock | Bin 0 -> 17 bytes .../.gradle/4.9/fileContent/parsedCSource.bin | Bin 4542342 -> 4543839 bytes .../.gradle/4.9/fileHashes/fileHashes.bin | Bin 882335 -> 883035 bytes .../.gradle/4.9/fileHashes/fileHashes.lock | Bin 0 -> 17 bytes .../4.9/fileHashes/resourceHashesCache.bin | Bin .../4.9/nativeCompile/nativeCompile.bin | Bin 50817 -> 62218 bytes .../4.9/nativeCompile/nativeCompile.lock | Bin 0 -> 17 bytes .../.gradle/4.9/taskHistory/taskHistory.bin | Bin 12054698 -> 12084605 bytes .../.gradle/4.9/taskHistory/taskHistory.lock | Bin 0 -> 17 bytes .../buildOutputCleanup.lock | Bin 0 -> 17 bytes .../buildOutputCleanup/cache.properties | 0 .../buildOutputCleanup/outputFiles.bin | Bin 57533 -> 57803 bytes .../.gradle/vcsWorkingDirs/gc.properties | 0 .../compiler => compiler}/BUILD.bazel | 0 .../compiler => compiler}/README.md | 159 ++-- .../compiler => compiler}/build.gradle | 14 +- .../compiler => compiler}/check-artifact.sh | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 0 .../compiler => compiler}/gradlew | 0 .../compiler => compiler}/gradlew.bat | 0 .../java_plugin/cpp/java_dubbo_generator.cpp | 572 ++++++++++++ .../src/java_plugin/cpp/java_generator.cpp | 186 ++-- .../src/java_plugin/cpp/java_generator.h | 21 + compiler/src/java_plugin/cpp/java_plugin.cpp | 87 ++ .../golden/TestDeprecatedService.java.txt | 0 .../src/test/golden/TestService.java.txt | 0 .../proto/grpc/testing/compiler/test.proto | 0 .../golden/TestDeprecatedService.java.txt | 0 .../src/testLite/golden/TestService.java.txt | 0 .../golden/TestDeprecatedService.java.txt | 0 .../src/testNano/golden/TestService.java.txt | 0 dubbo-all/pom.xml | 4 +- dubbo-bom/pom.xml | 2 +- .../common/protobuf/ProtobufService.java | 24 + dubbo-dependencies-bom/pom.xml | 2 +- .../src/assembly/source-release.xml | 2 +- .../exchange/codec/ExchangeCodec.java | 8 +- .../curator/CuratorZookeeperClient.java | 1 + .../protocol/dubbo/DecodeableRpcResult.java | 3 +- .../dubbo/rpc/protocol/dubbo/DubboCodec.java | 12 +- .../.gradle/4.9/fileContent/fileContent.lock | Bin 17 -> 0 bytes .../.gradle/4.9/fileHashes/fileHashes.lock | Bin 17 -> 0 bytes .../4.9/nativeCompile/nativeCompile.lock | Bin 17 -> 0 bytes .../.gradle/4.9/taskHistory/taskHistory.lock | Bin 17 -> 0 bytes .../buildOutputCleanup.lock | Bin 17 -> 0 bytes .../src/java_plugin/cpp/java_plugin.cpp | 70 -- .../dubbo/rpc/protocol/grpc/GrpcProtocol.java | 1 + .../rpc/protocol/grpc/GrpcServerUtils.java | 36 + .../dubbo/common/serialize/ObjectInput.java | 7 +- .../dubbo/common/serialize/ObjectOutput.java | 24 + .../kryo/optimized/KryoObjectInput2.java | 170 ++++ .../kryo/optimized/KryoObjectOutput2.java | 122 +++ .../kryo/optimized/KryoSerialization2.java | 58 ++ ...pache.dubbo.common.serialize.Serialization | 3 +- .../dubbo-serialization-protobuf-json/pom.xml | 47 - .../serialize/protobuf/support/MapValue.java | 830 ------------------ .../protobuf/support/ProtobufUtils.java | 61 -- ...pache.dubbo.common.serialize.Serialization | 1 - .../dubbo-serialization-protobuf/pom.xml | 105 +++ .../GenericProtobufJsonObjectInput.java} | 27 +- .../GenericProtobufJsonObjectOutput.java} | 9 +- .../GenericProtobufJsonSerialization.java} | 7 +- .../support/GenericProtobufObjectInput.java | 137 +++ .../support/GenericProtobufObjectOutput.java | 141 +++ .../support/GenericProtobufSerialization.java | 64 ++ .../protobuf/support/ProtobufUtils.java | 193 ++++ .../support/ProtobufWrappedException.java | 68 ++ .../src/main/proto/MapValue.proto | 26 + .../src/main/proto/ThrowablePB.proto | 63 ++ ...pache.dubbo.common.serialize.Serialization | 2 + .../dubbo-serialization-test/pom.xml | 2 +- .../AbstractProtobufSerializationTest.java | 360 ++++++++ ... GenericProtobufJsonObjectOutputTest.java} | 10 +- .../GenericProtobufJsonSerializationTest.java | 23 + .../GenericProtobufSerializationTest.java | 7 +- .../protobuf => proto}/GooglePB.proto | 0 dubbo-serialization/pom.xml | 2 +- 91 files changed, 2556 insertions(+), 1225 deletions(-) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.3/fileChanges/last-build.bin (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.3/fileContent/annotation-processors.bin (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.3/fileContent/fileContent.lock (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.3/fileHashes/fileHashes.bin (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.3/fileHashes/fileHashes.lock (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.3/fileHashes/resourceHashesCache.bin (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.3/nativeCompile/nativeCompile.bin (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.3/nativeCompile/nativeCompile.lock (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.3/taskHistory/taskHistory.bin (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.3/taskHistory/taskHistory.lock (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.9/fileChanges/last-build.bin (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.9/fileContent/annotation-processors.bin (100%) create mode 100644 compiler/.gradle/4.9/fileContent/fileContent.lock rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.9/fileContent/parsedCSource.bin (56%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.9/fileHashes/fileHashes.bin (98%) create mode 100644 compiler/.gradle/4.9/fileHashes/fileHashes.lock rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.9/fileHashes/resourceHashesCache.bin (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.9/nativeCompile/nativeCompile.bin (81%) create mode 100644 compiler/.gradle/4.9/nativeCompile/nativeCompile.lock rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/4.9/taskHistory/taskHistory.bin (99%) create mode 100644 compiler/.gradle/4.9/taskHistory/taskHistory.lock create mode 100644 compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/buildOutputCleanup/cache.properties (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/buildOutputCleanup/outputFiles.bin (75%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/.gradle/vcsWorkingDirs/gc.properties (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/BUILD.bazel (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/README.md (51%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/build.gradle (97%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/check-artifact.sh (98%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/gradle/wrapper/gradle-wrapper.properties (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/gradlew (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/gradlew.bat (100%) create mode 100644 compiler/src/java_plugin/cpp/java_dubbo_generator.cpp rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/src/java_plugin/cpp/java_generator.cpp (93%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/src/java_plugin/cpp/java_generator.h (69%) create mode 100644 compiler/src/java_plugin/cpp/java_plugin.cpp rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/src/test/golden/TestDeprecatedService.java.txt (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/src/test/golden/TestService.java.txt (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/src/test/proto/grpc/testing/compiler/test.proto (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/src/testLite/golden/TestDeprecatedService.java.txt (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/src/testLite/golden/TestService.java.txt (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/src/testNano/golden/TestDeprecatedService.java.txt (100%) rename {dubbo-rpc/dubbo-rpc-grpc/compiler => compiler}/src/testNano/golden/TestService.java.txt (100%) create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/protobuf/ProtobufService.java delete mode 100644 dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileContent/fileContent.lock delete mode 100644 dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileHashes/fileHashes.lock delete mode 100644 dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock delete mode 100644 dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/taskHistory/taskHistory.lock delete mode 100644 dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock delete mode 100644 dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_plugin.cpp create mode 100644 dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcServerUtils.java create mode 100644 dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectInput2.java create mode 100644 dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectOutput2.java create mode 100644 dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoSerialization2.java delete mode 100644 dubbo-serialization/dubbo-serialization-protobuf-json/pom.xml delete mode 100644 dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/MapValue.java delete mode 100644 dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java delete mode 100644 dubbo-serialization/dubbo-serialization-protobuf-json/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization create mode 100644 dubbo-serialization/dubbo-serialization-protobuf/pom.xml rename dubbo-serialization/{dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java => dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectInput.java} (76%) rename dubbo-serialization/{dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java => dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutput.java} (89%) rename dubbo-serialization/{dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java => dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerialization.java} (90%) create mode 100644 dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java create mode 100644 dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java create mode 100644 dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java create mode 100644 dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java create mode 100644 dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufWrappedException.java create mode 100644 dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/MapValue.proto create mode 100644 dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/ThrowablePB.proto create mode 100644 dubbo-serialization/dubbo-serialization-protobuf/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization create mode 100644 dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/AbstractProtobufSerializationTest.java rename dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/{GenericProtobufObjectOutputTest.java => GenericProtobufJsonObjectOutputTest.java} (95%) create mode 100644 dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerializationTest.java rename dubbo-serialization/dubbo-serialization-test/src/test/{resources/protobuf => proto}/GooglePB.proto (100%) diff --git a/.gitignore b/.gitignore index f5360c9509..54366f7037 100644 --- a/.gitignore +++ b/.gitignore @@ -37,5 +37,5 @@ Thumbs.db license-list.txt # grpc compiler -dubbo-rpc/dubbo-rpc-grpc/compiler/gradle.properties -dubbo-rpc/dubbo-rpc-grpc/compiler/build/* \ No newline at end of file +compiler/gradle.properties +compiler/build/* \ No newline at end of file diff --git a/LICENSE b/LICENSE index 38ba0906fc..fac06a21dc 100644 --- a/LICENSE +++ b/LICENSE @@ -227,4 +227,4 @@ This product contains a modified portion of 'edazdarevic.commons.net.CIDRUtils', This product contains a modified portion of 'proto-gen-grpc-java' - a protobuf plugin used to generate grpc-java stubs, under a "Apache License 2.0" license, see https://github.com/grpc/grpc-java/blob/v1.22.1/NOTICE.txt. All files are placed - under '/dubbo/dubbo-rpc/dubbo-rpc-grpc/compiler' + under '/dubbo/compiler' diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileChanges/last-build.bin b/compiler/.gradle/4.3/fileChanges/last-build.bin similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileChanges/last-build.bin rename to compiler/.gradle/4.3/fileChanges/last-build.bin diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileContent/annotation-processors.bin b/compiler/.gradle/4.3/fileContent/annotation-processors.bin similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileContent/annotation-processors.bin rename to compiler/.gradle/4.3/fileContent/annotation-processors.bin diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileContent/fileContent.lock b/compiler/.gradle/4.3/fileContent/fileContent.lock similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileContent/fileContent.lock rename to compiler/.gradle/4.3/fileContent/fileContent.lock diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileHashes/fileHashes.bin b/compiler/.gradle/4.3/fileHashes/fileHashes.bin similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileHashes/fileHashes.bin rename to compiler/.gradle/4.3/fileHashes/fileHashes.bin diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileHashes/fileHashes.lock b/compiler/.gradle/4.3/fileHashes/fileHashes.lock similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileHashes/fileHashes.lock rename to compiler/.gradle/4.3/fileHashes/fileHashes.lock diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileHashes/resourceHashesCache.bin b/compiler/.gradle/4.3/fileHashes/resourceHashesCache.bin similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/fileHashes/resourceHashesCache.bin rename to compiler/.gradle/4.3/fileHashes/resourceHashesCache.bin diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/nativeCompile/nativeCompile.bin b/compiler/.gradle/4.3/nativeCompile/nativeCompile.bin similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/nativeCompile/nativeCompile.bin rename to compiler/.gradle/4.3/nativeCompile/nativeCompile.bin diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/nativeCompile/nativeCompile.lock b/compiler/.gradle/4.3/nativeCompile/nativeCompile.lock similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/nativeCompile/nativeCompile.lock rename to compiler/.gradle/4.3/nativeCompile/nativeCompile.lock diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/taskHistory/taskHistory.bin b/compiler/.gradle/4.3/taskHistory/taskHistory.bin similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/taskHistory/taskHistory.bin rename to compiler/.gradle/4.3/taskHistory/taskHistory.bin diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/taskHistory/taskHistory.lock b/compiler/.gradle/4.3/taskHistory/taskHistory.lock similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.3/taskHistory/taskHistory.lock rename to compiler/.gradle/4.3/taskHistory/taskHistory.lock diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileChanges/last-build.bin b/compiler/.gradle/4.9/fileChanges/last-build.bin similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileChanges/last-build.bin rename to compiler/.gradle/4.9/fileChanges/last-build.bin diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileContent/annotation-processors.bin b/compiler/.gradle/4.9/fileContent/annotation-processors.bin similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileContent/annotation-processors.bin rename to compiler/.gradle/4.9/fileContent/annotation-processors.bin diff --git a/compiler/.gradle/4.9/fileContent/fileContent.lock b/compiler/.gradle/4.9/fileContent/fileContent.lock new file mode 100644 index 0000000000000000000000000000000000000000..30f4129c791cc1f8006a4cbf1b59af575426cd5f GIT binary patch literal 17 VcmZQ}+r5eH?vzYn1~6c3001wd1S
mvE(|Hlru>&KtLyqFu@E9tmr~FZ0JER`e26x{TP4~F1Rs>A$Ty15sYFC zUW{V`K8Tpa6sFQlIkVXbstRRO~)1d+ WlN4FDR3+u@{Odd0)|{KN&G-wuAc~{_ delta 324 zcmWN=$u0u{007X;&}r>kF_xmG6t%XsZ-XXtcJec5 z2OMmHmEac_4K6)d}=K5)fV7ck$ zx4MVf88>czXu5tGqr&EicO;ql72CJ&m|)}uRq}W9!uyZJnWP0b&;1@(%xJy+PZndP z1pmAr8(tNCKLt@#Hh+6gGb1-Eo=)i5e=-_F8%k&j=y?8u=w z>nRW&72mhl3$qsUFh)*)pvYyr-9v%(Q6!`3cI_%wL2mwkfvU6G%iExaU)*lo%KDLm z-)FXie3N$*)Lo~yOZTxp;$V{HY}cR83dC$c%nrmH+x4e&esp2f*{*nplTm{IXw=WQ zhO<{f?Mo3GuPhYN_gw_Ee@%;INM+G#kTLx;jv`rPvx`CbWOPjwMu__ zZa3S{?N3U0ZV56fZdCjr3ej_Q4$p@WMz-z8KJq9s@=uv8n;*{B0JVa7`@K&*+2V`~ zH!2p0LzF*I z1u0U#<0Ao9#Q0SONb4B`2~8kY1YvCF`XW$!6__{Rn^n#6+l&l6tyQ1R`gi&1+pR) i^S%=YI2ZE%@%(&%k5{Ex8tka24;{dY7#Q~gX*~c&tY@_V delta 364 zcmXBMO(+Cm7{GDQyYueM*mtnDwX-NYijr)^irEsPNRg}q2XT|ui4;zov@20guOuG_ zmrdC<>IpXo;lzPj-znvyh7?LM*~9Pl?|<_iSbq&9YE;mTfLbOQ6TW4|DD@wR5W#_% zTmi;??d}#78B4cbn{o7z@{s&*e%I+JG2)-yW1!>D2u!NDFaw0rNQT(D!}V`zH|n1Q z3$fVHKPSYdp%_u17g@OBq9Y8N_=%R;i)}vo)CbjAK1H1l49(IP2}6rCC6U4u-|vw} zqhU@hc8h3{FwEt>7AQyURt6RI4>?x=Z&Lem@rG?jRy4>mEe;Gawvr7#yeeQrZtSXJ zaSF~&&HZ1Y*}=|y;Ksu+s~7piyxqi~adzzlIjKo`>E?2knIWKf{KhoEX2C8AD1Nej v7Y?^8+=GvrB4h)>=St;N!23JWNYGxVBy#wgNg_mTN^0kx^y+s|*>L{>DX4;M diff --git a/compiler/.gradle/4.9/fileHashes/fileHashes.lock b/compiler/.gradle/4.9/fileHashes/fileHashes.lock new file mode 100644 index 0000000000000000000000000000000000000000..a6f3649fdee38b2125b984b23adc93aef4e19733 GIT binary patch literal 17 VcmZRMT;p5)Rp+w=0~q9F0RS^q1k(Tj literal 0 HcmV?d00001 diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileHashes/resourceHashesCache.bin b/compiler/.gradle/4.9/fileHashes/resourceHashesCache.bin similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileHashes/resourceHashesCache.bin rename to compiler/.gradle/4.9/fileHashes/resourceHashesCache.bin diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/nativeCompile/nativeCompile.bin b/compiler/.gradle/4.9/nativeCompile/nativeCompile.bin similarity index 81% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/nativeCompile/nativeCompile.bin rename to compiler/.gradle/4.9/nativeCompile/nativeCompile.bin index d95131f93d05cfe6700c33ea6812134cb74b4e9a..72cf47a29fa3878890fde2324a721b600dc67c07 100644 GIT binary patch delta 449 zcmZqdW$t>$JV8X3i2)3X{1_NCS3}sde=;y=bpYAA8x6H2n2t4Wj+IbZ$8XHQpwj@v z6(G#=d~$$?_+BV(eGfnql)4n6k$7rXDc?TGWfpB6M{a7MZAVbue`@bun#jD(GQk?qPa? T#ZG+;ZJYn*PGDpKMnEe7Pdcws delta 45 wcmeBr#@yJ;JV8W|kpT>f{1_NCR|A=f8x3EGPjuj!EGgl{H2de~SP7MN0R7YqL;wH) diff --git a/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock b/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock new file mode 100644 index 0000000000000000000000000000000000000000..f3aa1b308a71dffbe5ef805dfd851f1ad8201c8a GIT binary patch literal 17 UcmZQ}zaJp#boZkt0|dkX05Bv3L;wH) literal 0 HcmV?d00001 diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/taskHistory/taskHistory.bin b/compiler/.gradle/4.9/taskHistory/taskHistory.bin similarity index 99% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/taskHistory/taskHistory.bin rename to compiler/.gradle/4.9/taskHistory/taskHistory.bin index 343bd6e598cc8c11a2947cbcaebc1f0db242e11c..51c48d0eda0bbd449f83674ce62429494b5e6b5b 100644 GIT binary patch delta 2456 zcmeIz{ZCbO90&08z(qhVTpmI$h+vwe$iuxLVCq##u$!3=8CoKEAI^QgocqANo{OL$ z0xCXWmR}VzEitvUsN}n9OR(C?xom4qx0a5%=m%{=ZMCLIZ^+GddH4%D+iN>J=ll3M zpY#2k>%Ao#ywWRcjaPEa@I|-gF$}By_r9iyw~Ghik>1+yR> zo`%^l2QpwTWI`5XLk_4w4Y`m9^B^Azpb+N6Gq3;_!XnVXVpsx8p$MLZWppsDxcA1w zhzy2_$Y9&d7N^VUQ|sM+v*0(mt8G=bfZJs7)b|u)HF$WxIGGgLBgT2B zBwY`R6$)qQfzKW=JlT7`=hoz=^EZgL^VrnZ7(XXajhh zF?VEznZt|a71K+HiY}Iw{B6B1|2C#cQ^v9_4r`@dFqT*y!(WgLWQ7MsZFr2-iO2Yq z)Nv(AWGD)sdi9A}a@rrIDdo9{LbCLx_IL7g2mc!}wcBa)+0YVL4$pxWo`)6i0<44= zVHK=~HLw<5f_3mRl)`%00I$HSuo22&6O=;*Yz7_Z!2m`OzyxNnfE8?D2M0Kz5=3x; z8$95JD)50HwtxfysD`aj1GTUXwnH7%!wzVGozMtP&t!MS3>0%QiH}z%U^<*fvq}8S}-0fYopCREw5MtJ>fZMXMvv`RIU1L8h7tl@sMG z(t2Q-ag3~;Hc`g$E6G5&ES}{_eF7WwCtQ=4DaqyQi-N|)<8*SUBPXc!r7)^WdpuQ^ zAPJ*?5*i&&%Q-IO7ZTGNznhb}=s-O^VxUt*Ix8&2#I|`vi%HD$Z!znQMw82H_j?Kg z4y)Cn7s#fqG>P1yu|e~G@k5L{j#m`y|E4?qr2K*QkM1b>%!Xu^luL9isgS6S_0lsE ziHeD4o>5@Ip z8Hf9*eA>gSHGMQCdwbu?+Ul(GT?_d2%;Q5mg!JAI4k~(P$ClpNW#7=A-!H6byuG9M zQZ2up=)NDLt8SIo+m5YCw!HM=AF`5&C^HX|DPk&;BxVbTYvR5 z^d0my_FY}3ng8WtJG!ej%EsAI?C2d4U5hi04JW;=d{C!)7gdc{YyK}(L8m{;_k@Ki ZW>ldfZZBO<6q6$(={7Izeu@WMIh8Tr}hx+D2)o+17vw=xI$z<}InN0GV zp&th<#|JK3cG?PsHaygZQcV*}m=$S@{`pPQ9GiNlpSSDn9h-;ji6Ogy4g)E$AQcZF z4OXP%L5xBMGLeOBIID8Wq3LMfg^8Okvmb1)b4Fdt8$0+o0g3$PH+;8`_fUo>zb)!MIV)_%FI zT@~B3LA}fGsR$|!xud-6}Cue;Z# z?Bq>nOlOawTd%5;OV(nMxRT<;b6AWeSc+wM9xq@yUc?Hl#41$bCA^GR@G4%z>sXC7 zSc^CCCf1=ECTie9E!?O>J=VhmFMRN$0RaTjh$e&(Mg+}hK@>5xq756+jt;zqPHaRR zo3I&M(1o{=z&qHAZP<<-co*;CeeA?8e1P59gT2@XiT(HxAE6r`;}aafL41nO@Hr0Q zFpl6TzQ8ejiQ_ndlQ@Ob_zFGf#n<=--{K6uQ&&>dEHSl8(=1h@yF5@9Z40`5u8fm{U4iPLDc{N diff --git a/compiler/.gradle/4.9/taskHistory/taskHistory.lock b/compiler/.gradle/4.9/taskHistory/taskHistory.lock new file mode 100644 index 0000000000000000000000000000000000000000..b52f3b63571fcba2252a079376168aed278e3661 GIT binary patch literal 17 VcmZQ(6u5Nn(hrGa3}C=~3;;Da1vUTx literal 0 HcmV?d00001 diff --git a/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000000000000000000000000000000000000..b9c10e995aba224cce2c8c82a217cce87c02bd41 GIT binary patch literal 17 UcmZQ}b#>JgwZGcR00tZk03SL6vH$=8 literal 0 HcmV?d00001 diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/buildOutputCleanup/cache.properties b/compiler/.gradle/buildOutputCleanup/cache.properties similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/buildOutputCleanup/cache.properties rename to compiler/.gradle/buildOutputCleanup/cache.properties diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/buildOutputCleanup/outputFiles.bin b/compiler/.gradle/buildOutputCleanup/outputFiles.bin similarity index 75% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/buildOutputCleanup/outputFiles.bin rename to compiler/.gradle/buildOutputCleanup/outputFiles.bin index 6da938ccce54cd1f2de605461778b55dfa0ccfa6..a82673eb4258bd909d9b3e36bcb2b99099532698 100644 GIT binary patch delta 384 zcmdmckoojs<_#tijQyKUB_x;yIy+^Gv`?3XGJwIu=FP6s2}}Z$ADbOG>bdY3MD)Su z&2wclm<8snoHFafGWj&9THnoo6&zRu)_%Cgx8GpXJgC}-n@v?68TpS!{d{XUdnHt9 z{N!A^$&3blDaf}Nl7tZkz`1kvb_8a+&4iL2u&Trm0=Yp6(z>Qi3g+D)c zLrqw|xpK272mikQ2RB(7%b|kSlX+bfCg0p`$UpVPo(Y2cFG0mMH#6>$VrNnpT&T#o Wx%P~M$mH|Bp_4x(FPfa-Ar1h7!iXFI delta 130 zcmV-|0Db?0;?k144mM2I9 zv-T=41G7CY$qJJmIl!~_Ie-DPjyo9w0wi&hEwCh$nXr+QLa|`8wmrID0i2U@oJh0L koX8fF9X~L$;j + + + kr.motd.maven + os-maven-plugin + 1.6.1 + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + 0.5.1 + + com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier} + grpc-java + org.apache.dubbo:protoc-gen-grpc-java:${proto_dubbo_plugin_version}:exe:${os.detected.classifier} + build/generated/source/proto/main/java + false + + dubbo + + + + + compile + compile-custom + test-compile + test-compile-custom + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + generate-sources + + add-source + + + + build/generated/source/proto/main/java + + + + + + + +``` + +2. Decide which protocol to use: Dubbo or gRPC + * Dubbo, ` dubbo` + * gRPC, ` grpc` + +3. Define service using IDL +```text +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "org.apache.dubbo.demo"; +option java_outer_classname = "DemoServiceProto"; +option objc_class_prefix = "DEMOSRV"; + +package demoservice; + +// The demo service definition. +service DemoService { + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} +``` + +4. Build +mvn clean compile + +## Customized 1. Dubbo Interface ```java @@ -81,7 +172,7 @@ public static abstract class GreeterImplBase implements io.grpc.BindableService, } ``` -## 如何构建 +## Build locally To compile the plugin: ``` @@ -93,7 +184,7 @@ To publish to local repository $ ../gradlew publishToMavenLocal ``` -## 远程发布 +## Publish to maven repository Add gradle.properties ```properties @@ -108,64 +199,4 @@ $ ../gradlew publishMavenPublicationToDubboRepository Notice current groupId is `com.alibaba`. -gRPC Java Codegen Plugin for Protobuf Compiler -============================================== - -This generates the Java interfaces out of the service definition from a -`.proto` file. It works with the Protobuf Compiler (``protoc``). - -Normally you don't need to compile the codegen by yourself, since pre-compiled -binaries for common platforms are available on Maven Central. However, if the -pre-compiled binaries are not compatible with your system, you may want to -build your own codegen. - -## System requirement - -* Linux, Mac OS X with Clang, or Windows with MSYS2 -* Java 7 or up -* [Protobuf](https://github.com/google/protobuf) 3.0.0-beta-3 or up - -## Compiling and testing the codegen -Change to the `compiler` directory: -``` -$ cd $GRPC_JAVA_ROOT/compiler -``` - -To compile the plugin: -``` -$ ../gradlew java_pluginExecutable -``` - -To test the plugin with the compiler: -``` -$ ../gradlew test -``` -You will see a `PASS` if the test succeeds. - -To compile a proto file and generate Java interfaces out of the service definitions: -``` -$ protoc --plugin=protoc-gen-grpc-java=build/exe/java_plugin/protoc-gen-grpc-java \ - --grpc-java_out="$OUTPUT_FILE" --proto_path="$DIR_OF_PROTO_FILE" "$PROTO_FILE" -``` -To generate Java interfaces with protobuf lite: -``` -$ protoc --plugin=protoc-gen-grpc-java=build/exe/java_plugin/protoc-gen-grpc-java \ - --grpc-java_out=lite:"$OUTPUT_FILE" --proto_path="$DIR_OF_PROTO_FILE" "$PROTO_FILE" -``` -To generate Java interfaces with protobuf nano: -``` -$ protoc --plugin=protoc-gen-grpc-java=build/exe/java_plugin/protoc-gen-grpc-java \ - --grpc-java_out=nano:"$OUTPUT_FILE" --proto_path="$DIR_OF_PROTO_FILE" "$PROTO_FILE" -``` - -## Installing the codegen to Maven local repository -This will compile a codegen and put it under your ``~/.m2/repository``. This -will make it available to any build tool that pulls codegens from Maven -repostiories. -``` -$ ../gradlew publishToMavenLocal -``` - -## Creating a release of GRPC Java -Please follow the instructions in ``RELEASING.md`` under the root directory for -details on how to create a new release. +Check [here](https://github.com/grpc/grpc-java/blob/master/compiler/README.md) for basic requirements and usage of protoc plugin. diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/build.gradle b/compiler/build.gradle similarity index 97% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/build.gradle rename to compiler/build.gradle index 56dfc7fdfb..04765f9faa 100644 --- a/dubbo-rpc/dubbo-rpc-grpc/compiler/build.gradle +++ b/compiler/build.gradle @@ -69,7 +69,7 @@ def boolean usingVisualCpp // Whether VisualCpp is actually available and select ext{ def exeSuffix = osdetector.os == 'windows' ? ".exe" : "" - protocPluginBaseName = 'protoc-gen-grpc-java' + protocPluginBaseName = 'protoc-gen-dubbo-java' javaPluginPath = "$rootDir/build/exe/java_plugin/$protocPluginBaseName$exeSuffix" nettyVersion = '4.1.32.Final' @@ -191,12 +191,6 @@ configurations { testNanoCompile } -//dependencies { -// testCompile "io.grpc:grpc-protobuf:1.22.1", -// "io.grpc:grpc-stub:1.22.1", -// "javax.annotation:javax.annotation-api:1.2" -//} - sourceSets { testLite { proto { setSrcDirs(['src/test/proto']) } @@ -279,13 +273,13 @@ checkstyleTestNano { } println "*** Building codegen requires Protobuf version ${protocVersion}" -println "*** Please refer to https://github.com/grpc/grpc-java/blob/master/COMPILING.md#how-to-build-code-generation-plugin" +println "*** Please refer to https://github.com/apache/dubbo/blob/master/compiler/README.md" task buildArtifacts(type: Copy) { dependsOn 'java_pluginExecutable' from("$buildDir/exe") { if (osdetector.os != 'windows') { - rename 'protoc-gen-grpc-java', '$0.exe' + rename 'protoc-gen-dubbo-java', '$0.exe' } } into artifactStagingPath @@ -359,7 +353,7 @@ publishing { maven(MavenPublication) { // Removes all artifacts since grpc-compiler doesn't generates any Jar artifacts = [] - artifactId 'protoc-gen-grpc-java' + artifactId 'protoc-gen-dubbo-java' artifact("$artifactStagingPath/java_plugin/${protocPluginBaseName}.exe" as File) { classifier osdetector.os + "-" + arch extension "exe" diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/check-artifact.sh b/compiler/check-artifact.sh similarity index 98% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/check-artifact.sh rename to compiler/check-artifact.sh index b06492e2ac..05b57a1d1a 100755 --- a/dubbo-rpc/dubbo-rpc-grpc/compiler/check-artifact.sh +++ b/compiler/check-artifact.sh @@ -127,5 +127,5 @@ checkDependencies () echo } -FILE="build/artifacts/java_plugin/protoc-gen-grpc-java.exe" +FILE="build/artifacts/java_plugin/protoc-gen-dubbo-java.exe" checkArch "$FILE" && checkDependencies "$FILE" diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/gradle/wrapper/gradle-wrapper.properties b/compiler/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/gradle/wrapper/gradle-wrapper.properties rename to compiler/gradle/wrapper/gradle-wrapper.properties diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/gradlew b/compiler/gradlew similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/gradlew rename to compiler/gradlew diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/gradlew.bat b/compiler/gradlew.bat similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/gradlew.bat rename to compiler/gradlew.bat diff --git a/compiler/src/java_plugin/cpp/java_dubbo_generator.cpp b/compiler/src/java_plugin/cpp/java_dubbo_generator.cpp new file mode 100644 index 0000000000..0f13cafe6b --- /dev/null +++ b/compiler/src/java_plugin/cpp/java_dubbo_generator.cpp @@ -0,0 +1,572 @@ +#include "java_generator.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Stringify helpers used solely to cast GRPC_VERSION +#ifndef STR +#define STR(s) #s +#endif + +#ifndef XSTR +#define XSTR(s) STR(s) +#endif + +#ifndef FALLTHROUGH_INTENDED +#define FALLTHROUGH_INTENDED +#endif + +namespace java_dubbo_generator { + +using google::protobuf::FileDescriptor; +using google::protobuf::ServiceDescriptor; +using google::protobuf::MethodDescriptor; +using google::protobuf::Descriptor; +using google::protobuf::io::Printer; +using google::protobuf::SourceLocation; +using std::to_string; + +// java keywords from: https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.9 +static std::set java_keywords = { + "abstract", + "assert", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "default", + "do", + "double", + "else", + "enum", + "extends", + "final", + "finally", + "float", + "for", + "goto", + "if", + "implements", + "import", + "instanceof", + "int", + "interface", + "long", + "native", + "new", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "strictfp", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "try", + "void", + "volatile", + "while", + // additional ones added by us + "true", + "false", +}; + +// Adjust a method name prefix identifier to follow the JavaBean spec: +// - decapitalize the first letter +// - remove embedded underscores & capitalize the following letter +// Finally, if the result is a reserved java keyword, append an underscore. +static string MixedLower(const string& word) { + string w; + w += tolower(word[0]); + bool after_underscore = false; + for (size_t i = 1; i < word.length(); ++i) { + if (word[i] == '_') { + after_underscore = true; + } else { + w += after_underscore ? toupper(word[i]) : word[i]; + after_underscore = false; + } + } + if (java_keywords.find(w) != java_keywords.end()) { + return w + "_"; + } + return w; +} + +// Converts to the identifier to the ALL_UPPER_CASE format. +// - An underscore is inserted where a lower case letter is followed by an +// upper case letter. +// - All letters are converted to upper case +static string ToAllUpperCase(const string& word) { + string w; + for (size_t i = 0; i < word.length(); ++i) { + w += toupper(word[i]); + if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) { + w += '_'; + } + } + return w; +} + +static inline string LowerMethodName(const MethodDescriptor* method) { + return MixedLower(method->name()); +} + +static inline string MethodPropertiesFieldName(const MethodDescriptor* method) { + return "METHOD_" + ToAllUpperCase(method->name()); +} + +static inline string MethodPropertiesGetterName(const MethodDescriptor* method) { + return MixedLower("get_" + method->name() + "_method"); +} + +static inline string MethodIdFieldName(const MethodDescriptor* method) { + return "METHODID_" + ToAllUpperCase(method->name()); +} + +static inline bool ShouldGenerateAsLite(const Descriptor* desc) { + return false; +} + +static inline string MessageFullJavaName(bool nano, const Descriptor* desc) { + string name = google::protobuf::compiler::java::ClassName(desc); + if (nano && !ShouldGenerateAsLite(desc)) { + // XXX: Add "nano" to the original package + // (https://github.com/grpc/grpc-java/issues/900) + if (isupper(name[0])) { + // No java package specified. + return "nano." + name; + } + for (size_t i = 0; i < name.size(); ++i) { + if ((name[i] == '.') && (i < (name.size() - 1)) && isupper(name[i + 1])) { + return name.substr(0, i + 1) + "nano." + name.substr(i + 1); + } + } + } + return name; +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution. +template +static void GrpcSplitStringToIteratorUsing(const string& full, + const char* delim, + ITR& result) { + // Optimize the common case where delim is a single character. + if (delim[0] != '\0' && delim[1] == '\0') { + char c = delim[0]; + const char* p = full.data(); + const char* end = p + full.size(); + while (p != end) { + if (*p == c) { + ++p; + } else { + const char* start = p; + while (++p != end && *p != c); + *result++ = string(start, p - start); + } + } + return; + } + + string::size_type begin_index, end_index; + begin_index = full.find_first_not_of(delim); + while (begin_index != string::npos) { + end_index = full.find_first_of(delim, begin_index); + if (end_index == string::npos) { + *result++ = full.substr(begin_index); + return; + } + *result++ = full.substr(begin_index, (end_index - begin_index)); + begin_index = full.find_first_not_of(delim, end_index); + } +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution. +static void GrpcSplitStringUsing(const string& full, + const char* delim, + std::vector* result) { + std::back_insert_iterator< std::vector > it(*result); + GrpcSplitStringToIteratorUsing(full, delim, it); +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution. +static std::vector GrpcSplit(const string& full, const char* delim) { + std::vector result; + GrpcSplitStringUsing(full, delim, &result); + return result; +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution. +static string GrpcEscapeJavadoc(const string& input) { + string result; + result.reserve(input.size() * 2); + + char prev = '*'; + + for (string::size_type i = 0; i < input.size(); i++) { + char c = input[i]; + switch (c) { + case '*': + // Avoid "/*". + if (prev == '/') { + result.append("*"); + } else { + result.push_back(c); + } + break; + case '/': + // Avoid "*/". + if (prev == '*') { + result.append("/"); + } else { + result.push_back(c); + } + break; + case '@': + // '@' starts javadoc tags including the @deprecated tag, which will + // cause a compile-time error if inserted before a declaration that + // does not have a corresponding @Deprecated annotation. + result.append("@"); + break; + case '<': + // Avoid interpretation as HTML. + result.append("<"); + break; + case '>': + // Avoid interpretation as HTML. + result.append(">"); + break; + case '&': + // Avoid interpretation as HTML. + result.append("&"); + break; + case '\\': + // Java interprets Unicode escape sequences anywhere! + result.append("\"); + break; + default: + result.push_back(c); + break; + } + + prev = c; + } + + return result; +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution. +template +static string GrpcGetCommentsForDescriptor(const DescriptorType* descriptor) { + SourceLocation location; + if (descriptor->GetSourceLocation(&location)) { + return location.leading_comments.empty() ? + location.trailing_comments : location.leading_comments; + } + return string(); +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution. +static std::vector GrpcGetDocLines(const string& comments) { + if (!comments.empty()) { + // TODO(kenton): Ideally we should parse the comment text as Markdown and + // write it back as HTML, but this requires a Markdown parser. For now + // we just use
 to get fixed-width text formatting.
+
+    // If the comment itself contains block comment start or end markers,
+    // HTML-escape them so that they don't accidentally close the doc comment.
+    string escapedComments = GrpcEscapeJavadoc(comments);
+
+    std::vector lines = GrpcSplit(escapedComments, "\n");
+    while (!lines.empty() && lines.back().empty()) {
+      lines.pop_back();
+    }
+    return lines;
+  }
+  return std::vector();
+}
+
+// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
+template 
+static std::vector GrpcGetDocLinesForDescriptor(const DescriptorType* descriptor) {
+  return GrpcGetDocLines(GrpcGetCommentsForDescriptor(descriptor));
+}
+
+// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
+static void GrpcWriteDocCommentBody(Printer* printer,
+                                    const std::vector& lines,
+                                    bool surroundWithPreTag) {
+  if (!lines.empty()) {
+    if (surroundWithPreTag) {
+      printer->Print(" * 
\n");
+    }
+
+    for (size_t i = 0; i < lines.size(); i++) {
+      // Most lines should start with a space.  Watch out for lines that start
+      // with a /, since putting that right after the leading asterisk will
+      // close the comment.
+      if (!lines[i].empty() && lines[i][0] == '/') {
+        printer->Print(" * $line$\n", "line", lines[i]);
+      } else {
+        printer->Print(" *$line$\n", "line", lines[i]);
+      }
+    }
+
+    if (surroundWithPreTag) {
+      printer->Print(" * 
\n"); + } + } +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution. +static void GrpcWriteDocComment(Printer* printer, const string& comments) { + printer->Print("/**\n"); + std::vector lines = GrpcGetDocLines(comments); + GrpcWriteDocCommentBody(printer, lines, false); + printer->Print(" */\n"); +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution. +static void GrpcWriteServiceDocComment(Printer* printer, + const ServiceDescriptor* service) { + // Deviating from protobuf to avoid extraneous docs + // (see https://github.com/google/protobuf/issues/1406); + printer->Print("/**\n"); + std::vector lines = GrpcGetDocLinesForDescriptor(service); + GrpcWriteDocCommentBody(printer, lines, true); + printer->Print(" */\n"); +} + +// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution. +void GrpcWriteMethodDocComment(Printer* printer, + const MethodDescriptor* method) { + // Deviating from protobuf to avoid extraneous docs + // (see https://github.com/google/protobuf/issues/1406); + printer->Print("/**\n"); + std::vector lines = GrpcGetDocLinesForDescriptor(method); + GrpcWriteDocCommentBody(printer, lines, true); + printer->Print(" */\n"); +} + +enum StubType { + ASYNC_INTERFACE = 0, + BLOCKING_CLIENT_INTERFACE = 1, + FUTURE_CLIENT_INTERFACE = 2, + BLOCKING_SERVER_INTERFACE = 3, + ASYNC_CLIENT_IMPL = 4, + BLOCKING_CLIENT_IMPL = 5, + FUTURE_CLIENT_IMPL = 6, + ABSTRACT_CLASS = 7, +}; + +enum CallType { + ASYNC_CALL = 0, + BLOCKING_CALL = 1, + FUTURE_CALL = 2 +}; + +static void PrintMarshallerStaticBlock(const ServiceDescriptor* service, + std::map* vars, + Printer* p) { + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + (*vars)["input_type"] = google::protobuf::compiler::java::ClassName(method->input_type()); + (*vars)["output_type"] = google::protobuf::compiler::java::ClassName(method->output_type()); + p->Print( + *vars, + "private static final AtomicBoolean registered = new AtomicBoolean();\n\n"); + + p->Print( + *vars, + "static {\n" + " if (registered.compareAndSet(false, true)) {\n" + " $ProtobufUtils$.marshaller(\n" + " $input_type$.getDefaultInstance());\n" + " $ProtobufUtils$.marshaller(\n" + " $output_type$.getDefaultInstance());\n" + " }\n" + "}\n\n"); + } +} + +static void PrintDubboInterface( + const ServiceDescriptor* service, + std::map* vars, + Printer* p, bool generate_nano) { + const string service_name = service->name(); + (*vars)["service_name"] = service_name; + (*vars)["dubbo_interface"] = "I" + service_name; + + p->Print( + "/**\n " + "* Code generated for Dubbo\n " + "*/\n" + ); + p->Print( + *vars, + "public interface $dubbo_interface$ {\n\n"); + + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + (*vars)["input_type"] = MessageFullJavaName(generate_nano, + method->input_type()); + (*vars)["output_type"] = MessageFullJavaName(generate_nano, + method->output_type()); + (*vars)["lower_method_name"] = LowerMethodName(method); + + // Simple RPC + p->Print( + *vars, + "$output_type$ $lower_method_name$($input_type$ request);\n\n"); + // Simple Future RPC + p->Print( + *vars, + "$CompletableFuture$<$output_type$> $lower_method_name$Async(\n$input_type$ request);\n\n"); +// p->Print( +// *vars, +// "default $CompletableFuture$<$output_type$> $lower_method_name$Async(\n" +// " $input_type$ request) {\n return CompletableFuture.completedFuture($lower_method_name$(request));\n}\n\n"); + p->Outdent(); + } + + p->Outdent(); + p->Print("}\n\n"); + +} + +static void PrintService(const ServiceDescriptor* service, + std::map* vars, + Printer* p, + bool disable_version) { + (*vars)["service_name"] = service->name(); + (*vars)["file_name"] = service->file()->name(); + (*vars)["service_class_name"] = ServiceClassName(service); + (*vars)["grpc_version"] = ""; + #ifdef GRPC_VERSION + if (!disable_version) { + (*vars)["grpc_version"] = " (version " XSTR(GRPC_VERSION) ")"; + } + #endif + // TODO(nmittler): Replace with WriteServiceDocComment once included by protobuf distro. + GrpcWriteServiceDocComment(p, service); + p->Print( + *vars, + "@$Generated$(\n" + " value = \"by gRPC proto compiler$grpc_version$\",\n" + " comments = \"Source: $file_name$\")\n"); + + if (service->options().deprecated()) { + p->Print(*vars, "@$Deprecated$\n"); + } + + p->Print( + *vars, + "public final class $service_class_name$ {\n\n"); + p->Indent(); + + PrintMarshallerStaticBlock(service, vars, p); + + p->Print( + *vars, + "private $service_class_name$() {}\n\n"); + + p->Print( + *vars, + "public static final String SERVICE_NAME = " + "\"$Package$$service_name$\";\n\n"); + + PrintDubboInterface(service, vars, p, false); + + p->Outdent(); + p->Print("}\n"); +} + +void PrintImports(Printer* p) { + p->Print( + "import " + "java.util.concurrent.CompletableFuture;\n"); + p->Print( + "import " + "java.util.concurrent.atomic.AtomicBoolean;\n"); +} + +void GenerateService(const ServiceDescriptor* service, + google::protobuf::io::ZeroCopyOutputStream* out, + ProtoFlavor flavor, + bool disable_version) { + // All non-generated classes must be referred by fully qualified names to + // avoid collision with generated classes. + std::map vars; + vars["String"] = "java.lang.String"; + vars["Deprecated"] = "java.lang.Deprecated"; + vars["Override"] = "java.lang.Override"; + vars["Iterator"] = "java.util.Iterator"; + vars["Generated"] = "javax.annotation.Generated"; + vars["CompletableFuture"] = + "java.util.concurrent.CompletableFuture"; + vars["AtomicBoolean"] = + "java.util.concurrent.atomic.AtomicBoolean"; + vars["ProtobufUtils"] = + "org.apache.dubbo.common.serialize.protobuf.support.ProtobufUtils"; + + Printer printer(out, '$'); + string package_name = ServiceJavaPackage(service->file(),false); + if (!package_name.empty()) { + printer.Print( + "package $package_name$;\n\n", + "package_name", package_name); + } + + PrintImports(&printer); + + // Package string is used to fully qualify method names. + vars["Package"] = service->file()->package(); + if (!vars["Package"].empty()) { + vars["Package"].append("."); + } + PrintService(service, &vars, &printer, false); +} + +string ServiceJavaPackage(const FileDescriptor* file, bool nano) { + string result = google::protobuf::compiler::java::ClassName(file); + size_t last_dot_pos = result.find_last_of('.'); + if (last_dot_pos != string::npos) { + result.resize(last_dot_pos); + } else { + result = ""; + } + if (nano) { + if (!result.empty()) { + result += "."; + } + result += "nano"; + } + return result; +} + +string ServiceClassName(const google::protobuf::ServiceDescriptor* service) { + return service->name() + "Dubbo"; +} + +} // namespace java_dubbo_generator diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.cpp b/compiler/src/java_plugin/cpp/java_generator.cpp similarity index 93% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.cpp rename to compiler/src/java_plugin/cpp/java_generator.cpp index 224ccb51d5..1fbc483cee 100644 --- a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.cpp +++ b/compiler/src/java_plugin/cpp/java_generator.cpp @@ -1182,105 +1182,105 @@ static void PrintMethodHandlerClass(const ServiceDescriptor* service, } static void PrintGetServiceDescriptorMethod(const ServiceDescriptor* service, - std::map* vars, - Printer* p, - ProtoFlavor flavor) { - (*vars)["service_name"] = service->name(); + std::map* vars, + Printer* p, + ProtoFlavor flavor) { + (*vars)["service_name"] = service->name(); - if (flavor == ProtoFlavor::NORMAL) { - (*vars)["proto_base_descriptor_supplier"] = service->name() + "BaseDescriptorSupplier"; - (*vars)["proto_file_descriptor_supplier"] = service->name() + "FileDescriptorSupplier"; - (*vars)["proto_method_descriptor_supplier"] = service->name() + "MethodDescriptorSupplier"; - (*vars)["proto_class_name"] = google::protobuf::compiler::java::ClassName(service->file()); - p->Print( - *vars, - "private static abstract class $proto_base_descriptor_supplier$\n" - " implements $ProtoFileDescriptorSupplier$, $ProtoServiceDescriptorSupplier$ {\n" - " $proto_base_descriptor_supplier$() {}\n" - "\n" - " @$Override$\n" - " public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {\n" - " return $proto_class_name$.getDescriptor();\n" - " }\n" - "\n" - " @$Override$\n" - " public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {\n" - " return getFileDescriptor().findServiceByName(\"$service_name$\");\n" - " }\n" - "}\n" - "\n" - "private static final class $proto_file_descriptor_supplier$\n" - " extends $proto_base_descriptor_supplier$ {\n" - " $proto_file_descriptor_supplier$() {}\n" - "}\n" - "\n" - "private static final class $proto_method_descriptor_supplier$\n" - " extends $proto_base_descriptor_supplier$\n" - " implements $ProtoMethodDescriptorSupplier$ {\n" - " private final String methodName;\n" - "\n" - " $proto_method_descriptor_supplier$(String methodName) {\n" - " this.methodName = methodName;\n" - " }\n" - "\n" - " @$Override$\n" - " public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {\n" - " return getServiceDescriptor().findMethodByName(methodName);\n" - " }\n" - "}\n\n"); - } + if (flavor == ProtoFlavor::NORMAL) { + (*vars)["proto_base_descriptor_supplier"] = service->name() + "BaseDescriptorSupplier"; + (*vars)["proto_file_descriptor_supplier"] = service->name() + "FileDescriptorSupplier"; + (*vars)["proto_method_descriptor_supplier"] = service->name() + "MethodDescriptorSupplier"; + (*vars)["proto_class_name"] = google::protobuf::compiler::java::ClassName(service->file()); + p->Print( + *vars, + "private static abstract class $proto_base_descriptor_supplier$\n" + " implements $ProtoFileDescriptorSupplier$, $ProtoServiceDescriptorSupplier$ {\n" + " $proto_base_descriptor_supplier$() {}\n" + "\n" + " @$Override$\n" + " public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {\n" + " return $proto_class_name$.getDescriptor();\n" + " }\n" + "\n" + " @$Override$\n" + " public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {\n" + " return getFileDescriptor().findServiceByName(\"$service_name$\");\n" + " }\n" + "}\n" + "\n" + "private static final class $proto_file_descriptor_supplier$\n" + " extends $proto_base_descriptor_supplier$ {\n" + " $proto_file_descriptor_supplier$() {}\n" + "}\n" + "\n" + "private static final class $proto_method_descriptor_supplier$\n" + " extends $proto_base_descriptor_supplier$\n" + " implements $ProtoMethodDescriptorSupplier$ {\n" + " private final String methodName;\n" + "\n" + " $proto_method_descriptor_supplier$(String methodName) {\n" + " this.methodName = methodName;\n" + " }\n" + "\n" + " @$Override$\n" + " public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {\n" + " return getServiceDescriptor().findMethodByName(methodName);\n" + " }\n" + "}\n\n"); + } - p->Print( - *vars, - "private static volatile $ServiceDescriptor$ serviceDescriptor;\n\n"); + p->Print( + *vars, + "private static volatile $ServiceDescriptor$ serviceDescriptor;\n\n"); - p->Print( - *vars, - "public static $ServiceDescriptor$ getServiceDescriptor() {\n"); - p->Indent(); - p->Print( - *vars, - "$ServiceDescriptor$ result = serviceDescriptor;\n"); - p->Print("if (result == null) {\n"); - p->Indent(); - p->Print( - *vars, - "synchronized ($service_class_name$.class) {\n"); - p->Indent(); - p->Print("result = serviceDescriptor;\n"); - p->Print("if (result == null) {\n"); - p->Indent(); + p->Print( + *vars, + "public static $ServiceDescriptor$ getServiceDescriptor() {\n"); + p->Indent(); + p->Print( + *vars, + "$ServiceDescriptor$ result = serviceDescriptor;\n"); + p->Print("if (result == null) {\n"); + p->Indent(); + p->Print( + *vars, + "synchronized ($service_class_name$.class) {\n"); + p->Indent(); + p->Print("result = serviceDescriptor;\n"); + p->Print("if (result == null) {\n"); + p->Indent(); - p->Print( - *vars, - "serviceDescriptor = result = $ServiceDescriptor$.newBuilder(SERVICE_NAME)"); - p->Indent(); - p->Indent(); - if (flavor == ProtoFlavor::NORMAL) { - p->Print( - *vars, - "\n.setSchemaDescriptor(new $proto_file_descriptor_supplier$())"); - } - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* method = service->method(i); - (*vars)["method_method_name"] = MethodPropertiesGetterName(method); - p->Print(*vars, "\n.addMethod($method_method_name$())"); - } - p->Print("\n.build();\n"); - p->Outdent(); - p->Outdent(); + p->Print( + *vars, + "serviceDescriptor = result = $ServiceDescriptor$.newBuilder(SERVICE_NAME)"); + p->Indent(); + p->Indent(); + if (flavor == ProtoFlavor::NORMAL) { + p->Print( + *vars, + "\n.setSchemaDescriptor(new $proto_file_descriptor_supplier$())"); + } + for (int i = 0; i < service->method_count(); ++i) { + const MethodDescriptor* method = service->method(i); + (*vars)["method_method_name"] = MethodPropertiesGetterName(method); + p->Print(*vars, "\n.addMethod($method_method_name$())"); + } + p->Print("\n.build();\n"); + p->Outdent(); + p->Outdent(); - p->Outdent(); - p->Print("}\n"); - p->Outdent(); - p->Print("}\n"); - p->Outdent(); - p->Print("}\n"); - p->Print("return result;\n"); - p->Outdent(); - p->Print("}\n"); -} + p->Outdent(); + p->Print("}\n"); + p->Outdent(); + p->Print("}\n"); + p->Outdent(); + p->Print("}\n"); + p->Print("return result;\n"); + p->Outdent(); + p->Print("}\n"); + } static void PrintBindServiceMethodBody(const ServiceDescriptor* service, std::map* vars, diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.h b/compiler/src/java_plugin/cpp/java_generator.h similarity index 69% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.h rename to compiler/src/java_plugin/cpp/java_generator.h index ab265d06c7..7106c54e37 100644 --- a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.h +++ b/compiler/src/java_plugin/cpp/java_generator.h @@ -54,4 +54,25 @@ void GenerateService(const google::protobuf::ServiceDescriptor* service, } // namespace java_grpc_generator +namespace java_dubbo_generator { + +enum ProtoFlavor { + NORMAL +}; + +// Returns the package name of the Dubbo services defined in the given file. +string ServiceJavaPackage(const google::protobuf::FileDescriptor* file, bool nano); + +// Returns the name of the outer class that wraps in all the generated code for +// the given service. +string ServiceClassName(const google::protobuf::ServiceDescriptor* service); + +// Writes the generated service interface into the given ZeroCopyOutputStream +void GenerateService(const google::protobuf::ServiceDescriptor* service, + google::protobuf::io::ZeroCopyOutputStream* out, + ProtoFlavor flavor, + bool disable_version); + +} // namespace java_dubbo_generator + #endif // NET_GRPC_COMPILER_JAVA_GENERATOR_H_ diff --git a/compiler/src/java_plugin/cpp/java_plugin.cpp b/compiler/src/java_plugin/cpp/java_plugin.cpp new file mode 100644 index 0000000000..c8af98cffa --- /dev/null +++ b/compiler/src/java_plugin/cpp/java_plugin.cpp @@ -0,0 +1,87 @@ +// Generates Java gRPC service interface out of Protobuf IDL. +// +// This is a Proto2 compiler plugin. See net/proto2/compiler/proto/plugin.proto +// and net/proto2/compiler/public/plugin.h for more information on plugins. + +#include + +#include "java_generator.h" +#include +#include +#include +#include + +static string JavaPackageToDir(const string& package_name) { + string package_dir = package_name; + for (size_t i = 0; i < package_dir.size(); ++i) { + if (package_dir[i] == '.') { + package_dir[i] = '/'; + } + } + if (!package_dir.empty()) package_dir += "/"; + return package_dir; +} + +class JavaGrpcGenerator : public google::protobuf::compiler::CodeGenerator { + public: + + JavaGrpcGenerator() {} + virtual ~JavaGrpcGenerator() {} + + virtual bool Generate(const google::protobuf::FileDescriptor* file, + const string& parameter, + google::protobuf::compiler::GeneratorContext* context, + string* error) const { + std::vector > options; + google::protobuf::compiler::ParseGeneratorParameter(parameter, &options); + string DUBBO("dubbo"); + + if (DUBBO == parameter) { + string package_name = java_dubbo_generator::ServiceJavaPackage( + file, false); + string package_filename = JavaPackageToDir(package_name); + for (int i = 0; i < file->service_count(); ++i) { + const google::protobuf::ServiceDescriptor* service = file->service(i); + string filename = package_filename + + java_dubbo_generator::ServiceClassName(service) + ".java"; + std::unique_ptr output( + context->Open(filename)); + java_dubbo_generator::GenerateService( + service, output.get(), java_dubbo_generator::ProtoFlavor::NORMAL, false); + } + } else { + java_grpc_generator::ProtoFlavor flavor = + java_grpc_generator::ProtoFlavor::NORMAL; + + bool disable_version = false; + for (size_t i = 0; i < options.size(); i++) { + if (options[i].first == "nano") { + flavor = java_grpc_generator::ProtoFlavor::NANO; + } else if (options[i].first == "lite") { + flavor = java_grpc_generator::ProtoFlavor::LITE; + } else if (options[i].first == "noversion") { + disable_version = true; + } + } + + string package_name = java_grpc_generator::ServiceJavaPackage( + file, flavor == java_grpc_generator::ProtoFlavor::NANO); + string package_filename = JavaPackageToDir(package_name); + for (int i = 0; i < file->service_count(); ++i) { + const google::protobuf::ServiceDescriptor* service = file->service(i); + string filename = package_filename + + java_grpc_generator::ServiceClassName(service) + ".java"; + std::unique_ptr output( + context->Open(filename)); + java_grpc_generator::GenerateService( + service, output.get(), flavor, disable_version); + } + } + return true; + } +}; + +int main(int argc, char* argv[]) { + JavaGrpcGenerator generator; + return google::protobuf::compiler::PluginMain(argc, argv, &generator); +} diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/golden/TestDeprecatedService.java.txt b/compiler/src/test/golden/TestDeprecatedService.java.txt similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/golden/TestDeprecatedService.java.txt rename to compiler/src/test/golden/TestDeprecatedService.java.txt diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/golden/TestService.java.txt rename to compiler/src/test/golden/TestService.java.txt diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/proto/grpc/testing/compiler/test.proto b/compiler/src/test/proto/grpc/testing/compiler/test.proto similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/proto/grpc/testing/compiler/test.proto rename to compiler/src/test/proto/grpc/testing/compiler/test.proto diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/testLite/golden/TestDeprecatedService.java.txt b/compiler/src/testLite/golden/TestDeprecatedService.java.txt similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/testLite/golden/TestDeprecatedService.java.txt rename to compiler/src/testLite/golden/TestDeprecatedService.java.txt diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/testLite/golden/TestService.java.txt b/compiler/src/testLite/golden/TestService.java.txt similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/testLite/golden/TestService.java.txt rename to compiler/src/testLite/golden/TestService.java.txt diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/testNano/golden/TestDeprecatedService.java.txt b/compiler/src/testNano/golden/TestDeprecatedService.java.txt similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/testNano/golden/TestDeprecatedService.java.txt rename to compiler/src/testNano/golden/TestDeprecatedService.java.txt diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/testNano/golden/TestService.java.txt b/compiler/src/testNano/golden/TestService.java.txt similarity index 100% rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/testNano/golden/TestService.java.txt rename to compiler/src/testNano/golden/TestService.java.txt diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml index 89de0c64b5..3316261769 100644 --- a/dubbo-all/pom.xml +++ b/dubbo-all/pom.xml @@ -420,7 +420,7 @@ org.apache.dubbo - dubbo-serialization-protobuf-json + dubbo-serialization-protobuf ${project.version} compile true @@ -662,7 +662,7 @@ org.apache.dubbo:dubbo-serialization-jdk org.apache.dubbo:dubbo-serialization-protostuff org.apache.dubbo:dubbo-serialization-gson - org.apache.dubbo:dubbo-serialization-protobuf-json + org.apache.dubbo:dubbo-serialization-protobuf org.apache.dubbo:dubbo-configcenter-api org.apache.dubbo:dubbo-configcenter-definition org.apache.dubbo:dubbo-configcenter-apollo diff --git a/dubbo-bom/pom.xml b/dubbo-bom/pom.xml index 6ccbc1b337..77697c414d 100644 --- a/dubbo-bom/pom.xml +++ b/dubbo-bom/pom.xml @@ -360,7 +360,7 @@ org.apache.dubbo - dubbo-serialization-protobuf-json + dubbo-serialization-protobuf ${project.version} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/protobuf/ProtobufService.java b/dubbo-common/src/main/java/org/apache/dubbo/common/protobuf/ProtobufService.java new file mode 100644 index 0000000000..1c3db1104d --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/protobuf/ProtobufService.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.protobuf; + +/** + * proto-gen-dubbo-java + */ +public interface ProtobufService { + +} diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 3c5b432750..ac5d44616b 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -116,7 +116,7 @@ 5.4.1.Final 3.0.1-b08 1.0.0 - 4.0.1 + 4.0.2 0.42 2.48-jdk-6 1.8.2 diff --git a/dubbo-distribution/src/assembly/source-release.xml b/dubbo-distribution/src/assembly/source-release.xml index e79afe2484..fb799ceefd 100644 --- a/dubbo-distribution/src/assembly/source-release.xml +++ b/dubbo-distribution/src/assembly/source-release.xml @@ -51,7 +51,7 @@ **/*.jar **/mvnw* **/.flattened-pom.xml - **/dubbo-rpc-grpc/compiler/** + **/compiler/** diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java index 8f25250c98..d4eae092e2 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java @@ -278,7 +278,7 @@ public class ExchangeCodec extends TelnetCodec { // encode response data or error message. if (status == Response.OK) { if (res.isHeartbeat()) { - encodeHeartbeatData(channel, out, res.getResult()); + encodeEventData(channel, out, res.getResult()); } else { encodeResponseData(channel, out, res.getResult(), res.getVersion()); } @@ -401,9 +401,9 @@ public class ExchangeCodec extends TelnetCodec { protected Object decodeEventData(Channel channel, ObjectInput in) throws IOException { try { - return in.readObject(); - } catch (ClassNotFoundException e) { - throw new IOException(StringUtils.toString("Read object failed.", e)); + return in.readUTF(); + } catch (IOException e) { + throw new IOException(StringUtils.toString("Decode dubbo protocol event failed.", e)); } } diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java index 2df67de8ce..dd16a66985 100644 --- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java +++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java @@ -99,6 +99,7 @@ public class CuratorZookeeperClient extends AbstractZookeeperClient) returnTypes[0]); @@ -141,7 +142,7 @@ public class DecodeableRpcResult extends AppResponse implements Codec, Decodeabl private void handleException(ObjectInput in) throws IOException { try { - Object obj = in.readObject(); + Object obj = in.readThrowable(); if (!(obj instanceof Throwable)) { throw new IOException("Response data error, expect Throwable, but get " + obj); } diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java index f9134379ad..c9e43e7e2a 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java @@ -78,10 +78,7 @@ public class DubboCodec extends ExchangeCodec { try { if (status == Response.OK) { Object data; - if (res.isHeartbeat()) { - ObjectInput in = CodecSupport.deserialize(channel.getUrl(), is, proto); - data = decodeHeartbeatData(channel, in); - } else if (res.isEvent()) { + if (res.isEvent()) { ObjectInput in = CodecSupport.deserialize(channel.getUrl(), is, proto); data = decodeEventData(channel, in); } else { @@ -120,10 +117,7 @@ public class DubboCodec extends ExchangeCodec { } try { Object data; - if (req.isHeartbeat()) { - ObjectInput in = CodecSupport.deserialize(channel.getUrl(), is, proto); - data = decodeHeartbeatData(channel, in); - } else if (req.isEvent()) { + if (req.isEvent()) { ObjectInput in = CodecSupport.deserialize(channel.getUrl(), is, proto); data = decodeEventData(channel, in); } else { @@ -205,7 +199,7 @@ public class DubboCodec extends ExchangeCodec { } } else { out.writeByte(attach ? RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS : RESPONSE_WITH_EXCEPTION); - out.writeObject(th); + out.writeThrowable(th); } if (attach) { diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileContent/fileContent.lock b/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileContent/fileContent.lock deleted file mode 100644 index 2c23b323efcc4734a005d6769c1065136f2a77dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 VcmZQ}+r5eH?vzYn1~6bO2LLab1R?+c diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileHashes/fileHashes.lock b/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileHashes/fileHashes.lock deleted file mode 100644 index 49305170c43c786d400d49b2a1996ae5d74e91e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 VcmZRMT;p5)Rp+w=0~q9}0RS@*1djj! diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock b/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock deleted file mode 100644 index e83e9f9397d42d9276aaebb508af4f563709b8d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 UcmZQ}zaJp#boZkt0|bNt05Bc|J^%m! diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/taskHistory/taskHistory.lock b/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/taskHistory/taskHistory.lock deleted file mode 100644 index 46a3559812da2041bf74da374b036f18102a1ebb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 VcmZQ(6u5Nn(hrGa3}C>#8UQsN1sebW diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock deleted file mode 100644 index bdc02da418e45bdb78eaf8e7a7df1da0ae636483..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17 UcmZQ}b#>JgwZGcR00!(g03Z+pi2wiq diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_plugin.cpp b/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_plugin.cpp deleted file mode 100644 index b2cbd0bae1..0000000000 --- a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_plugin.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Generates Java gRPC service interface out of Protobuf IDL. -// -// This is a Proto2 compiler plugin. See net/proto2/compiler/proto/plugin.proto -// and net/proto2/compiler/public/plugin.h for more information on plugins. - -#include - -#include "java_generator.h" -#include -#include -#include -#include - -static string JavaPackageToDir(const string& package_name) { - string package_dir = package_name; - for (size_t i = 0; i < package_dir.size(); ++i) { - if (package_dir[i] == '.') { - package_dir[i] = '/'; - } - } - if (!package_dir.empty()) package_dir += "/"; - return package_dir; -} - -class JavaGrpcGenerator : public google::protobuf::compiler::CodeGenerator { - public: - JavaGrpcGenerator() {} - virtual ~JavaGrpcGenerator() {} - - virtual bool Generate(const google::protobuf::FileDescriptor* file, - const string& parameter, - google::protobuf::compiler::GeneratorContext* context, - string* error) const { - std::vector > options; - google::protobuf::compiler::ParseGeneratorParameter(parameter, &options); - - java_grpc_generator::ProtoFlavor flavor = - java_grpc_generator::ProtoFlavor::NORMAL; - - bool disable_version = false; - for (size_t i = 0; i < options.size(); i++) { - if (options[i].first == "nano") { - flavor = java_grpc_generator::ProtoFlavor::NANO; - } else if (options[i].first == "lite") { - flavor = java_grpc_generator::ProtoFlavor::LITE; - } else if (options[i].first == "noversion") { - disable_version = true; - } - } - - string package_name = java_grpc_generator::ServiceJavaPackage( - file, flavor == java_grpc_generator::ProtoFlavor::NANO); - string package_filename = JavaPackageToDir(package_name); - for (int i = 0; i < file->service_count(); ++i) { - const google::protobuf::ServiceDescriptor* service = file->service(i); - string filename = package_filename - + java_grpc_generator::ServiceClassName(service) + ".java"; - std::unique_ptr output( - context->Open(filename)); - java_grpc_generator::GenerateService( - service, output.get(), flavor, disable_version); - } - return true; - } -}; - -int main(int argc, char* argv[]) { - JavaGrpcGenerator generator; - return google::protobuf::compiler::PluginMain(argc, argv, &generator); -} diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java index 73fd8040f5..ee9d7ebad2 100644 --- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java +++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java @@ -60,6 +60,7 @@ public class GrpcProtocol extends AbstractProxyProtocol { String key = url.getAddress(); GrpcServer grpcServer = serverMap.computeIfAbsent(key, k -> { DubboHandlerRegistry registry = new DubboHandlerRegistry(); + Server originalServer = ServerBuilder .forPort(url.getPort()) .fallbackHandlerRegistry(registry) diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcServerUtils.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcServerUtils.java new file mode 100644 index 0000000000..e0007e3594 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcServerUtils.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.rpc.protocol.grpc; + +import org.apache.dubbo.common.URL; + +import io.grpc.ManagedChannelBuilder; +import io.grpc.ServerBuilder; + +/** + * Support gRPC configs in the Dubbo specific way. + */ +public class GrpcServerUtils { + + public static void configureServer(URL url, ServerBuilder builder) { + + } + + public static void configureChannel(URL url, ManagedChannelBuilder builder) { + + } +} diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java index 1d8646e880..e4c82644d8 100644 --- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java +++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java @@ -25,14 +25,19 @@ import java.lang.reflect.Type; public interface ObjectInput extends DataInput { /** - * read object + * Consider use {@link #readObject(Class)} or {@link #readObject(Class, Type)} where possible * * @return object * @throws IOException if an I/O error occurs * @throws ClassNotFoundException if an ClassNotFoundException occurs */ + @Deprecated Object readObject() throws IOException, ClassNotFoundException; + default Object readThrowable() throws IOException, ClassNotFoundException { + return readObject(); + } + /** * read object * diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java index 73fa3b61fd..a5f71919d1 100644 --- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java +++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java @@ -30,4 +30,28 @@ public interface ObjectOutput extends DataOutput { */ void writeObject(Object obj) throws IOException; + /** + * The following methods are customized for the requirement of Dubbo's RPC protocol implementation. Legacy protocol + * implementation will try to write Map, Throwable and Null value directly to the stream, which does not meet the + * restrictions of all serialization protocols. + *

+ * See ProtobufSerialization, KryoSerialization for more details. + *

+ * The binding of RPC protocol and biz serialization protocol is not a good practice. The encoding of RPC protocol + * should be highly independent and portable, easy to cross platforms and languages, for example, like the http headers, + * restricting the headers / attachments to Ascii strings and uses ISO_8859_1 to encode. + * https://tools.ietf.org/html/rfc7540#section-8.1.2 + */ + default void writeThrowable(Object obj) throws IOException { + writeObject(obj); + } + + default void writeEvent(String data) throws IOException { + writeObject(data); + } + + default void writeAttachments(Object obj) throws IOException { + + } + } \ No newline at end of file diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectInput2.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectInput2.java new file mode 100644 index 0000000000..71670d9887 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectInput2.java @@ -0,0 +1,170 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.serialize.kryo.optimized; + +import org.apache.dubbo.common.serialize.Cleanable; +import org.apache.dubbo.common.serialize.ObjectInput; +import org.apache.dubbo.common.serialize.kryo.utils.KryoUtils; + +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.KryoException; +import com.esotericsoftware.kryo.io.Input; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; + +/** + * Kryo object input implementation, kryo object can be clean + */ +public class KryoObjectInput2 implements ObjectInput, Cleanable { + + private Kryo kryo; + private Input input; + + public KryoObjectInput2(InputStream inputStream) { + input = new Input(inputStream); + this.kryo = KryoUtils.get(); + } + + @Override + public boolean readBool() throws IOException { + try { + return input.readBoolean(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + @Override + public byte readByte() throws IOException { + try { + return input.readByte(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + @Override + public short readShort() throws IOException { + try { + return input.readShort(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + @Override + public int readInt() throws IOException { + try { + return input.readInt(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + @Override + public long readLong() throws IOException { + try { + return input.readLong(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + @Override + public float readFloat() throws IOException { + try { + return input.readFloat(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + @Override + public double readDouble() throws IOException { + try { + return input.readDouble(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + @Override + public byte[] readBytes() throws IOException { + try { + int len = input.readInt(); + if (len < 0) { + return null; + } else if (len == 0) { + return new byte[]{}; + } else { + return input.readBytes(len); + } + } catch (KryoException e) { + throw new IOException(e); + } + } + + @Override + public String readUTF() throws IOException { + try { + return input.readString(); + } catch (KryoException e) { + throw new IOException(e); + } + } + + /** + * works as the only endpoint + * + * @return + * @throws IOException + * @throws ClassNotFoundException + */ + @Override + public Object readObject() throws IOException, ClassNotFoundException { + try { + return kryo.readObjectOrNull(input, String.class); + } catch (KryoException e) { + throw new IOException(e); + } + } + + @Override + public Object readThrowable() throws IOException, ClassNotFoundException { + return kryo.readClassAndObject(input); + } + + @Override + @SuppressWarnings("unchecked") + public T readObject(Class clazz) throws IOException, ClassNotFoundException { + return kryo.readObjectOrNull(input, clazz); + } + + @Override + @SuppressWarnings("unchecked") + public T readObject(Class clazz, Type type) throws IOException, ClassNotFoundException { + return readObject(clazz); + } + + @Override + public void cleanup() { + KryoUtils.release(kryo); + kryo = null; + } +} diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectOutput2.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectOutput2.java new file mode 100644 index 0000000000..8500a06b7e --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectOutput2.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.serialize.kryo.optimized; + +import org.apache.dubbo.common.serialize.Cleanable; +import org.apache.dubbo.common.serialize.ObjectOutput; +import org.apache.dubbo.common.serialize.kryo.utils.KryoUtils; + +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Output; + +import java.io.IOException; +import java.io.OutputStream; + +/** + * Kryo object output implementation, kryo object can be clean + */ +public class KryoObjectOutput2 implements ObjectOutput, Cleanable { + + private Output output; + private Kryo kryo; + + public KryoObjectOutput2(OutputStream outputStream) { + output = new Output(outputStream); + this.kryo = KryoUtils.get(); + } + + @Override + public void writeBool(boolean v) throws IOException { + output.writeBoolean(v); + } + + @Override + public void writeByte(byte v) throws IOException { + output.writeByte(v); + } + + @Override + public void writeShort(short v) throws IOException { + output.writeShort(v); + } + + @Override + public void writeInt(int v) throws IOException { + output.writeInt(v); + } + + @Override + public void writeLong(long v) throws IOException { + output.writeLong(v); + } + + @Override + public void writeFloat(float v) throws IOException { + output.writeFloat(v); + } + + @Override + public void writeDouble(double v) throws IOException { + output.writeDouble(v); + } + + @Override + public void writeBytes(byte[] v) throws IOException { + if (v == null) { + output.writeInt(-1); + } else { + writeBytes(v, 0, v.length); + } + } + + @Override + public void writeBytes(byte[] v, int off, int len) throws IOException { + if (v == null) { + output.writeInt(-1); + } else { + output.writeInt(len); + output.write(v, off, len); + } + } + + + @Override + public void writeUTF(String v) throws IOException { + output.writeString(v); + } + + @Override + public void writeObject(Object v) throws IOException { + kryo.writeObjectOrNull(output, v, v.getClass()); + } + + @Override + public void writeThrowable(Object v) throws IOException { + kryo.writeClassAndObject(output, v); + } + + @Override + public void flushBuffer() throws IOException { + output.flush(); + } + + @Override + public void cleanup() { + KryoUtils.release(kryo); + kryo = null; + } +} diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoSerialization2.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoSerialization2.java new file mode 100644 index 0000000000..4bb592399d --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoSerialization2.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.serialize.kryo.optimized; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.serialize.ObjectInput; +import org.apache.dubbo.common.serialize.ObjectOutput; +import org.apache.dubbo.common.serialize.Serialization; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import static org.apache.dubbo.common.serialize.Constants.KRYO_SERIALIZATION_ID; + +/** + * TODO for now kryo serialization doesn't deny classes that don't implement the serializable interface + * + *

+ *     e.g. <dubbo:protocol serialization="kryo" />
+ * 
+ */ +public class KryoSerialization2 implements Serialization { + + @Override + public byte getContentTypeId() { + return KRYO_SERIALIZATION_ID; + } + + @Override + public String getContentType() { + return "x-application/kryo"; + } + + @Override + public ObjectOutput serialize(URL url, OutputStream out) throws IOException { + return new KryoObjectOutput2(out); + } + + @Override + public ObjectInput deserialize(URL url, InputStream is) throws IOException { + return new KryoObjectInput2(is); + } +} diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization b/dubbo-serialization/dubbo-serialization-kryo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization index 531a00804e..331e520ec9 100644 --- a/dubbo-serialization/dubbo-serialization-kryo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization +++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization @@ -1 +1,2 @@ -kryo=org.apache.dubbo.common.serialize.kryo.KryoSerialization \ No newline at end of file +kryo=org.apache.dubbo.common.serialize.kryo.KryoSerialization +kryo2=org.apache.dubbo.common.serialize.kryo.optimized.KryoSerialization2 \ No newline at end of file diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/pom.xml b/dubbo-serialization/dubbo-serialization-protobuf-json/pom.xml deleted file mode 100644 index c39e288f93..0000000000 --- a/dubbo-serialization/dubbo-serialization-protobuf-json/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - 4.0.0 - - org.apache.dubbo - dubbo-serialization - ${revision} - ../pom.xml - - dubbo-serialization-protobuf-json - jar - ${project.artifactId} - The protobuf serialization module of dubbo project - - false - - - - org.apache.dubbo - dubbo-serialization-api - ${project.parent.version} - - - com.google.protobuf - protobuf-java - - - com.google.protobuf - protobuf-java-util - - - diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/MapValue.java b/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/MapValue.java deleted file mode 100644 index fd24618d45..0000000000 --- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/MapValue.java +++ /dev/null @@ -1,830 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ -package org.apache.dubbo.common.serialize.protobuf.support; - -/** - * Generated by the protocol buffer compiler. DO NOT EDIT! - */ -public final class MapValue { - private MapValue() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistryLite registry) { - } - - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - registerAllExtensions( - (com.google.protobuf.ExtensionRegistryLite) registry); - } - public interface MapOrBuilder extends - // @@protoc_insertion_point(interface_extends:Map) - com.google.protobuf.MessageOrBuilder { - - /** - * map<string, string> attachments = 1; - */ - int getAttachmentsCount(); - /** - * map<string, string> attachments = 1; - */ - boolean containsAttachments( - String key); - /** - * Use {@link #getAttachmentsMap()} instead. - */ - @Deprecated - java.util.Map - getAttachments(); - /** - * map<string, string> attachments = 1; - */ - java.util.Map - getAttachmentsMap(); - /** - * map<string, string> attachments = 1; - */ - - String getAttachmentsOrDefault( - String key, - String defaultValue); - /** - * map<string, string> attachments = 1; - */ - - String getAttachmentsOrThrow( - String key); - } - /** - * Protobuf type {@code Map} - */ - public static final class Map extends - com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:Map) - MapOrBuilder { - private static final long serialVersionUID = 0L; - // Use Map.newBuilder() to construct. - private Map(com.google.protobuf.GeneratedMessageV3.Builder builder) { - super(builder); - } - private Map() { - } - - @Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private Map( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - this(); - if (extensionRegistry == null) { - throw new NullPointerException(); - } - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) { - attachments_ = com.google.protobuf.MapField.newMapField( - AttachmentsDefaultEntryHolder.defaultEntry); - mutable_bitField0_ |= 0x00000001; - } - com.google.protobuf.MapEntry - attachments__ = input.readMessage( - AttachmentsDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - attachments_.getMutableMap().put( - attachments__.getKey(), attachments__.getValue()); - break; - } - default: { - if (!parseUnknownFieldProto3( - input, unknownFields, extensionRegistry, tag)) { - done = true; - } - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return MapValue.internal_static_Map_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @Override - protected com.google.protobuf.MapField internalGetMapField( - int number) { - switch (number) { - case 1: - return internalGetAttachments(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @Override - protected FieldAccessorTable - internalGetFieldAccessorTable() { - return MapValue.internal_static_Map_fieldAccessorTable - .ensureFieldAccessorsInitialized( - Map.class, Builder.class); - } - - public static final int ATTACHMENTS_FIELD_NUMBER = 1; - private static final class AttachmentsDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - String, String> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - MapValue.internal_static_Map_AttachmentsEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - private com.google.protobuf.MapField< - String, String> attachments_; - private com.google.protobuf.MapField - internalGetAttachments() { - if (attachments_ == null) { - return com.google.protobuf.MapField.emptyMapField( - AttachmentsDefaultEntryHolder.defaultEntry); - } - return attachments_; - } - - @Override - public int getAttachmentsCount() { - return internalGetAttachments().getMap().size(); - } - /** - * map<string, string> attachments = 1; - */ - - @Override - public boolean containsAttachments( - String key) { - if (key == null) { throw new NullPointerException(); } - return internalGetAttachments().getMap().containsKey(key); - } - /** - * Use {@link #getAttachmentsMap()} instead. - */ - @Override - @Deprecated - public java.util.Map getAttachments() { - return getAttachmentsMap(); - } - /** - * map<string, string> attachments = 1; - */ - - @Override - public java.util.Map getAttachmentsMap() { - return internalGetAttachments().getMap(); - } - /** - * map<string, string> attachments = 1; - */ - - @Override - public String getAttachmentsOrDefault( - String key, - String defaultValue) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetAttachments().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, string> attachments = 1; - */ - - @Override - public String getAttachmentsOrThrow( - String key) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetAttachments().getMap(); - if (!map.containsKey(key)) { - throw new IllegalArgumentException(); - } - return map.get(key); - } - - private byte memoizedIsInitialized = -1; - @Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) { - return true; - } - if (isInitialized == 0) { - return false; - } - - memoizedIsInitialized = 1; - return true; - } - - @Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - com.google.protobuf.GeneratedMessageV3 - .serializeStringMapTo( - output, - internalGetAttachments(), - AttachmentsDefaultEntryHolder.defaultEntry, - 1); - unknownFields.writeTo(output); - } - - @Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) { - return size; - } - - size = 0; - for (java.util.Map.Entry entry - : internalGetAttachments().getMap().entrySet()) { - com.google.protobuf.MapEntry - attachments__ = AttachmentsDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(1, attachments__); - } - size += unknownFields.getSerializedSize(); - memoizedSize = size; - return size; - } - - @Override - public boolean equals(final Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof Map)) { - return super.equals(obj); - } - Map other = (Map) obj; - - boolean result = true; - result = result && internalGetAttachments().equals( - other.internalGetAttachments()); - result = result && unknownFields.equals(other.unknownFields); - return result; - } - - @Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - if (!internalGetAttachments().getMap().isEmpty()) { - hash = (37 * hash) + ATTACHMENTS_FIELD_NUMBER; - hash = (53 * hash) + internalGetAttachments().hashCode(); - } - hash = (29 * hash) + unknownFields.hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static Map parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static Map parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static Map parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static Map parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static Map parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static Map parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static Map parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - public static Map parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - public static Map parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); - } - public static Map parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static Map parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - public static Map parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(Map prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @Override - protected Builder newBuilderForType( - BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code Map} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:Map) - MapOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return MapValue.internal_static_Map_descriptor; - } - - @Override - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMapField( - int number) { - switch (number) { - case 1: - return internalGetAttachments(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @Override - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMutableMapField( - int number) { - switch (number) { - case 1: - return internalGetMutableAttachments(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @Override - protected FieldAccessorTable - internalGetFieldAccessorTable() { - return MapValue.internal_static_Map_fieldAccessorTable - .ensureFieldAccessorsInitialized( - Map.class, Builder.class); - } - - // Construct using org.apache.dubbo.common.serialize.protobuf.support.MapValue.Map.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { - } - } - @Override - public Builder clear() { - super.clear(); - internalGetMutableAttachments().clear(); - return this; - } - - @Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return MapValue.internal_static_Map_descriptor; - } - - @Override - public Map getDefaultInstanceForType() { - return Map.getDefaultInstance(); - } - - @Override - public Map build() { - Map result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @Override - public Map buildPartial() { - Map result = new Map(this); - int from_bitField0_ = bitField0_; - result.attachments_ = internalGetAttachments(); - result.attachments_.makeImmutable(); - onBuilt(); - return result; - } - - @Override - public Builder clone() { - return (Builder) super.clone(); - } - @Override - public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); - } - @Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); - } - @Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); - } - @Override - public Builder setRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); - } - @Override - public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); - } - @Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof Map) { - return mergeFrom((Map)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(Map other) { - if (other == Map.getDefaultInstance()) { - return this; - } - internalGetMutableAttachments().mergeFrom( - other.internalGetAttachments()); - this.mergeUnknownFields(other.unknownFields); - onChanged(); - return this; - } - - @Override - public final boolean isInitialized() { - return true; - } - - @Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - Map parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (Map) e.getUnfinishedMessage(); - throw e.unwrapIOException(); - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - private com.google.protobuf.MapField< - String, String> attachments_; - private com.google.protobuf.MapField - internalGetAttachments() { - if (attachments_ == null) { - return com.google.protobuf.MapField.emptyMapField( - AttachmentsDefaultEntryHolder.defaultEntry); - } - return attachments_; - } - private com.google.protobuf.MapField - internalGetMutableAttachments() { - onChanged();; - if (attachments_ == null) { - attachments_ = com.google.protobuf.MapField.newMapField( - AttachmentsDefaultEntryHolder.defaultEntry); - } - if (!attachments_.isMutable()) { - attachments_ = attachments_.copy(); - } - return attachments_; - } - - @Override - public int getAttachmentsCount() { - return internalGetAttachments().getMap().size(); - } - /** - * map<string, string> attachments = 1; - */ - - @Override - public boolean containsAttachments( - String key) { - if (key == null) { throw new NullPointerException(); } - return internalGetAttachments().getMap().containsKey(key); - } - /** - * Use {@link #getAttachmentsMap()} instead. - */ - @Override - @Deprecated - public java.util.Map getAttachments() { - return getAttachmentsMap(); - } - /** - * map<string, string> attachments = 1; - */ - - @Override - public java.util.Map getAttachmentsMap() { - return internalGetAttachments().getMap(); - } - /** - * map<string, string> attachments = 1; - */ - - @Override - public String getAttachmentsOrDefault( - String key, - String defaultValue) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetAttachments().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, string> attachments = 1; - */ - - @Override - public String getAttachmentsOrThrow( - String key) { - if (key == null) { throw new NullPointerException(); } - java.util.Map map = - internalGetAttachments().getMap(); - if (!map.containsKey(key)) { - throw new IllegalArgumentException(); - } - return map.get(key); - } - - public Builder clearAttachments() { - internalGetMutableAttachments().getMutableMap() - .clear(); - return this; - } - /** - * map<string, string> attachments = 1; - */ - - public Builder removeAttachments( - String key) { - if (key == null) { throw new NullPointerException(); } - internalGetMutableAttachments().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @Deprecated - public java.util.Map - getMutableAttachments() { - return internalGetMutableAttachments().getMutableMap(); - } - /** - * map<string, string> attachments = 1; - */ - public Builder putAttachments( - String key, - String value) { - if (key == null) { throw new NullPointerException(); } - if (value == null) { throw new NullPointerException(); } - internalGetMutableAttachments().getMutableMap() - .put(key, value); - return this; - } - /** - * map<string, string> attachments = 1; - */ - - public Builder putAllAttachments( - java.util.Map values) { - internalGetMutableAttachments().getMutableMap() - .putAll(values); - return this; - } - @Override - public final Builder setUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return super.setUnknownFieldsProto3(unknownFields); - } - - @Override - public final Builder mergeUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return super.mergeUnknownFields(unknownFields); - } - - - // @@protoc_insertion_point(builder_scope:Map) - } - - // @@protoc_insertion_point(class_scope:Map) - private static final Map DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new Map(); - } - - public static Map getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @Override - public Map parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new Map(input, extensionRegistry); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @Override - public Map getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - - } - - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Map_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_Map_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_Map_AttachmentsEntry_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_Map_AttachmentsEntry_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { - return descriptor; - } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; - static { - String[] descriptorData = { - "\n\tmap.proto\"e\n\003Map\022*\n\013attachments\030\001 \003(\0132" + - "\025.Map.AttachmentsEntry\0322\n\020AttachmentsEnt" + - "ry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001B>\n2or" + - "g.apache.dubbo.common.serialize.protobuf" + - ".supportB\010MapValueb\006proto3" - }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { - @Override - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); - internal_static_Map_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_Map_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Map_descriptor, - new String[] { "Attachments", }); - internal_static_Map_AttachmentsEntry_descriptor = - internal_static_Map_descriptor.getNestedTypes().get(0); - internal_static_Map_AttachmentsEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_Map_AttachmentsEntry_descriptor, - new String[] { "Key", "Value", }); - } - - // @@protoc_insertion_point(outer_class_scope) -} diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java b/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java deleted file mode 100644 index 7a2eda8814..0000000000 --- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ -package org.apache.dubbo.common.serialize.protobuf.support; - -import com.google.protobuf.GeneratedMessageV3; -import com.google.protobuf.GeneratedMessageV3.Builder; -import com.google.protobuf.InvalidProtocolBufferException; -import com.google.protobuf.MessageOrBuilder; -import com.google.protobuf.util.JsonFormat; -import com.google.protobuf.util.JsonFormat.Printer; - -import java.lang.reflect.Method; - -public class ProtobufUtils { - - static boolean isSupported(Class clazz) { - if (clazz == null) { - return false; - } - - if (GeneratedMessageV3.class.isAssignableFrom(clazz)) { - return true; - } - return false; - } - - static T deserialize(String json, Class requestClass) throws InvalidProtocolBufferException { - Builder builder; - try { - builder = getMessageBuilder(requestClass); - } catch (Exception e) { - throw new IllegalArgumentException("Get google protobuf message builder from " + requestClass.getName() + "failed", e); - } - JsonFormat.parser().merge(json, builder); - return (T) builder.build(); - } - - static String serialize(Object value) throws InvalidProtocolBufferException { - Printer printer = JsonFormat.printer().omittingInsignificantWhitespace(); - return printer.print((MessageOrBuilder) value); - } - - private static Builder getMessageBuilder(Class requestType) throws Exception { - Method method = requestType.getMethod("newBuilder"); - return (Builder) method.invoke(null, null); - } -} \ No newline at end of file diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization b/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization deleted file mode 100644 index 56d6b68bf0..0000000000 --- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization +++ /dev/null @@ -1 +0,0 @@ -protobuf-json=org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufSerialization \ No newline at end of file diff --git a/dubbo-serialization/dubbo-serialization-protobuf/pom.xml b/dubbo-serialization/dubbo-serialization-protobuf/pom.xml new file mode 100644 index 0000000000..eb169424ae --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-protobuf/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + + org.apache.dubbo + dubbo-serialization + ${revision} + ../pom.xml + + dubbo-serialization-protobuf + jar + ${project.artifactId} + The protobuf serialization module of dubbo project + + false + + 1.19.0-SNAPSHOT + + + + org.apache.dubbo + dubbo-serialization-api + ${project.parent.version} + + + com.google.protobuf + protobuf-java + + + com.google.protobuf + protobuf-java-util + + + + + + + kr.motd.maven + os-maven-plugin + 1.6.1 + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + 0.5.1 + + com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier} + grpc-java + + org.apache.dubbo:protoc-gen-grpc-java:${proto_dubbo_plugin_version}:exe:${os.detected.classifier} + + build/generated/source/proto/main/java + false + + dubbo + + + + + compile + compile-custom + test-compile + test-compile-custom + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + generate-sources + + add-source + + + + build/generated/source/proto/main/java + + + + + + + + diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectInput.java similarity index 76% rename from dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java rename to dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectInput.java index 0641c4d820..20d5d477ad 100644 --- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectInput.java @@ -17,10 +17,13 @@ package org.apache.dubbo.common.serialize.protobuf.support; import org.apache.dubbo.common.serialize.ObjectInput; +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.MapValue; +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB; import com.google.protobuf.BoolValue; import com.google.protobuf.BytesValue; import com.google.protobuf.DoubleValue; +import com.google.protobuf.Empty; import com.google.protobuf.FloatValue; import com.google.protobuf.Int32Value; import com.google.protobuf.Int64Value; @@ -37,10 +40,10 @@ import java.util.Map; /** * GenericGoogleProtobuf object input implementation */ -public class GenericProtobufObjectInput implements ObjectInput { +public class GenericProtobufJsonObjectInput implements ObjectInput { private final BufferedReader reader; - public GenericProtobufObjectInput(InputStream in) { + public GenericProtobufJsonObjectInput(InputStream in) { this.reader = new BufferedReader(new InputStreamReader(in)); } @@ -91,7 +94,17 @@ public class GenericProtobufObjectInput implements ObjectInput { @Override public Object readObject() { - throw new UnsupportedOperationException(); + try { + read(Empty.class); + return null; + } catch (Exception e) { + throw new UnsupportedOperationException("Provide the protobuf message type you want to read."); + } + } + + @Override + public Object readThrowable() throws IOException, ClassNotFoundException { + return read(Throwable.class); } @Override @@ -117,12 +130,16 @@ public class GenericProtobufObjectInput implements ObjectInput { if (cls.equals(Map.class)) { // only for attachments String json = readLine(); - return (T) ProtobufUtils.deserialize(json, MapValue.Map.class).getAttachmentsMap(); + return (T) ProtobufUtils.deserializeJson(json, MapValue.Map.class).getAttachmentsMap(); + } else if (getClass().isAssignableFrom(Throwable.class)) { + String json = readLine(); + ThrowablePB.ThrowableProto throwableProto = ProtobufUtils.deserializeJson(json, ThrowablePB.ThrowableProto.class); + return (T) ProtobufUtils.convertToException(throwableProto); } else if (!ProtobufUtils.isSupported(cls)) { throw new IllegalArgumentException("This serialization only support google protobuf entity, the class is :" + cls.getName()); } String json = readLine(); - return ProtobufUtils.deserialize(json, cls); + return ProtobufUtils.deserializeJson(json, cls); } } diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutput.java similarity index 89% rename from dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java rename to dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutput.java index 7384fddcf2..78f6284378 100644 --- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutput.java @@ -17,6 +17,7 @@ package org.apache.dubbo.common.serialize.protobuf.support; import org.apache.dubbo.common.serialize.ObjectOutput; +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.MapValue; import com.google.protobuf.BoolValue; import com.google.protobuf.ByteString; @@ -36,11 +37,11 @@ import java.util.Map; /** * GenericGoogleProtobuf object output implementation */ -public class GenericProtobufObjectOutput implements ObjectOutput { +public class GenericProtobufJsonObjectOutput implements ObjectOutput { private final PrintWriter writer; - public GenericProtobufObjectOutput(OutputStream out) { + public GenericProtobufJsonObjectOutput(OutputStream out) { this.writer = new PrintWriter(new OutputStreamWriter(out)); } @@ -104,11 +105,13 @@ public class GenericProtobufObjectOutput implements ObjectOutput { if (obj instanceof Map) { // only for attachment obj = MapValue.Map.newBuilder().putAllAttachments((Map) obj).build(); + } else if (obj instanceof Throwable && !ProtobufUtils.isSupported(obj.getClass())) { + obj = ProtobufUtils.serializeJson(ProtobufUtils.convertToThrowableProto((Throwable) obj)); } else if (!ProtobufUtils.isSupported(obj.getClass())) { throw new IllegalArgumentException("This serialization only support google protobuf object, the object class is: " + obj.getClass().getName()); } - writer.write(ProtobufUtils.serialize(obj)); + writer.write(ProtobufUtils.serializeJson(obj)); writer.println(); writer.flush(); } diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerialization.java similarity index 90% rename from dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java rename to dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerialization.java index d3d2330017..0d2fae628c 100644 --- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerialization.java @@ -29,9 +29,8 @@ import static org.apache.dubbo.common.serialize.Constants.PROTOBUF_JSON_SERIALIZ /** * This serizalization is use for google protobuf generic reference. * The entity be transported between client and server by json string. - * */ -public class GenericProtobufSerialization implements Serialization { +public class GenericProtobufJsonSerialization implements Serialization { @Override public byte getContentTypeId() { @@ -45,11 +44,11 @@ public class GenericProtobufSerialization implements Serialization { @Override public ObjectOutput serialize(URL url, OutputStream output) { - return new GenericProtobufObjectOutput(output); + return new GenericProtobufJsonObjectOutput(output); } @Override public ObjectInput deserialize(URL url, InputStream input) { - return new GenericProtobufObjectInput(input); + return new GenericProtobufJsonObjectInput(input); } } diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java new file mode 100644 index 0000000000..0ad98d6387 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.serialize.protobuf.support; + +import org.apache.dubbo.common.serialize.ObjectInput; +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.MapValue; +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB; + +import com.google.protobuf.BoolValue; +import com.google.protobuf.BytesValue; +import com.google.protobuf.DoubleValue; +import com.google.protobuf.Empty; +import com.google.protobuf.FloatValue; +import com.google.protobuf.Int32Value; +import com.google.protobuf.Int64Value; +import com.google.protobuf.StringValue; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.util.Map; + +public class GenericProtobufObjectInput implements ObjectInput { + private final InputStream is; + + public GenericProtobufObjectInput(InputStream is) { + this.is = is; + } + + @Override + public boolean readBool() throws IOException { + return read(BoolValue.class).getValue(); + } + + @Override + public byte readByte() throws IOException { + return (byte) read(Int32Value.class).getValue(); + } + + @Override + public short readShort() throws IOException { + return (short) read(Int32Value.class).getValue(); + } + + @Override + public int readInt() throws IOException { + return read(Int32Value.class).getValue(); + } + + @Override + public long readLong() throws IOException { + return read(Int64Value.class).getValue(); + } + + @Override + public float readFloat() throws IOException { + return read(FloatValue.class).getValue(); + } + + @Override + public double readDouble() throws IOException { + return read(DoubleValue.class).getValue(); + } + + @Override + public String readUTF() throws IOException { + return read(StringValue.class).getValue(); + } + + @Override + public byte[] readBytes() throws IOException { + return read(BytesValue.class).getValue().toByteArray(); + } + + /** + * FIXME assume this method only has the following single entry point: + * DecodeableRpcResult#readValue, decode empty value for heart beat event. + *

+ * Avoid using readObject, always try to pass the target class type for the data you want to read. + * + * @return + */ + @Deprecated + @Override + public Object readObject() { + try { + read(Empty.class); + return null; + } catch (Exception e) { + throw new UnsupportedOperationException("Provide the protobuf message type you want to read."); + } + } + + @Override + public Object readThrowable() throws IOException, ClassNotFoundException { + return read(Throwable.class); + } + + @Override + public T readObject(Class cls) throws IOException { + return read(cls); + } + + @Override + public T readObject(Class cls, Type type) throws IOException { + return readObject(cls); + } + + @SuppressWarnings("unchecked") + private T read(Class cls) throws IOException { + if (cls.isAssignableFrom(Map.class)) { + // only for attachments + return (T) ProtobufUtils.deserialize(is, MapValue.Map.class).getAttachmentsMap(); + } else if (getClass().isAssignableFrom(Throwable.class)) { + ThrowablePB.ThrowableProto throwableProto = ProtobufUtils.deserialize(is, ThrowablePB.ThrowableProto.class); + return (T) ProtobufUtils.convertToException(throwableProto); + } else if (!ProtobufUtils.isSupported(cls)) { + throw new IllegalArgumentException("This serialization only support google protobuf entity, the class is :" + cls.getName()); + } + + return ProtobufUtils.deserialize(is, cls); + } +} diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java new file mode 100644 index 0000000000..c6eed65d36 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java @@ -0,0 +1,141 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.serialize.protobuf.support; + +import org.apache.dubbo.common.serialize.ObjectOutput; +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.MapValue; + +import com.google.protobuf.BoolValue; +import com.google.protobuf.ByteString; +import com.google.protobuf.BytesValue; +import com.google.protobuf.DoubleValue; +import com.google.protobuf.FloatValue; +import com.google.protobuf.Int32Value; +import com.google.protobuf.Int64Value; +import com.google.protobuf.MessageLite; +import com.google.protobuf.StringValue; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; + +/** + * GenericGoogleProtobuf object output implementation + */ +public class GenericProtobufObjectOutput implements ObjectOutput { + + private final OutputStream os; + + public GenericProtobufObjectOutput(OutputStream os) { + this.os = os; + } + + @Override + public void writeBool(boolean v) throws IOException { + + writeObject(BoolValue.newBuilder().setValue(v).build()); + } + + @Override + public void writeByte(byte v) throws IOException { + writeObject(Int32Value.newBuilder().setValue((v)).build()); + } + + @Override + public void writeShort(short v) throws IOException { + writeObject(Int32Value.newBuilder().setValue(v).build()); + } + + @Override + public void writeInt(int v) throws IOException { + writeObject(Int32Value.newBuilder().setValue(v).build()); + } + + @Override + public void writeLong(long v) throws IOException { + writeObject(Int64Value.newBuilder().setValue(v).build()); + } + + @Override + public void writeFloat(float v) throws IOException { + writeObject(FloatValue.newBuilder().setValue(v).build()); + } + + @Override + public void writeDouble(double v) throws IOException { + writeObject(DoubleValue.newBuilder().setValue(v).build()); + } + + @Override + public void writeUTF(String v) throws IOException { + writeObject(StringValue.newBuilder().setValue(v).build()); + } + + @Override + public void writeBytes(byte[] b) throws IOException { + writeObject(BytesValue.newBuilder().setValue(ByteString.copyFrom(b)).build()); + } + + @Override + public void writeBytes(byte[] b, int off, int len) throws IOException { + writeObject(BytesValue.newBuilder().setValue(ByteString.copyFrom(b, off, len)).build()); + } + + @SuppressWarnings("unchecked") + @Override + public void writeObject(Object obj) throws IOException { + /** + * Protobuf does not allow writing of non-protobuf generated message, including null value. + * Writing of null value from developers should be denied immediately by throwing exception. + */ + if (obj == null) { + throw new IllegalStateException("This serialization only supports google protobuf objects, " + + "please use com.google.protobuf.Empty instead if you want to transmit null values."); + // obj = ProtobufUtils.convertNullToEmpty(); + } + if (obj instanceof Map) { + // only for attachment + obj = MapValue.Map.newBuilder().putAllAttachments((Map) obj).build(); + } else if (!ProtobufUtils.isSupported(obj.getClass())) { + throw new IllegalArgumentException("This serialization only supports google protobuf objects, current object class is: " + obj.getClass().getName()); + } + + ProtobufUtils.serialize(obj, os); + os.flush(); + } + + @Override + public void writeEvent(String data) throws IOException { + if (data == null) { + data = "H"; + } + writeUTF(data); + } + + @Override + public void writeThrowable(Object obj) throws IOException { + if (obj instanceof Throwable && !(obj instanceof MessageLite)) { + obj = ProtobufUtils.convertToThrowableProto((Throwable) obj); + } + } + + @Override + public void flushBuffer() throws IOException { + os.flush(); + } + +} \ No newline at end of file diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java new file mode 100644 index 0000000000..c2a5afdfe4 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.serialize.protobuf.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.serialize.ObjectInput; +import org.apache.dubbo.common.serialize.ObjectOutput; +import org.apache.dubbo.common.serialize.Serialization; + +import java.io.InputStream; +import java.io.OutputStream; + +import static org.apache.dubbo.common.serialize.Constants.PROTOBUF_JSON_SERIALIZATION_ID; + +/** + *

+ * Currently, the Dubbo protocol / framework data, such as attachments, event data, etc., + * depends on business layer serialization protocol to do serialization before transmitted. + * That's a problem when using Protobuf as business serialization protocol, because Protobuf does not support raw java Object types, + * to solve it, we can use one of the following methods: + * + *

    + *
  • 1. Package these data with Protobuf so that they can be serialized.
  • + *
  • 2. Separate the serialization of Dubbo protocol/framework and the service args (easy to cross-platform, cross-language serialization) to avoid the binding of this part and serialization protocol.
  • + *
+ * + *

+ */ +public class GenericProtobufSerialization implements Serialization { + + @Override + public byte getContentTypeId() { + return PROTOBUF_JSON_SERIALIZATION_ID; + } + + @Override + public String getContentType() { + return "text/json"; + } + + @Override + public ObjectOutput serialize(URL url, OutputStream output) { + return new GenericProtobufJsonObjectOutput(output); + } + + @Override + public ObjectInput deserialize(URL url, InputStream input) { + return new GenericProtobufJsonObjectInput(input); + } +} diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java new file mode 100644 index 0000000000..56b2f9082f --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java @@ -0,0 +1,193 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.serialize.protobuf.support; + +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.MapValue; +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB.StackTraceElementProto; +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB.ThrowableProto; + +import com.google.common.base.Strings; +import com.google.protobuf.CodedInputStream; +import com.google.protobuf.Empty; +import com.google.protobuf.ExtensionRegistryLite; +import com.google.protobuf.GeneratedMessageV3; +import com.google.protobuf.GeneratedMessageV3.Builder; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.MessageLite; +import com.google.protobuf.MessageOrBuilder; +import com.google.protobuf.Parser; +import com.google.protobuf.util.JsonFormat; +import com.google.protobuf.util.JsonFormat.Printer; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Method; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public class ProtobufUtils { + + static boolean isSupported(Class clazz) { + if (clazz == null) { + return false; + } + + if (GeneratedMessageV3.class.isAssignableFrom(clazz)) { + return true; + } + return false; + } + + /* Protobuf json */ + + static T deserializeJson(String json, Class requestClass) throws InvalidProtocolBufferException { + Builder builder; + try { + builder = getMessageBuilder(requestClass); + } catch (Exception e) { + throw new IllegalArgumentException("Get google protobuf message builder from " + requestClass.getName() + "failed", e); + } + JsonFormat.parser().merge(json, builder); + return (T) builder.build(); + } + + static String serializeJson(Object value) throws InvalidProtocolBufferException { + Printer printer = JsonFormat.printer().omittingInsignificantWhitespace(); + return printer.print((MessageOrBuilder) value); + } + + private static Builder getMessageBuilder(Class requestType) throws Exception { + Method method = requestType.getMethod("newBuilder"); + return (Builder) method.invoke(null, null); + } + + + /* Protobuf */ + + private static ConcurrentMap, MessageMarshaller> marshallers = + new ConcurrentHashMap<>(); + + private static volatile ExtensionRegistryLite globalRegistry = + ExtensionRegistryLite.getEmptyRegistry(); + + static { + // Builtin types needed to be registered in advance + marshaller(MapValue.Map.getDefaultInstance()); + marshaller(Empty.getDefaultInstance()); + marshaller(ThrowableProto.getDefaultInstance()); + } + + public static void marshaller(T defaultInstance) { + marshallers.put(defaultInstance.getClass(), new MessageMarshaller<>(defaultInstance)); + } + + static void serialize(Object value, OutputStream os) throws IOException { + MessageLite messageLite = (MessageLite) value; + messageLite.writeTo(os); + } + + @SuppressWarnings("unchecked") + static T deserialize(InputStream is, Class requestClass) throws InvalidProtocolBufferException { + MessageMarshaller marshaller = marshallers.get(requestClass); + if (marshaller == null) { + throw new IllegalStateException(String.format("Protobuf classes should be registered in advance before " + + "do serialization, class name: %s", requestClass.getName())); + } + return (T) marshaller.parse(is); + } + + public static Empty convertNullToEmpty() { + return Empty.newBuilder().build(); + } + + public static Object convertEmptyToNull(Empty empty) { + return null; + } + + public static ThrowableProto convertToThrowableProto(Throwable throwable) { + final ThrowableProto.Builder builder = ThrowableProto.newBuilder(); + builder.setOriginalClassName(throwable.getClass().getCanonicalName()); + builder.setOriginalMessage(Strings.nullToEmpty(throwable.getMessage())); + + for (StackTraceElement e : throwable.getStackTrace()) { + builder.addStackTrace(toStackTraceElement(e)); + } + + if (throwable.getCause() != null) { + builder.setCause(convertToThrowableProto(throwable.getCause())); + } + return builder.build(); + } + + public static Throwable convertToException(ThrowableProto throwableProto) { + return new ProtobufWrappedException(throwableProto); + } + + private static StackTraceElementProto toStackTraceElement(StackTraceElement element) { + final StackTraceElementProto.Builder builder = + StackTraceElementProto.newBuilder() + .setClassName(element.getClassName()) + .setMethodName(element.getMethodName()) + .setLineNumber(element.getLineNumber()); + if (element.getFileName() != null) { + builder.setFileName(element.getFileName()); + } + return builder.build(); + } + + private static final class MessageMarshaller { + private final Parser parser; + private final T defaultInstance; + + @SuppressWarnings("unchecked") + MessageMarshaller(T defaultInstance) { + this.defaultInstance = defaultInstance; + parser = (Parser) defaultInstance.getParserForType(); + } + + + @SuppressWarnings("unchecked") + public Class getMessageClass() { + // Precisely T since protobuf doesn't let messages extend other messages. + return (Class) defaultInstance.getClass(); + } + + public T getMessagePrototype() { + return defaultInstance; + } + + public T parse(InputStream stream) throws InvalidProtocolBufferException { + CodedInputStream cis = CodedInputStream.newInstance(stream); + // Pre-create the CodedInputStream so that we can remove the size limit restriction + // when parsing. + cis.setSizeLimit(Integer.MAX_VALUE); + return parseFrom(cis); + } + + private T parseFrom(CodedInputStream stream) throws InvalidProtocolBufferException { + T message = parser.parseFrom(stream, globalRegistry); + try { + stream.checkLastTagWas(0); + return message; + } catch (InvalidProtocolBufferException e) { + e.setUnfinishedMessage(message); + throw e; + } + } + } +} \ No newline at end of file diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufWrappedException.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufWrappedException.java new file mode 100644 index 0000000000..83939a97cb --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufWrappedException.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.serialize.protobuf.support; + +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB; +import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB.ThrowableProto; + +import com.google.common.base.Strings; + +/** + * For protobuf, all server side exceptions should be wrapped using this specific one. + */ +public class ProtobufWrappedException extends RuntimeException { + + private static final long serialVersionUID = -1792808536714102039L; + + private String originalClassName; + private String originalMessage; + + public ProtobufWrappedException(ThrowableProto throwableProto) { + super(throwableProto.getOriginalClassName() + ": " + throwableProto.getOriginalMessage()); + + originalClassName = throwableProto.getOriginalClassName(); + originalMessage = throwableProto.getOriginalMessage(); + + if (throwableProto.getStackTraceCount() > 0) { + setStackTrace(throwableProto.getStackTraceList().stream() + .map(ProtobufWrappedException::toStackTraceElement) + .toArray(StackTraceElement[]::new)); + } + + if (throwableProto.hasCause()) { + initCause(new ProtobufWrappedException(throwableProto.getCause())); + } + } + + public String getOriginalClassName() { + return originalClassName; + } + + public String getOriginalMessage() { + return originalMessage; + } + + private static StackTraceElement toStackTraceElement(ThrowablePB.StackTraceElementProto proto) { + return new StackTraceElement( + proto.getClassName(), + proto.getMethodName(), + Strings.emptyToNull(proto.getFileName()), + proto.getLineNumber()); + } + +} + diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/MapValue.proto b/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/MapValue.proto new file mode 100644 index 0000000000..bb52c240b2 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/MapValue.proto @@ -0,0 +1,26 @@ +// Copyright 2018 LINE Corporation +// +// LINE Corporation licenses this file to you 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: +// +// https://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. + +// Messages used for transporting debug information between server and client. + +syntax = "proto3"; + +package org.apache.dubbo.common.serialize.protobuf.support.wrapper; + +option java_package = "org.apache.dubbo.common.serialize.protobuf.support.wrapper"; +option java_multiple_files = false; + +message Map{ + map attachments = 1; +} \ No newline at end of file diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/ThrowablePB.proto b/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/ThrowablePB.proto new file mode 100644 index 0000000000..2937d79d5a --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/ThrowablePB.proto @@ -0,0 +1,63 @@ +// Copyright 2018 LINE Corporation +// +// LINE Corporation licenses this file to you 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: +// +// https://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. + +// Messages used for transporting debug information between server and client. + +syntax = "proto3"; + +package org.apache.dubbo.common.serialize.protobuf.support.wrapper; + +option java_package = "org.apache.dubbo.common.serialize.protobuf.support.wrapper"; +option java_multiple_files = false; + +// An element in a stack trace, based on the Java type of the same name. +// +// See: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/StackTraceElement.html +message StackTraceElementProto { + // The fully qualified name of the class containing the execution point + // represented by the stack trace element. + string class_name = 1; + + // The name of the method containing the execution point represented by the + // stack trace element + string method_name = 2; + + // The name of the file containing the execution point represented by the + // stack trace element, or null if this information is unavailable. + string file_name = 3; + + // The line number of the source line containing the execution point represented + // by this stack trace element, or a negative number if this information is + // unavailable. + int32 line_number = 4; +} + +// An exception that was thrown by some code, based on the Java type of the same name. +// +// See: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Throwable.html +message ThrowableProto { + // The name of the class of the exception that was actually thrown. Downstream readers + // of this message may or may not have the actual class available to initialize, so + // this is just used to prefix the message of a generic exception type. + string original_class_name = 1; + + // The message of this throwable. Not filled if there is no message. + string original_message = 2; + + // The stack trace of this Throwable. + repeated StackTraceElementProto stack_trace = 3; + + // The cause of this Throwable. Not filled if there is no cause. + ThrowableProto cause = 4; +} diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization b/dubbo-serialization/dubbo-serialization-protobuf/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization new file mode 100644 index 0000000000..b18b8be488 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization @@ -0,0 +1,2 @@ +protobuf-json=org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufJsonSerialization +protobuf=org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufSerialization \ No newline at end of file diff --git a/dubbo-serialization/dubbo-serialization-test/pom.xml b/dubbo-serialization/dubbo-serialization-test/pom.xml index 6799a9cdf1..122b15b7a5 100644 --- a/dubbo-serialization/dubbo-serialization-test/pom.xml +++ b/dubbo-serialization/dubbo-serialization-test/pom.xml @@ -80,7 +80,7 @@
org.apache.dubbo - dubbo-serialization-protobuf-json + dubbo-serialization-protobuf ${project.parent.version} diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/AbstractProtobufSerializationTest.java b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/AbstractProtobufSerializationTest.java new file mode 100644 index 0000000000..65bec38971 --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/AbstractProtobufSerializationTest.java @@ -0,0 +1,360 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.serialize.protobuf.support; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.serialize.ObjectInput; +import org.apache.dubbo.common.serialize.ObjectOutput; +import org.apache.dubbo.common.serialize.Serialization; +import org.apache.dubbo.common.serialize.protobuf.support.model.GooglePB; + +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.fail; + +public class AbstractProtobufSerializationTest { + protected static Random random = new Random(); + protected URL url = new URL("protocol", "1.1.1.1", 1234); + protected ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + protected Serialization serialization = new GenericProtobufSerialization(); + + @Test + public void test_Bool() throws Exception { + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeBool(false); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + assertFalse(deserialize.readBool()); + + try { + deserialize.readBool(); + fail(); + } catch (IOException expected) { + } + } + + @Test + public void test_Bool_Multi() throws Exception { + boolean[] array = new boolean[100]; + for (int i = 0; i < array.length; i++) { + array[i] = random.nextBoolean(); + } + + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + for (boolean b : array) { + objectOutput.writeBool(b); + } + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + for (boolean b : array) { + assertEquals(b, deserialize.readBool()); + } + + try { + deserialize.readBool(); + fail(); + } catch (IOException expected) { + } + } + + @Test + public void test_Byte() throws Exception { + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeByte((byte) 123); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + assertEquals((byte) 123, deserialize.readByte()); + + try { + deserialize.readByte(); + fail(); + } catch (IOException expected) { + } + } + + @Test + public void test_Byte_Multi() throws Exception { + byte[] array = new byte[100]; + random.nextBytes(array); + + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + for (byte b : array) { + objectOutput.writeByte(b); + } + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + for (byte b : array) { + assertEquals(b, deserialize.readByte()); + } + + try { + deserialize.readByte(); + fail(); + } catch (IOException expected) { + } + } + + @Test + public void test_Short() throws Exception { + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeShort((short) 123); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + assertEquals((short) 123, deserialize.readShort()); + + try { + deserialize.readShort(); + fail(); + } catch (IOException expected) { + } + } + + @Test + public void test_Integer() throws Exception { + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeInt(1); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + int i = deserialize.readInt(); + assertEquals(1, i); + + try { + deserialize.readInt(); + fail(); + } catch (IOException expected) { + } + } + + @Test + public void test_Long() throws Exception { + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeLong(123L); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + assertEquals(123L, deserialize.readLong()); + + try { + deserialize.readLong(); + fail(); + } catch (IOException expected) { + } + } + + @Test + public void test_Float() throws Exception { + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeFloat(1.28F); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + assertEquals(1.28F, deserialize.readFloat()); + + try { + deserialize.readFloat(); + fail(); + } catch (IOException expected) { + } + } + + // ================== Util methods ================== + + @Test + public void test_Double() throws Exception { + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeDouble(1.28); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + assertEquals(1.28, deserialize.readDouble()); + + try { + deserialize.readDouble(); + fail(); + } catch (IOException expected) { + } + } + + @Test + public void test_UtfString() throws Exception { + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeUTF("123中华人民共和国"); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + assertEquals("123中华人民共和国", deserialize.readUTF()); + + try { + deserialize.readUTF(); + fail(); + } catch (IOException expected) { + } + } + + @Test + public void test_Bytes() throws Exception { + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeBytes("123中华人民共和国".getBytes()); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + assertArrayEquals("123中华人民共和国".getBytes(), deserialize.readBytes()); + + try { + deserialize.readBytes(); + fail(); + } catch (IOException expected) { + } + } + + @Test + public void test_BytesRange() throws Exception { + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeBytes("123中华人民共和国-新疆维吾尔自治区".getBytes(), 1, 9); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream); + + byte[] expectedArray = new byte[9]; + System.arraycopy("123中华人民共和国-新疆维吾尔自治区".getBytes(), 1, expectedArray, 0, expectedArray.length); + assertArrayEquals(expectedArray, deserialize.readBytes()); + + try { + deserialize.readBytes(); + fail(); + } catch (IOException expected) { + } + } + + private GooglePB.PBRequestType buildPbMessage() { + Random random = new Random(); + final int bound = 100000; + List phoneNumberList = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + phoneNumberList.add(GooglePB.PhoneNumber.newBuilder().setNumber(random.nextInt(bound) + "").setType(GooglePB.PhoneType.forNumber(random.nextInt(GooglePB.PhoneType.values().length - 1))).build()); + } + + Map phoneNumberMap = new HashMap<>(); + for (int i = 0; i < 5; i++) { + phoneNumberMap.put("phoneNumber" + i, GooglePB.PhoneNumber.newBuilder().setNumber(random.nextInt(bound) + "").setType(GooglePB.PhoneType.forNumber(random.nextInt(GooglePB.PhoneType.values().length - 1))).build()); + } + GooglePB.PBRequestType request = GooglePB.PBRequestType.newBuilder() + .setAge(15).setCash(10).setMoney(16.0).setNum(100L) + .addAllPhone(phoneNumberList).putAllDoubleMap(phoneNumberMap).build(); + return request; + } + + @Test + public void testPbNormal() throws Exception { + GooglePB.PBRequestType request = buildPbMessage(); + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeObject(request); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput objectInput = serialization.deserialize(url, byteArrayInputStream); + + GooglePB.PBRequestType derializedRequest = objectInput.readObject(GooglePB.PBRequestType.class); + assertEquals(request, derializedRequest); + } + + /** + * Special test case + * Dubbo protocol will directly writes native map (Invocation.attachments) using protobuf. + * this should definitely be fixed but not done yet. + */ + @Test + public void testPbMap() throws Exception { + Map attachments = new HashMap<>(); + attachments.put("key", "value"); + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeObject(attachments); + objectOutput.flushBuffer(); + + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( + byteArrayOutputStream.toByteArray()); + ObjectInput objectInput = serialization.deserialize(url, byteArrayInputStream); + + Map derializedAttachments = objectInput.readObject(Map.class); + assertEquals(attachments, derializedAttachments); + } + + @Test + public void testPbThrowable() { + + } + + @Test + public void testNotPb() { + + } + +} diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutputTest.java b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutputTest.java similarity index 95% rename from dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutputTest.java rename to dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutputTest.java index 2d7a86aa2e..5f0ee4ae9b 100644 --- a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutputTest.java +++ b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutputTest.java @@ -35,16 +35,16 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; -public class GenericProtobufObjectOutputTest { +public class GenericProtobufJsonObjectOutputTest { private ByteArrayOutputStream byteArrayOutputStream; - private GenericProtobufObjectOutput genericProtobufObjectOutput; - private GenericProtobufObjectInput genericProtobufObjectInput; + private GenericProtobufJsonObjectOutput genericProtobufObjectOutput; + private GenericProtobufJsonObjectInput genericProtobufObjectInput; private ByteArrayInputStream byteArrayInputStream; @BeforeEach public void setUp() { this.byteArrayOutputStream = new ByteArrayOutputStream(); - this.genericProtobufObjectOutput = new GenericProtobufObjectOutput(byteArrayOutputStream); + this.genericProtobufObjectOutput = new GenericProtobufJsonObjectOutput(byteArrayOutputStream); } @Test @@ -200,7 +200,7 @@ public class GenericProtobufObjectOutputTest { private void flushToInput() { this.genericProtobufObjectOutput.flushBuffer(); this.byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); - this.genericProtobufObjectInput = new GenericProtobufObjectInput(byteArrayInputStream); + this.genericProtobufObjectInput = new GenericProtobufJsonObjectInput(byteArrayInputStream); } } diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerializationTest.java b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerializationTest.java new file mode 100644 index 0000000000..e50fda48fd --- /dev/null +++ b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerializationTest.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.dubbo.common.serialize.protobuf.support; + +public class GenericProtobufJsonSerializationTest extends AbstractProtobufSerializationTest { + { + serialization = new GenericProtobufJsonSerialization(); + } +} diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerializationTest.java b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerializationTest.java index 6a7748edd6..aec42c34e0 100644 --- a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerializationTest.java +++ b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerializationTest.java @@ -16,11 +16,8 @@ */ package org.apache.dubbo.common.serialize.protobuf.support; -import org.apache.dubbo.common.serialize.base.AbstractSerializationTest; -import org.apache.dubbo.common.serialize.protostuff.ProtostuffSerialization; - -public class GenericProtobufSerializationTest extends AbstractSerializationTest { +public class GenericProtobufSerializationTest extends AbstractProtobufSerializationTest { { - serialization = new ProtostuffSerialization(); + serialization = new GenericProtobufSerialization(); } } diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/resources/protobuf/GooglePB.proto b/dubbo-serialization/dubbo-serialization-test/src/test/proto/GooglePB.proto similarity index 100% rename from dubbo-serialization/dubbo-serialization-test/src/test/resources/protobuf/GooglePB.proto rename to dubbo-serialization/dubbo-serialization-test/src/test/proto/GooglePB.proto diff --git a/dubbo-serialization/pom.xml b/dubbo-serialization/pom.xml index 31e4175d43..04bbef4c7a 100644 --- a/dubbo-serialization/pom.xml +++ b/dubbo-serialization/pom.xml @@ -40,7 +40,7 @@ dubbo-serialization-avro dubbo-serialization-test dubbo-serialization-gson - dubbo-serialization-protobuf-json + dubbo-serialization-protobuf dubbo-serialization-native-hession