GrpcGetDocLines(const string& comments) {
+ if (!comments.empty()) {
+ // TODO(kenton): Ideally we should parse the comment text as Markdown and
+ // write it back as HTML, but this requires a Markdown parser. For now
+ // we just use to get fixed-width text formatting.
+
+ // If the comment itself contains block comment start or end markers,
+ // HTML-escape them so that they don't accidentally close the doc comment.
+ string escapedComments = GrpcEscapeJavadoc(comments);
+
+ std::vector lines = GrpcSplit(escapedComments, "\n");
+ while (!lines.empty() && lines.back().empty()) {
+ lines.pop_back();
+ }
+ return lines;
+ }
+ return std::vector();
+}
+
+// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
+template
+static std::vector GrpcGetDocLinesForDescriptor(const DescriptorType* descriptor) {
+ return GrpcGetDocLines(GrpcGetCommentsForDescriptor(descriptor));
+}
+
+// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
+static void GrpcWriteDocCommentBody(Printer* printer,
+ const std::vector& lines,
+ bool surroundWithPreTag) {
+ if (!lines.empty()) {
+ if (surroundWithPreTag) {
+ printer->Print(" * \n");
+ }
+
+ for (size_t i = 0; i < lines.size(); i++) {
+ // Most lines should start with a space. Watch out for lines that start
+ // with a /, since putting that right after the leading asterisk will
+ // close the comment.
+ if (!lines[i].empty() && lines[i][0] == '/') {
+ printer->Print(" * $line$\n", "line", lines[i]);
+ } else {
+ printer->Print(" *$line$\n", "line", lines[i]);
+ }
+ }
+
+ if (surroundWithPreTag) {
+ printer->Print(" * \n");
+ }
+ }
+}
+
+// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
+static void GrpcWriteDocComment(Printer* printer, const string& comments) {
+ printer->Print("/**\n");
+ std::vector lines = GrpcGetDocLines(comments);
+ GrpcWriteDocCommentBody(printer, lines, false);
+ printer->Print(" */\n");
+}
+
+// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
+static void GrpcWriteServiceDocComment(Printer* printer,
+ const ServiceDescriptor* service) {
+ // Deviating from protobuf to avoid extraneous docs
+ // (see https://github.com/google/protobuf/issues/1406);
+ printer->Print("/**\n");
+ std::vector lines = GrpcGetDocLinesForDescriptor(service);
+ GrpcWriteDocCommentBody(printer, lines, true);
+ printer->Print(" */\n");
+}
+
+// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
+void GrpcWriteMethodDocComment(Printer* printer,
+ const MethodDescriptor* method) {
+ // Deviating from protobuf to avoid extraneous docs
+ // (see https://github.com/google/protobuf/issues/1406);
+ printer->Print("/**\n");
+ std::vector lines = GrpcGetDocLinesForDescriptor(method);
+ GrpcWriteDocCommentBody(printer, lines, true);
+ printer->Print(" */\n");
+}
+
+enum StubType {
+ ASYNC_INTERFACE = 0,
+ BLOCKING_CLIENT_INTERFACE = 1,
+ FUTURE_CLIENT_INTERFACE = 2,
+ BLOCKING_SERVER_INTERFACE = 3,
+ ASYNC_CLIENT_IMPL = 4,
+ BLOCKING_CLIENT_IMPL = 5,
+ FUTURE_CLIENT_IMPL = 6,
+ ABSTRACT_CLASS = 7,
+};
+
+enum CallType {
+ ASYNC_CALL = 0,
+ BLOCKING_CALL = 1,
+ FUTURE_CALL = 2
+};
+
+static void PrintMarshallerStaticBlock(const ServiceDescriptor* service,
+ std::map* vars,
+ Printer* p) {
+ for (int i = 0; i < service->method_count(); ++i) {
+ const MethodDescriptor* method = service->method(i);
+ (*vars)["input_type"] = google::protobuf::compiler::java::ClassName(method->input_type());
+ (*vars)["output_type"] = google::protobuf::compiler::java::ClassName(method->output_type());
+ p->Print(
+ *vars,
+ "private static final AtomicBoolean registered = new AtomicBoolean();\n\n");
+
+ p->Print(
+ *vars,
+ "static {\n"
+ " if (registered.compareAndSet(false, true)) {\n"
+ " $ProtobufUtils$.marshaller(\n"
+ " $input_type$.getDefaultInstance());\n"
+ " $ProtobufUtils$.marshaller(\n"
+ " $output_type$.getDefaultInstance());\n"
+ " }\n"
+ "}\n\n");
+ }
+}
+
+static void PrintDubboInterface(
+ const ServiceDescriptor* service,
+ std::map* vars,
+ Printer* p, bool generate_nano) {
+ const string service_name = service->name();
+ (*vars)["service_name"] = service_name;
+ (*vars)["dubbo_interface"] = "I" + service_name;
+
+ p->Print(
+ "/**\n "
+ "* Code generated for Dubbo\n "
+ "*/\n"
+ );
+ p->Print(
+ *vars,
+ "public interface $dubbo_interface$ {\n\n");
+
+ for (int i = 0; i < service->method_count(); ++i) {
+ const MethodDescriptor* method = service->method(i);
+ (*vars)["input_type"] = MessageFullJavaName(generate_nano,
+ method->input_type());
+ (*vars)["output_type"] = MessageFullJavaName(generate_nano,
+ method->output_type());
+ (*vars)["lower_method_name"] = LowerMethodName(method);
+
+ // Simple RPC
+ p->Print(
+ *vars,
+ "$output_type$ $lower_method_name$($input_type$ request);\n\n");
+ // Simple Future RPC
+ p->Print(
+ *vars,
+ "$CompletableFuture$<$output_type$> $lower_method_name$Async(\n$input_type$ request);\n\n");
+// p->Print(
+// *vars,
+// "default $CompletableFuture$<$output_type$> $lower_method_name$Async(\n"
+// " $input_type$ request) {\n return CompletableFuture.completedFuture($lower_method_name$(request));\n}\n\n");
+ p->Outdent();
+ }
+
+ p->Outdent();
+ p->Print("}\n\n");
+
+}
+
+static void PrintService(const ServiceDescriptor* service,
+ std::map* vars,
+ Printer* p,
+ bool disable_version) {
+ (*vars)["service_name"] = service->name();
+ (*vars)["file_name"] = service->file()->name();
+ (*vars)["service_class_name"] = ServiceClassName(service);
+ (*vars)["grpc_version"] = "";
+ #ifdef GRPC_VERSION
+ if (!disable_version) {
+ (*vars)["grpc_version"] = " (version " XSTR(GRPC_VERSION) ")";
+ }
+ #endif
+ // TODO(nmittler): Replace with WriteServiceDocComment once included by protobuf distro.
+ GrpcWriteServiceDocComment(p, service);
+ p->Print(
+ *vars,
+ "@$Generated$(\n"
+ " value = \"by gRPC proto compiler$grpc_version$\",\n"
+ " comments = \"Source: $file_name$\")\n");
+
+ if (service->options().deprecated()) {
+ p->Print(*vars, "@$Deprecated$\n");
+ }
+
+ p->Print(
+ *vars,
+ "public final class $service_class_name$ {\n\n");
+ p->Indent();
+
+ PrintMarshallerStaticBlock(service, vars, p);
+
+ p->Print(
+ *vars,
+ "private $service_class_name$() {}\n\n");
+
+ p->Print(
+ *vars,
+ "public static final String SERVICE_NAME = "
+ "\"$Package$$service_name$\";\n\n");
+
+ PrintDubboInterface(service, vars, p, false);
+
+ p->Outdent();
+ p->Print("}\n");
+}
+
+void PrintImports(Printer* p) {
+ p->Print(
+ "import "
+ "java.util.concurrent.CompletableFuture;\n");
+ p->Print(
+ "import "
+ "java.util.concurrent.atomic.AtomicBoolean;\n");
+}
+
+void GenerateService(const ServiceDescriptor* service,
+ google::protobuf::io::ZeroCopyOutputStream* out,
+ ProtoFlavor flavor,
+ bool disable_version) {
+ // All non-generated classes must be referred by fully qualified names to
+ // avoid collision with generated classes.
+ std::map vars;
+ vars["String"] = "java.lang.String";
+ vars["Deprecated"] = "java.lang.Deprecated";
+ vars["Override"] = "java.lang.Override";
+ vars["Iterator"] = "java.util.Iterator";
+ vars["Generated"] = "javax.annotation.Generated";
+ vars["CompletableFuture"] =
+ "java.util.concurrent.CompletableFuture";
+ vars["AtomicBoolean"] =
+ "java.util.concurrent.atomic.AtomicBoolean";
+ vars["ProtobufUtils"] =
+ "org.apache.dubbo.common.serialize.protobuf.support.ProtobufUtils";
+
+ Printer printer(out, '$');
+ string package_name = ServiceJavaPackage(service->file(),false);
+ if (!package_name.empty()) {
+ printer.Print(
+ "package $package_name$;\n\n",
+ "package_name", package_name);
+ }
+
+ PrintImports(&printer);
+
+ // Package string is used to fully qualify method names.
+ vars["Package"] = service->file()->package();
+ if (!vars["Package"].empty()) {
+ vars["Package"].append(".");
+ }
+ PrintService(service, &vars, &printer, false);
+}
+
+string ServiceJavaPackage(const FileDescriptor* file, bool nano) {
+ string result = google::protobuf::compiler::java::ClassName(file);
+ size_t last_dot_pos = result.find_last_of('.');
+ if (last_dot_pos != string::npos) {
+ result.resize(last_dot_pos);
+ } else {
+ result = "";
+ }
+ if (nano) {
+ if (!result.empty()) {
+ result += ".";
+ }
+ result += "nano";
+ }
+ return result;
+}
+
+string ServiceClassName(const google::protobuf::ServiceDescriptor* service) {
+ return service->name() + "Dubbo";
+}
+
+} // namespace java_dubbo_generator
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.cpp b/compiler/src/java_plugin/cpp/java_generator.cpp
similarity index 93%
rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.cpp
rename to compiler/src/java_plugin/cpp/java_generator.cpp
index 224ccb51d5..1fbc483cee 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.cpp
+++ b/compiler/src/java_plugin/cpp/java_generator.cpp
@@ -1182,105 +1182,105 @@ static void PrintMethodHandlerClass(const ServiceDescriptor* service,
}
static void PrintGetServiceDescriptorMethod(const ServiceDescriptor* service,
- std::map* vars,
- Printer* p,
- ProtoFlavor flavor) {
- (*vars)["service_name"] = service->name();
+ std::map* vars,
+ Printer* p,
+ ProtoFlavor flavor) {
+ (*vars)["service_name"] = service->name();
- if (flavor == ProtoFlavor::NORMAL) {
- (*vars)["proto_base_descriptor_supplier"] = service->name() + "BaseDescriptorSupplier";
- (*vars)["proto_file_descriptor_supplier"] = service->name() + "FileDescriptorSupplier";
- (*vars)["proto_method_descriptor_supplier"] = service->name() + "MethodDescriptorSupplier";
- (*vars)["proto_class_name"] = google::protobuf::compiler::java::ClassName(service->file());
- p->Print(
- *vars,
- "private static abstract class $proto_base_descriptor_supplier$\n"
- " implements $ProtoFileDescriptorSupplier$, $ProtoServiceDescriptorSupplier$ {\n"
- " $proto_base_descriptor_supplier$() {}\n"
- "\n"
- " @$Override$\n"
- " public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {\n"
- " return $proto_class_name$.getDescriptor();\n"
- " }\n"
- "\n"
- " @$Override$\n"
- " public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {\n"
- " return getFileDescriptor().findServiceByName(\"$service_name$\");\n"
- " }\n"
- "}\n"
- "\n"
- "private static final class $proto_file_descriptor_supplier$\n"
- " extends $proto_base_descriptor_supplier$ {\n"
- " $proto_file_descriptor_supplier$() {}\n"
- "}\n"
- "\n"
- "private static final class $proto_method_descriptor_supplier$\n"
- " extends $proto_base_descriptor_supplier$\n"
- " implements $ProtoMethodDescriptorSupplier$ {\n"
- " private final String methodName;\n"
- "\n"
- " $proto_method_descriptor_supplier$(String methodName) {\n"
- " this.methodName = methodName;\n"
- " }\n"
- "\n"
- " @$Override$\n"
- " public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {\n"
- " return getServiceDescriptor().findMethodByName(methodName);\n"
- " }\n"
- "}\n\n");
- }
+ if (flavor == ProtoFlavor::NORMAL) {
+ (*vars)["proto_base_descriptor_supplier"] = service->name() + "BaseDescriptorSupplier";
+ (*vars)["proto_file_descriptor_supplier"] = service->name() + "FileDescriptorSupplier";
+ (*vars)["proto_method_descriptor_supplier"] = service->name() + "MethodDescriptorSupplier";
+ (*vars)["proto_class_name"] = google::protobuf::compiler::java::ClassName(service->file());
+ p->Print(
+ *vars,
+ "private static abstract class $proto_base_descriptor_supplier$\n"
+ " implements $ProtoFileDescriptorSupplier$, $ProtoServiceDescriptorSupplier$ {\n"
+ " $proto_base_descriptor_supplier$() {}\n"
+ "\n"
+ " @$Override$\n"
+ " public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {\n"
+ " return $proto_class_name$.getDescriptor();\n"
+ " }\n"
+ "\n"
+ " @$Override$\n"
+ " public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {\n"
+ " return getFileDescriptor().findServiceByName(\"$service_name$\");\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "private static final class $proto_file_descriptor_supplier$\n"
+ " extends $proto_base_descriptor_supplier$ {\n"
+ " $proto_file_descriptor_supplier$() {}\n"
+ "}\n"
+ "\n"
+ "private static final class $proto_method_descriptor_supplier$\n"
+ " extends $proto_base_descriptor_supplier$\n"
+ " implements $ProtoMethodDescriptorSupplier$ {\n"
+ " private final String methodName;\n"
+ "\n"
+ " $proto_method_descriptor_supplier$(String methodName) {\n"
+ " this.methodName = methodName;\n"
+ " }\n"
+ "\n"
+ " @$Override$\n"
+ " public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {\n"
+ " return getServiceDescriptor().findMethodByName(methodName);\n"
+ " }\n"
+ "}\n\n");
+ }
- p->Print(
- *vars,
- "private static volatile $ServiceDescriptor$ serviceDescriptor;\n\n");
+ p->Print(
+ *vars,
+ "private static volatile $ServiceDescriptor$ serviceDescriptor;\n\n");
- p->Print(
- *vars,
- "public static $ServiceDescriptor$ getServiceDescriptor() {\n");
- p->Indent();
- p->Print(
- *vars,
- "$ServiceDescriptor$ result = serviceDescriptor;\n");
- p->Print("if (result == null) {\n");
- p->Indent();
- p->Print(
- *vars,
- "synchronized ($service_class_name$.class) {\n");
- p->Indent();
- p->Print("result = serviceDescriptor;\n");
- p->Print("if (result == null) {\n");
- p->Indent();
+ p->Print(
+ *vars,
+ "public static $ServiceDescriptor$ getServiceDescriptor() {\n");
+ p->Indent();
+ p->Print(
+ *vars,
+ "$ServiceDescriptor$ result = serviceDescriptor;\n");
+ p->Print("if (result == null) {\n");
+ p->Indent();
+ p->Print(
+ *vars,
+ "synchronized ($service_class_name$.class) {\n");
+ p->Indent();
+ p->Print("result = serviceDescriptor;\n");
+ p->Print("if (result == null) {\n");
+ p->Indent();
- p->Print(
- *vars,
- "serviceDescriptor = result = $ServiceDescriptor$.newBuilder(SERVICE_NAME)");
- p->Indent();
- p->Indent();
- if (flavor == ProtoFlavor::NORMAL) {
- p->Print(
- *vars,
- "\n.setSchemaDescriptor(new $proto_file_descriptor_supplier$())");
- }
- for (int i = 0; i < service->method_count(); ++i) {
- const MethodDescriptor* method = service->method(i);
- (*vars)["method_method_name"] = MethodPropertiesGetterName(method);
- p->Print(*vars, "\n.addMethod($method_method_name$())");
- }
- p->Print("\n.build();\n");
- p->Outdent();
- p->Outdent();
+ p->Print(
+ *vars,
+ "serviceDescriptor = result = $ServiceDescriptor$.newBuilder(SERVICE_NAME)");
+ p->Indent();
+ p->Indent();
+ if (flavor == ProtoFlavor::NORMAL) {
+ p->Print(
+ *vars,
+ "\n.setSchemaDescriptor(new $proto_file_descriptor_supplier$())");
+ }
+ for (int i = 0; i < service->method_count(); ++i) {
+ const MethodDescriptor* method = service->method(i);
+ (*vars)["method_method_name"] = MethodPropertiesGetterName(method);
+ p->Print(*vars, "\n.addMethod($method_method_name$())");
+ }
+ p->Print("\n.build();\n");
+ p->Outdent();
+ p->Outdent();
- p->Outdent();
- p->Print("}\n");
- p->Outdent();
- p->Print("}\n");
- p->Outdent();
- p->Print("}\n");
- p->Print("return result;\n");
- p->Outdent();
- p->Print("}\n");
-}
+ p->Outdent();
+ p->Print("}\n");
+ p->Outdent();
+ p->Print("}\n");
+ p->Outdent();
+ p->Print("}\n");
+ p->Print("return result;\n");
+ p->Outdent();
+ p->Print("}\n");
+ }
static void PrintBindServiceMethodBody(const ServiceDescriptor* service,
std::map* vars,
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.h b/compiler/src/java_plugin/cpp/java_generator.h
similarity index 69%
rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.h
rename to compiler/src/java_plugin/cpp/java_generator.h
index ab265d06c7..7106c54e37 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_generator.h
+++ b/compiler/src/java_plugin/cpp/java_generator.h
@@ -54,4 +54,25 @@ void GenerateService(const google::protobuf::ServiceDescriptor* service,
} // namespace java_grpc_generator
+namespace java_dubbo_generator {
+
+enum ProtoFlavor {
+ NORMAL
+};
+
+// Returns the package name of the Dubbo services defined in the given file.
+string ServiceJavaPackage(const google::protobuf::FileDescriptor* file, bool nano);
+
+// Returns the name of the outer class that wraps in all the generated code for
+// the given service.
+string ServiceClassName(const google::protobuf::ServiceDescriptor* service);
+
+// Writes the generated service interface into the given ZeroCopyOutputStream
+void GenerateService(const google::protobuf::ServiceDescriptor* service,
+ google::protobuf::io::ZeroCopyOutputStream* out,
+ ProtoFlavor flavor,
+ bool disable_version);
+
+} // namespace java_dubbo_generator
+
#endif // NET_GRPC_COMPILER_JAVA_GENERATOR_H_
diff --git a/compiler/src/java_plugin/cpp/java_plugin.cpp b/compiler/src/java_plugin/cpp/java_plugin.cpp
new file mode 100644
index 0000000000..c8af98cffa
--- /dev/null
+++ b/compiler/src/java_plugin/cpp/java_plugin.cpp
@@ -0,0 +1,87 @@
+// Generates Java gRPC service interface out of Protobuf IDL.
+//
+// This is a Proto2 compiler plugin. See net/proto2/compiler/proto/plugin.proto
+// and net/proto2/compiler/public/plugin.h for more information on plugins.
+
+#include
+
+#include "java_generator.h"
+#include
+#include
+#include
+#include
+
+static string JavaPackageToDir(const string& package_name) {
+ string package_dir = package_name;
+ for (size_t i = 0; i < package_dir.size(); ++i) {
+ if (package_dir[i] == '.') {
+ package_dir[i] = '/';
+ }
+ }
+ if (!package_dir.empty()) package_dir += "/";
+ return package_dir;
+}
+
+class JavaGrpcGenerator : public google::protobuf::compiler::CodeGenerator {
+ public:
+
+ JavaGrpcGenerator() {}
+ virtual ~JavaGrpcGenerator() {}
+
+ virtual bool Generate(const google::protobuf::FileDescriptor* file,
+ const string& parameter,
+ google::protobuf::compiler::GeneratorContext* context,
+ string* error) const {
+ std::vector > options;
+ google::protobuf::compiler::ParseGeneratorParameter(parameter, &options);
+ string DUBBO("dubbo");
+
+ if (DUBBO == parameter) {
+ string package_name = java_dubbo_generator::ServiceJavaPackage(
+ file, false);
+ string package_filename = JavaPackageToDir(package_name);
+ for (int i = 0; i < file->service_count(); ++i) {
+ const google::protobuf::ServiceDescriptor* service = file->service(i);
+ string filename = package_filename
+ + java_dubbo_generator::ServiceClassName(service) + ".java";
+ std::unique_ptr output(
+ context->Open(filename));
+ java_dubbo_generator::GenerateService(
+ service, output.get(), java_dubbo_generator::ProtoFlavor::NORMAL, false);
+ }
+ } else {
+ java_grpc_generator::ProtoFlavor flavor =
+ java_grpc_generator::ProtoFlavor::NORMAL;
+
+ bool disable_version = false;
+ for (size_t i = 0; i < options.size(); i++) {
+ if (options[i].first == "nano") {
+ flavor = java_grpc_generator::ProtoFlavor::NANO;
+ } else if (options[i].first == "lite") {
+ flavor = java_grpc_generator::ProtoFlavor::LITE;
+ } else if (options[i].first == "noversion") {
+ disable_version = true;
+ }
+ }
+
+ string package_name = java_grpc_generator::ServiceJavaPackage(
+ file, flavor == java_grpc_generator::ProtoFlavor::NANO);
+ string package_filename = JavaPackageToDir(package_name);
+ for (int i = 0; i < file->service_count(); ++i) {
+ const google::protobuf::ServiceDescriptor* service = file->service(i);
+ string filename = package_filename
+ + java_grpc_generator::ServiceClassName(service) + ".java";
+ std::unique_ptr output(
+ context->Open(filename));
+ java_grpc_generator::GenerateService(
+ service, output.get(), flavor, disable_version);
+ }
+ }
+ return true;
+ }
+};
+
+int main(int argc, char* argv[]) {
+ JavaGrpcGenerator generator;
+ return google::protobuf::compiler::PluginMain(argc, argv, &generator);
+}
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/golden/TestDeprecatedService.java.txt b/compiler/src/test/golden/TestDeprecatedService.java.txt
similarity index 100%
rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/golden/TestDeprecatedService.java.txt
rename to compiler/src/test/golden/TestDeprecatedService.java.txt
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt
similarity index 100%
rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/golden/TestService.java.txt
rename to compiler/src/test/golden/TestService.java.txt
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/proto/grpc/testing/compiler/test.proto b/compiler/src/test/proto/grpc/testing/compiler/test.proto
similarity index 100%
rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/test/proto/grpc/testing/compiler/test.proto
rename to compiler/src/test/proto/grpc/testing/compiler/test.proto
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/testLite/golden/TestDeprecatedService.java.txt b/compiler/src/testLite/golden/TestDeprecatedService.java.txt
similarity index 100%
rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/testLite/golden/TestDeprecatedService.java.txt
rename to compiler/src/testLite/golden/TestDeprecatedService.java.txt
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/testLite/golden/TestService.java.txt b/compiler/src/testLite/golden/TestService.java.txt
similarity index 100%
rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/testLite/golden/TestService.java.txt
rename to compiler/src/testLite/golden/TestService.java.txt
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/testNano/golden/TestDeprecatedService.java.txt b/compiler/src/testNano/golden/TestDeprecatedService.java.txt
similarity index 100%
rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/testNano/golden/TestDeprecatedService.java.txt
rename to compiler/src/testNano/golden/TestDeprecatedService.java.txt
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/testNano/golden/TestService.java.txt b/compiler/src/testNano/golden/TestService.java.txt
similarity index 100%
rename from dubbo-rpc/dubbo-rpc-grpc/compiler/src/testNano/golden/TestService.java.txt
rename to compiler/src/testNano/golden/TestService.java.txt
diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml
index 89de0c64b5..3316261769 100644
--- a/dubbo-all/pom.xml
+++ b/dubbo-all/pom.xml
@@ -420,7 +420,7 @@
org.apache.dubbo
- dubbo-serialization-protobuf-json
+ dubbo-serialization-protobuf
${project.version}
compile
true
@@ -662,7 +662,7 @@
org.apache.dubbo:dubbo-serialization-jdk
org.apache.dubbo:dubbo-serialization-protostuff
org.apache.dubbo:dubbo-serialization-gson
- org.apache.dubbo:dubbo-serialization-protobuf-json
+ org.apache.dubbo:dubbo-serialization-protobuf
org.apache.dubbo:dubbo-configcenter-api
org.apache.dubbo:dubbo-configcenter-definition
org.apache.dubbo:dubbo-configcenter-apollo
diff --git a/dubbo-bom/pom.xml b/dubbo-bom/pom.xml
index 6ccbc1b337..77697c414d 100644
--- a/dubbo-bom/pom.xml
+++ b/dubbo-bom/pom.xml
@@ -360,7 +360,7 @@
org.apache.dubbo
- dubbo-serialization-protobuf-json
+ dubbo-serialization-protobuf
${project.version}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/protobuf/ProtobufService.java b/dubbo-common/src/main/java/org/apache/dubbo/common/protobuf/ProtobufService.java
new file mode 100644
index 0000000000..1c3db1104d
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/protobuf/ProtobufService.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.protobuf;
+
+/**
+ * proto-gen-dubbo-java
+ */
+public interface ProtobufService {
+
+}
diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml
index 3c5b432750..ac5d44616b 100644
--- a/dubbo-dependencies-bom/pom.xml
+++ b/dubbo-dependencies-bom/pom.xml
@@ -116,7 +116,7 @@
5.4.1.Final
3.0.1-b08
1.0.0
- 4.0.1
+ 4.0.2
0.42
2.48-jdk-6
1.8.2
diff --git a/dubbo-distribution/src/assembly/source-release.xml b/dubbo-distribution/src/assembly/source-release.xml
index e79afe2484..fb799ceefd 100644
--- a/dubbo-distribution/src/assembly/source-release.xml
+++ b/dubbo-distribution/src/assembly/source-release.xml
@@ -51,7 +51,7 @@
**/*.jar
**/mvnw*
**/.flattened-pom.xml
- **/dubbo-rpc-grpc/compiler/**
+ **/compiler/**
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java
index 8f25250c98..d4eae092e2 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java
@@ -278,7 +278,7 @@ public class ExchangeCodec extends TelnetCodec {
// encode response data or error message.
if (status == Response.OK) {
if (res.isHeartbeat()) {
- encodeHeartbeatData(channel, out, res.getResult());
+ encodeEventData(channel, out, res.getResult());
} else {
encodeResponseData(channel, out, res.getResult(), res.getVersion());
}
@@ -401,9 +401,9 @@ public class ExchangeCodec extends TelnetCodec {
protected Object decodeEventData(Channel channel, ObjectInput in) throws IOException {
try {
- return in.readObject();
- } catch (ClassNotFoundException e) {
- throw new IOException(StringUtils.toString("Read object failed.", e));
+ return in.readUTF();
+ } catch (IOException e) {
+ throw new IOException(StringUtils.toString("Decode dubbo protocol event failed.", e));
}
}
diff --git a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java
index 2df67de8ce..dd16a66985 100644
--- a/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java
+++ b/dubbo-remoting/dubbo-remoting-zookeeper/src/main/java/org/apache/dubbo/remoting/zookeeper/curator/CuratorZookeeperClient.java
@@ -99,6 +99,7 @@ public class CuratorZookeeperClient extends AbstractZookeeperClient) returnTypes[0]);
@@ -141,7 +142,7 @@ public class DecodeableRpcResult extends AppResponse implements Codec, Decodeabl
private void handleException(ObjectInput in) throws IOException {
try {
- Object obj = in.readObject();
+ Object obj = in.readThrowable();
if (!(obj instanceof Throwable)) {
throw new IOException("Response data error, expect Throwable, but get " + obj);
}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java
index f9134379ad..c9e43e7e2a 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java
@@ -78,10 +78,7 @@ public class DubboCodec extends ExchangeCodec {
try {
if (status == Response.OK) {
Object data;
- if (res.isHeartbeat()) {
- ObjectInput in = CodecSupport.deserialize(channel.getUrl(), is, proto);
- data = decodeHeartbeatData(channel, in);
- } else if (res.isEvent()) {
+ if (res.isEvent()) {
ObjectInput in = CodecSupport.deserialize(channel.getUrl(), is, proto);
data = decodeEventData(channel, in);
} else {
@@ -120,10 +117,7 @@ public class DubboCodec extends ExchangeCodec {
}
try {
Object data;
- if (req.isHeartbeat()) {
- ObjectInput in = CodecSupport.deserialize(channel.getUrl(), is, proto);
- data = decodeHeartbeatData(channel, in);
- } else if (req.isEvent()) {
+ if (req.isEvent()) {
ObjectInput in = CodecSupport.deserialize(channel.getUrl(), is, proto);
data = decodeEventData(channel, in);
} else {
@@ -205,7 +199,7 @@ public class DubboCodec extends ExchangeCodec {
}
} else {
out.writeByte(attach ? RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS : RESPONSE_WITH_EXCEPTION);
- out.writeObject(th);
+ out.writeThrowable(th);
}
if (attach) {
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileContent/fileContent.lock b/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileContent/fileContent.lock
deleted file mode 100644
index 2c23b323ef..0000000000
Binary files a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileContent/fileContent.lock and /dev/null differ
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileHashes/fileHashes.lock b/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileHashes/fileHashes.lock
deleted file mode 100644
index 49305170c4..0000000000
Binary files a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/fileHashes/fileHashes.lock and /dev/null differ
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock b/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock
deleted file mode 100644
index e83e9f9397..0000000000
Binary files a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock and /dev/null differ
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/taskHistory/taskHistory.lock b/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/taskHistory/taskHistory.lock
deleted file mode 100644
index 46a3559812..0000000000
Binary files a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/4.9/taskHistory/taskHistory.lock and /dev/null differ
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock
deleted file mode 100644
index bdc02da418..0000000000
Binary files a/dubbo-rpc/dubbo-rpc-grpc/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock and /dev/null differ
diff --git a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_plugin.cpp b/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_plugin.cpp
deleted file mode 100644
index b2cbd0bae1..0000000000
--- a/dubbo-rpc/dubbo-rpc-grpc/compiler/src/java_plugin/cpp/java_plugin.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-// Generates Java gRPC service interface out of Protobuf IDL.
-//
-// This is a Proto2 compiler plugin. See net/proto2/compiler/proto/plugin.proto
-// and net/proto2/compiler/public/plugin.h for more information on plugins.
-
-#include
-
-#include "java_generator.h"
-#include
-#include
-#include
-#include
-
-static string JavaPackageToDir(const string& package_name) {
- string package_dir = package_name;
- for (size_t i = 0; i < package_dir.size(); ++i) {
- if (package_dir[i] == '.') {
- package_dir[i] = '/';
- }
- }
- if (!package_dir.empty()) package_dir += "/";
- return package_dir;
-}
-
-class JavaGrpcGenerator : public google::protobuf::compiler::CodeGenerator {
- public:
- JavaGrpcGenerator() {}
- virtual ~JavaGrpcGenerator() {}
-
- virtual bool Generate(const google::protobuf::FileDescriptor* file,
- const string& parameter,
- google::protobuf::compiler::GeneratorContext* context,
- string* error) const {
- std::vector > options;
- google::protobuf::compiler::ParseGeneratorParameter(parameter, &options);
-
- java_grpc_generator::ProtoFlavor flavor =
- java_grpc_generator::ProtoFlavor::NORMAL;
-
- bool disable_version = false;
- for (size_t i = 0; i < options.size(); i++) {
- if (options[i].first == "nano") {
- flavor = java_grpc_generator::ProtoFlavor::NANO;
- } else if (options[i].first == "lite") {
- flavor = java_grpc_generator::ProtoFlavor::LITE;
- } else if (options[i].first == "noversion") {
- disable_version = true;
- }
- }
-
- string package_name = java_grpc_generator::ServiceJavaPackage(
- file, flavor == java_grpc_generator::ProtoFlavor::NANO);
- string package_filename = JavaPackageToDir(package_name);
- for (int i = 0; i < file->service_count(); ++i) {
- const google::protobuf::ServiceDescriptor* service = file->service(i);
- string filename = package_filename
- + java_grpc_generator::ServiceClassName(service) + ".java";
- std::unique_ptr output(
- context->Open(filename));
- java_grpc_generator::GenerateService(
- service, output.get(), flavor, disable_version);
- }
- return true;
- }
-};
-
-int main(int argc, char* argv[]) {
- JavaGrpcGenerator generator;
- return google::protobuf::compiler::PluginMain(argc, argv, &generator);
-}
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java
index 73fd8040f5..ee9d7ebad2 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java
@@ -60,6 +60,7 @@ public class GrpcProtocol extends AbstractProxyProtocol {
String key = url.getAddress();
GrpcServer grpcServer = serverMap.computeIfAbsent(key, k -> {
DubboHandlerRegistry registry = new DubboHandlerRegistry();
+
Server originalServer = ServerBuilder
.forPort(url.getPort())
.fallbackHandlerRegistry(registry)
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcServerUtils.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcServerUtils.java
new file mode 100644
index 0000000000..e0007e3594
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcServerUtils.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.protocol.grpc;
+
+import org.apache.dubbo.common.URL;
+
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.ServerBuilder;
+
+/**
+ * Support gRPC configs in the Dubbo specific way.
+ */
+public class GrpcServerUtils {
+
+ public static void configureServer(URL url, ServerBuilder builder) {
+
+ }
+
+ public static void configureChannel(URL url, ManagedChannelBuilder builder) {
+
+ }
+}
diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java
index 1d8646e880..e4c82644d8 100644
--- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java
+++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectInput.java
@@ -25,14 +25,19 @@ import java.lang.reflect.Type;
public interface ObjectInput extends DataInput {
/**
- * read object
+ * Consider use {@link #readObject(Class)} or {@link #readObject(Class, Type)} where possible
*
* @return object
* @throws IOException if an I/O error occurs
* @throws ClassNotFoundException if an ClassNotFoundException occurs
*/
+ @Deprecated
Object readObject() throws IOException, ClassNotFoundException;
+ default Object readThrowable() throws IOException, ClassNotFoundException {
+ return readObject();
+ }
+
/**
* read object
*
diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java
index 73fa3b61fd..a5f71919d1 100644
--- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java
+++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/ObjectOutput.java
@@ -30,4 +30,28 @@ public interface ObjectOutput extends DataOutput {
*/
void writeObject(Object obj) throws IOException;
+ /**
+ * The following methods are customized for the requirement of Dubbo's RPC protocol implementation. Legacy protocol
+ * implementation will try to write Map, Throwable and Null value directly to the stream, which does not meet the
+ * restrictions of all serialization protocols.
+ *
+ * See ProtobufSerialization, KryoSerialization for more details.
+ *
+ * The binding of RPC protocol and biz serialization protocol is not a good practice. The encoding of RPC protocol
+ * should be highly independent and portable, easy to cross platforms and languages, for example, like the http headers,
+ * restricting the headers / attachments to Ascii strings and uses ISO_8859_1 to encode.
+ * https://tools.ietf.org/html/rfc7540#section-8.1.2
+ */
+ default void writeThrowable(Object obj) throws IOException {
+ writeObject(obj);
+ }
+
+ default void writeEvent(String data) throws IOException {
+ writeObject(data);
+ }
+
+ default void writeAttachments(Object obj) throws IOException {
+
+ }
+
}
\ No newline at end of file
diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectInput2.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectInput2.java
new file mode 100644
index 0000000000..71670d9887
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectInput2.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.kryo.optimized;
+
+import org.apache.dubbo.common.serialize.Cleanable;
+import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.kryo.utils.KryoUtils;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.KryoException;
+import com.esotericsoftware.kryo.io.Input;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Type;
+
+/**
+ * Kryo object input implementation, kryo object can be clean
+ */
+public class KryoObjectInput2 implements ObjectInput, Cleanable {
+
+ private Kryo kryo;
+ private Input input;
+
+ public KryoObjectInput2(InputStream inputStream) {
+ input = new Input(inputStream);
+ this.kryo = KryoUtils.get();
+ }
+
+ @Override
+ public boolean readBool() throws IOException {
+ try {
+ return input.readBoolean();
+ } catch (KryoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public byte readByte() throws IOException {
+ try {
+ return input.readByte();
+ } catch (KryoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public short readShort() throws IOException {
+ try {
+ return input.readShort();
+ } catch (KryoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public int readInt() throws IOException {
+ try {
+ return input.readInt();
+ } catch (KryoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public long readLong() throws IOException {
+ try {
+ return input.readLong();
+ } catch (KryoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public float readFloat() throws IOException {
+ try {
+ return input.readFloat();
+ } catch (KryoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public double readDouble() throws IOException {
+ try {
+ return input.readDouble();
+ } catch (KryoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public byte[] readBytes() throws IOException {
+ try {
+ int len = input.readInt();
+ if (len < 0) {
+ return null;
+ } else if (len == 0) {
+ return new byte[]{};
+ } else {
+ return input.readBytes(len);
+ }
+ } catch (KryoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public String readUTF() throws IOException {
+ try {
+ return input.readString();
+ } catch (KryoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ /**
+ * works as the only endpoint
+ *
+ * @return
+ * @throws IOException
+ * @throws ClassNotFoundException
+ */
+ @Override
+ public Object readObject() throws IOException, ClassNotFoundException {
+ try {
+ return kryo.readObjectOrNull(input, String.class);
+ } catch (KryoException e) {
+ throw new IOException(e);
+ }
+ }
+
+ @Override
+ public Object readThrowable() throws IOException, ClassNotFoundException {
+ return kryo.readClassAndObject(input);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T readObject(Class clazz) throws IOException, ClassNotFoundException {
+ return kryo.readObjectOrNull(input, clazz);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public T readObject(Class clazz, Type type) throws IOException, ClassNotFoundException {
+ return readObject(clazz);
+ }
+
+ @Override
+ public void cleanup() {
+ KryoUtils.release(kryo);
+ kryo = null;
+ }
+}
diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectOutput2.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectOutput2.java
new file mode 100644
index 0000000000..8500a06b7e
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoObjectOutput2.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.kryo.optimized;
+
+import org.apache.dubbo.common.serialize.Cleanable;
+import org.apache.dubbo.common.serialize.ObjectOutput;
+import org.apache.dubbo.common.serialize.kryo.utils.KryoUtils;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Output;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Kryo object output implementation, kryo object can be clean
+ */
+public class KryoObjectOutput2 implements ObjectOutput, Cleanable {
+
+ private Output output;
+ private Kryo kryo;
+
+ public KryoObjectOutput2(OutputStream outputStream) {
+ output = new Output(outputStream);
+ this.kryo = KryoUtils.get();
+ }
+
+ @Override
+ public void writeBool(boolean v) throws IOException {
+ output.writeBoolean(v);
+ }
+
+ @Override
+ public void writeByte(byte v) throws IOException {
+ output.writeByte(v);
+ }
+
+ @Override
+ public void writeShort(short v) throws IOException {
+ output.writeShort(v);
+ }
+
+ @Override
+ public void writeInt(int v) throws IOException {
+ output.writeInt(v);
+ }
+
+ @Override
+ public void writeLong(long v) throws IOException {
+ output.writeLong(v);
+ }
+
+ @Override
+ public void writeFloat(float v) throws IOException {
+ output.writeFloat(v);
+ }
+
+ @Override
+ public void writeDouble(double v) throws IOException {
+ output.writeDouble(v);
+ }
+
+ @Override
+ public void writeBytes(byte[] v) throws IOException {
+ if (v == null) {
+ output.writeInt(-1);
+ } else {
+ writeBytes(v, 0, v.length);
+ }
+ }
+
+ @Override
+ public void writeBytes(byte[] v, int off, int len) throws IOException {
+ if (v == null) {
+ output.writeInt(-1);
+ } else {
+ output.writeInt(len);
+ output.write(v, off, len);
+ }
+ }
+
+
+ @Override
+ public void writeUTF(String v) throws IOException {
+ output.writeString(v);
+ }
+
+ @Override
+ public void writeObject(Object v) throws IOException {
+ kryo.writeObjectOrNull(output, v, v.getClass());
+ }
+
+ @Override
+ public void writeThrowable(Object v) throws IOException {
+ kryo.writeClassAndObject(output, v);
+ }
+
+ @Override
+ public void flushBuffer() throws IOException {
+ output.flush();
+ }
+
+ @Override
+ public void cleanup() {
+ KryoUtils.release(kryo);
+ kryo = null;
+ }
+}
diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoSerialization2.java b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoSerialization2.java
new file mode 100644
index 0000000000..4bb592399d
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/java/org/apache/dubbo/common/serialize/kryo/optimized/KryoSerialization2.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.kryo.optimized;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.ObjectOutput;
+import org.apache.dubbo.common.serialize.Serialization;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import static org.apache.dubbo.common.serialize.Constants.KRYO_SERIALIZATION_ID;
+
+/**
+ * TODO for now kryo serialization doesn't deny classes that don't implement the serializable interface
+ *
+ *
+ * e.g. <dubbo:protocol serialization="kryo" />
+ *
+ */
+public class KryoSerialization2 implements Serialization {
+
+ @Override
+ public byte getContentTypeId() {
+ return KRYO_SERIALIZATION_ID;
+ }
+
+ @Override
+ public String getContentType() {
+ return "x-application/kryo";
+ }
+
+ @Override
+ public ObjectOutput serialize(URL url, OutputStream out) throws IOException {
+ return new KryoObjectOutput2(out);
+ }
+
+ @Override
+ public ObjectInput deserialize(URL url, InputStream is) throws IOException {
+ return new KryoObjectInput2(is);
+ }
+}
diff --git a/dubbo-serialization/dubbo-serialization-kryo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization b/dubbo-serialization/dubbo-serialization-kryo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
index 531a00804e..331e520ec9 100644
--- a/dubbo-serialization/dubbo-serialization-kryo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
+++ b/dubbo-serialization/dubbo-serialization-kryo/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
@@ -1 +1,2 @@
-kryo=org.apache.dubbo.common.serialize.kryo.KryoSerialization
\ No newline at end of file
+kryo=org.apache.dubbo.common.serialize.kryo.KryoSerialization
+kryo2=org.apache.dubbo.common.serialize.kryo.optimized.KryoSerialization2
\ No newline at end of file
diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/pom.xml b/dubbo-serialization/dubbo-serialization-protobuf-json/pom.xml
deleted file mode 100644
index c39e288f93..0000000000
--- a/dubbo-serialization/dubbo-serialization-protobuf-json/pom.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
- 4.0.0
-
- org.apache.dubbo
- dubbo-serialization
- ${revision}
- ../pom.xml
-
- dubbo-serialization-protobuf-json
- jar
- ${project.artifactId}
- The protobuf serialization module of dubbo project
-
- false
-
-
-
- org.apache.dubbo
- dubbo-serialization-api
- ${project.parent.version}
-
-
- com.google.protobuf
- protobuf-java
-
-
- com.google.protobuf
- protobuf-java-util
-
-
-
diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/MapValue.java b/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/MapValue.java
deleted file mode 100644
index fd24618d45..0000000000
--- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/MapValue.java
+++ /dev/null
@@ -1,830 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.common.serialize.protobuf.support;
-
-/**
- * Generated by the protocol buffer compiler. DO NOT EDIT!
- */
-public final class MapValue {
- private MapValue() {}
- public static void registerAllExtensions(
- com.google.protobuf.ExtensionRegistryLite registry) {
- }
-
- public static void registerAllExtensions(
- com.google.protobuf.ExtensionRegistry registry) {
- registerAllExtensions(
- (com.google.protobuf.ExtensionRegistryLite) registry);
- }
- public interface MapOrBuilder extends
- // @@protoc_insertion_point(interface_extends:Map)
- com.google.protobuf.MessageOrBuilder {
-
- /**
- * map<string, string> attachments = 1;
- */
- int getAttachmentsCount();
- /**
- * map<string, string> attachments = 1;
- */
- boolean containsAttachments(
- String key);
- /**
- * Use {@link #getAttachmentsMap()} instead.
- */
- @Deprecated
- java.util.Map
- getAttachments();
- /**
- * map<string, string> attachments = 1;
- */
- java.util.Map
- getAttachmentsMap();
- /**
- * map<string, string> attachments = 1;
- */
-
- String getAttachmentsOrDefault(
- String key,
- String defaultValue);
- /**
- * map<string, string> attachments = 1;
- */
-
- String getAttachmentsOrThrow(
- String key);
- }
- /**
- * Protobuf type {@code Map}
- */
- public static final class Map extends
- com.google.protobuf.GeneratedMessageV3 implements
- // @@protoc_insertion_point(message_implements:Map)
- MapOrBuilder {
- private static final long serialVersionUID = 0L;
- // Use Map.newBuilder() to construct.
- private Map(com.google.protobuf.GeneratedMessageV3.Builder> builder) {
- super(builder);
- }
- private Map() {
- }
-
- @Override
- public final com.google.protobuf.UnknownFieldSet
- getUnknownFields() {
- return this.unknownFields;
- }
- private Map(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- this();
- if (extensionRegistry == null) {
- throw new NullPointerException();
- }
- int mutable_bitField0_ = 0;
- com.google.protobuf.UnknownFieldSet.Builder unknownFields =
- com.google.protobuf.UnknownFieldSet.newBuilder();
- try {
- boolean done = false;
- while (!done) {
- int tag = input.readTag();
- switch (tag) {
- case 0:
- done = true;
- break;
- case 10: {
- if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
- attachments_ = com.google.protobuf.MapField.newMapField(
- AttachmentsDefaultEntryHolder.defaultEntry);
- mutable_bitField0_ |= 0x00000001;
- }
- com.google.protobuf.MapEntry
- attachments__ = input.readMessage(
- AttachmentsDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
- attachments_.getMutableMap().put(
- attachments__.getKey(), attachments__.getValue());
- break;
- }
- default: {
- if (!parseUnknownFieldProto3(
- input, unknownFields, extensionRegistry, tag)) {
- done = true;
- }
- break;
- }
- }
- }
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- throw e.setUnfinishedMessage(this);
- } catch (java.io.IOException e) {
- throw new com.google.protobuf.InvalidProtocolBufferException(
- e).setUnfinishedMessage(this);
- } finally {
- this.unknownFields = unknownFields.build();
- makeExtensionsImmutable();
- }
- }
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return MapValue.internal_static_Map_descriptor;
- }
-
- @SuppressWarnings({"rawtypes"})
- @Override
- protected com.google.protobuf.MapField internalGetMapField(
- int number) {
- switch (number) {
- case 1:
- return internalGetAttachments();
- default:
- throw new RuntimeException(
- "Invalid map field number: " + number);
- }
- }
- @Override
- protected FieldAccessorTable
- internalGetFieldAccessorTable() {
- return MapValue.internal_static_Map_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- Map.class, Builder.class);
- }
-
- public static final int ATTACHMENTS_FIELD_NUMBER = 1;
- private static final class AttachmentsDefaultEntryHolder {
- static final com.google.protobuf.MapEntry<
- String, String> defaultEntry =
- com.google.protobuf.MapEntry
- .newDefaultInstance(
- MapValue.internal_static_Map_AttachmentsEntry_descriptor,
- com.google.protobuf.WireFormat.FieldType.STRING,
- "",
- com.google.protobuf.WireFormat.FieldType.STRING,
- "");
- }
- private com.google.protobuf.MapField<
- String, String> attachments_;
- private com.google.protobuf.MapField
- internalGetAttachments() {
- if (attachments_ == null) {
- return com.google.protobuf.MapField.emptyMapField(
- AttachmentsDefaultEntryHolder.defaultEntry);
- }
- return attachments_;
- }
-
- @Override
- public int getAttachmentsCount() {
- return internalGetAttachments().getMap().size();
- }
- /**
- * map<string, string> attachments = 1;
- */
-
- @Override
- public boolean containsAttachments(
- String key) {
- if (key == null) { throw new NullPointerException(); }
- return internalGetAttachments().getMap().containsKey(key);
- }
- /**
- * Use {@link #getAttachmentsMap()} instead.
- */
- @Override
- @Deprecated
- public java.util.Map getAttachments() {
- return getAttachmentsMap();
- }
- /**
- * map<string, string> attachments = 1;
- */
-
- @Override
- public java.util.Map getAttachmentsMap() {
- return internalGetAttachments().getMap();
- }
- /**
- * map<string, string> attachments = 1;
- */
-
- @Override
- public String getAttachmentsOrDefault(
- String key,
- String defaultValue) {
- if (key == null) { throw new NullPointerException(); }
- java.util.Map map =
- internalGetAttachments().getMap();
- return map.containsKey(key) ? map.get(key) : defaultValue;
- }
- /**
- * map<string, string> attachments = 1;
- */
-
- @Override
- public String getAttachmentsOrThrow(
- String key) {
- if (key == null) { throw new NullPointerException(); }
- java.util.Map map =
- internalGetAttachments().getMap();
- if (!map.containsKey(key)) {
- throw new IllegalArgumentException();
- }
- return map.get(key);
- }
-
- private byte memoizedIsInitialized = -1;
- @Override
- public final boolean isInitialized() {
- byte isInitialized = memoizedIsInitialized;
- if (isInitialized == 1) {
- return true;
- }
- if (isInitialized == 0) {
- return false;
- }
-
- memoizedIsInitialized = 1;
- return true;
- }
-
- @Override
- public void writeTo(com.google.protobuf.CodedOutputStream output)
- throws java.io.IOException {
- com.google.protobuf.GeneratedMessageV3
- .serializeStringMapTo(
- output,
- internalGetAttachments(),
- AttachmentsDefaultEntryHolder.defaultEntry,
- 1);
- unknownFields.writeTo(output);
- }
-
- @Override
- public int getSerializedSize() {
- int size = memoizedSize;
- if (size != -1) {
- return size;
- }
-
- size = 0;
- for (java.util.Map.Entry entry
- : internalGetAttachments().getMap().entrySet()) {
- com.google.protobuf.MapEntry
- attachments__ = AttachmentsDefaultEntryHolder.defaultEntry.newBuilderForType()
- .setKey(entry.getKey())
- .setValue(entry.getValue())
- .build();
- size += com.google.protobuf.CodedOutputStream
- .computeMessageSize(1, attachments__);
- }
- size += unknownFields.getSerializedSize();
- memoizedSize = size;
- return size;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (obj == this) {
- return true;
- }
- if (!(obj instanceof Map)) {
- return super.equals(obj);
- }
- Map other = (Map) obj;
-
- boolean result = true;
- result = result && internalGetAttachments().equals(
- other.internalGetAttachments());
- result = result && unknownFields.equals(other.unknownFields);
- return result;
- }
-
- @Override
- public int hashCode() {
- if (memoizedHashCode != 0) {
- return memoizedHashCode;
- }
- int hash = 41;
- hash = (19 * hash) + getDescriptor().hashCode();
- if (!internalGetAttachments().getMap().isEmpty()) {
- hash = (37 * hash) + ATTACHMENTS_FIELD_NUMBER;
- hash = (53 * hash) + internalGetAttachments().hashCode();
- }
- hash = (29 * hash) + unknownFields.hashCode();
- memoizedHashCode = hash;
- return hash;
- }
-
- public static Map parseFrom(
- java.nio.ByteBuffer data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static Map parseFrom(
- java.nio.ByteBuffer data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static Map parseFrom(
- com.google.protobuf.ByteString data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static Map parseFrom(
- com.google.protobuf.ByteString data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static Map parseFrom(byte[] data)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data);
- }
- public static Map parseFrom(
- byte[] data,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return PARSER.parseFrom(data, extensionRegistry);
- }
- public static Map parseFrom(java.io.InputStream input)
- throws java.io.IOException {
- return com.google.protobuf.GeneratedMessageV3
- .parseWithIOException(PARSER, input);
- }
- public static Map parseFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return com.google.protobuf.GeneratedMessageV3
- .parseWithIOException(PARSER, input, extensionRegistry);
- }
- public static Map parseDelimitedFrom(java.io.InputStream input)
- throws java.io.IOException {
- return com.google.protobuf.GeneratedMessageV3
- .parseDelimitedWithIOException(PARSER, input);
- }
- public static Map parseDelimitedFrom(
- java.io.InputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return com.google.protobuf.GeneratedMessageV3
- .parseDelimitedWithIOException(PARSER, input, extensionRegistry);
- }
- public static Map parseFrom(
- com.google.protobuf.CodedInputStream input)
- throws java.io.IOException {
- return com.google.protobuf.GeneratedMessageV3
- .parseWithIOException(PARSER, input);
- }
- public static Map parseFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- return com.google.protobuf.GeneratedMessageV3
- .parseWithIOException(PARSER, input, extensionRegistry);
- }
-
- @Override
- public Builder newBuilderForType() { return newBuilder(); }
- public static Builder newBuilder() {
- return DEFAULT_INSTANCE.toBuilder();
- }
- public static Builder newBuilder(Map prototype) {
- return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
- }
- @Override
- public Builder toBuilder() {
- return this == DEFAULT_INSTANCE
- ? new Builder() : new Builder().mergeFrom(this);
- }
-
- @Override
- protected Builder newBuilderForType(
- BuilderParent parent) {
- Builder builder = new Builder(parent);
- return builder;
- }
- /**
- * Protobuf type {@code Map}
- */
- public static final class Builder extends
- com.google.protobuf.GeneratedMessageV3.Builder implements
- // @@protoc_insertion_point(builder_implements:Map)
- MapOrBuilder {
- public static final com.google.protobuf.Descriptors.Descriptor
- getDescriptor() {
- return MapValue.internal_static_Map_descriptor;
- }
-
- @Override
- @SuppressWarnings({"rawtypes"})
- protected com.google.protobuf.MapField internalGetMapField(
- int number) {
- switch (number) {
- case 1:
- return internalGetAttachments();
- default:
- throw new RuntimeException(
- "Invalid map field number: " + number);
- }
- }
- @Override
- @SuppressWarnings({"rawtypes"})
- protected com.google.protobuf.MapField internalGetMutableMapField(
- int number) {
- switch (number) {
- case 1:
- return internalGetMutableAttachments();
- default:
- throw new RuntimeException(
- "Invalid map field number: " + number);
- }
- }
- @Override
- protected FieldAccessorTable
- internalGetFieldAccessorTable() {
- return MapValue.internal_static_Map_fieldAccessorTable
- .ensureFieldAccessorsInitialized(
- Map.class, Builder.class);
- }
-
- // Construct using org.apache.dubbo.common.serialize.protobuf.support.MapValue.Map.newBuilder()
- private Builder() {
- maybeForceBuilderInitialization();
- }
-
- private Builder(
- BuilderParent parent) {
- super(parent);
- maybeForceBuilderInitialization();
- }
- private void maybeForceBuilderInitialization() {
- if (com.google.protobuf.GeneratedMessageV3
- .alwaysUseFieldBuilders) {
- }
- }
- @Override
- public Builder clear() {
- super.clear();
- internalGetMutableAttachments().clear();
- return this;
- }
-
- @Override
- public com.google.protobuf.Descriptors.Descriptor
- getDescriptorForType() {
- return MapValue.internal_static_Map_descriptor;
- }
-
- @Override
- public Map getDefaultInstanceForType() {
- return Map.getDefaultInstance();
- }
-
- @Override
- public Map build() {
- Map result = buildPartial();
- if (!result.isInitialized()) {
- throw newUninitializedMessageException(result);
- }
- return result;
- }
-
- @Override
- public Map buildPartial() {
- Map result = new Map(this);
- int from_bitField0_ = bitField0_;
- result.attachments_ = internalGetAttachments();
- result.attachments_.makeImmutable();
- onBuilt();
- return result;
- }
-
- @Override
- public Builder clone() {
- return (Builder) super.clone();
- }
- @Override
- public Builder setField(
- com.google.protobuf.Descriptors.FieldDescriptor field,
- Object value) {
- return (Builder) super.setField(field, value);
- }
- @Override
- public Builder clearField(
- com.google.protobuf.Descriptors.FieldDescriptor field) {
- return (Builder) super.clearField(field);
- }
- @Override
- public Builder clearOneof(
- com.google.protobuf.Descriptors.OneofDescriptor oneof) {
- return (Builder) super.clearOneof(oneof);
- }
- @Override
- public Builder setRepeatedField(
- com.google.protobuf.Descriptors.FieldDescriptor field,
- int index, Object value) {
- return (Builder) super.setRepeatedField(field, index, value);
- }
- @Override
- public Builder addRepeatedField(
- com.google.protobuf.Descriptors.FieldDescriptor field,
- Object value) {
- return (Builder) super.addRepeatedField(field, value);
- }
- @Override
- public Builder mergeFrom(com.google.protobuf.Message other) {
- if (other instanceof Map) {
- return mergeFrom((Map)other);
- } else {
- super.mergeFrom(other);
- return this;
- }
- }
-
- public Builder mergeFrom(Map other) {
- if (other == Map.getDefaultInstance()) {
- return this;
- }
- internalGetMutableAttachments().mergeFrom(
- other.internalGetAttachments());
- this.mergeUnknownFields(other.unknownFields);
- onChanged();
- return this;
- }
-
- @Override
- public final boolean isInitialized() {
- return true;
- }
-
- @Override
- public Builder mergeFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws java.io.IOException {
- Map parsedMessage = null;
- try {
- parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
- } catch (com.google.protobuf.InvalidProtocolBufferException e) {
- parsedMessage = (Map) e.getUnfinishedMessage();
- throw e.unwrapIOException();
- } finally {
- if (parsedMessage != null) {
- mergeFrom(parsedMessage);
- }
- }
- return this;
- }
- private int bitField0_;
-
- private com.google.protobuf.MapField<
- String, String> attachments_;
- private com.google.protobuf.MapField
- internalGetAttachments() {
- if (attachments_ == null) {
- return com.google.protobuf.MapField.emptyMapField(
- AttachmentsDefaultEntryHolder.defaultEntry);
- }
- return attachments_;
- }
- private com.google.protobuf.MapField
- internalGetMutableAttachments() {
- onChanged();;
- if (attachments_ == null) {
- attachments_ = com.google.protobuf.MapField.newMapField(
- AttachmentsDefaultEntryHolder.defaultEntry);
- }
- if (!attachments_.isMutable()) {
- attachments_ = attachments_.copy();
- }
- return attachments_;
- }
-
- @Override
- public int getAttachmentsCount() {
- return internalGetAttachments().getMap().size();
- }
- /**
- * map<string, string> attachments = 1;
- */
-
- @Override
- public boolean containsAttachments(
- String key) {
- if (key == null) { throw new NullPointerException(); }
- return internalGetAttachments().getMap().containsKey(key);
- }
- /**
- * Use {@link #getAttachmentsMap()} instead.
- */
- @Override
- @Deprecated
- public java.util.Map getAttachments() {
- return getAttachmentsMap();
- }
- /**
- * map<string, string> attachments = 1;
- */
-
- @Override
- public java.util.Map getAttachmentsMap() {
- return internalGetAttachments().getMap();
- }
- /**
- * map<string, string> attachments = 1;
- */
-
- @Override
- public String getAttachmentsOrDefault(
- String key,
- String defaultValue) {
- if (key == null) { throw new NullPointerException(); }
- java.util.Map map =
- internalGetAttachments().getMap();
- return map.containsKey(key) ? map.get(key) : defaultValue;
- }
- /**
- * map<string, string> attachments = 1;
- */
-
- @Override
- public String getAttachmentsOrThrow(
- String key) {
- if (key == null) { throw new NullPointerException(); }
- java.util.Map map =
- internalGetAttachments().getMap();
- if (!map.containsKey(key)) {
- throw new IllegalArgumentException();
- }
- return map.get(key);
- }
-
- public Builder clearAttachments() {
- internalGetMutableAttachments().getMutableMap()
- .clear();
- return this;
- }
- /**
- * map<string, string> attachments = 1;
- */
-
- public Builder removeAttachments(
- String key) {
- if (key == null) { throw new NullPointerException(); }
- internalGetMutableAttachments().getMutableMap()
- .remove(key);
- return this;
- }
- /**
- * Use alternate mutation accessors instead.
- */
- @Deprecated
- public java.util.Map
- getMutableAttachments() {
- return internalGetMutableAttachments().getMutableMap();
- }
- /**
- * map<string, string> attachments = 1;
- */
- public Builder putAttachments(
- String key,
- String value) {
- if (key == null) { throw new NullPointerException(); }
- if (value == null) { throw new NullPointerException(); }
- internalGetMutableAttachments().getMutableMap()
- .put(key, value);
- return this;
- }
- /**
- * map<string, string> attachments = 1;
- */
-
- public Builder putAllAttachments(
- java.util.Map values) {
- internalGetMutableAttachments().getMutableMap()
- .putAll(values);
- return this;
- }
- @Override
- public final Builder setUnknownFields(
- final com.google.protobuf.UnknownFieldSet unknownFields) {
- return super.setUnknownFieldsProto3(unknownFields);
- }
-
- @Override
- public final Builder mergeUnknownFields(
- final com.google.protobuf.UnknownFieldSet unknownFields) {
- return super.mergeUnknownFields(unknownFields);
- }
-
-
- // @@protoc_insertion_point(builder_scope:Map)
- }
-
- // @@protoc_insertion_point(class_scope:Map)
- private static final Map DEFAULT_INSTANCE;
- static {
- DEFAULT_INSTANCE = new Map();
- }
-
- public static Map getDefaultInstance() {
- return DEFAULT_INSTANCE;
- }
-
- private static final com.google.protobuf.Parser
- PARSER = new com.google.protobuf.AbstractParser() {
- @Override
- public Map parsePartialFrom(
- com.google.protobuf.CodedInputStream input,
- com.google.protobuf.ExtensionRegistryLite extensionRegistry)
- throws com.google.protobuf.InvalidProtocolBufferException {
- return new Map(input, extensionRegistry);
- }
- };
-
- public static com.google.protobuf.Parser parser() {
- return PARSER;
- }
-
- @Override
- public com.google.protobuf.Parser getParserForType() {
- return PARSER;
- }
-
- @Override
- public Map getDefaultInstanceForType() {
- return DEFAULT_INSTANCE;
- }
-
- }
-
- private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_Map_descriptor;
- private static final
- com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
- internal_static_Map_fieldAccessorTable;
- private static final com.google.protobuf.Descriptors.Descriptor
- internal_static_Map_AttachmentsEntry_descriptor;
- private static final
- com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
- internal_static_Map_AttachmentsEntry_fieldAccessorTable;
-
- public static com.google.protobuf.Descriptors.FileDescriptor
- getDescriptor() {
- return descriptor;
- }
- private static com.google.protobuf.Descriptors.FileDescriptor
- descriptor;
- static {
- String[] descriptorData = {
- "\n\tmap.proto\"e\n\003Map\022*\n\013attachments\030\001 \003(\0132" +
- "\025.Map.AttachmentsEntry\0322\n\020AttachmentsEnt" +
- "ry\022\013\n\003key\030\001 \001(\t\022\r\n\005value\030\002 \001(\t:\0028\001B>\n2or" +
- "g.apache.dubbo.common.serialize.protobuf" +
- ".supportB\010MapValueb\006proto3"
- };
- com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
- new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
- @Override
- public com.google.protobuf.ExtensionRegistry assignDescriptors(
- com.google.protobuf.Descriptors.FileDescriptor root) {
- descriptor = root;
- return null;
- }
- };
- com.google.protobuf.Descriptors.FileDescriptor
- .internalBuildGeneratedFileFrom(descriptorData,
- new com.google.protobuf.Descriptors.FileDescriptor[] {
- }, assigner);
- internal_static_Map_descriptor =
- getDescriptor().getMessageTypes().get(0);
- internal_static_Map_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
- internal_static_Map_descriptor,
- new String[] { "Attachments", });
- internal_static_Map_AttachmentsEntry_descriptor =
- internal_static_Map_descriptor.getNestedTypes().get(0);
- internal_static_Map_AttachmentsEntry_fieldAccessorTable = new
- com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
- internal_static_Map_AttachmentsEntry_descriptor,
- new String[] { "Key", "Value", });
- }
-
- // @@protoc_insertion_point(outer_class_scope)
-}
diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java b/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java
deleted file mode 100644
index 7a2eda8814..0000000000
--- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.common.serialize.protobuf.support;
-
-import com.google.protobuf.GeneratedMessageV3;
-import com.google.protobuf.GeneratedMessageV3.Builder;
-import com.google.protobuf.InvalidProtocolBufferException;
-import com.google.protobuf.MessageOrBuilder;
-import com.google.protobuf.util.JsonFormat;
-import com.google.protobuf.util.JsonFormat.Printer;
-
-import java.lang.reflect.Method;
-
-public class ProtobufUtils {
-
- static boolean isSupported(Class> clazz) {
- if (clazz == null) {
- return false;
- }
-
- if (GeneratedMessageV3.class.isAssignableFrom(clazz)) {
- return true;
- }
- return false;
- }
-
- static T deserialize(String json, Class requestClass) throws InvalidProtocolBufferException {
- Builder builder;
- try {
- builder = getMessageBuilder(requestClass);
- } catch (Exception e) {
- throw new IllegalArgumentException("Get google protobuf message builder from " + requestClass.getName() + "failed", e);
- }
- JsonFormat.parser().merge(json, builder);
- return (T) builder.build();
- }
-
- static String serialize(Object value) throws InvalidProtocolBufferException {
- Printer printer = JsonFormat.printer().omittingInsignificantWhitespace();
- return printer.print((MessageOrBuilder) value);
- }
-
- private static Builder getMessageBuilder(Class> requestType) throws Exception {
- Method method = requestType.getMethod("newBuilder");
- return (Builder) method.invoke(null, null);
- }
-}
\ No newline at end of file
diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization b/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
deleted file mode 100644
index 56d6b68bf0..0000000000
--- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
+++ /dev/null
@@ -1 +0,0 @@
-protobuf-json=org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufSerialization
\ No newline at end of file
diff --git a/dubbo-serialization/dubbo-serialization-protobuf/pom.xml b/dubbo-serialization/dubbo-serialization-protobuf/pom.xml
new file mode 100644
index 0000000000..eb169424ae
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-protobuf/pom.xml
@@ -0,0 +1,105 @@
+
+
+ 4.0.0
+
+ org.apache.dubbo
+ dubbo-serialization
+ ${revision}
+ ../pom.xml
+
+ dubbo-serialization-protobuf
+ jar
+ ${project.artifactId}
+ The protobuf serialization module of dubbo project
+
+ false
+
+ 1.19.0-SNAPSHOT
+
+
+
+ org.apache.dubbo
+ dubbo-serialization-api
+ ${project.parent.version}
+
+
+ com.google.protobuf
+ protobuf-java
+
+
+ com.google.protobuf
+ protobuf-java-util
+
+
+
+
+
+
+ kr.motd.maven
+ os-maven-plugin
+ 1.6.1
+
+
+
+
+ org.xolstice.maven.plugins
+ protobuf-maven-plugin
+ 0.5.1
+
+ com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}
+ grpc-java
+
+ org.apache.dubbo:protoc-gen-grpc-java:${proto_dubbo_plugin_version}:exe:${os.detected.classifier}
+
+ build/generated/source/proto/main/java
+ false
+
+ dubbo
+
+
+
+
+ compile
+ compile-custom
+ test-compile
+ test-compile-custom
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ generate-sources
+
+ add-source
+
+
+
+ build/generated/source/proto/main/java
+
+
+
+
+
+
+
+
diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectInput.java
similarity index 76%
rename from dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java
rename to dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectInput.java
index 0641c4d820..20d5d477ad 100644
--- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectInput.java
@@ -17,10 +17,13 @@
package org.apache.dubbo.common.serialize.protobuf.support;
import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.MapValue;
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB;
import com.google.protobuf.BoolValue;
import com.google.protobuf.BytesValue;
import com.google.protobuf.DoubleValue;
+import com.google.protobuf.Empty;
import com.google.protobuf.FloatValue;
import com.google.protobuf.Int32Value;
import com.google.protobuf.Int64Value;
@@ -37,10 +40,10 @@ import java.util.Map;
/**
* GenericGoogleProtobuf object input implementation
*/
-public class GenericProtobufObjectInput implements ObjectInput {
+public class GenericProtobufJsonObjectInput implements ObjectInput {
private final BufferedReader reader;
- public GenericProtobufObjectInput(InputStream in) {
+ public GenericProtobufJsonObjectInput(InputStream in) {
this.reader = new BufferedReader(new InputStreamReader(in));
}
@@ -91,7 +94,17 @@ public class GenericProtobufObjectInput implements ObjectInput {
@Override
public Object readObject() {
- throw new UnsupportedOperationException();
+ try {
+ read(Empty.class);
+ return null;
+ } catch (Exception e) {
+ throw new UnsupportedOperationException("Provide the protobuf message type you want to read.");
+ }
+ }
+
+ @Override
+ public Object readThrowable() throws IOException, ClassNotFoundException {
+ return read(Throwable.class);
}
@Override
@@ -117,12 +130,16 @@ public class GenericProtobufObjectInput implements ObjectInput {
if (cls.equals(Map.class)) {
// only for attachments
String json = readLine();
- return (T) ProtobufUtils.deserialize(json, MapValue.Map.class).getAttachmentsMap();
+ return (T) ProtobufUtils.deserializeJson(json, MapValue.Map.class).getAttachmentsMap();
+ } else if (getClass().isAssignableFrom(Throwable.class)) {
+ String json = readLine();
+ ThrowablePB.ThrowableProto throwableProto = ProtobufUtils.deserializeJson(json, ThrowablePB.ThrowableProto.class);
+ return (T) ProtobufUtils.convertToException(throwableProto);
} else if (!ProtobufUtils.isSupported(cls)) {
throw new IllegalArgumentException("This serialization only support google protobuf entity, the class is :" + cls.getName());
}
String json = readLine();
- return ProtobufUtils.deserialize(json, cls);
+ return ProtobufUtils.deserializeJson(json, cls);
}
}
diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutput.java
similarity index 89%
rename from dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java
rename to dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutput.java
index 7384fddcf2..78f6284378 100644
--- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutput.java
@@ -17,6 +17,7 @@
package org.apache.dubbo.common.serialize.protobuf.support;
import org.apache.dubbo.common.serialize.ObjectOutput;
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.MapValue;
import com.google.protobuf.BoolValue;
import com.google.protobuf.ByteString;
@@ -36,11 +37,11 @@ import java.util.Map;
/**
* GenericGoogleProtobuf object output implementation
*/
-public class GenericProtobufObjectOutput implements ObjectOutput {
+public class GenericProtobufJsonObjectOutput implements ObjectOutput {
private final PrintWriter writer;
- public GenericProtobufObjectOutput(OutputStream out) {
+ public GenericProtobufJsonObjectOutput(OutputStream out) {
this.writer = new PrintWriter(new OutputStreamWriter(out));
}
@@ -104,11 +105,13 @@ public class GenericProtobufObjectOutput implements ObjectOutput {
if (obj instanceof Map) {
// only for attachment
obj = MapValue.Map.newBuilder().putAllAttachments((Map) obj).build();
+ } else if (obj instanceof Throwable && !ProtobufUtils.isSupported(obj.getClass())) {
+ obj = ProtobufUtils.serializeJson(ProtobufUtils.convertToThrowableProto((Throwable) obj));
} else if (!ProtobufUtils.isSupported(obj.getClass())) {
throw new IllegalArgumentException("This serialization only support google protobuf object, the object class is: " + obj.getClass().getName());
}
- writer.write(ProtobufUtils.serialize(obj));
+ writer.write(ProtobufUtils.serializeJson(obj));
writer.println();
writer.flush();
}
diff --git a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerialization.java
similarity index 90%
rename from dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java
rename to dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerialization.java
index d3d2330017..0d2fae628c 100644
--- a/dubbo-serialization/dubbo-serialization-protobuf-json/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerialization.java
@@ -29,9 +29,8 @@ import static org.apache.dubbo.common.serialize.Constants.PROTOBUF_JSON_SERIALIZ
/**
* This serizalization is use for google protobuf generic reference.
* The entity be transported between client and server by json string.
- *
*/
-public class GenericProtobufSerialization implements Serialization {
+public class GenericProtobufJsonSerialization implements Serialization {
@Override
public byte getContentTypeId() {
@@ -45,11 +44,11 @@ public class GenericProtobufSerialization implements Serialization {
@Override
public ObjectOutput serialize(URL url, OutputStream output) {
- return new GenericProtobufObjectOutput(output);
+ return new GenericProtobufJsonObjectOutput(output);
}
@Override
public ObjectInput deserialize(URL url, InputStream input) {
- return new GenericProtobufObjectInput(input);
+ return new GenericProtobufJsonObjectInput(input);
}
}
diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java
new file mode 100644
index 0000000000..0ad98d6387
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectInput.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.protobuf.support;
+
+import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.MapValue;
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB;
+
+import com.google.protobuf.BoolValue;
+import com.google.protobuf.BytesValue;
+import com.google.protobuf.DoubleValue;
+import com.google.protobuf.Empty;
+import com.google.protobuf.FloatValue;
+import com.google.protobuf.Int32Value;
+import com.google.protobuf.Int64Value;
+import com.google.protobuf.StringValue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Type;
+import java.util.Map;
+
+public class GenericProtobufObjectInput implements ObjectInput {
+ private final InputStream is;
+
+ public GenericProtobufObjectInput(InputStream is) {
+ this.is = is;
+ }
+
+ @Override
+ public boolean readBool() throws IOException {
+ return read(BoolValue.class).getValue();
+ }
+
+ @Override
+ public byte readByte() throws IOException {
+ return (byte) read(Int32Value.class).getValue();
+ }
+
+ @Override
+ public short readShort() throws IOException {
+ return (short) read(Int32Value.class).getValue();
+ }
+
+ @Override
+ public int readInt() throws IOException {
+ return read(Int32Value.class).getValue();
+ }
+
+ @Override
+ public long readLong() throws IOException {
+ return read(Int64Value.class).getValue();
+ }
+
+ @Override
+ public float readFloat() throws IOException {
+ return read(FloatValue.class).getValue();
+ }
+
+ @Override
+ public double readDouble() throws IOException {
+ return read(DoubleValue.class).getValue();
+ }
+
+ @Override
+ public String readUTF() throws IOException {
+ return read(StringValue.class).getValue();
+ }
+
+ @Override
+ public byte[] readBytes() throws IOException {
+ return read(BytesValue.class).getValue().toByteArray();
+ }
+
+ /**
+ * FIXME assume this method only has the following single entry point:
+ * DecodeableRpcResult#readValue, decode empty value for heart beat event.
+ *
+ * Avoid using readObject, always try to pass the target class type for the data you want to read.
+ *
+ * @return
+ */
+ @Deprecated
+ @Override
+ public Object readObject() {
+ try {
+ read(Empty.class);
+ return null;
+ } catch (Exception e) {
+ throw new UnsupportedOperationException("Provide the protobuf message type you want to read.");
+ }
+ }
+
+ @Override
+ public Object readThrowable() throws IOException, ClassNotFoundException {
+ return read(Throwable.class);
+ }
+
+ @Override
+ public T readObject(Class cls) throws IOException {
+ return read(cls);
+ }
+
+ @Override
+ public T readObject(Class cls, Type type) throws IOException {
+ return readObject(cls);
+ }
+
+ @SuppressWarnings("unchecked")
+ private T read(Class cls) throws IOException {
+ if (cls.isAssignableFrom(Map.class)) {
+ // only for attachments
+ return (T) ProtobufUtils.deserialize(is, MapValue.Map.class).getAttachmentsMap();
+ } else if (getClass().isAssignableFrom(Throwable.class)) {
+ ThrowablePB.ThrowableProto throwableProto = ProtobufUtils.deserialize(is, ThrowablePB.ThrowableProto.class);
+ return (T) ProtobufUtils.convertToException(throwableProto);
+ } else if (!ProtobufUtils.isSupported(cls)) {
+ throw new IllegalArgumentException("This serialization only support google protobuf entity, the class is :" + cls.getName());
+ }
+
+ return ProtobufUtils.deserialize(is, cls);
+ }
+}
diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java
new file mode 100644
index 0000000000..c6eed65d36
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutput.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.protobuf.support;
+
+import org.apache.dubbo.common.serialize.ObjectOutput;
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.MapValue;
+
+import com.google.protobuf.BoolValue;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.BytesValue;
+import com.google.protobuf.DoubleValue;
+import com.google.protobuf.FloatValue;
+import com.google.protobuf.Int32Value;
+import com.google.protobuf.Int64Value;
+import com.google.protobuf.MessageLite;
+import com.google.protobuf.StringValue;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+
+/**
+ * GenericGoogleProtobuf object output implementation
+ */
+public class GenericProtobufObjectOutput implements ObjectOutput {
+
+ private final OutputStream os;
+
+ public GenericProtobufObjectOutput(OutputStream os) {
+ this.os = os;
+ }
+
+ @Override
+ public void writeBool(boolean v) throws IOException {
+
+ writeObject(BoolValue.newBuilder().setValue(v).build());
+ }
+
+ @Override
+ public void writeByte(byte v) throws IOException {
+ writeObject(Int32Value.newBuilder().setValue((v)).build());
+ }
+
+ @Override
+ public void writeShort(short v) throws IOException {
+ writeObject(Int32Value.newBuilder().setValue(v).build());
+ }
+
+ @Override
+ public void writeInt(int v) throws IOException {
+ writeObject(Int32Value.newBuilder().setValue(v).build());
+ }
+
+ @Override
+ public void writeLong(long v) throws IOException {
+ writeObject(Int64Value.newBuilder().setValue(v).build());
+ }
+
+ @Override
+ public void writeFloat(float v) throws IOException {
+ writeObject(FloatValue.newBuilder().setValue(v).build());
+ }
+
+ @Override
+ public void writeDouble(double v) throws IOException {
+ writeObject(DoubleValue.newBuilder().setValue(v).build());
+ }
+
+ @Override
+ public void writeUTF(String v) throws IOException {
+ writeObject(StringValue.newBuilder().setValue(v).build());
+ }
+
+ @Override
+ public void writeBytes(byte[] b) throws IOException {
+ writeObject(BytesValue.newBuilder().setValue(ByteString.copyFrom(b)).build());
+ }
+
+ @Override
+ public void writeBytes(byte[] b, int off, int len) throws IOException {
+ writeObject(BytesValue.newBuilder().setValue(ByteString.copyFrom(b, off, len)).build());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void writeObject(Object obj) throws IOException {
+ /**
+ * Protobuf does not allow writing of non-protobuf generated message, including null value.
+ * Writing of null value from developers should be denied immediately by throwing exception.
+ */
+ if (obj == null) {
+ throw new IllegalStateException("This serialization only supports google protobuf objects, " +
+ "please use com.google.protobuf.Empty instead if you want to transmit null values.");
+ // obj = ProtobufUtils.convertNullToEmpty();
+ }
+ if (obj instanceof Map) {
+ // only for attachment
+ obj = MapValue.Map.newBuilder().putAllAttachments((Map) obj).build();
+ } else if (!ProtobufUtils.isSupported(obj.getClass())) {
+ throw new IllegalArgumentException("This serialization only supports google protobuf objects, current object class is: " + obj.getClass().getName());
+ }
+
+ ProtobufUtils.serialize(obj, os);
+ os.flush();
+ }
+
+ @Override
+ public void writeEvent(String data) throws IOException {
+ if (data == null) {
+ data = "H";
+ }
+ writeUTF(data);
+ }
+
+ @Override
+ public void writeThrowable(Object obj) throws IOException {
+ if (obj instanceof Throwable && !(obj instanceof MessageLite)) {
+ obj = ProtobufUtils.convertToThrowableProto((Throwable) obj);
+ }
+ }
+
+ @Override
+ public void flushBuffer() throws IOException {
+ os.flush();
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java
new file mode 100644
index 0000000000..c2a5afdfe4
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerialization.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.protobuf.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.ObjectOutput;
+import org.apache.dubbo.common.serialize.Serialization;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import static org.apache.dubbo.common.serialize.Constants.PROTOBUF_JSON_SERIALIZATION_ID;
+
+/**
+ *
+ * Currently, the Dubbo protocol / framework data, such as attachments, event data, etc.,
+ * depends on business layer serialization protocol to do serialization before transmitted.
+ * That's a problem when using Protobuf as business serialization protocol, because Protobuf does not support raw java Object types,
+ * to solve it, we can use one of the following methods:
+ *
+ *
+ * 1. Package these data with Protobuf so that they can be serialized.
+ * 2. Separate the serialization of Dubbo protocol/framework and the service args (easy to cross-platform, cross-language serialization) to avoid the binding of this part and serialization protocol.
+ *
+ *
+ *
+ */
+public class GenericProtobufSerialization implements Serialization {
+
+ @Override
+ public byte getContentTypeId() {
+ return PROTOBUF_JSON_SERIALIZATION_ID;
+ }
+
+ @Override
+ public String getContentType() {
+ return "text/json";
+ }
+
+ @Override
+ public ObjectOutput serialize(URL url, OutputStream output) {
+ return new GenericProtobufJsonObjectOutput(output);
+ }
+
+ @Override
+ public ObjectInput deserialize(URL url, InputStream input) {
+ return new GenericProtobufJsonObjectInput(input);
+ }
+}
diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java
new file mode 100644
index 0000000000..56b2f9082f
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufUtils.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.protobuf.support;
+
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.MapValue;
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB.StackTraceElementProto;
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB.ThrowableProto;
+
+import com.google.common.base.Strings;
+import com.google.protobuf.CodedInputStream;
+import com.google.protobuf.Empty;
+import com.google.protobuf.ExtensionRegistryLite;
+import com.google.protobuf.GeneratedMessageV3;
+import com.google.protobuf.GeneratedMessageV3.Builder;
+import com.google.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.MessageLite;
+import com.google.protobuf.MessageOrBuilder;
+import com.google.protobuf.Parser;
+import com.google.protobuf.util.JsonFormat;
+import com.google.protobuf.util.JsonFormat.Printer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class ProtobufUtils {
+
+ static boolean isSupported(Class> clazz) {
+ if (clazz == null) {
+ return false;
+ }
+
+ if (GeneratedMessageV3.class.isAssignableFrom(clazz)) {
+ return true;
+ }
+ return false;
+ }
+
+ /* Protobuf json */
+
+ static T deserializeJson(String json, Class requestClass) throws InvalidProtocolBufferException {
+ Builder builder;
+ try {
+ builder = getMessageBuilder(requestClass);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Get google protobuf message builder from " + requestClass.getName() + "failed", e);
+ }
+ JsonFormat.parser().merge(json, builder);
+ return (T) builder.build();
+ }
+
+ static String serializeJson(Object value) throws InvalidProtocolBufferException {
+ Printer printer = JsonFormat.printer().omittingInsignificantWhitespace();
+ return printer.print((MessageOrBuilder) value);
+ }
+
+ private static Builder getMessageBuilder(Class> requestType) throws Exception {
+ Method method = requestType.getMethod("newBuilder");
+ return (Builder) method.invoke(null, null);
+ }
+
+
+ /* Protobuf */
+
+ private static ConcurrentMap, MessageMarshaller> marshallers =
+ new ConcurrentHashMap<>();
+
+ private static volatile ExtensionRegistryLite globalRegistry =
+ ExtensionRegistryLite.getEmptyRegistry();
+
+ static {
+ // Builtin types needed to be registered in advance
+ marshaller(MapValue.Map.getDefaultInstance());
+ marshaller(Empty.getDefaultInstance());
+ marshaller(ThrowableProto.getDefaultInstance());
+ }
+
+ public static void marshaller(T defaultInstance) {
+ marshallers.put(defaultInstance.getClass(), new MessageMarshaller<>(defaultInstance));
+ }
+
+ static void serialize(Object value, OutputStream os) throws IOException {
+ MessageLite messageLite = (MessageLite) value;
+ messageLite.writeTo(os);
+ }
+
+ @SuppressWarnings("unchecked")
+ static T deserialize(InputStream is, Class requestClass) throws InvalidProtocolBufferException {
+ MessageMarshaller> marshaller = marshallers.get(requestClass);
+ if (marshaller == null) {
+ throw new IllegalStateException(String.format("Protobuf classes should be registered in advance before " +
+ "do serialization, class name: %s", requestClass.getName()));
+ }
+ return (T) marshaller.parse(is);
+ }
+
+ public static Empty convertNullToEmpty() {
+ return Empty.newBuilder().build();
+ }
+
+ public static Object convertEmptyToNull(Empty empty) {
+ return null;
+ }
+
+ public static ThrowableProto convertToThrowableProto(Throwable throwable) {
+ final ThrowableProto.Builder builder = ThrowableProto.newBuilder();
+ builder.setOriginalClassName(throwable.getClass().getCanonicalName());
+ builder.setOriginalMessage(Strings.nullToEmpty(throwable.getMessage()));
+
+ for (StackTraceElement e : throwable.getStackTrace()) {
+ builder.addStackTrace(toStackTraceElement(e));
+ }
+
+ if (throwable.getCause() != null) {
+ builder.setCause(convertToThrowableProto(throwable.getCause()));
+ }
+ return builder.build();
+ }
+
+ public static Throwable convertToException(ThrowableProto throwableProto) {
+ return new ProtobufWrappedException(throwableProto);
+ }
+
+ private static StackTraceElementProto toStackTraceElement(StackTraceElement element) {
+ final StackTraceElementProto.Builder builder =
+ StackTraceElementProto.newBuilder()
+ .setClassName(element.getClassName())
+ .setMethodName(element.getMethodName())
+ .setLineNumber(element.getLineNumber());
+ if (element.getFileName() != null) {
+ builder.setFileName(element.getFileName());
+ }
+ return builder.build();
+ }
+
+ private static final class MessageMarshaller {
+ private final Parser parser;
+ private final T defaultInstance;
+
+ @SuppressWarnings("unchecked")
+ MessageMarshaller(T defaultInstance) {
+ this.defaultInstance = defaultInstance;
+ parser = (Parser) defaultInstance.getParserForType();
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public Class getMessageClass() {
+ // Precisely T since protobuf doesn't let messages extend other messages.
+ return (Class) defaultInstance.getClass();
+ }
+
+ public T getMessagePrototype() {
+ return defaultInstance;
+ }
+
+ public T parse(InputStream stream) throws InvalidProtocolBufferException {
+ CodedInputStream cis = CodedInputStream.newInstance(stream);
+ // Pre-create the CodedInputStream so that we can remove the size limit restriction
+ // when parsing.
+ cis.setSizeLimit(Integer.MAX_VALUE);
+ return parseFrom(cis);
+ }
+
+ private T parseFrom(CodedInputStream stream) throws InvalidProtocolBufferException {
+ T message = parser.parseFrom(stream, globalRegistry);
+ try {
+ stream.checkLastTagWas(0);
+ return message;
+ } catch (InvalidProtocolBufferException e) {
+ e.setUnfinishedMessage(message);
+ throw e;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufWrappedException.java b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufWrappedException.java
new file mode 100644
index 0000000000..83939a97cb
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/java/org/apache/dubbo/common/serialize/protobuf/support/ProtobufWrappedException.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.protobuf.support;
+
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB;
+import org.apache.dubbo.common.serialize.protobuf.support.wrapper.ThrowablePB.ThrowableProto;
+
+import com.google.common.base.Strings;
+
+/**
+ * For protobuf, all server side exceptions should be wrapped using this specific one.
+ */
+public class ProtobufWrappedException extends RuntimeException {
+
+ private static final long serialVersionUID = -1792808536714102039L;
+
+ private String originalClassName;
+ private String originalMessage;
+
+ public ProtobufWrappedException(ThrowableProto throwableProto) {
+ super(throwableProto.getOriginalClassName() + ": " + throwableProto.getOriginalMessage());
+
+ originalClassName = throwableProto.getOriginalClassName();
+ originalMessage = throwableProto.getOriginalMessage();
+
+ if (throwableProto.getStackTraceCount() > 0) {
+ setStackTrace(throwableProto.getStackTraceList().stream()
+ .map(ProtobufWrappedException::toStackTraceElement)
+ .toArray(StackTraceElement[]::new));
+ }
+
+ if (throwableProto.hasCause()) {
+ initCause(new ProtobufWrappedException(throwableProto.getCause()));
+ }
+ }
+
+ public String getOriginalClassName() {
+ return originalClassName;
+ }
+
+ public String getOriginalMessage() {
+ return originalMessage;
+ }
+
+ private static StackTraceElement toStackTraceElement(ThrowablePB.StackTraceElementProto proto) {
+ return new StackTraceElement(
+ proto.getClassName(),
+ proto.getMethodName(),
+ Strings.emptyToNull(proto.getFileName()),
+ proto.getLineNumber());
+ }
+
+}
+
diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/MapValue.proto b/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/MapValue.proto
new file mode 100644
index 0000000000..bb52c240b2
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/MapValue.proto
@@ -0,0 +1,26 @@
+// Copyright 2018 LINE Corporation
+//
+// LINE Corporation licenses this file to you under the Apache License,
+// version 2.0 (the "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at:
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+// Messages used for transporting debug information between server and client.
+
+syntax = "proto3";
+
+package org.apache.dubbo.common.serialize.protobuf.support.wrapper;
+
+option java_package = "org.apache.dubbo.common.serialize.protobuf.support.wrapper";
+option java_multiple_files = false;
+
+message Map{
+ map attachments = 1;
+}
\ No newline at end of file
diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/ThrowablePB.proto b/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/ThrowablePB.proto
new file mode 100644
index 0000000000..2937d79d5a
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/proto/ThrowablePB.proto
@@ -0,0 +1,63 @@
+// Copyright 2018 LINE Corporation
+//
+// LINE Corporation licenses this file to you under the Apache License,
+// version 2.0 (the "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at:
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+// Messages used for transporting debug information between server and client.
+
+syntax = "proto3";
+
+package org.apache.dubbo.common.serialize.protobuf.support.wrapper;
+
+option java_package = "org.apache.dubbo.common.serialize.protobuf.support.wrapper";
+option java_multiple_files = false;
+
+// An element in a stack trace, based on the Java type of the same name.
+//
+// See: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/StackTraceElement.html
+message StackTraceElementProto {
+ // The fully qualified name of the class containing the execution point
+ // represented by the stack trace element.
+ string class_name = 1;
+
+ // The name of the method containing the execution point represented by the
+ // stack trace element
+ string method_name = 2;
+
+ // The name of the file containing the execution point represented by the
+ // stack trace element, or null if this information is unavailable.
+ string file_name = 3;
+
+ // The line number of the source line containing the execution point represented
+ // by this stack trace element, or a negative number if this information is
+ // unavailable.
+ int32 line_number = 4;
+}
+
+// An exception that was thrown by some code, based on the Java type of the same name.
+//
+// See: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Throwable.html
+message ThrowableProto {
+ // The name of the class of the exception that was actually thrown. Downstream readers
+ // of this message may or may not have the actual class available to initialize, so
+ // this is just used to prefix the message of a generic exception type.
+ string original_class_name = 1;
+
+ // The message of this throwable. Not filled if there is no message.
+ string original_message = 2;
+
+ // The stack trace of this Throwable.
+ repeated StackTraceElementProto stack_trace = 3;
+
+ // The cause of this Throwable. Not filled if there is no cause.
+ ThrowableProto cause = 4;
+}
diff --git a/dubbo-serialization/dubbo-serialization-protobuf/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization b/dubbo-serialization/dubbo-serialization-protobuf/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
new file mode 100644
index 0000000000..b18b8be488
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-protobuf/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
@@ -0,0 +1,2 @@
+protobuf-json=org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufJsonSerialization
+protobuf=org.apache.dubbo.common.serialize.protobuf.support.GenericProtobufSerialization
\ No newline at end of file
diff --git a/dubbo-serialization/dubbo-serialization-test/pom.xml b/dubbo-serialization/dubbo-serialization-test/pom.xml
index 6799a9cdf1..122b15b7a5 100644
--- a/dubbo-serialization/dubbo-serialization-test/pom.xml
+++ b/dubbo-serialization/dubbo-serialization-test/pom.xml
@@ -80,7 +80,7 @@
org.apache.dubbo
- dubbo-serialization-protobuf-json
+ dubbo-serialization-protobuf
${project.parent.version}
diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/AbstractProtobufSerializationTest.java b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/AbstractProtobufSerializationTest.java
new file mode 100644
index 0000000000..65bec38971
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/AbstractProtobufSerializationTest.java
@@ -0,0 +1,360 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.protobuf.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.serialize.ObjectInput;
+import org.apache.dubbo.common.serialize.ObjectOutput;
+import org.apache.dubbo.common.serialize.Serialization;
+import org.apache.dubbo.common.serialize.protobuf.support.model.GooglePB;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class AbstractProtobufSerializationTest {
+ protected static Random random = new Random();
+ protected URL url = new URL("protocol", "1.1.1.1", 1234);
+ protected ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ protected Serialization serialization = new GenericProtobufSerialization();
+
+ @Test
+ public void test_Bool() throws Exception {
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeBool(false);
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ assertFalse(deserialize.readBool());
+
+ try {
+ deserialize.readBool();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ @Test
+ public void test_Bool_Multi() throws Exception {
+ boolean[] array = new boolean[100];
+ for (int i = 0; i < array.length; i++) {
+ array[i] = random.nextBoolean();
+ }
+
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ for (boolean b : array) {
+ objectOutput.writeBool(b);
+ }
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ for (boolean b : array) {
+ assertEquals(b, deserialize.readBool());
+ }
+
+ try {
+ deserialize.readBool();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ @Test
+ public void test_Byte() throws Exception {
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeByte((byte) 123);
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ assertEquals((byte) 123, deserialize.readByte());
+
+ try {
+ deserialize.readByte();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ @Test
+ public void test_Byte_Multi() throws Exception {
+ byte[] array = new byte[100];
+ random.nextBytes(array);
+
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ for (byte b : array) {
+ objectOutput.writeByte(b);
+ }
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ for (byte b : array) {
+ assertEquals(b, deserialize.readByte());
+ }
+
+ try {
+ deserialize.readByte();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ @Test
+ public void test_Short() throws Exception {
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeShort((short) 123);
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ assertEquals((short) 123, deserialize.readShort());
+
+ try {
+ deserialize.readShort();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ @Test
+ public void test_Integer() throws Exception {
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeInt(1);
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ int i = deserialize.readInt();
+ assertEquals(1, i);
+
+ try {
+ deserialize.readInt();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ @Test
+ public void test_Long() throws Exception {
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeLong(123L);
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ assertEquals(123L, deserialize.readLong());
+
+ try {
+ deserialize.readLong();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ @Test
+ public void test_Float() throws Exception {
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeFloat(1.28F);
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ assertEquals(1.28F, deserialize.readFloat());
+
+ try {
+ deserialize.readFloat();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ // ================== Util methods ==================
+
+ @Test
+ public void test_Double() throws Exception {
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeDouble(1.28);
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ assertEquals(1.28, deserialize.readDouble());
+
+ try {
+ deserialize.readDouble();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ @Test
+ public void test_UtfString() throws Exception {
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeUTF("123中华人民共和国");
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ assertEquals("123中华人民共和国", deserialize.readUTF());
+
+ try {
+ deserialize.readUTF();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ @Test
+ public void test_Bytes() throws Exception {
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeBytes("123中华人民共和国".getBytes());
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ assertArrayEquals("123中华人民共和国".getBytes(), deserialize.readBytes());
+
+ try {
+ deserialize.readBytes();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ @Test
+ public void test_BytesRange() throws Exception {
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeBytes("123中华人民共和国-新疆维吾尔自治区".getBytes(), 1, 9);
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput deserialize = serialization.deserialize(url, byteArrayInputStream);
+
+ byte[] expectedArray = new byte[9];
+ System.arraycopy("123中华人民共和国-新疆维吾尔自治区".getBytes(), 1, expectedArray, 0, expectedArray.length);
+ assertArrayEquals(expectedArray, deserialize.readBytes());
+
+ try {
+ deserialize.readBytes();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ private GooglePB.PBRequestType buildPbMessage() {
+ Random random = new Random();
+ final int bound = 100000;
+ List phoneNumberList = new ArrayList<>();
+ for (int i = 0; i < 5; i++) {
+ phoneNumberList.add(GooglePB.PhoneNumber.newBuilder().setNumber(random.nextInt(bound) + "").setType(GooglePB.PhoneType.forNumber(random.nextInt(GooglePB.PhoneType.values().length - 1))).build());
+ }
+
+ Map phoneNumberMap = new HashMap<>();
+ for (int i = 0; i < 5; i++) {
+ phoneNumberMap.put("phoneNumber" + i, GooglePB.PhoneNumber.newBuilder().setNumber(random.nextInt(bound) + "").setType(GooglePB.PhoneType.forNumber(random.nextInt(GooglePB.PhoneType.values().length - 1))).build());
+ }
+ GooglePB.PBRequestType request = GooglePB.PBRequestType.newBuilder()
+ .setAge(15).setCash(10).setMoney(16.0).setNum(100L)
+ .addAllPhone(phoneNumberList).putAllDoubleMap(phoneNumberMap).build();
+ return request;
+ }
+
+ @Test
+ public void testPbNormal() throws Exception {
+ GooglePB.PBRequestType request = buildPbMessage();
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeObject(request);
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput objectInput = serialization.deserialize(url, byteArrayInputStream);
+
+ GooglePB.PBRequestType derializedRequest = objectInput.readObject(GooglePB.PBRequestType.class);
+ assertEquals(request, derializedRequest);
+ }
+
+ /**
+ * Special test case
+ * Dubbo protocol will directly writes native map (Invocation.attachments) using protobuf.
+ * this should definitely be fixed but not done yet.
+ */
+ @Test
+ public void testPbMap() throws Exception {
+ Map attachments = new HashMap<>();
+ attachments.put("key", "value");
+ ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
+ objectOutput.writeObject(attachments);
+ objectOutput.flushBuffer();
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
+ byteArrayOutputStream.toByteArray());
+ ObjectInput objectInput = serialization.deserialize(url, byteArrayInputStream);
+
+ Map derializedAttachments = objectInput.readObject(Map.class);
+ assertEquals(attachments, derializedAttachments);
+ }
+
+ @Test
+ public void testPbThrowable() {
+
+ }
+
+ @Test
+ public void testNotPb() {
+
+ }
+
+}
diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutputTest.java b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutputTest.java
similarity index 95%
rename from dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutputTest.java
rename to dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutputTest.java
index 2d7a86aa2e..5f0ee4ae9b 100644
--- a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufObjectOutputTest.java
+++ b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonObjectOutputTest.java
@@ -35,16 +35,16 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
-public class GenericProtobufObjectOutputTest {
+public class GenericProtobufJsonObjectOutputTest {
private ByteArrayOutputStream byteArrayOutputStream;
- private GenericProtobufObjectOutput genericProtobufObjectOutput;
- private GenericProtobufObjectInput genericProtobufObjectInput;
+ private GenericProtobufJsonObjectOutput genericProtobufObjectOutput;
+ private GenericProtobufJsonObjectInput genericProtobufObjectInput;
private ByteArrayInputStream byteArrayInputStream;
@BeforeEach
public void setUp() {
this.byteArrayOutputStream = new ByteArrayOutputStream();
- this.genericProtobufObjectOutput = new GenericProtobufObjectOutput(byteArrayOutputStream);
+ this.genericProtobufObjectOutput = new GenericProtobufJsonObjectOutput(byteArrayOutputStream);
}
@Test
@@ -200,7 +200,7 @@ public class GenericProtobufObjectOutputTest {
private void flushToInput() {
this.genericProtobufObjectOutput.flushBuffer();
this.byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
- this.genericProtobufObjectInput = new GenericProtobufObjectInput(byteArrayInputStream);
+ this.genericProtobufObjectInput = new GenericProtobufJsonObjectInput(byteArrayInputStream);
}
}
diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerializationTest.java b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerializationTest.java
new file mode 100644
index 0000000000..e50fda48fd
--- /dev/null
+++ b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufJsonSerializationTest.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.serialize.protobuf.support;
+
+public class GenericProtobufJsonSerializationTest extends AbstractProtobufSerializationTest {
+ {
+ serialization = new GenericProtobufJsonSerialization();
+ }
+}
diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerializationTest.java b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerializationTest.java
index 6a7748edd6..aec42c34e0 100644
--- a/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerializationTest.java
+++ b/dubbo-serialization/dubbo-serialization-test/src/test/java/org/apache/dubbo/common/serialize/protobuf/support/GenericProtobufSerializationTest.java
@@ -16,11 +16,8 @@
*/
package org.apache.dubbo.common.serialize.protobuf.support;
-import org.apache.dubbo.common.serialize.base.AbstractSerializationTest;
-import org.apache.dubbo.common.serialize.protostuff.ProtostuffSerialization;
-
-public class GenericProtobufSerializationTest extends AbstractSerializationTest {
+public class GenericProtobufSerializationTest extends AbstractProtobufSerializationTest {
{
- serialization = new ProtostuffSerialization();
+ serialization = new GenericProtobufSerialization();
}
}
diff --git a/dubbo-serialization/dubbo-serialization-test/src/test/resources/protobuf/GooglePB.proto b/dubbo-serialization/dubbo-serialization-test/src/test/proto/GooglePB.proto
similarity index 100%
rename from dubbo-serialization/dubbo-serialization-test/src/test/resources/protobuf/GooglePB.proto
rename to dubbo-serialization/dubbo-serialization-test/src/test/proto/GooglePB.proto
diff --git a/dubbo-serialization/pom.xml b/dubbo-serialization/pom.xml
index 31e4175d43..04bbef4c7a 100644
--- a/dubbo-serialization/pom.xml
+++ b/dubbo-serialization/pom.xml
@@ -40,7 +40,7 @@
dubbo-serialization-avro
dubbo-serialization-test
dubbo-serialization-gson
- dubbo-serialization-protobuf-json
+ dubbo-serialization-protobuf
dubbo-serialization-native-hession