Protobuf service definition and serialization support
This commit is contained in:
parent
0dad8290ea
commit
6b86651ee7
|
|
@ -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/*
|
||||
compiler/gradle.properties
|
||||
compiler/build/*
|
||||
2
LICENSE
2
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'
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,6 +1,97 @@
|
|||
# Dubbo customized version
|
||||
|
||||
## 修改内容
|
||||
## Get Started, how to use
|
||||
1. Add maven dependency
|
||||
```xml
|
||||
<build>
|
||||
<extensions>
|
||||
<extension>
|
||||
<groupId>kr.motd.maven</groupId>
|
||||
<artifactId>os-maven-plugin</artifactId>
|
||||
<version>1.6.1</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.xolstice.maven.plugins</groupId>
|
||||
<artifactId>protobuf-maven-plugin</artifactId>
|
||||
<version>0.5.1</version>
|
||||
<configuration>
|
||||
<protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}</protocArtifact>
|
||||
<pluginId>grpc-java</pluginId>
|
||||
<pluginArtifact>org.apache.dubbo:protoc-gen-grpc-java:${proto_dubbo_plugin_version}:exe:${os.detected.classifier}</pluginArtifact>
|
||||
<outputDirectory>build/generated/source/proto/main/java</outputDirectory>
|
||||
<clearOutputDirectory>false</clearOutputDirectory>
|
||||
<!-- supports 'dubbo' and 'grpc' -->
|
||||
<pluginParameter>dubbo</pluginParameter>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>compile-custom</goal>
|
||||
<goal>test-compile</goal>
|
||||
<goal>test-compile-custom</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>build/generated/source/proto/main/java</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
```
|
||||
|
||||
2. Decide which protocol to use: Dubbo or gRPC
|
||||
* Dubbo, ` <pluginParameter>dubbo</pluginParameter>`
|
||||
* gRPC, ` <pluginParameter>grpc</pluginParameter>`
|
||||
|
||||
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.
|
||||
|
|
@ -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"
|
||||
|
|
@ -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"
|
||||
|
|
@ -0,0 +1,572 @@
|
|||
#include "java_generator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <google/protobuf/compiler/java/java_names.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/descriptor.pb.h>
|
||||
#include <google/protobuf/io/printer.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
|
||||
// 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<string> 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 <typename ITR>
|
||||
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<string>* result) {
|
||||
std::back_insert_iterator< std::vector<string> > it(*result);
|
||||
GrpcSplitStringToIteratorUsing(full, delim, it);
|
||||
}
|
||||
|
||||
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
|
||||
static std::vector<string> GrpcSplit(const string& full, const char* delim) {
|
||||
std::vector<string> 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 <typename DescriptorType>
|
||||
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<string> 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 <pre> 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<string> lines = GrpcSplit(escapedComments, "\n");
|
||||
while (!lines.empty() && lines.back().empty()) {
|
||||
lines.pop_back();
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
return std::vector<string>();
|
||||
}
|
||||
|
||||
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
|
||||
template <typename DescriptorType>
|
||||
static std::vector<string> 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<string>& lines,
|
||||
bool surroundWithPreTag) {
|
||||
if (!lines.empty()) {
|
||||
if (surroundWithPreTag) {
|
||||
printer->Print(" * <pre>\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(" * </pre>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
|
||||
static void GrpcWriteDocComment(Printer* printer, const string& comments) {
|
||||
printer->Print("/**\n");
|
||||
std::vector<string> 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<string> 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<string> 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<string, string>* 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<string, string>* 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<string, string>* 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<string, string> 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
|
||||
|
|
@ -1182,105 +1182,105 @@ static void PrintMethodHandlerClass(const ServiceDescriptor* service,
|
|||
}
|
||||
|
||||
static void PrintGetServiceDescriptorMethod(const ServiceDescriptor* service,
|
||||
std::map<string, string>* vars,
|
||||
Printer* p,
|
||||
ProtoFlavor flavor) {
|
||||
(*vars)["service_name"] = service->name();
|
||||
std::map<string, string>* 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<string, string>* vars,
|
||||
|
|
@ -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_
|
||||
|
|
@ -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 <memory>
|
||||
|
||||
#include "java_generator.h"
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/plugin.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
|
||||
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<std::pair<string, string> > 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<google::protobuf::io::ZeroCopyOutputStream> 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<google::protobuf::io::ZeroCopyOutputStream> 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);
|
||||
}
|
||||
|
|
@ -420,7 +420,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-serialization-protobuf-json</artifactId>
|
||||
<artifactId>dubbo-serialization-protobuf</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
|
|
@ -662,7 +662,7 @@
|
|||
<include>org.apache.dubbo:dubbo-serialization-jdk</include>
|
||||
<include>org.apache.dubbo:dubbo-serialization-protostuff</include>
|
||||
<include>org.apache.dubbo:dubbo-serialization-gson</include>
|
||||
<include>org.apache.dubbo:dubbo-serialization-protobuf-json</include>
|
||||
<include>org.apache.dubbo:dubbo-serialization-protobuf</include>
|
||||
<include>org.apache.dubbo:dubbo-configcenter-api</include>
|
||||
<include>org.apache.dubbo:dubbo-configcenter-definition</include>
|
||||
<include>org.apache.dubbo:dubbo-configcenter-apollo</include>
|
||||
|
|
|
|||
|
|
@ -360,7 +360,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-serialization-protobuf-json</artifactId>
|
||||
<artifactId>dubbo-serialization-protobuf</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
|
@ -116,7 +116,7 @@
|
|||
<hibernate_validator_version>5.4.1.Final</hibernate_validator_version>
|
||||
<jel_version>3.0.1-b08</jel_version>
|
||||
<jcache_version>1.0.0</jcache_version>
|
||||
<kryo_version>4.0.1</kryo_version>
|
||||
<kryo_version>4.0.2</kryo_version>
|
||||
<kryo_serializers_version>0.42</kryo_serializers_version>
|
||||
<fst_version>2.48-jdk-6</fst_version>
|
||||
<avro_version>1.8.2</avro_version>
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
<exclude>**/*.jar</exclude>
|
||||
<exclude>**/mvnw*</exclude>
|
||||
<exclude>**/.flattened-pom.xml</exclude>
|
||||
<exclude>**/dubbo-rpc-grpc/compiler/**</exclude>
|
||||
<exclude>**/compiler/**</exclude>
|
||||
</excludes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ public class CuratorZookeeperClient extends AbstractZookeeperClient<CuratorZooke
|
|||
try {
|
||||
client.create().forPath(path);
|
||||
} catch (NodeExistsException e) {
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e.getMessage(), e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ public class DecodeableRpcResult extends AppResponse implements Codec, Decodeabl
|
|||
Type[] returnTypes = RpcUtils.getReturnTypes(invocation);
|
||||
Object value = null;
|
||||
if (ArrayUtils.isEmpty(returnTypes)) {
|
||||
// This almost never happens?
|
||||
value = in.readObject();
|
||||
} else if (returnTypes.length == 1) {
|
||||
value = in.readObject((Class<?>) 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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 <memory>
|
||||
|
||||
#include "java_generator.h"
|
||||
#include <google/protobuf/compiler/code_generator.h>
|
||||
#include <google/protobuf/compiler/plugin.h>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <google/protobuf/io/zero_copy_stream.h>
|
||||
|
||||
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<std::pair<string, string> > 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<google::protobuf::io::ZeroCopyOutputStream> 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);
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
* <p>
|
||||
* See ProtobufSerialization, KryoSerialization for more details.
|
||||
* <p>
|
||||
* 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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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> T readObject(Class<T> clazz) throws IOException, ClassNotFoundException {
|
||||
return kryo.readObjectOrNull(input, clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T readObject(Class<T> clazz, Type type) throws IOException, ClassNotFoundException {
|
||||
return readObject(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
KryoUtils.release(kryo);
|
||||
kryo = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
*
|
||||
* <pre>
|
||||
* e.g. <dubbo:protocol serialization="kryo" />
|
||||
* </pre>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1,2 @@
|
|||
kryo=org.apache.dubbo.common.serialize.kryo.KryoSerialization
|
||||
kryo=org.apache.dubbo.common.serialize.kryo.KryoSerialization
|
||||
kryo2=org.apache.dubbo.common.serialize.kryo.optimized.KryoSerialization2
|
||||
|
|
@ -1,47 +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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-serialization</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>dubbo-serialization-protobuf-json</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>The protobuf serialization module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-serialization-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java-util</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -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 {
|
||||
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
int getAttachmentsCount();
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
boolean containsAttachments(
|
||||
String key);
|
||||
/**
|
||||
* Use {@link #getAttachmentsMap()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
java.util.Map<String, String>
|
||||
getAttachments();
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
java.util.Map<String, String>
|
||||
getAttachmentsMap();
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
String getAttachmentsOrDefault(
|
||||
String key,
|
||||
String defaultValue);
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
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<String, String>
|
||||
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
|
||||
.<String, String>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<String, String>
|
||||
internalGetAttachments() {
|
||||
if (attachments_ == null) {
|
||||
return com.google.protobuf.MapField.emptyMapField(
|
||||
AttachmentsDefaultEntryHolder.defaultEntry);
|
||||
}
|
||||
return attachments_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAttachmentsCount() {
|
||||
return internalGetAttachments().getMap().size();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
@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<String, String> getAttachments() {
|
||||
return getAttachmentsMap();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
@Override
|
||||
public java.util.Map<String, String> getAttachmentsMap() {
|
||||
return internalGetAttachments().getMap();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String getAttachmentsOrDefault(
|
||||
String key,
|
||||
String defaultValue) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
java.util.Map<String, String> map =
|
||||
internalGetAttachments().getMap();
|
||||
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String getAttachmentsOrThrow(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
java.util.Map<String, String> 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<String, String> entry
|
||||
: internalGetAttachments().getMap().entrySet()) {
|
||||
com.google.protobuf.MapEntry<String, String>
|
||||
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<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<String, String>
|
||||
internalGetAttachments() {
|
||||
if (attachments_ == null) {
|
||||
return com.google.protobuf.MapField.emptyMapField(
|
||||
AttachmentsDefaultEntryHolder.defaultEntry);
|
||||
}
|
||||
return attachments_;
|
||||
}
|
||||
private com.google.protobuf.MapField<String, String>
|
||||
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();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
@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<String, String> getAttachments() {
|
||||
return getAttachmentsMap();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
@Override
|
||||
public java.util.Map<String, String> getAttachmentsMap() {
|
||||
return internalGetAttachments().getMap();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String getAttachmentsOrDefault(
|
||||
String key,
|
||||
String defaultValue) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
java.util.Map<String, String> map =
|
||||
internalGetAttachments().getMap();
|
||||
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String getAttachmentsOrThrow(
|
||||
String key) {
|
||||
if (key == null) { throw new NullPointerException(); }
|
||||
java.util.Map<String, String> map =
|
||||
internalGetAttachments().getMap();
|
||||
if (!map.containsKey(key)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public Builder clearAttachments() {
|
||||
internalGetMutableAttachments().getMutableMap()
|
||||
.clear();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
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<String, String>
|
||||
getMutableAttachments() {
|
||||
return internalGetMutableAttachments().getMutableMap();
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* <code>map<string, string> attachments = 1;</code>
|
||||
*/
|
||||
|
||||
public Builder putAllAttachments(
|
||||
java.util.Map<String, String> 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<Map>
|
||||
PARSER = new com.google.protobuf.AbstractParser<Map>() {
|
||||
@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<Map> parser() {
|
||||
return PARSER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.google.protobuf.Parser<Map> 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)
|
||||
}
|
||||
|
|
@ -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> T deserialize(String json, Class<T> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
protobuf-json=org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufSerialization
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-serialization</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>dubbo-serialization-protobuf</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>The protobuf serialization module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
<!-- /compiler/build.gradle -->
|
||||
<proto_dubbo_plugin_version>1.19.0-SNAPSHOT</proto_dubbo_plugin_version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-serialization-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java-util</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<extensions>
|
||||
<extension>
|
||||
<groupId>kr.motd.maven</groupId>
|
||||
<artifactId>os-maven-plugin</artifactId>
|
||||
<version>1.6.1</version>
|
||||
</extension>
|
||||
</extensions>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.xolstice.maven.plugins</groupId>
|
||||
<artifactId>protobuf-maven-plugin</artifactId>
|
||||
<version>0.5.1</version>
|
||||
<configuration>
|
||||
<protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}</protocArtifact>
|
||||
<pluginId>grpc-java</pluginId>
|
||||
<pluginArtifact>
|
||||
org.apache.dubbo:protoc-gen-grpc-java:${proto_dubbo_plugin_version}:exe:${os.detected.classifier}
|
||||
</pluginArtifact>
|
||||
<outputDirectory>build/generated/source/proto/main/java</outputDirectory>
|
||||
<clearOutputDirectory>false</clearOutputDirectory>
|
||||
<!-- supports 'dubbo' and 'grpc' -->
|
||||
<pluginParameter>dubbo</pluginParameter>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
<goal>compile-custom</goal>
|
||||
<goal>test-compile</goal>
|
||||
<goal>test-compile-custom</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>build/generated/source/proto/main/java</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
* <p>
|
||||
* 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> T readObject(Class<T> cls) throws IOException {
|
||||
return read(cls);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T readObject(Class<T> cls, Type type) throws IOException {
|
||||
return readObject(cls);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T read(Class<T> 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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:
|
||||
*
|
||||
* <ul>
|
||||
* <li>1. Package these data with Protobuf so that they can be serialized.</li>
|
||||
* <li>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.</li>
|
||||
* </ul>
|
||||
*
|
||||
* </p>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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> T deserializeJson(String json, Class<T> 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<Class<? extends MessageLite>, 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 <T extends MessageLite> 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> T deserialize(InputStream is, Class<T> 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<T extends MessageLite> {
|
||||
private final Parser<T> parser;
|
||||
private final T defaultInstance;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
MessageMarshaller(T defaultInstance) {
|
||||
this.defaultInstance = defaultInstance;
|
||||
parser = (Parser<T>) defaultInstance.getParserForType();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<T> getMessageClass() {
|
||||
// Precisely T since protobuf doesn't let messages extend other messages.
|
||||
return (Class<T>) 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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<string,string> attachments = 1;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
protobuf-json=org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufJsonSerialization
|
||||
protobuf=org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufSerialization
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-serialization-protobuf-json</artifactId>
|
||||
<artifactId>dubbo-serialization-protobuf</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -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<GooglePB.PhoneNumber> 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<String, GooglePB.PhoneNumber> 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<String, Object> 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<String, Object> derializedAttachments = objectInput.readObject(Map.class);
|
||||
assertEquals(attachments, derializedAttachments);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPbThrowable() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotPb() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
<module>dubbo-serialization-avro</module>
|
||||
<module>dubbo-serialization-test</module>
|
||||
<module>dubbo-serialization-gson</module>
|
||||
<module>dubbo-serialization-protobuf-json</module>
|
||||
<module>dubbo-serialization-protobuf</module>
|
||||
<module>dubbo-serialization-native-hession</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
|||
Loading…
Reference in New Issue