You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2019/11/28 07:29:36 UTC

[dubbo] branch 2.7.5-release updated: Refactor protobuf compiler support (gRPC and Dubbo), add Reactive gRPC support.

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch 2.7.5-release
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/2.7.5-release by this push:
     new 9eaf949  Refactor protobuf compiler support (gRPC and Dubbo), add Reactive gRPC support.
9eaf949 is described below

commit 9eaf949998949a459352bd02d53de2e241d87968
Author: ken.lj <ke...@gmail.com>
AuthorDate: Thu Nov 28 15:28:36 2019 +0800

    Refactor protobuf compiler support (gRPC and Dubbo), add Reactive gRPC support.
---
 LICENSE                                            |    6 +-
 NOTICE                                             |    9 -
 compiler/.gradle/4.3/fileChanges/last-build.bin    |  Bin 1 -> 0 bytes
 .../4.3/fileContent/annotation-processors.bin      |  Bin 19793 -> 0 bytes
 compiler/.gradle/4.3/fileContent/fileContent.lock  |  Bin 17 -> 0 bytes
 compiler/.gradle/4.3/fileHashes/fileHashes.bin     |  Bin 523091 -> 0 bytes
 compiler/.gradle/4.3/fileHashes/fileHashes.lock    |  Bin 17 -> 0 bytes
 .../.gradle/4.3/fileHashes/resourceHashesCache.bin |  Bin 193707 -> 0 bytes
 .../.gradle/4.3/nativeCompile/nativeCompile.bin    |  Bin 18497 -> 0 bytes
 .../.gradle/4.3/nativeCompile/nativeCompile.lock   |  Bin 17 -> 0 bytes
 compiler/.gradle/4.3/taskHistory/taskHistory.bin   |  Bin 5498488 -> 0 bytes
 compiler/.gradle/4.3/taskHistory/taskHistory.lock  |  Bin 17 -> 0 bytes
 compiler/.gradle/4.9/fileChanges/last-build.bin    |  Bin 1 -> 0 bytes
 .../4.9/fileContent/annotation-processors.bin      |  Bin 19064 -> 0 bytes
 compiler/.gradle/4.9/fileContent/fileContent.lock  |  Bin 17 -> 0 bytes
 compiler/.gradle/4.9/fileContent/parsedCSource.bin |  Bin 4544877 -> 0 bytes
 compiler/.gradle/4.9/fileHashes/fileHashes.bin     |  Bin 883135 -> 0 bytes
 compiler/.gradle/4.9/fileHashes/fileHashes.lock    |  Bin 17 -> 0 bytes
 .../.gradle/4.9/fileHashes/resourceHashesCache.bin |  Bin 397477 -> 0 bytes
 .../.gradle/4.9/nativeCompile/nativeCompile.bin    |  Bin 62218 -> 0 bytes
 .../.gradle/4.9/nativeCompile/nativeCompile.lock   |  Bin 17 -> 0 bytes
 compiler/.gradle/4.9/taskHistory/taskHistory.bin   |  Bin 12084605 -> 0 bytes
 compiler/.gradle/4.9/taskHistory/taskHistory.lock  |  Bin 17 -> 0 bytes
 .../buildOutputCleanup/buildOutputCleanup.lock     |  Bin 17 -> 0 bytes
 .../.gradle/buildOutputCleanup/cache.properties    |    2 -
 .../.gradle/buildOutputCleanup/outputFiles.bin     |  Bin 57857 -> 0 bytes
 compiler/.gradle/vcsWorkingDirs/gc.properties      |    0
 compiler/BUILD.bazel                               |   12 -
 compiler/README.md                                 |  202 ---
 compiler/build.gradle                              |  406 -----
 compiler/check-artifact.sh                         |  131 --
 compiler/gradle/wrapper/gradle-wrapper.jar         |  Bin 54413 -> 0 bytes
 compiler/gradle/wrapper/gradle-wrapper.properties  |    5 -
 compiler/gradlew                                   |  172 ---
 compiler/gradlew.bat                               |   84 --
 compiler/pom.xml                                   |  178 +++
 .../src/java_plugin/cpp/java_dubbo_generator.cpp   |  580 --------
 compiler/src/java_plugin/cpp/java_generator.cpp    | 1558 --------------------
 compiler/src/java_plugin/cpp/java_generator.h      |   78 -
 compiler/src/java_plugin/cpp/java_plugin.cpp       |   87 --
 .../org/apache/dubbo/gen/AbstractGenerator.java    |  293 ++++
 .../org/apache/dubbo/gen/dubbo/DubboGenerator.java |   42 +
 .../apache/dubbo/gen/grpc/DubboGrpcGenerator.java  |   41 +
 .../grpc/reactive/ReactorDubboGrpcGenerator.java   |   42 +
 .../gen/grpc/reactive/RxDubboGrpcGenerator.java    |   41 +
 compiler/src/main/resources/DubboGrpcStub.mustache |  312 ++++
 compiler/src/main/resources/DubboStub.mustache     |   53 +
 .../main/resources/ReactorDubboGrpcStub.mustache   |  212 +++
 .../src/main/resources/RxDubboGrpcStub.mustache    |  246 ++++
 .../dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java  |   11 +-
 .../dubbo/rpc/protocol/grpc/GrpcProtocol.java      |   11 +-
 .../dubbo-serialization-protobuf/pom.xml           |   12 +-
 52 files changed, 1476 insertions(+), 3350 deletions(-)

diff --git a/LICENSE b/LICENSE
index 02ae1cd..03d3e19 100644
--- a/LICENSE
+++ b/LICENSE
@@ -241,8 +241,4 @@ https://github.com/edazdarevic/CIDRUtils. The project is licensed under a MIT Li
     * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-    * THE SOFTWARE.
-
-This product contains a modified portion of 'proto-gen-grpc-java' - a protobuf plugin used to generate grpc-java stubs,
- under a "Apache License 2.0" license, see https://github.com/grpc/grpc-java/blob/v1.22.1/NOTICE.txt. All files are placed
- under '/dubbo/compiler'
+    * THE SOFTWARE.
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
index 8d33f86..83785ff 100644
--- a/NOTICE
+++ b/NOTICE
@@ -13,12 +13,3 @@ Please visit the Netty web site for more information:
 
 Copyright 2014 The Netty Project
 
-
-This product contains code for the gRPC Project:
-
-The gRPC Project
-=================
-Please visit the gRPC web site for more information:
-  * http://grpc.io/
-
-Copyright 2014 The gRPC Project
diff --git a/compiler/.gradle/4.3/fileChanges/last-build.bin b/compiler/.gradle/4.3/fileChanges/last-build.bin
deleted file mode 100644
index f76dd23..0000000
Binary files a/compiler/.gradle/4.3/fileChanges/last-build.bin and /dev/null differ
diff --git a/compiler/.gradle/4.3/fileContent/annotation-processors.bin b/compiler/.gradle/4.3/fileContent/annotation-processors.bin
deleted file mode 100644
index aa6e57c..0000000
Binary files a/compiler/.gradle/4.3/fileContent/annotation-processors.bin and /dev/null differ
diff --git a/compiler/.gradle/4.3/fileContent/fileContent.lock b/compiler/.gradle/4.3/fileContent/fileContent.lock
deleted file mode 100644
index f0536e6..0000000
Binary files a/compiler/.gradle/4.3/fileContent/fileContent.lock and /dev/null differ
diff --git a/compiler/.gradle/4.3/fileHashes/fileHashes.bin b/compiler/.gradle/4.3/fileHashes/fileHashes.bin
deleted file mode 100644
index d219abd..0000000
Binary files a/compiler/.gradle/4.3/fileHashes/fileHashes.bin and /dev/null differ
diff --git a/compiler/.gradle/4.3/fileHashes/fileHashes.lock b/compiler/.gradle/4.3/fileHashes/fileHashes.lock
deleted file mode 100644
index 067763a..0000000
Binary files a/compiler/.gradle/4.3/fileHashes/fileHashes.lock and /dev/null differ
diff --git a/compiler/.gradle/4.3/fileHashes/resourceHashesCache.bin b/compiler/.gradle/4.3/fileHashes/resourceHashesCache.bin
deleted file mode 100644
index 827d8b9..0000000
Binary files a/compiler/.gradle/4.3/fileHashes/resourceHashesCache.bin and /dev/null differ
diff --git a/compiler/.gradle/4.3/nativeCompile/nativeCompile.bin b/compiler/.gradle/4.3/nativeCompile/nativeCompile.bin
deleted file mode 100644
index 7c2e6cd..0000000
Binary files a/compiler/.gradle/4.3/nativeCompile/nativeCompile.bin and /dev/null differ
diff --git a/compiler/.gradle/4.3/nativeCompile/nativeCompile.lock b/compiler/.gradle/4.3/nativeCompile/nativeCompile.lock
deleted file mode 100644
index 91ced25..0000000
Binary files a/compiler/.gradle/4.3/nativeCompile/nativeCompile.lock and /dev/null differ
diff --git a/compiler/.gradle/4.3/taskHistory/taskHistory.bin b/compiler/.gradle/4.3/taskHistory/taskHistory.bin
deleted file mode 100644
index 70d6d25..0000000
Binary files a/compiler/.gradle/4.3/taskHistory/taskHistory.bin and /dev/null differ
diff --git a/compiler/.gradle/4.3/taskHistory/taskHistory.lock b/compiler/.gradle/4.3/taskHistory/taskHistory.lock
deleted file mode 100644
index a68d1b7..0000000
Binary files a/compiler/.gradle/4.3/taskHistory/taskHistory.lock and /dev/null differ
diff --git a/compiler/.gradle/4.9/fileChanges/last-build.bin b/compiler/.gradle/4.9/fileChanges/last-build.bin
deleted file mode 100644
index f76dd23..0000000
Binary files a/compiler/.gradle/4.9/fileChanges/last-build.bin and /dev/null differ
diff --git a/compiler/.gradle/4.9/fileContent/annotation-processors.bin b/compiler/.gradle/4.9/fileContent/annotation-processors.bin
deleted file mode 100644
index ea3f5e8..0000000
Binary files a/compiler/.gradle/4.9/fileContent/annotation-processors.bin and /dev/null differ
diff --git a/compiler/.gradle/4.9/fileContent/fileContent.lock b/compiler/.gradle/4.9/fileContent/fileContent.lock
deleted file mode 100644
index 6766d56..0000000
Binary files a/compiler/.gradle/4.9/fileContent/fileContent.lock and /dev/null differ
diff --git a/compiler/.gradle/4.9/fileContent/parsedCSource.bin b/compiler/.gradle/4.9/fileContent/parsedCSource.bin
deleted file mode 100644
index d63153f..0000000
Binary files a/compiler/.gradle/4.9/fileContent/parsedCSource.bin and /dev/null differ
diff --git a/compiler/.gradle/4.9/fileHashes/fileHashes.bin b/compiler/.gradle/4.9/fileHashes/fileHashes.bin
deleted file mode 100644
index 656cb52..0000000
Binary files a/compiler/.gradle/4.9/fileHashes/fileHashes.bin and /dev/null differ
diff --git a/compiler/.gradle/4.9/fileHashes/fileHashes.lock b/compiler/.gradle/4.9/fileHashes/fileHashes.lock
deleted file mode 100644
index 4c4991c..0000000
Binary files a/compiler/.gradle/4.9/fileHashes/fileHashes.lock and /dev/null differ
diff --git a/compiler/.gradle/4.9/fileHashes/resourceHashesCache.bin b/compiler/.gradle/4.9/fileHashes/resourceHashesCache.bin
deleted file mode 100644
index fa0f984..0000000
Binary files a/compiler/.gradle/4.9/fileHashes/resourceHashesCache.bin and /dev/null differ
diff --git a/compiler/.gradle/4.9/nativeCompile/nativeCompile.bin b/compiler/.gradle/4.9/nativeCompile/nativeCompile.bin
deleted file mode 100644
index f68f4d2..0000000
Binary files a/compiler/.gradle/4.9/nativeCompile/nativeCompile.bin and /dev/null differ
diff --git a/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock b/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock
deleted file mode 100644
index 7e2f718..0000000
Binary files a/compiler/.gradle/4.9/nativeCompile/nativeCompile.lock and /dev/null differ
diff --git a/compiler/.gradle/4.9/taskHistory/taskHistory.bin b/compiler/.gradle/4.9/taskHistory/taskHistory.bin
deleted file mode 100644
index 6467c7d..0000000
Binary files a/compiler/.gradle/4.9/taskHistory/taskHistory.bin and /dev/null differ
diff --git a/compiler/.gradle/4.9/taskHistory/taskHistory.lock b/compiler/.gradle/4.9/taskHistory/taskHistory.lock
deleted file mode 100644
index bfdcb35..0000000
Binary files a/compiler/.gradle/4.9/taskHistory/taskHistory.lock and /dev/null differ
diff --git a/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock
deleted file mode 100644
index 287f9ed..0000000
Binary files a/compiler/.gradle/buildOutputCleanup/buildOutputCleanup.lock and /dev/null differ
diff --git a/compiler/.gradle/buildOutputCleanup/cache.properties b/compiler/.gradle/buildOutputCleanup/cache.properties
deleted file mode 100644
index 0a57826..0000000
--- a/compiler/.gradle/buildOutputCleanup/cache.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-#Tue Oct 09 11:40:48 CST 2018
-gradle.version=4.9
diff --git a/compiler/.gradle/buildOutputCleanup/outputFiles.bin b/compiler/.gradle/buildOutputCleanup/outputFiles.bin
deleted file mode 100644
index 8bd6f36..0000000
Binary files a/compiler/.gradle/buildOutputCleanup/outputFiles.bin and /dev/null differ
diff --git a/compiler/.gradle/vcsWorkingDirs/gc.properties b/compiler/.gradle/vcsWorkingDirs/gc.properties
deleted file mode 100644
index e69de29..0000000
diff --git a/compiler/BUILD.bazel b/compiler/BUILD.bazel
deleted file mode 100644
index 1a2f2f3..0000000
--- a/compiler/BUILD.bazel
+++ /dev/null
@@ -1,12 +0,0 @@
-cc_binary(
-    name = "grpc_java_plugin",
-    srcs = [
-        "src/java_plugin/cpp/java_generator.cpp",
-        "src/java_plugin/cpp/java_generator.h",
-        "src/java_plugin/cpp/java_plugin.cpp",
-    ],
-    visibility = ["//visibility:public"],
-    deps = [
-        "@com_google_protobuf//:protoc_lib",
-    ],
-)
diff --git a/compiler/README.md b/compiler/README.md
deleted file mode 100644
index 6a8a643..0000000
--- a/compiler/README.md
+++ /dev/null
@@ -1,202 +0,0 @@
-# Dubbo customized version
-
-## Get Started, how to use
-1. Add maven dependency to your project
-```xml
-    <build>
-        <extensions>
-            <extension>
-                <groupId>kr.motd.maven</groupId>
-                <artifactId>os-maven-plugin</artifactId>
-                <version>1.6.1</version>
-            </extension>
-        </extensions>
-        <plugins>
-            <plugin>
-                <groupId>org.xolstice.maven.plugins</groupId>
-                <artifactId>protobuf-maven-plugin</artifactId>
-                <version>0.5.1</version>
-                <configuration>
-                    <protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}</protocArtifact>
-                    <pluginId>grpc-java</pluginId>
-                    <pluginArtifact>org.apache.dubbo:protoc-gen-dubbo-java:${proto_dubbo_plugin_version}:exe:${os.detected.classifier}</pluginArtifact>
-                    <outputDirectory>build/generated/source/proto/main/java</outputDirectory>
-                    <clearOutputDirectory>false</clearOutputDirectory>
-                    <!-- supports 'dubbo' and 'grpc' -->
-                    <pluginParameter>dubbo</pluginParameter>
-                </configuration>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>compile</goal>
-                            <goal>compile-custom</goal>
-                            <goal>test-compile</goal>
-                            <goal>test-compile-custom</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>build/generated/source/proto/main/java</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-```
-
-2. Decide which protocol to use: Dubbo or gRPC
-   * Dubbo, ` <pluginParameter>dubbo</pluginParameter>`
-   * gRPC, ` <pluginParameter>grpc</pluginParameter>`
-
-3. Define service using IDL
-```text
-syntax = "proto3";
-
-option java_multiple_files = true;
-option java_package = "org.apache.dubbo.demo";
-option java_outer_classname = "DemoServiceProto";
-option objc_class_prefix = "DEMOSRV";
-
-package demoservice;
-
-// The demo service definition.
-service DemoService {
-  rpc SayHello (HelloRequest) returns (HelloReply) {}
-}
-
-// The request message containing the user's name.
-message HelloRequest {
-  string name = 1;
-}
-
-// The response message containing the greetings
-message HelloReply {
-  string message = 1;
-}
-```
-
-4. Build
-mvn clean compile
-
-## Customized
-
-1. Dubbo Interface
-```java
-public interface IGreeter {
-
-    default public io.grpc.examples.helloworld.HelloReply sayHello(io.grpc.examples.helloworld.HelloRequest request) {
-       throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
-    }
-    
-    default public com.google.common.util.concurrent.ListenableFuture<io.grpc.examples.helloworld.HelloReply> sayHelloAsync(
-        io.grpc.examples.helloworld.HelloRequest request) {
-       throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
-    }
-    
-    public void sayHello(io.grpc.examples.helloworld.HelloRequest request,
-        io.grpc.stub.StreamObserver<io.grpc.examples.helloworld.HelloReply> responseObserver);
-
-}
-```
-
-2. Dubbo Stub
-```java
-public static DubboGreeterStub getDubboStub(io.grpc.Channel channel) {
-  return new DubboGreeterStub(channel);
-}
-
-public static class DubboGreeterStub implements IGreeter {
-
-    private GreeterBlockingStub blockingStub;
-    private GreeterFutureStub futureStub;
-    private GreeterStub stub;
-    
-    public DubboGreeterStub(io.grpc.Channel channel) {
-       blockingStub = GreeterGrpc.newBlockingStub(channel);
-       futureStub = GreeterGrpc.newFutureStub(channel);
-       stub = GreeterGrpc.newStub(channel);
-    }
-    
-    public io.grpc.examples.helloworld.HelloReply sayHello(io.grpc.examples.helloworld.HelloRequest request) {
-        return blockingStub.sayHello(request);
-    }
-    
-    public com.google.common.util.concurrent.ListenableFuture<io.grpc.examples.helloworld.HelloReply> sayHelloAsync(
-        io.grpc.examples.helloworld.HelloRequest request) {
-        return futureStub.sayHello(requesthttps://github.com/apache/dubbo-samples.git);
-    }
-    
-    public void sayHello(io.grpc.examples.helloworld.HelloRequest request,
-        io.grpc.stub.StreamObserver<io.grpc.examples.helloworld.HelloReply> responseObserver){
-        stub.sayHello(request, responseObserver);
-    }
-
-}
-
-```
-
-3. XxxImplBase implements DubboInterface
-```java
-public static abstract class GreeterImplBase implements io.grpc.BindableService, IGreeter {
-
-  @java.lang.Override
-  public final io.grpc.examples.helloworld.HelloReply sayHello(io.grpc.examples.helloworld.HelloRequest request) {
-     throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
-  }
-
-  @java.lang.Override
-  public final com.google.common.util.concurrent.ListenableFuture<io.grpc.examples.helloworld.HelloReply> sayHelloAsync(
-      io.grpc.examples.helloworld.HelloRequest request) {
-     throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
-  }
-
-  public void sayHello(io.grpc.examples.helloworld.HelloRequest request,
-      io.grpc.stub.StreamObserver<io.grpc.examples.helloworld.HelloReply> responseObserver) {
-      asyncUnimplementedUnaryCall(getSayHelloMethod(), responseObserver);
-  }
-  
-  ...
-}
-```
-
-## Build locally
-
-To compile the plugin:
-```
-$ ./gradlew java_pluginExecutable
-```
-
-To publish to local repository
-```
-$ ./gradlew publishToMavenLocal
-```
-
-## Publish to maven repository
-
-Add gradle.properties
-```properties
-repositoryUser=user
-repositoryPasword=pwd
-```
-
-Then, run
-```
-$ ../gradlew publishMavenPublicationToDubboRepository
-```
-Notice current groupId is `com.alibaba`.
-
-
-Check [here](https://github.com/grpc/grpc-java/blob/master/compiler/README.md) for basic requirements and usage of protoc plugin.
diff --git a/compiler/build.gradle b/compiler/build.gradle
deleted file mode 100644
index f94fef7..0000000
--- a/compiler/build.gradle
+++ /dev/null
@@ -1,406 +0,0 @@
-apply plugin: "cpp"
-apply plugin: "com.google.protobuf"
-
-group = "org.apache.dubbo"
-version = "1.19.0-SNAPSHOT" // CURRENT_GRPC_VERSION
-
-description = 'The protoc plugin for gRPC Java'
-
-apply plugin: "checkstyle"
-apply plugin: "java"
-apply plugin: "maven"
-apply plugin: "maven-publish"
-apply plugin: "idea"
-apply plugin: "signing"
-apply plugin: "jacoco"
-
-apply plugin: "me.champeau.gradle.jmh"
-apply plugin: "com.google.osdetector"
-// The plugin only has an effect if a signature is specified
-apply plugin: "ru.vyarus.animalsniffer"
-
-apply plugin: "net.ltgt.errorprone"
-
-buildscript {
-    repositories {
-        maven { // The google mirror is less flaky than mavenCentral()
-            url "https://maven-central.storage-download.googleapis.com/repos/central/data/"
-        }
-        mavenLocal()
-        maven { url "https://plugins.gradle.org/m2/" }
-    }
-    dependencies {
-        classpath "com.google.protobuf:protobuf-gradle-plugin:0.8.5"
-        classpath "com.diffplug.spotless:spotless-plugin-gradle:3.13.0"
-        classpath 'com.google.gradle:osdetector-gradle-plugin:1.4.0'
-        classpath 'ru.vyarus:gradle-animalsniffer-plugin:1.4.5'
-        classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.6'
-        classpath "me.champeau.gradle:jmh-gradle-plugin:0.4.5"
-        classpath 'me.champeau.gradle:japicmp-gradle-plugin:0.2.5'
-    }
-}
-
-import net.ltgt.gradle.errorprone.CheckSeverity
-
-def artifactStagingPath = "$buildDir/artifacts" as File
-// Adds space-delimited arguments from the environment variable env to the
-// argList.
-def addEnvArgs = { env, argList ->
-    def value = System.getenv(env)
-    if (value != null) {
-        value.split(' +').each() { it -> argList.add(it) }
-    }
-}
-
-// Adds corresponding "-l" option to the argList if libName is not found in
-// LDFLAGS. This is only used for Mac because when building for uploadArchives
-// artifacts, we add the ".a" files directly to LDFLAGS and without "-l" in
-// order to get statically linked, otherwise we add the libraries through "-l"
-// so that they can be searched for in default search paths.
-def addLibraryIfNotLinked = { libName, argList ->
-    def ldflags = System.env.LDFLAGS
-    if (ldflags == null || !ldflags.contains('lib' + libName + '.a')) {
-        argList.add('-l' + libName)
-    }
-}
-
-def String arch = rootProject.hasProperty('targetArch') ? rootProject.targetArch : osdetector.arch
-def boolean vcDisable = rootProject.hasProperty('vcDisable') ? rootProject.vcDisable : false
-def boolean usingVisualCpp // Whether VisualCpp is actually available and selected
-
-ext{
-    def exeSuffix = osdetector.os == 'windows' ? ".exe" : ""
-    protocPluginBaseName = 'protoc-gen-dubbo-java'
-    javaPluginPath = "$rootDir/build/exe/java_plugin/$protocPluginBaseName$exeSuffix"
-
-    nettyVersion = '4.1.32.Final'
-    googleauthVersion = '0.9.0'
-    guavaVersion = '26.0-android'
-    protobufVersion = '3.6.1'
-    protocVersion = protobufVersion
-    protobufNanoVersion = '3.0.0-alpha-5'
-    opencensusVersion = '0.19.2'
-
-    libraries = [
-            animalsniffer_annotations: "org.codehaus.mojo:animal-sniffer-annotations:1.17",
-            errorprone: "com.google.errorprone:error_prone_annotations:2.2.0",
-            gson: "com.google.code.gson:gson:2.7",
-            guava: "com.google.guava:guava:26.0-android",
-            hpack: 'com.twitter:hpack:0.10.1',
-            javax_annotation: 'javax.annotation:javax.annotation-api:1.2',
-            jsr305: 'com.google.code.findbugs:jsr305:3.0.2',
-            google_api_protos: 'com.google.api.grpc:proto-google-common-protos:1.12.0',
-
-            // Keep the following references of tcnative version in sync whenever it's updated
-            // SECURITY.md (multiple occurrences)
-            // examples/example-tls/build.gradle
-            // examples/example-tls/pom.xml
-            netty_tcnative: 'io.netty:netty-tcnative-boringssl-static:2.0.20.Final',
-
-            conscrypt: 'org.conscrypt:conscrypt-openjdk-uber:1.0.1',
-            re2j: 'com.google.re2j:re2j:1.2'
-    ]
-}
-
-model {
-    toolChains {
-        // If you have both VC and Gcc installed, VC will be selected, unless you
-        // set 'vcDisable=true'
-        if (!vcDisable) {
-            visualCpp(VisualCpp) {
-                // Prefer vcvars-provided environment over registry-discovered environment
-                def String vsDir = System.getenv("VSINSTALLDIR")
-                def String winDir = System.getenv("WindowsSdkDir")
-                if (vsDir != null && winDir != null) {
-                    installDir = vsDir
-                    windowsSdkDir = winDir
-                }
-            }
-        }
-        gcc(Gcc) {
-            target("ppcle_64")
-            target("aarch_64")
-        }
-        clang(Clang) {
-        }
-    }
-
-    platforms {
-        x86_32 { architecture "x86" }
-        x86_64 { architecture "x86_64" }
-        ppcle_64 { architecture "ppcle_64" }
-        aarch_64 { architecture "aarch_64" }
-    }
-
-    components {
-        java_plugin(NativeExecutableSpec) {
-            if (arch in [
-                'x86_32',
-                'x86_64',
-                'ppcle_64',
-                'aarch_64'
-            ]) {
-                // If arch is not within the defined platforms, we do not specify the
-                // targetPlatform so that Gradle will choose what is appropriate.
-                targetPlatform arch
-            }
-            baseName "$protocPluginBaseName"
-        }
-    }
-
-    binaries {
-        all {
-            if (toolChain in Gcc || toolChain in Clang) {
-                cppCompiler.define("GRPC_VERSION", version)
-                cppCompiler.args "--std=c++0x"
-                addEnvArgs("CXXFLAGS", cppCompiler.args)
-                addEnvArgs("CPPFLAGS", cppCompiler.args)
-                if (osdetector.os == "osx") {
-                    cppCompiler.args "-mmacosx-version-min=10.7", "-stdlib=libc++"
-                    addLibraryIfNotLinked('protoc', linker.args)
-                    addLibraryIfNotLinked('protobuf', linker.args)
-                } else if (osdetector.os == "windows") {
-                    linker.args "-static", "-lprotoc", "-lprotobuf", "-static-libgcc", "-static-libstdc++",
-                            "-s"
-                } else {
-                    // Link protoc, protobuf, libgcc and libstdc++ statically.
-                    // Link other (system) libraries dynamically.
-                    // Clang under OSX doesn't support these options.
-                    linker.args "-Wl,-Bstatic", "-lprotoc", "-lprotobuf", "-static-libgcc",
-                            "-static-libstdc++",
-                            "-Wl,-Bdynamic", "-lpthread", "-s"
-                }
-                addEnvArgs("LDFLAGS", linker.args)
-            } else if (toolChain in VisualCpp) {
-                usingVisualCpp = true
-                cppCompiler.define("GRPC_VERSION", version)
-                cppCompiler.args "/EHsc", "/MT"
-                if (rootProject.hasProperty('vcProtobufInclude')) {
-                    cppCompiler.args "/I${rootProject.vcProtobufInclude}"
-                }
-                linker.args "libprotobuf.lib", "libprotoc.lib"
-                if (rootProject.hasProperty('vcProtobufLibs')) {
-                    linker.args "/LIBPATH:${rootProject.vcProtobufLibs}"
-                }
-            }
-        }
-    }
-}
-
-configurations {
-    testLiteCompile
-    testNanoCompile
-}
-
-sourceSets {
-    testLite {
-        proto { setSrcDirs(['src/test/proto']) }
-    }
-    testNano {
-        proto { setSrcDirs(['src/test/proto']) }
-    }
-}
-
-
-compileTestJava {
-    options.compilerArgs += [
-        "-Xlint:-cast"
-    ]
-    options.errorprone.excludedPaths = ".*/build/generated/source/proto/.*"
-}
-
-compileTestLiteJava {
-    options.compilerArgs = compileTestJava.options.compilerArgs
-    // Protobuf-generated Lite produces quite a few warnings.
-    options.compilerArgs += [
-        "-Xlint:-rawtypes",
-        "-Xlint:-unchecked",
-        "-Xlint:-fallthrough"
-    ]
-    options.errorprone.excludedPaths = ".*/build/generated/source/proto/.*"
-}
-
-compileTestNanoJava {
-    options.compilerArgs = compileTestJava.options.compilerArgs
-    options.errorprone.excludedPaths = ".*/build/generated/source/proto/.*"
-}
-
-protobuf {
-    protoc {
-        if (project.hasProperty('protoc')) {
-            path = project.protoc
-        } else {
-            // Since nano is removed from newer versions of protoc, use an older version for the
-            // while. This means we won't be able to test any descriptor.proto additions, but that
-            // should be fine for a while.
-            artifact = libraries.protoc_nano
-        }
-    }
-    plugins {
-        javalite {
-            if (project.hasProperty('protoc-gen-javalite')) {
-                path = project['protoc-gen-javalite']
-            } else {
-                artifact = libraries.protoc_lite
-            }
-        }
-        grpc { path = javaPluginPath }
-    }
-    generateProtoTasks {
-        all().each { task ->
-            task.dependsOn 'java_pluginExecutable'
-            task.inputs.file javaPluginPath
-        }
-        ofSourceSet('test')*.plugins { grpc {} }
-        ofSourceSet('testLite')*.each { task ->
-            task.builtins { remove java }
-            task.plugins {
-                javalite {}
-                grpc { option 'lite' }
-            }
-        }
-        ofSourceSet('testNano').each { task ->
-            task.builtins {
-                remove java
-                javanano { option 'ignore_services=true' }
-            }
-            task.plugins { grpc { option 'nano' } }
-        }
-    }
-}
-
-checkstyleTestNano {
-    source = fileTree(dir: "src/testNano", include: "**/*.java")
-}
-
-println "*** Building codegen requires Protobuf version ${protocVersion}"
-println "*** Please refer to https://github.com/apache/dubbo/blob/master/compiler/README.md"
-
-task buildArtifacts(type: Copy) {
-    dependsOn 'java_pluginExecutable'
-    from("$buildDir/exe") {
-        if (osdetector.os != 'windows') {
-            rename 'protoc-gen-dubbo-java', '$0.exe'
-        }
-    }
-    into artifactStagingPath
-}
-
-archivesBaseName = "$protocPluginBaseName"
-
-task checkArtifacts {
-    dependsOn buildArtifacts
-    doLast {
-        if (!usingVisualCpp) {
-            def ret = exec {
-                executable 'bash'
-                args 'check-artifact.sh', osdetector.os, arch
-            }
-            if (ret.exitValue != 0) {
-                throw new GradleException("check-artifact.sh exited with " + ret.exitValue)
-            }
-        } else {
-            def exeName = "$artifactStagingPath/java_plugin/${protocPluginBaseName}.exe"
-            def os = new ByteArrayOutputStream()
-            def ret = exec {
-                executable 'dumpbin'
-                args '/nologo', '/dependents', exeName
-                standardOutput = os
-            }
-            if (ret.exitValue != 0) {
-                throw new GradleException("dumpbin exited with " + ret.exitValue)
-            }
-            def dlls = os.toString() =~ /Image has the following dependencies:\s+(.*)\s+Summary/
-            if (dlls[0][1] != "KERNEL32.dll") {
-                throw new Exception("unexpected dll deps: " + dlls[0][1]);
-            }
-            os.reset()
-            ret = exec {
-                executable 'dumpbin'
-                args '/nologo', '/headers', exeName
-                standardOutput = os
-            }
-            if (ret.exitValue != 0) {
-                throw new GradleException("dumpbin exited with " + ret.exitValue)
-            }
-            def machine = os.toString() =~ / machine \(([^)]+)\)/
-            def expectedArch = [x86_32: "x86", x86_64: "x64"][arch]
-            if (machine[0][1] != expectedArch) {
-                throw new Exception("unexpected architecture: " + machine[0][1]);
-            }
-        }
-    }
-}
-
-// Exe files are skipped by Maven by default. Override it.
-// Also skip jar files that is generated by the java plugin.
-publishing {
-    repositories {
-        maven {
-            name "dubbo"
-            credentials {
-                username repositoryUser // 仓库发布用户名
-                password repositoryPassword // 仓库发布用户密码
-            }
-            if(project.version.endsWith('-SNAPSHOT')) {
-                url "https://repository.apache.org/content/repositories/snapshots"
-            } else {
-                url 'https://repository.apache.org/service/local/staging/deploy/maven2' // 仓库地址
-            }
-        }
-    }
-
-    publications {
-        maven(MavenPublication) {
-            // Removes all artifacts since grpc-compiler doesn't generates any Jar
-            artifacts = []
-            artifactId 'protoc-gen-dubbo-java'
-            artifact("$artifactStagingPath/java_plugin/${protocPluginBaseName}.exe" as File) {
-                classifier osdetector.os + "-" + arch
-                extension "exe"
-                builtBy checkArtifacts
-            }
-            pom.withXml {
-                // This isn't any sort of Java archive artifact, and OSSRH doesn't enforce
-                // javadoc for 'pom' packages. 'exe' would be a more appropriate packaging
-                // value, but it isn't clear how that will be interpreted. In addition,
-                // 'pom' is typically the value used when building an exe with Maven.
-                asNode().project.packaging*.value = 'pom'
-            }
-        }
-    }
-}
-
-signing {
-    useGpgCmd()
-    required false
-    sign publishing.publications.maven
-}
-
-def configureTestTask(Task task, String dep, String extraPackage, String serviceName) {
-    test.dependsOn task
-    task.dependsOn "generateTest${dep}Proto"
-    if (osdetector.os != 'windows') {
-        task.executable "diff"
-        task.args "-u"
-    } else {
-        task.executable "fc"
-    }
-    // File isn't found on Windows if last slash is forward-slash
-    def slash = System.getProperty("file.separator")
-    task.args "$buildDir/generated/source/proto/test${dep}/grpc/io/grpc/testing/compiler${extraPackage}${slash}${serviceName}Grpc.java",
-            "$projectDir/src/test${dep}/golden/${serviceName}.java.txt"
-}
-
-task testGolden(type: Exec)
-task testLiteGolden(type: Exec)
-task testNanoGolden(type: Exec)
-task testDeprecatedGolden(type: Exec)
-task testDeprecatedLiteGolden(type: Exec)
-task testDeprecatedNanoGolden(type: Exec)
-configureTestTask(testGolden, '', '', 'TestService')
-configureTestTask(testLiteGolden, 'Lite', '', 'TestService')
-configureTestTask(testNanoGolden, 'Nano', '/nano', 'TestService')
-configureTestTask(testDeprecatedGolden, '', '', 'TestDeprecatedService')
-configureTestTask(testDeprecatedLiteGolden, 'Lite', '', 'TestDeprecatedService')
-configureTestTask(testDeprecatedNanoGolden, 'Nano', '/nano', 'TestDeprecatedService')
diff --git a/compiler/check-artifact.sh b/compiler/check-artifact.sh
deleted file mode 100755
index 05b57a1..0000000
--- a/compiler/check-artifact.sh
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/bin/bash
-
-# Check that the codegen artifacts are of correct architecture and don't have
-# unexpected dependencies.
-# To be run from Gradle.
-# Usage: check-artifact <OS> <ARCH>
-# <OS> and <ARCH> are ${os.detected.name} and ${os.detected.arch} from
-# osdetector-gradle-plugin
-OS=$1
-ARCH=$2
-
-if [[ $# < 2 ]]; then
-  echo "No arguments provided. This script is intended to be run from Gradle."
-  exit 1
-fi
-
-# Under Cygwin, bash doesn't have these in PATH when called from Gradle which
-# runs in Windows version of Java.
-export PATH="/bin:/usr/bin:$PATH"
-
-E_PARAM_ERR=98
-E_ASSERT_FAILED=99
-
-# Usage: fail ERROR_MSG
-fail()
-{
-  echo "ERROR: $1"
-  echo
-  exit $E_ASSERT_FAILED
-}
-
-# Usage: assertEq VAL1 VAL2 $LINENO
-assertEq ()
-{
-  lineno=$3
-  if [ -z "$lineno" ]; then
-    echo "lineno not given"
-    exit $E_PARAM_ERR
-  fi
-
-  if [[ "$1" != "$2" ]]; then
-    echo "Assertion failed:  \"$1\" == \"$2\""
-    echo "File \"$0\", line $lineno"    # Give name of file and line number.
-    exit $E_ASSERT_FAILED
-  fi
-}
-
-# Checks the artifact is for the expected architecture
-# Usage: checkArch <path-to-protoc>
-checkArch ()
-{
-  echo
-  echo "Checking format of $1"
-  if [[ "$OS" == windows || "$OS" == linux ]]; then
-    format="$(objdump -f "$1" | grep -o "file format .*$" | grep -o "[^ ]*$")"
-    echo Format=$format
-    if [[ "$OS" == linux ]]; then
-      if [[ "$ARCH" == x86_32 ]]; then
-        assertEq "$format" "elf32-i386" $LINENO
-      elif [[ "$ARCH" == x86_64 ]]; then
-        assertEq "$format" "elf64-x86-64" $LINENO
-      else
-        fail "Unsupported arch: $ARCH"
-      fi
-    else
-      # $OS == windows
-      if [[ "$ARCH" == x86_32 ]]; then
-        assertEq "$format" "pei-i386" $LINENO
-      elif [[ "$ARCH" == x86_64 ]]; then
-        assertEq "$format" "pei-x86-64" $LINENO
-      else
-        fail "Unsupported arch: $ARCH"
-      fi
-    fi
-  elif [[ "$OS" == osx ]]; then
-    format="$(file -b "$1" | grep -o "[^ ]*$")"
-    echo Format=$format
-    if [[ "$ARCH" == x86_32 ]]; then
-      assertEq "$format" "i386" $LINENO
-    elif [[ "$ARCH" == x86_64 ]]; then
-      assertEq "$format" "x86_64" $LINENO
-    else
-      fail "Unsupported arch: $ARCH"
-    fi
-  else
-    fail "Unsupported system: $OS"
-  fi
-  echo
-}
-
-# Checks the dependencies of the artifact. Artifacts should only depend on
-# system libraries.
-# Usage: checkDependencies <path-to-protoc>
-checkDependencies ()
-{
-  echo "Checking dependencies of $1"
-  if [[ "$OS" == windows ]]; then
-    dump_cmd='objdump -x '"$1"' | fgrep "DLL Name"'
-    white_list="KERNEL32\.dll\|msvcrt\.dll\|USER32\.dll"
-  elif [[ "$OS" == linux ]]; then
-    dump_cmd='ldd '"$1"
-    if [[ "$ARCH" == x86_32 ]]; then
-      white_list="linux-gate\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux\.so\.2"
-    elif [[ "$ARCH" == x86_64 ]]; then
-      white_list="linux-vdso\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux-x86-64\.so\.2"
-    fi
-  elif [[ "$OS" == osx ]]; then
-    set +x
-    dump_cmd='otool -L '"$1"' | fgrep dylib'
-    white_list="libz\.1\.dylib\|libc++.1.dylib\|libstdc++\.6\.dylib\|libSystem\.B\.dylib"
-    set -x
-  fi
-  if [[ -z "$white_list" || -z "$dump_cmd" ]]; then
-    fail "Unsupported platform $OS-$ARCH."
-  fi
-  echo "Checking for expected dependencies ..."
-  eval $dump_cmd | grep -i "$white_list" || fail "doesn't show any expected dependencies"
-  echo "Checking for unexpected dependencies ..."
-  eval $dump_cmd | grep -i -v "$white_list"
-  ret=$?
-  if [[ $ret == 0 ]]; then
-    fail "found unexpected dependencies (listed above)."
-  elif [[ $ret != 1 ]]; then
-    fail "Error when checking dependencies."
-  fi  # grep returns 1 when "not found", which is what we expect
-  echo "Dependencies look good."
-  echo
-}
-
-FILE="build/artifacts/java_plugin/protoc-gen-dubbo-java.exe"
-checkArch "$FILE" && checkDependencies "$FILE"
diff --git a/compiler/gradle/wrapper/gradle-wrapper.jar b/compiler/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index 0d4a951..0000000
Binary files a/compiler/gradle/wrapper/gradle-wrapper.jar and /dev/null differ
diff --git a/compiler/gradle/wrapper/gradle-wrapper.properties b/compiler/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index a95009c..0000000
--- a/compiler/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
diff --git a/compiler/gradlew b/compiler/gradlew
deleted file mode 100755
index cccdd3d..0000000
--- a/compiler/gradlew
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/env sh
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/compiler/gradlew.bat b/compiler/gradlew.bat
deleted file mode 100644
index f955316..0000000
--- a/compiler/gradlew.bat
+++ /dev/null
@@ -1,84 +0,0 @@
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem  Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/compiler/pom.xml b/compiler/pom.xml
new file mode 100644
index 0000000..d0df460
--- /dev/null
+++ b/compiler/pom.xml
@@ -0,0 +1,178 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache</groupId>
+        <artifactId>apache</artifactId>
+        <version>21</version>
+    </parent>
+
+    <groupId>org.apache.dubbo</groupId>
+    <artifactId>dubbo-compiler</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+
+    <packaging>jar</packaging>
+
+    <properties>
+        <maven_compiler_version>3.6.0</maven_compiler_version>
+        <maven_jar_version>3.0.2</maven_jar_version>
+        <java_source_version>1.8</java_source_version>
+        <java_target_version>1.8</java_target_version>
+        <file_encoding>UTF-8</file_encoding>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.salesforce.servicelibs</groupId>
+            <artifactId>grpc-contrib</artifactId>
+            <version>0.8.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.salesforce.servicelibs</groupId>
+            <artifactId>jprotoc</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven_compiler_version}</version>
+                <configuration>
+                    <compilerArgument>-proc:none</compilerArgument>
+                    <fork>true</fork>
+                    <source>${java_source_version}</source>
+                    <target>${java_target_version}</target>
+                    <encoding>${file_encoding}</encoding>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>${maven_jar_version}</version>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <!--                            <addClasspath>true</addClasspath>-->
+                            <mainClass>org.apache.dubbo.gen.grpc.DubboGrpcGenerator</mainClass>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+
+            <!-- Optional, used to build directly executable packages (without using 'java -jar'),
+            for example 'artifactId-1.0.0-osx-x86_64.exe', 'artifactId-1.0.0-osx-x86_64.exe' -->
+            <plugin>
+                <groupId>com.salesforce.servicelibs</groupId>
+                <artifactId>canteen-maven-plugin</artifactId>
+                <version>1.0.0</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>bootstrap</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>release</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>sign</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+    <name>dubbo-compiler</name>
+    <description>Dubbo customized RPC stub compiler.</description>
+    <url>https://github.com/apache/dubbo</url>
+    <inceptionYear>2011</inceptionYear>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <scm>
+        <url>https://github.com/apache/dubbo</url>
+        <connection>scm:git:https://github.com/apache/dubbo.git</connection>
+        <developerConnection>scm:git:https://github.com/apache/dubbo.git</developerConnection>
+        <tag>HEAD</tag>
+    </scm>
+    <mailingLists>
+        <mailingList>
+            <name>Development List</name>
+            <subscribe>dev-subscribe@dubbo.apache.org</subscribe>
+            <unsubscribe>dev-unsubscribe@dubbo.apache.org</unsubscribe>
+            <post>dev@dubbo.apache.org</post>
+        </mailingList>
+        <mailingList>
+            <name>Commits List</name>
+            <subscribe>commits-subscribe@dubbo.apache.org</subscribe>
+            <unsubscribe>commits-unsubscribe@dubbo.apache.org</unsubscribe>
+            <post>commits@dubbo.apache.org</post>
+        </mailingList>
+        <mailingList>
+            <name>Issues List</name>
+            <subscribe>issues-subscribe@dubbo.apache.org</subscribe>
+            <unsubscribe>issues-unsubscribe@dubbo.apache.org</unsubscribe>
+            <post>issues@dubbo.apache.org</post>
+        </mailingList>
+    </mailingLists>
+    <developers>
+        <developer>
+            <id>dubbo.io</id>
+            <name>The Dubbo Project Contributors</name>
+            <email>dev-subscribe@dubbo.apache.org</email>
+            <url>http://dubbo.apache.org/</url>
+        </developer>
+    </developers>
+
+    <organization>
+        <name>The Apache Software Foundation</name>
+        <url>http://www.apache.org/</url>
+    </organization>
+
+    <issueManagement>
+        <system>Github Issues</system>
+        <url>https://github.com/apache/dubbo/issues</url>
+    </issueManagement>
+</project>
\ No newline at end of file
diff --git a/compiler/src/java_plugin/cpp/java_dubbo_generator.cpp b/compiler/src/java_plugin/cpp/java_dubbo_generator.cpp
deleted file mode 100644
index 8e7d7b1..0000000
--- a/compiler/src/java_plugin/cpp/java_dubbo_generator.cpp
+++ /dev/null
@@ -1,580 +0,0 @@
-#include "java_generator.h"
-
-#include <algorithm>
-#include <iostream>
-#include <iterator>
-#include <map>
-#include <set>
-#include <vector>
-#include <google/protobuf/compiler/java/java_names.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-
-// Stringify helpers used solely to cast GRPC_VERSION
-#ifndef STR
-#define STR(s) #s
-#endif
-
-#ifndef XSTR
-#define XSTR(s) STR(s)
-#endif
-
-#ifndef FALLTHROUGH_INTENDED
-#define FALLTHROUGH_INTENDED
-#endif
-
-namespace java_dubbo_generator {
-
-using google::protobuf::FileDescriptor;
-using google::protobuf::ServiceDescriptor;
-using google::protobuf::MethodDescriptor;
-using google::protobuf::Descriptor;
-using google::protobuf::io::Printer;
-using google::protobuf::SourceLocation;
-using std::to_string;
-
-// java keywords from: https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.9
-static std::set<string> java_keywords = {
-  "abstract",
-  "assert",
-  "boolean",
-  "break",
-  "byte",
-  "case",
-  "catch",
-  "char",
-  "class",
-  "const",
-  "continue",
-  "default",
-  "do",
-  "double",
-  "else",
-  "enum",
-  "extends",
-  "final",
-  "finally",
-  "float",
-  "for",
-  "goto",
-  "if",
-  "implements",
-  "import",
-  "instanceof",
-  "int",
-  "interface",
-  "long",
-  "native",
-  "new",
-  "package",
-  "private",
-  "protected",
-  "public",
-  "return",
-  "short",
-  "static",
-  "strictfp",
-  "super",
-  "switch",
-  "synchronized",
-  "this",
-  "throw",
-  "throws",
-  "transient",
-  "try",
-  "void",
-  "volatile",
-  "while",
-  // additional ones added by us
-  "true",
-  "false",
-};
-
-// Adjust a method name prefix identifier to follow the JavaBean spec:
-//   - decapitalize the first letter
-//   - remove embedded underscores & capitalize the following letter
-//  Finally, if the result is a reserved java keyword, append an underscore.
-static string MixedLower(const string& word) {
-  string w;
-  w += tolower(word[0]);
-  bool after_underscore = false;
-  for (size_t i = 1; i < word.length(); ++i) {
-    if (word[i] == '_') {
-      after_underscore = true;
-    } else {
-      w += after_underscore ? toupper(word[i]) : word[i];
-      after_underscore = false;
-    }
-  }
-  if (java_keywords.find(w) != java_keywords.end()) {
-    return w + "_";
-  }
-  return w;
-}
-
-// Converts to the identifier to the ALL_UPPER_CASE format.
-//   - An underscore is inserted where a lower case letter is followed by an
-//     upper case letter.
-//   - All letters are converted to upper case
-static string ToAllUpperCase(const string& word) {
-  string w;
-  for (size_t i = 0; i < word.length(); ++i) {
-    w += toupper(word[i]);
-    if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) {
-      w += '_';
-    }
-  }
-  return w;
-}
-
-static inline string LowerMethodName(const MethodDescriptor* method) {
-  return MixedLower(method->name());
-}
-
-static inline string MethodPropertiesFieldName(const MethodDescriptor* method) {
-  return "METHOD_" + ToAllUpperCase(method->name());
-}
-
-static inline string MethodPropertiesGetterName(const MethodDescriptor* method) {
-  return MixedLower("get_" + method->name() + "_method");
-}
-
-static inline string MethodIdFieldName(const MethodDescriptor* method) {
-  return "METHODID_" + ToAllUpperCase(method->name());
-}
-
-static inline bool ShouldGenerateAsLite(const Descriptor* desc) {
-  return false;
-}
-
-static inline string MessageFullJavaName(bool nano, const Descriptor* desc) {
-  string name = google::protobuf::compiler::java::ClassName(desc);
-  if (nano && !ShouldGenerateAsLite(desc)) {
-    // XXX: Add "nano" to the original package
-    // (https://github.com/grpc/grpc-java/issues/900)
-    if (isupper(name[0])) {
-      // No java package specified.
-      return "nano." + name;
-    }
-    for (size_t i = 0; i < name.size(); ++i) {
-      if ((name[i] == '.') && (i < (name.size() - 1)) && isupper(name[i + 1])) {
-        return name.substr(0, i + 1) + "nano." + name.substr(i + 1);
-      }
-    }
-  }
-  return name;
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-template <typename ITR>
-static void GrpcSplitStringToIteratorUsing(const string& full,
-                                       const char* delim,
-                                       ITR& result) {
-  // Optimize the common case where delim is a single character.
-  if (delim[0] != '\0' && delim[1] == '\0') {
-    char c = delim[0];
-    const char* p = full.data();
-    const char* end = p + full.size();
-    while (p != end) {
-      if (*p == c) {
-        ++p;
-      } else {
-        const char* start = p;
-        while (++p != end && *p != c);
-        *result++ = string(start, p - start);
-      }
-    }
-    return;
-  }
-
-  string::size_type begin_index, end_index;
-  begin_index = full.find_first_not_of(delim);
-  while (begin_index != string::npos) {
-    end_index = full.find_first_of(delim, begin_index);
-    if (end_index == string::npos) {
-      *result++ = full.substr(begin_index);
-      return;
-    }
-    *result++ = full.substr(begin_index, (end_index - begin_index));
-    begin_index = full.find_first_not_of(delim, end_index);
-  }
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static void GrpcSplitStringUsing(const string& full,
-                             const char* delim,
-                             std::vector<string>* result) {
-  std::back_insert_iterator< std::vector<string> > it(*result);
-  GrpcSplitStringToIteratorUsing(full, delim, it);
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static std::vector<string> GrpcSplit(const string& full, const char* delim) {
-  std::vector<string> result;
-  GrpcSplitStringUsing(full, delim, &result);
-  return result;
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static string GrpcEscapeJavadoc(const string& input) {
-  string result;
-  result.reserve(input.size() * 2);
-
-  char prev = '*';
-
-  for (string::size_type i = 0; i < input.size(); i++) {
-    char c = input[i];
-    switch (c) {
-      case '*':
-        // Avoid "/*".
-        if (prev == '/') {
-          result.append("&#42;");
-        } else {
-          result.push_back(c);
-        }
-        break;
-      case '/':
-        // Avoid "*/".
-        if (prev == '*') {
-          result.append("&#47;");
-        } else {
-          result.push_back(c);
-        }
-        break;
-      case '@':
-        // '@' starts javadoc tags including the @deprecated tag, which will
-        // cause a compile-time error if inserted before a declaration that
-        // does not have a corresponding @Deprecated annotation.
-        result.append("&#64;");
-        break;
-      case '<':
-        // Avoid interpretation as HTML.
-        result.append("&lt;");
-        break;
-      case '>':
-        // Avoid interpretation as HTML.
-        result.append("&gt;");
-        break;
-      case '&':
-        // Avoid interpretation as HTML.
-        result.append("&amp;");
-        break;
-      case '\\':
-        // Java interprets Unicode escape sequences anywhere!
-        result.append("&#92;");
-        break;
-      default:
-        result.push_back(c);
-        break;
-    }
-
-    prev = c;
-  }
-
-  return result;
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-template <typename DescriptorType>
-static string GrpcGetCommentsForDescriptor(const DescriptorType* descriptor) {
-  SourceLocation location;
-  if (descriptor->GetSourceLocation(&location)) {
-    return location.leading_comments.empty() ?
-      location.trailing_comments : location.leading_comments;
-  }
-  return string();
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static std::vector<string> GrpcGetDocLines(const string& comments) {
-  if (!comments.empty()) {
-    // TODO(kenton):  Ideally we should parse the comment text as Markdown and
-    //   write it back as HTML, but this requires a Markdown parser.  For now
-    //   we just use <pre> to get fixed-width text formatting.
-
-    // If the comment itself contains block comment start or end markers,
-    // HTML-escape them so that they don't accidentally close the doc comment.
-    string escapedComments = GrpcEscapeJavadoc(comments);
-
-    std::vector<string> lines = GrpcSplit(escapedComments, "\n");
-    while (!lines.empty() && lines.back().empty()) {
-      lines.pop_back();
-    }
-    return lines;
-  }
-  return std::vector<string>();
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-template <typename DescriptorType>
-static std::vector<string> GrpcGetDocLinesForDescriptor(const DescriptorType* descriptor) {
-  return GrpcGetDocLines(GrpcGetCommentsForDescriptor(descriptor));
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static void GrpcWriteDocCommentBody(Printer* printer,
-                                    const std::vector<string>& lines,
-                                    bool surroundWithPreTag) {
-  if (!lines.empty()) {
-    if (surroundWithPreTag) {
-      printer->Print(" * <pre>\n");
-    }
-
-    for (size_t i = 0; i < lines.size(); i++) {
-      // Most lines should start with a space.  Watch out for lines that start
-      // with a /, since putting that right after the leading asterisk will
-      // close the comment.
-      if (!lines[i].empty() && lines[i][0] == '/') {
-        printer->Print(" * $line$\n", "line", lines[i]);
-      } else {
-        printer->Print(" *$line$\n", "line", lines[i]);
-      }
-    }
-
-    if (surroundWithPreTag) {
-      printer->Print(" * </pre>\n");
-    }
-  }
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static void GrpcWriteDocComment(Printer* printer, const string& comments) {
-  printer->Print("/**\n");
-  std::vector<string> lines = GrpcGetDocLines(comments);
-  GrpcWriteDocCommentBody(printer, lines, false);
-  printer->Print(" */\n");
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static void GrpcWriteServiceDocComment(Printer* printer,
-                                       const ServiceDescriptor* service) {
-  // Deviating from protobuf to avoid extraneous docs
-  // (see https://github.com/google/protobuf/issues/1406);
-  printer->Print("/**\n");
-  std::vector<string> lines = GrpcGetDocLinesForDescriptor(service);
-  GrpcWriteDocCommentBody(printer, lines, true);
-  printer->Print(" */\n");
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-void GrpcWriteMethodDocComment(Printer* printer,
-                           const MethodDescriptor* method) {
-  // Deviating from protobuf to avoid extraneous docs
-  // (see https://github.com/google/protobuf/issues/1406);
-  printer->Print("/**\n");
-  std::vector<string> lines = GrpcGetDocLinesForDescriptor(method);
-  GrpcWriteDocCommentBody(printer, lines, true);
-  printer->Print(" */\n");
-}
-
-enum StubType {
-  ASYNC_INTERFACE = 0,
-  BLOCKING_CLIENT_INTERFACE = 1,
-  FUTURE_CLIENT_INTERFACE = 2,
-  BLOCKING_SERVER_INTERFACE = 3,
-  ASYNC_CLIENT_IMPL = 4,
-  BLOCKING_CLIENT_IMPL = 5,
-  FUTURE_CLIENT_IMPL = 6,
-  ABSTRACT_CLASS = 7,
-};
-
-enum CallType {
-  ASYNC_CALL = 0,
-  BLOCKING_CALL = 1,
-  FUTURE_CALL = 2
-};
-
-static void PrintMarshallerStaticBlock(const ServiceDescriptor* service,
-                                   std::map<string, string>* vars,
-                                   Printer* p) {
-   for (int i = 0; i < service->method_count(); ++i) {
-       const MethodDescriptor* method = service->method(i);
-       (*vars)["input_type"] = google::protobuf::compiler::java::ClassName(method->input_type());
-       (*vars)["output_type"] = google::protobuf::compiler::java::ClassName(method->output_type());
-       p->Print(
-          *vars,
-          "private static final AtomicBoolean registered = new AtomicBoolean();\n\n");
-
-       p->Print(
-           *vars,
-           "private static Class<?> init() {\n"
-           "    Class<?> clazz = null;\n"
-           "    try {\n"
-           "        clazz = Class.forName(DemoServiceDubbo.class.getName());\n"
-           "        if (registered.compareAndSet(false, true)) {\n"
-           "            $ProtobufUtils$.marshaller(\n"
-           "                $input_type$.getDefaultInstance());\n"
-           "            $ProtobufUtils$.marshaller(\n"
-           "                $output_type$.getDefaultInstance());\n"
-           "        }\n"
-           "     } catch (ClassNotFoundException e) {\n"
-           "        // ignore \n"
-           "     }\n"
-           "     return clazz;\n"
-           "}\n\n");
-   }
-}
-
-static void PrintDubboInterface(
-    const ServiceDescriptor* service,
-    std::map<string, string>* vars,
-    Printer* p, bool generate_nano) {
-    const string service_name = service->name();
-    (*vars)["service_name"] = service_name;
-    (*vars)["dubbo_interface"] = "I" + service_name;
-
-    p->Print(
-        "/**\n "
-        "* Code generated for Dubbo\n "
-        "*/\n"
-    );
-    p->Print(
-    *vars,
-    "public interface $dubbo_interface$ {\n\n"
-    "   static Class<?> clazz = init();\n\n");
-
-    for (int i = 0; i < service->method_count(); ++i) {
-        const MethodDescriptor* method = service->method(i);
-        (*vars)["input_type"] = MessageFullJavaName(generate_nano,
-                                                    method->input_type());
-        (*vars)["output_type"] = MessageFullJavaName(generate_nano,
-                                                     method->output_type());
-        (*vars)["lower_method_name"] = LowerMethodName(method);
-
-        // Simple RPC
-        p->Print(
-            *vars,
-            "   $output_type$ $lower_method_name$($input_type$ request);\n\n");
-       // Simple Future RPC
-        p->Print(
-            *vars,
-            "   $CompletableFuture$<$output_type$> $lower_method_name$Async(\n  $input_type$ request);\n\n");
-//            p->Print(
-//            *vars,
-//            "default $CompletableFuture$<$output_type$> $lower_method_name$Async(\n"
-//            "    $input_type$ request) {\n return CompletableFuture.completedFuture($lower_method_name$(request));\n}\n\n");
-        p->Outdent();
-    }
-
-    p->Outdent();
-    p->Print("  }\n\n");
-
-}
-
-static void PrintService(const ServiceDescriptor* service,
-                         std::map<string, string>* vars,
-                         Printer* p,
-                         bool disable_version) {
-  (*vars)["service_name"] = service->name();
-  (*vars)["file_name"] = service->file()->name();
-  (*vars)["service_class_name"] = ServiceClassName(service);
-  (*vars)["grpc_version"] = "";
-  #ifdef GRPC_VERSION
-  if (!disable_version) {
-    (*vars)["grpc_version"] = " (version " XSTR(GRPC_VERSION) ")";
-  }
-  #endif
-  // TODO(nmittler): Replace with WriteServiceDocComment once included by protobuf distro.
-  GrpcWriteServiceDocComment(p, service);
-  p->Print(
-      *vars,
-      "@$Generated$(\n"
-      "    value = \"by gRPC proto compiler$grpc_version$\",\n"
-      "    comments = \"Source: $file_name$\")\n");
-
-  if (service->options().deprecated()) {
-    p->Print(*vars, "@$Deprecated$\n");
-  }
-
-  p->Print(
-      *vars,
-      "public final class $service_class_name$ {\n\n");
-  p->Indent();
-
-  PrintMarshallerStaticBlock(service, vars, p);
-
-  p->Print(
-      *vars,
-      "private $service_class_name$() {}\n\n");
-
-  p->Print(
-      *vars,
-      "public static final String SERVICE_NAME = "
-      "\"$Package$$service_name$\";\n\n");
-
-  PrintDubboInterface(service, vars, p, false);
-
-  p->Outdent();
-  p->Print("}\n");
-}
-
-void PrintImports(Printer* p) {
-  p->Print(
-      "import "
-      "java.util.concurrent.CompletableFuture;\n");
-  p->Print(
-        "import "
-        "java.util.concurrent.atomic.AtomicBoolean;\n");
-}
-
-void GenerateService(const ServiceDescriptor* service,
-                     google::protobuf::io::ZeroCopyOutputStream* out,
-                     ProtoFlavor flavor,
-                     bool disable_version) {
-  // All non-generated classes must be referred by fully qualified names to
-  // avoid collision with generated classes.
-  std::map<string, string> vars;
-  vars["String"] = "java.lang.String";
-  vars["Deprecated"] = "java.lang.Deprecated";
-  vars["Override"] = "java.lang.Override";
-  vars["Iterator"] = "java.util.Iterator";
-  vars["Generated"] = "javax.annotation.Generated";
-  vars["CompletableFuture"] =
-      "java.util.concurrent.CompletableFuture";
-  vars["AtomicBoolean"] =
-        "java.util.concurrent.atomic.AtomicBoolean";
-  vars["ProtobufUtils"] =
-        "org.apache.dubbo.common.serialize.protobuf.support.ProtobufUtils";
-
-  Printer printer(out, '$');
-  string package_name = ServiceJavaPackage(service->file(),false);
-  if (!package_name.empty()) {
-    printer.Print(
-        "package $package_name$;\n\n",
-        "package_name", package_name);
-  }
-
-  PrintImports(&printer);
-
-  // Package string is used to fully qualify method names.
-  vars["Package"] = service->file()->package();
-  if (!vars["Package"].empty()) {
-    vars["Package"].append(".");
-  }
-  PrintService(service, &vars, &printer, false);
-}
-
-string ServiceJavaPackage(const FileDescriptor* file, bool nano) {
-  string result = google::protobuf::compiler::java::ClassName(file);
-  size_t last_dot_pos = result.find_last_of('.');
-  if (last_dot_pos != string::npos) {
-    result.resize(last_dot_pos);
-  } else {
-    result = "";
-  }
-  if (nano) {
-    if (!result.empty()) {
-      result += ".";
-    }
-    result += "nano";
-  }
-  return result;
-}
-
-string ServiceClassName(const google::protobuf::ServiceDescriptor* service) {
-  return service->name() + "Dubbo";
-}
-
-}  // namespace java_dubbo_generator
diff --git a/compiler/src/java_plugin/cpp/java_generator.cpp b/compiler/src/java_plugin/cpp/java_generator.cpp
deleted file mode 100644
index 98093ca..0000000
--- a/compiler/src/java_plugin/cpp/java_generator.cpp
+++ /dev/null
@@ -1,1558 +0,0 @@
-#include "java_generator.h"
-
-#include <algorithm>
-#include <iostream>
-#include <iterator>
-#include <map>
-#include <set>
-#include <vector>
-#include <google/protobuf/compiler/java/java_names.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-
-// Stringify helpers used solely to cast GRPC_VERSION
-#ifndef STR
-#define STR(s) #s
-#endif
-
-#ifndef XSTR
-#define XSTR(s) STR(s)
-#endif
-
-#ifndef FALLTHROUGH_INTENDED
-#define FALLTHROUGH_INTENDED
-#endif
-
-namespace java_grpc_generator {
-
-using google::protobuf::FileDescriptor;
-using google::protobuf::ServiceDescriptor;
-using google::protobuf::MethodDescriptor;
-using google::protobuf::Descriptor;
-using google::protobuf::io::Printer;
-using google::protobuf::SourceLocation;
-using std::to_string;
-
-// java keywords from: https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.9
-static std::set<string> java_keywords = {
-  "abstract",
-  "assert",
-  "boolean",
-  "break",
-  "byte",
-  "case",
-  "catch",
-  "char",
-  "class",
-  "const",
-  "continue",
-  "default",
-  "do",
-  "double",
-  "else",
-  "enum",
-  "extends",
-  "final",
-  "finally",
-  "float",
-  "for",
-  "goto",
-  "if",
-  "implements",
-  "import",
-  "instanceof",
-  "int",
-  "interface",
-  "long",
-  "native",
-  "new",
-  "package",
-  "private",
-  "protected",
-  "public",
-  "return",
-  "short",
-  "static",
-  "strictfp",
-  "super",
-  "switch",
-  "synchronized",
-  "this",
-  "throw",
-  "throws",
-  "transient",
-  "try",
-  "void",
-  "volatile",
-  "while",
-  // additional ones added by us
-  "true",
-  "false",
-};
-
-// Adjust a method name prefix identifier to follow the JavaBean spec:
-//   - decapitalize the first letter
-//   - remove embedded underscores & capitalize the following letter
-//  Finally, if the result is a reserved java keyword, append an underscore.
-static string MixedLower(const string& word) {
-  string w;
-  w += tolower(word[0]);
-  bool after_underscore = false;
-  for (size_t i = 1; i < word.length(); ++i) {
-    if (word[i] == '_') {
-      after_underscore = true;
-    } else {
-      w += after_underscore ? toupper(word[i]) : word[i];
-      after_underscore = false;
-    }
-  }
-  if (java_keywords.find(w) != java_keywords.end()) {
-    return w + "_";
-  }
-  return w;
-}
-
-// Converts to the identifier to the ALL_UPPER_CASE format.
-//   - An underscore is inserted where a lower case letter is followed by an
-//     upper case letter.
-//   - All letters are converted to upper case
-static string ToAllUpperCase(const string& word) {
-  string w;
-  for (size_t i = 0; i < word.length(); ++i) {
-    w += toupper(word[i]);
-    if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) {
-      w += '_';
-    }
-  }
-  return w;
-}
-
-static inline string LowerMethodName(const MethodDescriptor* method) {
-  return MixedLower(method->name());
-}
-
-static inline string MethodPropertiesFieldName(const MethodDescriptor* method) {
-  return "METHOD_" + ToAllUpperCase(method->name());
-}
-
-static inline string MethodPropertiesGetterName(const MethodDescriptor* method) {
-  return MixedLower("get_" + method->name() + "_method");
-}
-
-static inline string MethodIdFieldName(const MethodDescriptor* method) {
-  return "METHODID_" + ToAllUpperCase(method->name());
-}
-
-static inline bool ShouldGenerateAsLite(const Descriptor* desc) {
-  return false;
-}
-
-static inline string MessageFullJavaName(bool nano, const Descriptor* desc) {
-  string name = google::protobuf::compiler::java::ClassName(desc);
-  if (nano && !ShouldGenerateAsLite(desc)) {
-    // XXX: Add "nano" to the original package
-    // (https://github.com/grpc/grpc-java/issues/900)
-    if (isupper(name[0])) {
-      // No java package specified.
-      return "nano." + name;
-    }
-    for (size_t i = 0; i < name.size(); ++i) {
-      if ((name[i] == '.') && (i < (name.size() - 1)) && isupper(name[i + 1])) {
-        return name.substr(0, i + 1) + "nano." + name.substr(i + 1);
-      }
-    }
-  }
-  return name;
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-template <typename ITR>
-static void GrpcSplitStringToIteratorUsing(const string& full,
-                                       const char* delim,
-                                       ITR& result) {
-  // Optimize the common case where delim is a single character.
-  if (delim[0] != '\0' && delim[1] == '\0') {
-    char c = delim[0];
-    const char* p = full.data();
-    const char* end = p + full.size();
-    while (p != end) {
-      if (*p == c) {
-        ++p;
-      } else {
-        const char* start = p;
-        while (++p != end && *p != c);
-        *result++ = string(start, p - start);
-      }
-    }
-    return;
-  }
-
-  string::size_type begin_index, end_index;
-  begin_index = full.find_first_not_of(delim);
-  while (begin_index != string::npos) {
-    end_index = full.find_first_of(delim, begin_index);
-    if (end_index == string::npos) {
-      *result++ = full.substr(begin_index);
-      return;
-    }
-    *result++ = full.substr(begin_index, (end_index - begin_index));
-    begin_index = full.find_first_not_of(delim, end_index);
-  }
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static void GrpcSplitStringUsing(const string& full,
-                             const char* delim,
-                             std::vector<string>* result) {
-  std::back_insert_iterator< std::vector<string> > it(*result);
-  GrpcSplitStringToIteratorUsing(full, delim, it);
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static std::vector<string> GrpcSplit(const string& full, const char* delim) {
-  std::vector<string> result;
-  GrpcSplitStringUsing(full, delim, &result);
-  return result;
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static string GrpcEscapeJavadoc(const string& input) {
-  string result;
-  result.reserve(input.size() * 2);
-
-  char prev = '*';
-
-  for (string::size_type i = 0; i < input.size(); i++) {
-    char c = input[i];
-    switch (c) {
-      case '*':
-        // Avoid "/*".
-        if (prev == '/') {
-          result.append("&#42;");
-        } else {
-          result.push_back(c);
-        }
-        break;
-      case '/':
-        // Avoid "*/".
-        if (prev == '*') {
-          result.append("&#47;");
-        } else {
-          result.push_back(c);
-        }
-        break;
-      case '@':
-        // '@' starts javadoc tags including the @deprecated tag, which will
-        // cause a compile-time error if inserted before a declaration that
-        // does not have a corresponding @Deprecated annotation.
-        result.append("&#64;");
-        break;
-      case '<':
-        // Avoid interpretation as HTML.
-        result.append("&lt;");
-        break;
-      case '>':
-        // Avoid interpretation as HTML.
-        result.append("&gt;");
-        break;
-      case '&':
-        // Avoid interpretation as HTML.
-        result.append("&amp;");
-        break;
-      case '\\':
-        // Java interprets Unicode escape sequences anywhere!
-        result.append("&#92;");
-        break;
-      default:
-        result.push_back(c);
-        break;
-    }
-
-    prev = c;
-  }
-
-  return result;
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-template <typename DescriptorType>
-static string GrpcGetCommentsForDescriptor(const DescriptorType* descriptor) {
-  SourceLocation location;
-  if (descriptor->GetSourceLocation(&location)) {
-    return location.leading_comments.empty() ?
-      location.trailing_comments : location.leading_comments;
-  }
-  return string();
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static std::vector<string> GrpcGetDocLines(const string& comments) {
-  if (!comments.empty()) {
-    // TODO(kenton):  Ideally we should parse the comment text as Markdown and
-    //   write it back as HTML, but this requires a Markdown parser.  For now
-    //   we just use <pre> to get fixed-width text formatting.
-
-    // If the comment itself contains block comment start or end markers,
-    // HTML-escape them so that they don't accidentally close the doc comment.
-    string escapedComments = GrpcEscapeJavadoc(comments);
-
-    std::vector<string> lines = GrpcSplit(escapedComments, "\n");
-    while (!lines.empty() && lines.back().empty()) {
-      lines.pop_back();
-    }
-    return lines;
-  }
-  return std::vector<string>();
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-template <typename DescriptorType>
-static std::vector<string> GrpcGetDocLinesForDescriptor(const DescriptorType* descriptor) {
-  return GrpcGetDocLines(GrpcGetCommentsForDescriptor(descriptor));
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static void GrpcWriteDocCommentBody(Printer* printer,
-                                    const std::vector<string>& lines,
-                                    bool surroundWithPreTag) {
-  if (!lines.empty()) {
-    if (surroundWithPreTag) {
-      printer->Print(" * <pre>\n");
-    }
-
-    for (size_t i = 0; i < lines.size(); i++) {
-      // Most lines should start with a space.  Watch out for lines that start
-      // with a /, since putting that right after the leading asterisk will
-      // close the comment.
-      if (!lines[i].empty() && lines[i][0] == '/') {
-        printer->Print(" * $line$\n", "line", lines[i]);
-      } else {
-        printer->Print(" *$line$\n", "line", lines[i]);
-      }
-    }
-
-    if (surroundWithPreTag) {
-      printer->Print(" * </pre>\n");
-    }
-  }
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static void GrpcWriteDocComment(Printer* printer, const string& comments) {
-  printer->Print("/**\n");
-  std::vector<string> lines = GrpcGetDocLines(comments);
-  GrpcWriteDocCommentBody(printer, lines, false);
-  printer->Print(" */\n");
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-static void GrpcWriteServiceDocComment(Printer* printer,
-                                       const ServiceDescriptor* service) {
-  // Deviating from protobuf to avoid extraneous docs
-  // (see https://github.com/google/protobuf/issues/1406);
-  printer->Print("/**\n");
-  std::vector<string> lines = GrpcGetDocLinesForDescriptor(service);
-  GrpcWriteDocCommentBody(printer, lines, true);
-  printer->Print(" */\n");
-}
-
-// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
-void GrpcWriteMethodDocComment(Printer* printer,
-                           const MethodDescriptor* method) {
-  // Deviating from protobuf to avoid extraneous docs
-  // (see https://github.com/google/protobuf/issues/1406);
-  printer->Print("/**\n");
-  std::vector<string> lines = GrpcGetDocLinesForDescriptor(method);
-  GrpcWriteDocCommentBody(printer, lines, true);
-  printer->Print(" */\n");
-}
-
-static void PrintMethodFields(
-    const ServiceDescriptor* service, std::map<string, string>* vars,
-    Printer* p, ProtoFlavor flavor) {
-  p->Print("// Static method descriptors that strictly reflect the proto.\n");
-  (*vars)["service_name"] = service->name();
-  for (int i = 0; i < service->method_count(); ++i) {
-    const MethodDescriptor* method = service->method(i);
-    (*vars)["arg_in_id"] = to_string(2 * i);
-    (*vars)["arg_out_id"] = to_string(2 * i + 1);
-    (*vars)["method_name"] = method->name();
-    (*vars)["input_type"] = MessageFullJavaName(flavor == ProtoFlavor::NANO,
-                                                method->input_type());
-    (*vars)["output_type"] = MessageFullJavaName(flavor == ProtoFlavor::NANO,
-                                                 method->output_type());
-    (*vars)["method_field_name"] = MethodPropertiesFieldName(method);
-    (*vars)["method_new_field_name"] = MethodPropertiesGetterName(method);
-    (*vars)["method_method_name"] = MethodPropertiesGetterName(method);
-    bool client_streaming = method->client_streaming();
-    bool server_streaming = method->server_streaming();
-    if (client_streaming) {
-      if (server_streaming) {
-        (*vars)["method_type"] = "BIDI_STREAMING";
-      } else {
-        (*vars)["method_type"] = "CLIENT_STREAMING";
-      }
-    } else {
-      if (server_streaming) {
-        (*vars)["method_type"] = "SERVER_STREAMING";
-      } else {
-        (*vars)["method_type"] = "UNARY";
-      }
-    }
-
-    if (flavor == ProtoFlavor::NANO) {
-      // TODO(zsurocking): we're creating two NanoFactories for each method right now.
-      // We could instead create static NanoFactories and reuse them if some methods
-      // share the same request or response messages.
-      if (!ShouldGenerateAsLite(method->input_type())) {
-        p->Print(
-            *vars,
-            "private static final int ARG_IN_$method_field_name$ = $arg_in_id$;\n");
-      }
-      if (!ShouldGenerateAsLite(method->output_type())) {
-        p->Print(
-            *vars,
-            "private static final int ARG_OUT_$method_field_name$ = $arg_out_id$;\n");
-      }
-      p->Print(
-          *vars,
-          "private static volatile $MethodDescriptor$<$input_type$,\n"
-          "    $output_type$> $method_new_field_name$;\n"
-          "\n"
-          "public static $MethodDescriptor$<$input_type$,\n"
-          "    $output_type$> $method_method_name$() {\n"
-          "  $MethodDescriptor$<$input_type$, $output_type$> $method_new_field_name$;\n"
-          "  if (($method_new_field_name$ = $service_class_name$.$method_new_field_name$) == null) {\n"
-          "    synchronized ($service_class_name$.class) {\n"
-          "      if (($method_new_field_name$ = $service_class_name$.$method_new_field_name$) == null) {\n"
-          "        $service_class_name$.$method_new_field_name$ = $method_new_field_name$ = \n"
-          "            $MethodDescriptor$.<$input_type$, $output_type$>newBuilder()\n"
-          "            .setType($MethodType$.$method_type$)\n"
-          "            .setFullMethodName(generateFullMethodName(\n"
-          "                \"$Package$$service_name$\", \"$method_name$\"))\n"
-          "            .setSampledToLocalTracing(true)\n");
-
-      (*vars)["ProtoLiteUtils"] = "io.grpc.protobuf.lite.ProtoLiteUtils";
-
-      if (ShouldGenerateAsLite(method->input_type())) {
-        p->Print(
-            *vars,
-            "            .setRequestMarshaller($ProtoLiteUtils$.marshaller(\n"
-            "                $input_type$.getDefaultInstance()))\n");
-      } else {
-        p->Print(
-            *vars,
-            "            .setRequestMarshaller($NanoUtils$.<$input_type$>marshaller(\n"
-            "                new NanoFactory<$input_type$>(ARG_IN_$method_field_name$)))\n");
-      }
-      if (ShouldGenerateAsLite(method->output_type())) {
-        p->Print(
-            *vars,
-            "            .setResponseMarshaller($ProtoLiteUtils$.marshaller(\n"
-            "                $output_type$.getDefaultInstance()))\n");
-      } else {
-        p->Print(
-            *vars,
-            "            .setResponseMarshaller($NanoUtils$.<$output_type$>marshaller(\n"
-            "                new NanoFactory<$output_type$>(ARG_OUT_$method_field_name$)))\n");
-      }
-      p->Print(
-          *vars,
-          "            .build();\n"
-          "      }\n"
-          "    }\n"
-          "  }\n"
-          "  return $method_new_field_name$;\n"
-          "}\n"
-          "\n");
-    } else {
-      if (flavor == ProtoFlavor::LITE) {
-        (*vars)["ProtoUtils"] = "io.grpc.protobuf.lite.ProtoLiteUtils";
-      } else {
-        (*vars)["ProtoUtils"] = "io.grpc.protobuf.ProtoUtils";
-      }
-      p->Print(
-          *vars,
-          "private static volatile $MethodDescriptor$<$input_type$,\n"
-          "    $output_type$> $method_new_field_name$;\n"
-          "\n"
-          "@$RpcMethod$(\n"
-          "    fullMethodName = SERVICE_NAME + '/' + \"$method_name$\",\n"
-          "    requestType = $input_type$.class,\n"
-          "    responseType = $output_type$.class,\n"
-          "    methodType = $MethodType$.$method_type$)\n"
-          "public static $MethodDescriptor$<$input_type$,\n"
-          "    $output_type$> $method_method_name$() {\n"
-          "  $MethodDescriptor$<$input_type$, $output_type$> $method_new_field_name$;\n"
-          "  if (($method_new_field_name$ = $service_class_name$.$method_new_field_name$) == null) {\n"
-          "    synchronized ($service_class_name$.class) {\n"
-          "      if (($method_new_field_name$ = $service_class_name$.$method_new_field_name$) == null) {\n"
-          "        $service_class_name$.$method_new_field_name$ = $method_new_field_name$ = \n"
-          "            $MethodDescriptor$.<$input_type$, $output_type$>newBuilder()\n"
-          "            .setType($MethodType$.$method_type$)\n"
-          "            .setFullMethodName(generateFullMethodName(\n"
-          "                \"$Package$$service_name$\", \"$method_name$\"))\n"
-          "            .setSampledToLocalTracing(true)\n"
-          "            .setRequestMarshaller($ProtoUtils$.marshaller(\n"
-          "                $input_type$.getDefaultInstance()))\n"
-          "            .setResponseMarshaller($ProtoUtils$.marshaller(\n"
-          "                $output_type$.getDefaultInstance()))\n");
-
-      (*vars)["proto_method_descriptor_supplier"] = service->name() + "MethodDescriptorSupplier";
-      if (flavor == ProtoFlavor::NORMAL) {
-        p->Print(
-            *vars,
-          "                .setSchemaDescriptor(new $proto_method_descriptor_supplier$(\"$method_name$\"))\n");
-      }
-
-      p->Print(
-          *vars,
-          "                .build();\n");
-      p->Print(*vars,
-          "        }\n"
-          "      }\n"
-          "   }\n"
-          "   return $method_new_field_name$;\n"
-          "}\n"
-          "\n");
-    }
-  }
-
-  if (flavor == ProtoFlavor::NANO) {
-    p->Print(
-        *vars,
-        "private static final class NanoFactory<T extends com.google.protobuf.nano.MessageNano>\n"
-        "    implements io.grpc.protobuf.nano.MessageNanoFactory<T> {\n"
-        "  private final int id;\n"
-        "\n"
-        "  NanoFactory(int id) {\n"
-        "    this.id = id;\n"
-        "  }\n"
-        "\n"
-        "  @$Override$\n"
-        "  public T newInstance() {\n"
-        "    Object o;\n"
-        "    switch (id) {\n");
-    bool generate_nano = true;
-    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)["method_field_name"] = MethodPropertiesFieldName(method);
-      if (!ShouldGenerateAsLite(method->input_type())) {
-        p->Print(
-            *vars,
-            "    case ARG_IN_$method_field_name$:\n"
-            "      o = new $input_type$();\n"
-            "      break;\n");
-      }
-      if (!ShouldGenerateAsLite(method->output_type())) {
-        p->Print(
-            *vars,
-            "    case ARG_OUT_$method_field_name$:\n"
-            "      o = new $output_type$();\n"
-            "      break;\n");
-      }
-    }
-    p->Print(
-        "    default:\n"
-        "      throw new AssertionError();\n"
-        "    }\n"
-        "    @java.lang.SuppressWarnings(\"unchecked\")\n"
-        "    T t = (T) o;\n"
-        "    return t;\n"
-        "  }\n"
-        "}\n"
-        "\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 PrintBindServiceMethodBody(const ServiceDescriptor* service,
-                                   std::map<string, string>* vars,
-                                   Printer* p,
-                                   bool generate_nano);
-
-// Prints a client interface or implementation class, or a server interface.
-static void PrintStub(
-    const ServiceDescriptor* service,
-    std::map<string, string>* vars,
-    Printer* p, StubType type, bool generate_nano) {
-  const string service_name = service->name();
-  (*vars)["service_name"] = service_name;
-  string stub_name = service_name;
-  string client_name = service_name;
-  CallType call_type;
-  bool interface = false;
-  switch (type) {
-    case ASYNC_CLIENT_IMPL:
-      call_type = ASYNC_CALL;
-      stub_name += "Stub";
-      break;
-    case BLOCKING_CLIENT_INTERFACE:
-      interface = true;
-      FALLTHROUGH_INTENDED;
-    case BLOCKING_CLIENT_IMPL:
-      call_type = BLOCKING_CALL;
-      stub_name += "BlockingStub";
-      client_name += "BlockingClient";
-      break;
-    case FUTURE_CLIENT_INTERFACE:
-      interface = true;
-      FALLTHROUGH_INTENDED;
-    case FUTURE_CLIENT_IMPL:
-      call_type = FUTURE_CALL;
-      stub_name += "FutureStub";
-      client_name += "FutureClient";
-      break;
-    case ASYNC_INTERFACE:
-      call_type = ASYNC_CALL;
-      interface = true;
-      break;
-    default:
-      GRPC_CODEGEN_FAIL << "Cannot determine class name for StubType: " << type;
-  }
-  (*vars)["stub_name"] = stub_name;
-  (*vars)["client_name"] = client_name;
-
-  // Class head
-  if (!interface) {
-    GrpcWriteServiceDocComment(p, service);
-  }
-
-  if (service->options().deprecated()) {
-    p->Print(*vars, "@$Deprecated$\n");
-  }
-
-
-  p->Print(
-      *vars,
-      "public static final class $stub_name$ extends $AbstractStub$<$stub_name$> {\n");
-
-  p->Indent();
-
-  // Constructor and build() method
-  if (!interface) {
-    p->Print(
-        *vars,
-        "private $stub_name$($Channel$ channel) {\n");
-    p->Indent();
-    p->Print("super(channel);\n");
-    p->Outdent();
-    p->Print("}\n\n");
-    p->Print(
-        *vars,
-        "private $stub_name$($Channel$ channel,\n"
-        "    $CallOptions$ callOptions) {\n");
-    p->Indent();
-    p->Print("super(channel, callOptions);\n");
-    p->Outdent();
-    p->Print("}\n\n");
-    p->Print(
-        *vars,
-        "@$Override$\n"
-        "protected $stub_name$ build($Channel$ channel,\n"
-        "    $CallOptions$ callOptions) {\n");
-    p->Indent();
-    p->Print(
-        *vars,
-        "return new $stub_name$(channel, callOptions);\n");
-    p->Outdent();
-    p->Print("}\n");
-  }
-
-  // RPC methods
-  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);
-    (*vars)["method_method_name"] = MethodPropertiesGetterName(method);
-    bool client_streaming = method->client_streaming();
-    bool server_streaming = method->server_streaming();
-
-    if (call_type == BLOCKING_CALL && client_streaming) {
-      // Blocking client interface with client streaming is not available
-      continue;
-    }
-
-    if (call_type == FUTURE_CALL && (client_streaming || server_streaming)) {
-      // Future interface doesn't support streaming.
-      continue;
-    }
-
-    // Method signature
-    p->Print("\n");
-    // TODO(nmittler): Replace with WriteMethodDocComment once included by the protobuf distro.
-    if (!interface) {
-      GrpcWriteMethodDocComment(p, method);
-    }
-
-    if (method->options().deprecated()) {
-      p->Print(*vars, "@$Deprecated$\n");
-    }
-
-    p->Print("public ");
-    switch (call_type) {
-      case BLOCKING_CALL:
-        GRPC_CODEGEN_CHECK(!client_streaming)
-            << "Blocking client interface with client streaming is unavailable";
-        if (server_streaming) {
-          // Server streaming
-          p->Print(
-              *vars,
-              "$Iterator$<$output_type$> $lower_method_name$(\n"
-              "    $input_type$ request)");
-        } else {
-          // Simple RPC
-          p->Print(
-              *vars,
-              "$output_type$ $lower_method_name$($input_type$ request)");
-        }
-        break;
-      case ASYNC_CALL:
-        if (client_streaming) {
-          // Bidirectional streaming or client streaming
-          p->Print(
-              *vars,
-              "$StreamObserver$<$input_type$> $lower_method_name$(\n"
-              "    $StreamObserver$<$output_type$> responseObserver)");
-        } else {
-          // Server streaming or simple RPC
-          p->Print(
-              *vars,
-              "void $lower_method_name$($input_type$ request,\n"
-              "    $StreamObserver$<$output_type$> responseObserver)");
-        }
-        break;
-      case FUTURE_CALL:
-        GRPC_CODEGEN_CHECK(!client_streaming && !server_streaming)
-            << "Future interface doesn't support streaming. "
-            << "client_streaming=" << client_streaming << ", "
-            << "server_streaming=" << server_streaming;
-        p->Print(
-            *vars,
-            "$ListenableFuture$<$output_type$> $lower_method_name$(\n"
-            "    $input_type$ request)");
-        break;
-    }
-
-    if (interface) {
-      p->Print(";\n");
-      continue;
-    }
-    // Method body.
-    p->Print(" {\n");
-    p->Indent();
-    if (!interface) {
-      switch (call_type) {
-        case BLOCKING_CALL:
-          GRPC_CODEGEN_CHECK(!client_streaming)
-              << "Blocking client streaming interface is not available";
-          if (server_streaming) {
-            (*vars)["calls_method"] = "blockingServerStreamingCall";
-            (*vars)["params"] = "request";
-          } else {
-            (*vars)["calls_method"] = "blockingUnaryCall";
-            (*vars)["params"] = "request";
-          }
-          p->Print(
-              *vars,
-              "return $calls_method$(\n"
-              "    getChannel(), $method_method_name$(), getCallOptions(), $params$);\n");
-          break;
-        case ASYNC_CALL:
-          if (server_streaming) {
-            if (client_streaming) {
-              (*vars)["calls_method"] = "asyncBidiStreamingCall";
-              (*vars)["params"] = "responseObserver";
-            } else {
-              (*vars)["calls_method"] = "asyncServerStreamingCall";
-              (*vars)["params"] = "request, responseObserver";
-            }
-          } else {
-            if (client_streaming) {
-              (*vars)["calls_method"] = "asyncClientStreamingCall";
-              (*vars)["params"] = "responseObserver";
-            } else {
-              (*vars)["calls_method"] = "asyncUnaryCall";
-              (*vars)["params"] = "request, responseObserver";
-            }
-          }
-          (*vars)["last_line_prefix"] = client_streaming ? "return " : "";
-          p->Print(
-              *vars,
-              "$last_line_prefix$$calls_method$(\n"
-              "    getChannel().newCall($method_method_name$(), getCallOptions()), $params$);\n");
-          break;
-        case FUTURE_CALL:
-          GRPC_CODEGEN_CHECK(!client_streaming && !server_streaming)
-              << "Future interface doesn't support streaming. "
-              << "client_streaming=" << client_streaming << ", "
-              << "server_streaming=" << server_streaming;
-          (*vars)["calls_method"] = "futureUnaryCall";
-          p->Print(
-              *vars,
-              "return $calls_method$(\n"
-              "    getChannel().newCall($method_method_name$(), getCallOptions()), request);\n");
-          break;
-      }
-    }
-    p->Outdent();
-    p->Print("}\n");
-  }
-
-  p->Outdent();
-  p->Print("}\n\n");
-}
-
-static void PrintImplBase(
-    const ServiceDescriptor* service,
-    std::map<string, string>* vars,
-    Printer* p, bool generate_nano) {
-  const string service_name = service->name();
-  (*vars)["service_name"] = service_name;
-  (*vars)["abstract_name"] = service_name + "ImplBase";
-  string stub_name = service_name;
-  string client_name = service_name;
-  CallType call_type;
-
-  (*vars)["dubbo_interface"] = "I" + service_name;
-
-  p->Print(
-        *vars,
-        "public static abstract class $abstract_name$ implements $BindableService$, $dubbo_interface$ {\n\n");
-
-  p->Print(*vars, "private $dubbo_interface$ proxiedImpl;\n\n");
-  p->Print(*vars, "public final void setProxiedImpl($dubbo_interface$ proxiedImpl) {\n");
-  p->Print(*vars, " this.proxiedImpl = proxiedImpl;\n");
-  p->Print(*vars, "}\n\n");
-
-  // RPC methods
-  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);
-    (*vars)["method_method_name"] = MethodPropertiesGetterName(method);
-    bool client_streaming = method->client_streaming();
-    bool server_streaming = method->server_streaming();
-
-    if (client_streaming) {
-        p->Print(
-            *vars,
-            "public $StreamObserver$<$input_type$> $lower_method_name$(\n"
-            "    $StreamObserver$<$output_type$> responseObserver) {\n"
-            "    return asyncUnimplementedStreamingCall($method_method_name$(), responseObserver);\n"
-            "}\n\n");
-
-    } else if (server_streaming) {
-        p->Print(
-            *vars,
-            "@$Override$\n"
-            "public final $Iterator$<$output_type$> $lower_method_name$(\n"
-            "    $input_type$ request) {\n$default_method_body$\n}\n\n");
-        p->Print(
-            *vars,
-            "public void $lower_method_name$($input_type$ request,\n"
-            "    $StreamObserver$<$output_type$> responseObserver) {\n"
-            "    asyncUnimplementedUnaryCall($method_method_name$(), responseObserver);\n\n"
-            "}\n");
-    } else {
-       // Simple RPC
-        p->Print(
-            *vars,
-            "@$Override$\n"
-            "public final $output_type$ $lower_method_name$"
-            "($input_type$ request) {\n$default_method_body$\n}\n\n");
-       // Simple Future RPC
-        p->Print(
-            *vars,
-            "@$Override$\n"
-            "public final $ListenableFuture$<$output_type$> $lower_method_name$Async(\n"
-            "    $input_type$ request) {\n$default_method_body$\n}\n\n");
-       // Simple Stream RPC
-        p->Print(
-            *vars,
-            "public void $lower_method_name$($input_type$ request,\n"
-            "    $StreamObserver$<$output_type$> responseObserver) {\n"
-            "    asyncUnimplementedUnaryCall($method_method_name$(), responseObserver);\n"
-            "}\n\n");
-    }
-    p->Outdent();
-  }
-
-    p->Print("\n");
-    p->Print(
-        *vars,
-        "@$Override$\n public final $ServerServiceDefinition$ bindService() {\n");
-    (*vars)["instance"] = "proxiedImpl";
-    PrintBindServiceMethodBody(service, vars, p, generate_nano);
-    p->Print("}\n");
-    p->Outdent();
-    p->Print("}\n\n");
-}
-
-static void PrintDubboInterface(
-    const ServiceDescriptor* service,
-    std::map<string, string>* vars,
-    Printer* p, bool interface, bool generate_nano) {
-    const string service_name = service->name();
-    (*vars)["service_name"] = service_name;
-    (*vars)["dubbo_interface"] = "I" + service_name;
-    if (interface) {
-        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);
-            (*vars)["method_method_name"] = MethodPropertiesGetterName(method);
-            bool client_streaming = method->client_streaming();
-            bool server_streaming = method->server_streaming();
-
-            if (client_streaming) {
-                p->Print(
-                    *vars,
-                    "public $StreamObserver$<$input_type$> $lower_method_name$(\n"
-                    "    $StreamObserver$<$output_type$> responseObserver);\n\n");
-
-            } else if (server_streaming) {
-                p->Print(
-                    *vars,
-                    "default public $Iterator$<$output_type$> $lower_method_name$(\n"
-                    "    $input_type$ request) {\n$default_method_body$\n}\n\n");
-                p->Print(
-                    *vars,
-                    "public void $lower_method_name$($input_type$ request,\n"
-                    "    $StreamObserver$<$output_type$> responseObserver);\n\n");
-            } else {
-               // Simple RPC
-                p->Print(
-                    *vars,
-                    "default public $output_type$ $lower_method_name$"
-                    "($input_type$ request) {\n$default_method_body$\n}\n\n");
-               // Simple Future RPC
-                p->Print(
-                    *vars,
-                    "default public $ListenableFuture$<$output_type$> $lower_method_name$Async(\n"
-                    "    $input_type$ request) {\n$default_method_body$\n}\n\n");
-               // Simple Stream RPC
-                p->Print(
-                    *vars,
-                    "public void $lower_method_name$($input_type$ request,\n"
-                    "    $StreamObserver$<$output_type$> responseObserver);\n\n");
-            }
-            p->Outdent();
-        }
-
-        p->Outdent();
-        p->Print("}\n\n");
-    }
-    // Dubbo Stub
-    else {
-        (*vars)["dubbo_stub"] = "Dubbo" + service_name + "Stub";
-        p->Print(*vars, "public static class $dubbo_stub$ implements $dubbo_interface$ {\n\n");
-
-        // Properties
-        p->Print("private "); p->Print(service_name.c_str()); p->Print("BlockingStub blockingStub;\n");
-        p->Print("private "); p->Print(service_name.c_str()); p->Print("FutureStub futureStub;\n");
-        p->Print("private "); p->Print(service_name.c_str()); p->Print("Stub stub;\n\n");
-
-        // Consustor
-        p->Print(*vars, "public $dubbo_stub$($Channel$ channel, $CallOptions$ callOptions) {\n"
-        "   blockingStub = $service_class_name$.newBlockingStub(channel).build(channel, callOptions);\n"
-        "   futureStub = $service_class_name$.newFutureStub(channel).build(channel, callOptions);\n"
-        "   stub = $service_class_name$.newStub(channel).build(channel, callOptions);\n"
-        "}\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);
-            (*vars)["method_method_name"] = MethodPropertiesGetterName(method);
-            bool client_streaming = method->client_streaming();
-            bool server_streaming = method->server_streaming();
-
-            if (client_streaming) {
-                p->Print(
-                    *vars,
-                    "public $StreamObserver$<$input_type$> $lower_method_name$(\n"
-                    "    $StreamObserver$<$output_type$> responseObserver) {\n"
-                    "    return stub.$lower_method_name$(responseObserver);\n"
-                    "}\n\n");
-
-            } else if (server_streaming) {
-                p->Print(
-                    *vars,
-                    "public $Iterator$<$output_type$> $lower_method_name$(\n"
-                    "    $input_type$ request) {\n"
-                    "    return blockingStub.$lower_method_name$(request);\n"
-                    "}\n\n");
-                p->Print(
-                    *vars,
-                    "public void $lower_method_name$($input_type$ request,\n"
-                    "    $StreamObserver$<$output_type$> responseObserver) {\n"
-                    "    stub.$lower_method_name$(request, responseObserver);\n"
-                    "}\n\n");
-            } else {
-               // Simple RPC
-                p->Print(
-                    *vars,
-                    "public $output_type$ $lower_method_name$"
-                    "($input_type$ request) {\n"
-                    "    return blockingStub.$lower_method_name$(request);\n"
-                    "}\n\n");
-               // Simple Future RPC
-                p->Print(
-                    *vars,
-                    "public $ListenableFuture$<$output_type$> $lower_method_name$Async(\n"
-                    "    $input_type$ request) {\n"
-                    "    return futureStub.$lower_method_name$(request);\n"
-                    "}\n\n");
-               // Simple Stream RPC
-                p->Print(
-                    *vars,
-                    "public void $lower_method_name$($input_type$ request,\n"
-                    "    $StreamObserver$<$output_type$> responseObserver){\n"
-                    "    stub.$lower_method_name$(request, responseObserver);\n"
-                    "}\n\n");
-            }
-            p->Outdent();
-        }
-        p->Outdent();
-        p->Print("}\n\n");
-
-        p->Print(*vars, "public static $dubbo_stub$ getDubboStub($Channel$ channel, $CallOptions$ callOptions) {\n\n");
-        p->Print(*vars, "  return new $dubbo_stub$(channel, callOptions);\n");
-        p->Print("}\n\n");
-    }
-    p->Outdent();
-}
-
-static bool CompareMethodClientStreaming(const MethodDescriptor* method1,
-                                         const MethodDescriptor* method2)
-{
-  return method1->client_streaming() < method2->client_streaming();
-}
-
-// Place all method invocations into a single class to reduce memory footprint
-// on Android.
-static void PrintMethodHandlerClass(const ServiceDescriptor* service,
-                                   std::map<string, string>* vars,
-                                   Printer* p,
-                                   bool generate_nano) {
-  // Sort method ids based on client_streaming() so switch tables are compact.
-  std::vector<const MethodDescriptor*> sorted_methods(service->method_count());
-  for (int i = 0; i < service->method_count(); ++i) {
-    sorted_methods[i] = service->method(i);
-  }
-  stable_sort(sorted_methods.begin(), sorted_methods.end(),
-              CompareMethodClientStreaming);
-  for (size_t i = 0; i < sorted_methods.size(); i++) {
-    const MethodDescriptor* method = sorted_methods[i];
-    (*vars)["method_id"] = to_string(i);
-    (*vars)["method_id_name"] = MethodIdFieldName(method);
-    p->Print(
-        *vars,
-        "private static final int $method_id_name$ = $method_id$;\n");
-  }
-  p->Print("\n");
-  (*vars)["service_name"] = service->name() + "ImplBase";
-  (*vars)["dubbo_interface"] = "I" + service->name();
-  p->Print(
-      *vars,
-      "private static final class MethodHandlers<Req, Resp> implements\n"
-      "    io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,\n"
-      "    io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,\n"
-      "    io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,\n"
-      "    io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {\n"
-      "  private final $dubbo_interface$ serviceImpl;\n"
-      "  private final int methodId;\n"
-      "\n"
-      "  MethodHandlers($dubbo_interface$ serviceImpl, int methodId) {\n"
-      "    this.serviceImpl = serviceImpl;\n"
-      "    this.methodId = methodId;\n"
-      "  }\n\n");
-  p->Indent();
-  p->Print(
-      *vars,
-      "@$Override$\n"
-      "@java.lang.SuppressWarnings(\"unchecked\")\n"
-      "public void invoke(Req request, $StreamObserver$<Resp> responseObserver) {\n"
-      "  switch (methodId) {\n");
-  p->Indent();
-  p->Indent();
-
-  for (int i = 0; i < service->method_count(); ++i) {
-    const MethodDescriptor* method = service->method(i);
-    if (method->client_streaming()) {
-      continue;
-    }
-    (*vars)["method_id_name"] = MethodIdFieldName(method);
-    (*vars)["lower_method_name"] = LowerMethodName(method);
-    (*vars)["input_type"] = MessageFullJavaName(generate_nano,
-                                                method->input_type());
-    (*vars)["output_type"] = MessageFullJavaName(generate_nano,
-                                                 method->output_type());
-    p->Print(
-        *vars,
-        "case $method_id_name$:\n"
-        "  serviceImpl.$lower_method_name$(($input_type$) request,\n"
-        "      ($StreamObserver$<$output_type$>) responseObserver);\n"
-        "  break;\n");
-  }
-  p->Print("default:\n"
-           "  throw new AssertionError();\n");
-
-  p->Outdent();
-  p->Outdent();
-  p->Print("  }\n"
-           "}\n\n");
-
-  p->Print(
-      *vars,
-      "@$Override$\n"
-      "@java.lang.SuppressWarnings(\"unchecked\")\n"
-      "public $StreamObserver$<Req> invoke(\n"
-      "    $StreamObserver$<Resp> responseObserver) {\n"
-      "  switch (methodId) {\n");
-  p->Indent();
-  p->Indent();
-
-  for (int i = 0; i < service->method_count(); ++i) {
-    const MethodDescriptor* method = service->method(i);
-    if (!method->client_streaming()) {
-      continue;
-    }
-    (*vars)["method_id_name"] = MethodIdFieldName(method);
-    (*vars)["lower_method_name"] = LowerMethodName(method);
-    (*vars)["input_type"] = MessageFullJavaName(generate_nano,
-                                                method->input_type());
-    (*vars)["output_type"] = MessageFullJavaName(generate_nano,
-                                                 method->output_type());
-    p->Print(
-        *vars,
-        "case $method_id_name$:\n"
-        "  return ($StreamObserver$<Req>) serviceImpl.$lower_method_name$(\n"
-        "      ($StreamObserver$<$output_type$>) responseObserver);\n");
-  }
-  p->Print("default:\n"
-           "  throw new AssertionError();\n");
-
-  p->Outdent();
-  p->Outdent();
-  p->Print("  }\n"
-           "}\n");
-
-
-  p->Outdent();
-  p->Print("}\n\n");
-}
-
-static void PrintGetServiceDescriptorMethod(const ServiceDescriptor* service,
-                                    std::map<string, string>* vars,
-                                    Printer* p,
-                                    ProtoFlavor flavor) {
-   (*vars)["service_name"] = service->name();
-
-
-   if (flavor == ProtoFlavor::NORMAL) {
-     (*vars)["proto_base_descriptor_supplier"] = service->name() + "BaseDescriptorSupplier";
-     (*vars)["proto_file_descriptor_supplier"] = service->name() + "FileDescriptorSupplier";
-     (*vars)["proto_method_descriptor_supplier"] = service->name() + "MethodDescriptorSupplier";
-     (*vars)["proto_class_name"] = google::protobuf::compiler::java::ClassName(service->file());
-     p->Print(
-         *vars,
-         "private static abstract class $proto_base_descriptor_supplier$\n"
-         "    implements $ProtoFileDescriptorSupplier$, $ProtoServiceDescriptorSupplier$ {\n"
-         "  $proto_base_descriptor_supplier$() {}\n"
-         "\n"
-         "  @$Override$\n"
-         "  public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {\n"
-         "    return $proto_class_name$.getDescriptor();\n"
-         "  }\n"
-         "\n"
-         "  @$Override$\n"
-         "  public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {\n"
-         "    return getFileDescriptor().findServiceByName(\"$service_name$\");\n"
-         "  }\n"
-         "}\n"
-         "\n"
-         "private static final class $proto_file_descriptor_supplier$\n"
-         "    extends $proto_base_descriptor_supplier$ {\n"
-         "  $proto_file_descriptor_supplier$() {}\n"
-         "}\n"
-         "\n"
-         "private static final class $proto_method_descriptor_supplier$\n"
-         "    extends $proto_base_descriptor_supplier$\n"
-         "    implements $ProtoMethodDescriptorSupplier$ {\n"
-         "  private final String methodName;\n"
-         "\n"
-         "  $proto_method_descriptor_supplier$(String methodName) {\n"
-         "    this.methodName = methodName;\n"
-         "  }\n"
-         "\n"
-         "  @$Override$\n"
-         "  public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {\n"
-         "    return getServiceDescriptor().findMethodByName(methodName);\n"
-         "  }\n"
-         "}\n\n");
-   }
-
-   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,
-       "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");
- }
-
-static void PrintBindServiceMethodBody(const ServiceDescriptor* service,
-                                   std::map<string, string>* vars,
-                                   Printer* p,
-                                   bool generate_nano) {
-  (*vars)["service_name"] = service->name();
-  p->Indent();
-  p->Print(*vars,
-           "return "
-           "$ServerServiceDefinition$.builder(getServiceDescriptor())\n");
-  p->Indent();
-  p->Indent();
-  for (int i = 0; i < service->method_count(); ++i) {
-    const MethodDescriptor* method = service->method(i);
-    (*vars)["lower_method_name"] = LowerMethodName(method);
-    (*vars)["method_method_name"] = MethodPropertiesGetterName(method);
-    (*vars)["input_type"] = MessageFullJavaName(generate_nano,
-                                                method->input_type());
-    (*vars)["output_type"] = MessageFullJavaName(generate_nano,
-                                                 method->output_type());
-    (*vars)["method_id_name"] = MethodIdFieldName(method);
-    bool client_streaming = method->client_streaming();
-    bool server_streaming = method->server_streaming();
-    if (client_streaming) {
-      if (server_streaming) {
-        (*vars)["calls_method"] = "asyncBidiStreamingCall";
-      } else {
-        (*vars)["calls_method"] = "asyncClientStreamingCall";
-      }
-    } else {
-      if (server_streaming) {
-        (*vars)["calls_method"] = "asyncServerStreamingCall";
-      } else {
-        (*vars)["calls_method"] = "asyncUnaryCall";
-      }
-    }
-    p->Print(*vars, ".addMethod(\n");
-    p->Indent();
-    p->Print(
-        *vars,
-        "$method_method_name$(),\n"
-        "$calls_method$(\n");
-    p->Indent();
-    p->Print(
-        *vars,
-        "new MethodHandlers<\n"
-        "  $input_type$,\n"
-        "  $output_type$>(\n"
-        "    $instance$, $method_id_name$)))\n");
-    p->Outdent();
-    p->Outdent();
-  }
-  p->Print(".build();\n");
-  p->Outdent();
-  p->Outdent();
-  p->Outdent();
-}
-
-static void PrintService(const ServiceDescriptor* service,
-                         std::map<string, string>* vars,
-                         Printer* p,
-                         ProtoFlavor flavor,
-                         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();
-  p->Print(
-      *vars,
-      "private $service_class_name$() {}\n\n");
-
-  p->Print(
-      *vars,
-      "public static final String SERVICE_NAME = "
-      "\"$Package$$service_name$\";\n\n");
-
-  PrintMethodFields(service, vars, p, flavor);
-
-  // TODO(nmittler): Replace with WriteDocComment once included by protobuf distro.
-  GrpcWriteDocComment(p, " Creates a new async stub that supports all call types for the service");
-  p->Print(
-      *vars,
-      "public static $service_name$Stub newStub($Channel$ channel) {\n");
-  p->Indent();
-  p->Print(
-      *vars,
-      "return new $service_name$Stub(channel);\n");
-  p->Outdent();
-  p->Print("}\n\n");
-
-  // TODO(nmittler): Replace with WriteDocComment once included by protobuf distro.
-  GrpcWriteDocComment(p, " Creates a new blocking-style stub that supports unary and streaming "
-                         "output calls on the service");
-  p->Print(
-      *vars,
-      "public static $service_name$BlockingStub newBlockingStub(\n"
-      "    $Channel$ channel) {\n");
-  p->Indent();
-  p->Print(
-      *vars,
-      "return new $service_name$BlockingStub(channel);\n");
-  p->Outdent();
-  p->Print("}\n\n");
-
-  // TODO(nmittler): Replace with WriteDocComment once included by protobuf distro.
-  GrpcWriteDocComment(p, " Creates a new ListenableFuture-style stub that supports unary calls "
-                         "on the service");
-  p->Print(
-      *vars,
-      "public static $service_name$FutureStub newFutureStub(\n"
-      "    $Channel$ channel) {\n");
-  p->Indent();
-  p->Print(
-      *vars,
-      "return new $service_name$FutureStub(channel);\n");
-  p->Outdent();
-  p->Print("}\n\n");
-
-  bool generate_nano = flavor == ProtoFlavor::NANO;
-//  PrintStub(service, vars, p, ABSTRACT_CLASS, generate_nano);
-  PrintStub(service, vars, p, ASYNC_CLIENT_IMPL, generate_nano);
-  PrintStub(service, vars, p, BLOCKING_CLIENT_IMPL, generate_nano);
-  PrintStub(service, vars, p, FUTURE_CLIENT_IMPL, generate_nano);
-
-  PrintImplBase(service, vars, p, generate_nano);
-  PrintDubboInterface(service, vars, p, true, generate_nano);
-  PrintDubboInterface(service, vars, p, false, generate_nano);
-
-  PrintMethodHandlerClass(service, vars, p, generate_nano);
-  PrintGetServiceDescriptorMethod(service, vars, p, flavor);
-  p->Outdent();
-  p->Print("}\n");
-}
-
-void PrintImports(Printer* p, bool generate_nano) {
-  p->Print(
-      "import static "
-      "io.grpc.MethodDescriptor.generateFullMethodName;\n"
-      "import static "
-      "io.grpc.stub.ClientCalls.asyncBidiStreamingCall;\n"
-      "import static "
-      "io.grpc.stub.ClientCalls.asyncClientStreamingCall;\n"
-      "import static "
-      "io.grpc.stub.ClientCalls.asyncServerStreamingCall;\n"
-      "import static "
-      "io.grpc.stub.ClientCalls.asyncUnaryCall;\n"
-      "import static "
-      "io.grpc.stub.ClientCalls.blockingServerStreamingCall;\n"
-      "import static "
-      "io.grpc.stub.ClientCalls.blockingUnaryCall;\n"
-      "import static "
-      "io.grpc.stub.ClientCalls.futureUnaryCall;\n"
-      "import static "
-      "io.grpc.stub.ServerCalls.asyncBidiStreamingCall;\n"
-      "import static "
-      "io.grpc.stub.ServerCalls.asyncClientStreamingCall;\n"
-      "import static "
-      "io.grpc.stub.ServerCalls.asyncServerStreamingCall;\n"
-      "import static "
-      "io.grpc.stub.ServerCalls.asyncUnaryCall;\n"
-      "import static "
-      "io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;\n"
-      "import static "
-      "io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;\n\n");
-  if (generate_nano) {
-    p->Print("import java.io.IOException;\n\n");
-  }
-}
-
-void GenerateService(const ServiceDescriptor* service,
-                     google::protobuf::io::ZeroCopyOutputStream* out,
-                     ProtoFlavor flavor,
-                     bool disable_version) {
-  // All non-generated classes must be referred by fully qualified names to
-  // avoid collision with generated classes.
-  std::map<string, string> vars;
-  vars["String"] = "java.lang.String";
-  vars["Deprecated"] = "java.lang.Deprecated";
-  vars["Override"] = "java.lang.Override";
-  vars["Channel"] = "io.grpc.Channel";
-  vars["CallOptions"] = "io.grpc.CallOptions";
-  vars["MethodType"] = "io.grpc.MethodDescriptor.MethodType";
-  vars["ServerMethodDefinition"] =
-      "io.grpc.ServerMethodDefinition";
-  vars["BindableService"] = "io.grpc.BindableService";
-  vars["ServerServiceDefinition"] =
-      "io.grpc.ServerServiceDefinition";
-  vars["ServiceDescriptor"] =
-      "io.grpc.ServiceDescriptor";
-  vars["ProtoFileDescriptorSupplier"] =
-      "io.grpc.protobuf.ProtoFileDescriptorSupplier";
-  vars["ProtoServiceDescriptorSupplier"] =
-      "io.grpc.protobuf.ProtoServiceDescriptorSupplier";
-  vars["ProtoMethodDescriptorSupplier"] =
-      "io.grpc.protobuf.ProtoMethodDescriptorSupplier";
-  vars["AbstractStub"] = "io.grpc.stub.AbstractStub";
-  vars["RpcMethod"] = "io.grpc.stub.annotations.RpcMethod";
-  vars["MethodDescriptor"] = "io.grpc.MethodDescriptor";
-  vars["NanoUtils"] = "io.grpc.protobuf.nano.NanoUtils";
-  vars["StreamObserver"] = "io.grpc.stub.StreamObserver";
-  vars["Iterator"] = "java.util.Iterator";
-  vars["Generated"] = "javax.annotation.Generated";
-  vars["ListenableFuture"] = "com.google.common.util.concurrent.ListenableFuture";
-  vars["default_method_body"] = "   throw new UnsupportedOperationException(\""
-             "No need to override this method, extend XxxImplBase and override "
-             "all methods it allows.\");";
-
-  Printer printer(out, '$');
-  string package_name = ServiceJavaPackage(service->file(),
-                                           flavor == ProtoFlavor::NANO);
-  if (!package_name.empty()) {
-    printer.Print(
-        "package $package_name$;\n\n",
-        "package_name", package_name);
-  }
-
-  PrintImports(&printer, flavor == ProtoFlavor::NANO);
-
-  // 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, flavor, disable_version);
-}
-
-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() + "Grpc";
-}
-
-}  // namespace java_grpc_generator
diff --git a/compiler/src/java_plugin/cpp/java_generator.h b/compiler/src/java_plugin/cpp/java_generator.h
deleted file mode 100644
index 7106c54..0000000
--- a/compiler/src/java_plugin/cpp/java_generator.h
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef NET_GRPC_COMPILER_JAVA_GENERATOR_H_
-#define NET_GRPC_COMPILER_JAVA_GENERATOR_H_
-
-#include <stdlib.h>  // for abort()
-#include <iostream>
-#include <string>
-
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.h>
-
-class LogHelper {
-  std::ostream* os;
-
- public:
-  LogHelper(std::ostream* os) : os(os) {}
-  ~LogHelper() {
-    *os << std::endl;
-    ::abort();
-  }
-  std::ostream& get_os() {
-    return *os;
-  }
-};
-
-// Abort the program after logging the mesage if the given condition is not
-// true. Otherwise, do nothing.
-#define GRPC_CODEGEN_CHECK(x) !(x) && LogHelper(&std::cerr).get_os() \
-                             << "CHECK FAILED: " << __FILE__ << ":" \
-                             << __LINE__ << ": "
-
-// Abort the program after logging the mesage.
-#define GRPC_CODEGEN_FAIL GRPC_CODEGEN_CHECK(false)
-
-using namespace std;
-
-namespace java_grpc_generator {
-
-enum ProtoFlavor {
-  NORMAL, LITE, NANO
-};
-
-// Returns the package name of the gRPC 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_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
deleted file mode 100644
index c8af98c..0000000
--- a/compiler/src/java_plugin/cpp/java_plugin.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-// Generates Java gRPC service interface out of Protobuf IDL.
-//
-// This is a Proto2 compiler plugin.  See net/proto2/compiler/proto/plugin.proto
-// and net/proto2/compiler/public/plugin.h for more information on plugins.
-
-#include <memory>
-
-#include "java_generator.h"
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/plugin.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-
-static string JavaPackageToDir(const string& package_name) {
-  string package_dir = package_name;
-  for (size_t i = 0; i < package_dir.size(); ++i) {
-    if (package_dir[i] == '.') {
-      package_dir[i] = '/';
-    }
-  }
-  if (!package_dir.empty()) package_dir += "/";
-  return package_dir;
-}
-
-class JavaGrpcGenerator : public google::protobuf::compiler::CodeGenerator {
- public:
-
-  JavaGrpcGenerator() {}
-  virtual ~JavaGrpcGenerator() {}
-
-  virtual bool Generate(const google::protobuf::FileDescriptor* file,
-                        const string& parameter,
-                        google::protobuf::compiler::GeneratorContext* context,
-                        string* error) const {
-    std::vector<std::pair<string, string> > options;
-    google::protobuf::compiler::ParseGeneratorParameter(parameter, &options);
-    string DUBBO("dubbo");
-
-    if (DUBBO == parameter) {
-        string package_name = java_dubbo_generator::ServiceJavaPackage(
-            file, false);
-        string package_filename = JavaPackageToDir(package_name);
-        for (int i = 0; i < file->service_count(); ++i) {
-          const google::protobuf::ServiceDescriptor* service = file->service(i);
-          string filename = package_filename
-              + java_dubbo_generator::ServiceClassName(service) + ".java";
-          std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
-              context->Open(filename));
-          java_dubbo_generator::GenerateService(
-              service, output.get(), java_dubbo_generator::ProtoFlavor::NORMAL, false);
-        }
-    } else {
-        java_grpc_generator::ProtoFlavor flavor =
-            java_grpc_generator::ProtoFlavor::NORMAL;
-
-        bool disable_version = false;
-        for (size_t i = 0; i < options.size(); i++) {
-          if (options[i].first == "nano") {
-            flavor = java_grpc_generator::ProtoFlavor::NANO;
-          } else if (options[i].first == "lite") {
-            flavor = java_grpc_generator::ProtoFlavor::LITE;
-          } else if (options[i].first == "noversion") {
-            disable_version = true;
-          }
-        }
-
-        string package_name = java_grpc_generator::ServiceJavaPackage(
-            file, flavor == java_grpc_generator::ProtoFlavor::NANO);
-        string package_filename = JavaPackageToDir(package_name);
-        for (int i = 0; i < file->service_count(); ++i) {
-          const google::protobuf::ServiceDescriptor* service = file->service(i);
-          string filename = package_filename
-              + java_grpc_generator::ServiceClassName(service) + ".java";
-          std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
-              context->Open(filename));
-          java_grpc_generator::GenerateService(
-              service, output.get(), flavor, disable_version);
-        }
-    }
-    return true;
-  }
-};
-
-int main(int argc, char* argv[]) {
-  JavaGrpcGenerator generator;
-  return google::protobuf::compiler::PluginMain(argc, argv, &generator);
-}
diff --git a/compiler/src/main/java/org/apache/dubbo/gen/AbstractGenerator.java b/compiler/src/main/java/org/apache/dubbo/gen/AbstractGenerator.java
new file mode 100644
index 0000000..3e8dee1
--- /dev/null
+++ b/compiler/src/main/java/org/apache/dubbo/gen/AbstractGenerator.java
@@ -0,0 +1,293 @@
+/*
+ * 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.gen;
+
+import com.google.common.base.Strings;
+import com.google.common.html.HtmlEscapers;
+import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
+import com.google.protobuf.DescriptorProtos.FileOptions;
+import com.google.protobuf.DescriptorProtos.MethodDescriptorProto;
+import com.google.protobuf.DescriptorProtos.ServiceDescriptorProto;
+import com.google.protobuf.DescriptorProtos.SourceCodeInfo.Location;
+import com.google.protobuf.compiler.PluginProtos;
+import com.salesforce.jprotoc.Generator;
+import com.salesforce.jprotoc.GeneratorException;
+import com.salesforce.jprotoc.ProtoTypeMap;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public abstract class AbstractGenerator extends Generator {
+
+    private static final int SERVICE_NUMBER_OF_PATHS = 2;
+    private static final int METHOD_NUMBER_OF_PATHS = 4;
+
+    protected abstract String getClassPrefix();
+
+    protected abstract String getClassSuffix();
+
+    private String getServiceJavaDocPrefix() {
+        return "    ";
+    }
+
+    private String getMethodJavaDocPrefix() {
+        return "        ";
+    }
+
+    @Override
+    public List<PluginProtos.CodeGeneratorResponse.File> generateFiles(PluginProtos.CodeGeneratorRequest request) throws GeneratorException {
+        final ProtoTypeMap typeMap = ProtoTypeMap.of(request.getProtoFileList());
+
+        List<FileDescriptorProto> protosToGenerate = request.getProtoFileList().stream()
+                .filter(protoFile -> request.getFileToGenerateList().contains(protoFile.getName()))
+                .collect(Collectors.toList());
+
+        List<ServiceContext> services = findServices(protosToGenerate, typeMap);
+        return generateFiles(services);
+    }
+
+    private List<ServiceContext> findServices(List<FileDescriptorProto> protos, ProtoTypeMap typeMap) {
+        List<ServiceContext> contexts = new ArrayList<>();
+
+        protos.forEach(fileProto -> {
+            for (int serviceNumber = 0; serviceNumber < fileProto.getServiceCount(); serviceNumber++) {
+                ServiceContext serviceContext = buildServiceContext(
+                    fileProto.getService(serviceNumber),
+                    typeMap,
+                    fileProto.getSourceCodeInfo().getLocationList(),
+                    serviceNumber
+                );
+                serviceContext.protoName = fileProto.getName();
+                serviceContext.packageName = extractPackageName(fileProto);
+                contexts.add(serviceContext);
+            }
+        });
+
+        return contexts;
+    }
+
+    private String extractPackageName(FileDescriptorProto proto) {
+        FileOptions options = proto.getOptions();
+        if (options != null) {
+            String javaPackage = options.getJavaPackage();
+            if (!Strings.isNullOrEmpty(javaPackage)) {
+                return javaPackage;
+            }
+        }
+
+        return Strings.nullToEmpty(proto.getPackage());
+    }
+
+    private ServiceContext buildServiceContext(ServiceDescriptorProto serviceProto, ProtoTypeMap typeMap, List<Location> locations, int serviceNumber) {
+        ServiceContext serviceContext = new ServiceContext();
+        serviceContext.fileName = getClassPrefix() + serviceProto.getName() + getClassSuffix() + ".java";
+        serviceContext.className = getClassPrefix() + serviceProto.getName() + getClassSuffix();
+        serviceContext.serviceName = serviceProto.getName();
+        serviceContext.deprecated = serviceProto.getOptions() != null && serviceProto.getOptions().getDeprecated();
+
+        List<Location> allLocationsForService = locations.stream()
+                .filter(location ->
+                    location.getPathCount() >= 2 &&
+                       location.getPath(0) == FileDescriptorProto.SERVICE_FIELD_NUMBER &&
+                       location.getPath(1) == serviceNumber
+                )
+                .collect(Collectors.toList());
+
+        Location serviceLocation = allLocationsForService.stream()
+                .filter(location -> location.getPathCount() == SERVICE_NUMBER_OF_PATHS)
+                .findFirst()
+                .orElseGet(Location::getDefaultInstance);
+        serviceContext.javaDoc = getJavaDoc(getComments(serviceLocation), getServiceJavaDocPrefix());
+
+        for (int methodNumber = 0; methodNumber < serviceProto.getMethodCount(); methodNumber++) {
+            MethodContext methodContext = buildMethodContext(
+                serviceProto.getMethod(methodNumber),
+                typeMap,
+                locations,
+                methodNumber
+            );
+
+            serviceContext.methods.add(methodContext);
+            serviceContext.methodTypes.add(methodContext.inputType);
+            serviceContext.methodTypes.add(methodContext.outputType);
+        }
+        return serviceContext;
+    }
+
+    private MethodContext buildMethodContext(MethodDescriptorProto methodProto, ProtoTypeMap typeMap, List<Location> locations, int methodNumber) {
+        MethodContext methodContext = new MethodContext();
+        methodContext.methodName = lowerCaseFirst(methodProto.getName());
+        methodContext.inputType = typeMap.toJavaTypeName(methodProto.getInputType());
+        methodContext.outputType = typeMap.toJavaTypeName(methodProto.getOutputType());
+        methodContext.deprecated = methodProto.getOptions() != null && methodProto.getOptions().getDeprecated();
+        methodContext.isManyInput = methodProto.getClientStreaming();
+        methodContext.isManyOutput = methodProto.getServerStreaming();
+        methodContext.methodNumber = methodNumber;
+
+        Location methodLocation = locations.stream()
+                .filter(location ->
+                    location.getPathCount() == METHOD_NUMBER_OF_PATHS &&
+                        location.getPath(METHOD_NUMBER_OF_PATHS - 1) == methodNumber
+                )
+                .findFirst()
+                .orElseGet(Location::getDefaultInstance);
+        methodContext.javaDoc = getJavaDoc(getComments(methodLocation), getMethodJavaDocPrefix());
+
+        if (!methodProto.getClientStreaming() && !methodProto.getServerStreaming()) {
+            methodContext.reactiveCallsMethodName = "oneToOne";
+            methodContext.grpcCallsMethodName = "asyncUnaryCall";
+        }
+        if (!methodProto.getClientStreaming() && methodProto.getServerStreaming()) {
+            methodContext.reactiveCallsMethodName = "oneToMany";
+            methodContext.grpcCallsMethodName = "asyncServerStreamingCall";
+        }
+        if (methodProto.getClientStreaming() && !methodProto.getServerStreaming()) {
+            methodContext.reactiveCallsMethodName = "manyToOne";
+            methodContext.grpcCallsMethodName = "asyncClientStreamingCall";
+        }
+        if (methodProto.getClientStreaming() && methodProto.getServerStreaming()) {
+            methodContext.reactiveCallsMethodName = "manyToMany";
+            methodContext.grpcCallsMethodName = "asyncBidiStreamingCall";
+        }
+        return methodContext;
+    }
+
+    private String lowerCaseFirst(String s) {
+        return Character.toLowerCase(s.charAt(0)) + s.substring(1);
+    }
+
+    private List<PluginProtos.CodeGeneratorResponse.File> generateFiles(List<ServiceContext> services) {
+        return services.stream()
+                .map(this::buildFile)
+                .collect(Collectors.toList());
+    }
+
+    private PluginProtos.CodeGeneratorResponse.File buildFile(ServiceContext context) {
+        String content = applyTemplate(getClassPrefix() + getClassSuffix() + "Stub.mustache", context);
+        return PluginProtos.CodeGeneratorResponse.File
+                .newBuilder()
+                .setName(absoluteFileName(context))
+                .setContent(content)
+                .build();
+    }
+
+    private String absoluteFileName(ServiceContext ctx) {
+        String dir = ctx.packageName.replace('.', '/');
+        if (Strings.isNullOrEmpty(dir)) {
+            return ctx.fileName;
+        } else {
+            return dir + "/" + ctx.fileName;
+        }
+    }
+
+    private String getComments(Location location) {
+        return location.getLeadingComments().isEmpty() ? location.getTrailingComments() : location.getLeadingComments();
+    }
+
+    private String getJavaDoc(String comments, String prefix) {
+        if (!comments.isEmpty()) {
+            StringBuilder builder = new StringBuilder("/**\n")
+                    .append(prefix).append(" * <pre>\n");
+            Arrays.stream(HtmlEscapers.htmlEscaper().escape(comments).split("\n"))
+                    .map(line -> line.replace("*/", "&#42;&#47;").replace("*", "&#42;"))
+                    .forEach(line -> builder.append(prefix).append(" * ").append(line).append("\n"));
+            builder
+                    .append(prefix).append(" * </pre>\n")
+                    .append(prefix).append(" */");
+            return builder.toString();
+        }
+        return null;
+    }
+
+    /**
+     * Template class for proto Service objects.
+     */
+    private class ServiceContext {
+        // CHECKSTYLE DISABLE VisibilityModifier FOR 8 LINES
+        public String fileName;
+        public String protoName;
+        public String packageName;
+        public String className;
+        public String serviceName;
+        public boolean deprecated;
+        public String javaDoc;
+        public List<MethodContext> methods = new ArrayList<>();
+
+        public Set<String> methodTypes = new HashSet<>();
+
+        public List<MethodContext> unaryRequestMethods() {
+            return methods.stream().filter(m -> !m.isManyInput).collect(Collectors.toList());
+        }
+
+        public List<MethodContext> unaryMethods() {
+            return methods.stream().filter(m -> (!m.isManyInput && !m.isManyOutput)).collect(Collectors.toList());
+        }
+
+        public List<MethodContext> serverStreamingMethods() {
+            return methods.stream().filter(m -> !m.isManyInput && m.isManyOutput).collect(Collectors.toList());
+        }
+
+        public List<MethodContext> biStreamingMethods() {
+            return methods.stream().filter(m -> m.isManyInput).collect(Collectors.toList());
+        }
+    }
+
+    /**
+     * Template class for proto RPC objects.
+     */
+    private class MethodContext {
+        // CHECKSTYLE DISABLE VisibilityModifier FOR 10 LINES
+        public String methodName;
+        public String inputType;
+        public String outputType;
+        public boolean deprecated;
+        public boolean isManyInput;
+        public boolean isManyOutput;
+        public String reactiveCallsMethodName;
+        public String grpcCallsMethodName;
+        public int methodNumber;
+        public String javaDoc;
+
+        // This method mimics the upper-casing method ogf gRPC to ensure compatibility
+        // See https://github.com/grpc/grpc-java/blob/v1.8.0/compiler/src/java_plugin/cpp/java_generator.cpp#L58
+        public String methodNameUpperUnderscore() {
+            StringBuilder s = new StringBuilder();
+            for (int i = 0; i < methodName.length(); i++) {
+                char c = methodName.charAt(i);
+                s.append(Character.toUpperCase(c));
+                if ((i < methodName.length() - 1) && Character.isLowerCase(c) && Character.isUpperCase(methodName.charAt(i + 1))) {
+                    s.append('_');
+                }
+            }
+            return s.toString();
+        }
+
+        public String methodNamePascalCase() {
+            String mn = methodName.replace("_", "");
+            return String.valueOf(Character.toUpperCase(mn.charAt(0))) + mn.substring(1);
+        }
+
+        public String methodNameCamelCase() {
+            String mn = methodName.replace("_", "");
+            return String.valueOf(Character.toLowerCase(mn.charAt(0))) + mn.substring(1);
+        }
+    }
+}
diff --git a/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java b/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java
new file mode 100644
index 0000000..1c35f0a
--- /dev/null
+++ b/compiler/src/main/java/org/apache/dubbo/gen/dubbo/DubboGenerator.java
@@ -0,0 +1,42 @@
+/*
+ * 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.gen.dubbo;
+
+import org.apache.dubbo.gen.AbstractGenerator;
+
+import com.salesforce.jprotoc.ProtocPlugin;
+
+public class DubboGenerator extends AbstractGenerator {
+
+    public static void main(String[] args) {
+        if (args.length == 0) {
+            ProtocPlugin.generate(new DubboGenerator());
+        } else {
+            ProtocPlugin.debug(new DubboGenerator(), args[0]);
+        }
+    }
+
+    @Override
+    protected String getClassPrefix() {
+        return "";
+    }
+
+    @Override
+    protected String getClassSuffix() {
+        return "Dubbo";
+    }
+}
\ No newline at end of file
diff --git a/compiler/src/main/java/org/apache/dubbo/gen/grpc/DubboGrpcGenerator.java b/compiler/src/main/java/org/apache/dubbo/gen/grpc/DubboGrpcGenerator.java
new file mode 100644
index 0000000..dafdd5a
--- /dev/null
+++ b/compiler/src/main/java/org/apache/dubbo/gen/grpc/DubboGrpcGenerator.java
@@ -0,0 +1,41 @@
+/*
+ * 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.gen.grpc;
+
+import org.apache.dubbo.gen.AbstractGenerator;
+
+import com.salesforce.jprotoc.ProtocPlugin;
+
+public class DubboGrpcGenerator extends AbstractGenerator {
+
+    public static void main(String[] args) {
+        if (args.length == 0) {
+            ProtocPlugin.generate(new DubboGrpcGenerator());
+        } else {
+            ProtocPlugin.debug(new DubboGrpcGenerator(), args[0]);
+        }
+    }
+
+    @Override
+    protected String getClassPrefix() {
+        return "Dubbo";
+    }
+
+    protected String getClassSuffix() {
+        return "Grpc";
+    }
+}
diff --git a/compiler/src/main/java/org/apache/dubbo/gen/grpc/reactive/ReactorDubboGrpcGenerator.java b/compiler/src/main/java/org/apache/dubbo/gen/grpc/reactive/ReactorDubboGrpcGenerator.java
new file mode 100644
index 0000000..dd9520b
--- /dev/null
+++ b/compiler/src/main/java/org/apache/dubbo/gen/grpc/reactive/ReactorDubboGrpcGenerator.java
@@ -0,0 +1,42 @@
+/*
+ * 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.gen.grpc.reactive;
+
+import org.apache.dubbo.gen.AbstractGenerator;
+
+import com.salesforce.jprotoc.ProtocPlugin;
+
+public class ReactorDubboGrpcGenerator extends AbstractGenerator {
+
+    @Override
+    protected String getClassPrefix() {
+        return "ReactorDubbo";
+    }
+
+    @Override
+    protected String getClassSuffix() {
+        return "Grpc";
+    }
+
+    public static void main(String[] args) {
+        if (args.length == 0) {
+            ProtocPlugin.generate(new ReactorDubboGrpcGenerator());
+        } else {
+            ProtocPlugin.debug(new ReactorDubboGrpcGenerator(), args[0]);
+        }
+    }
+}
diff --git a/compiler/src/main/java/org/apache/dubbo/gen/grpc/reactive/RxDubboGrpcGenerator.java b/compiler/src/main/java/org/apache/dubbo/gen/grpc/reactive/RxDubboGrpcGenerator.java
new file mode 100644
index 0000000..028332a
--- /dev/null
+++ b/compiler/src/main/java/org/apache/dubbo/gen/grpc/reactive/RxDubboGrpcGenerator.java
@@ -0,0 +1,41 @@
+/*
+ * 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.gen.grpc.reactive;
+
+import org.apache.dubbo.gen.AbstractGenerator;
+
+import com.salesforce.jprotoc.ProtocPlugin;
+
+public class RxDubboGrpcGenerator extends AbstractGenerator {
+    @Override
+    protected String getClassPrefix() {
+        return "RxDubbo";
+    }
+
+    @Override
+    protected String getClassSuffix() {
+        return "Grpc";
+    }
+
+    public static void main(String[] args) {
+        if (args.length == 0) {
+            ProtocPlugin.generate(new RxDubboGrpcGenerator());
+        } else {
+            ProtocPlugin.debug(new RxDubboGrpcGenerator(), args[0]);
+        }
+    }
+}
diff --git a/compiler/src/main/resources/DubboGrpcStub.mustache b/compiler/src/main/resources/DubboGrpcStub.mustache
new file mode 100644
index 0000000..a02d0c4
--- /dev/null
+++ b/compiler/src/main/resources/DubboGrpcStub.mustache
@@ -0,0 +1,312 @@
+{{#packageName}}
+    package {{packageName}};
+{{/packageName}}
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.config.ReferenceConfigBase;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
+import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
+
+import static {{packageName}}.{{serviceName}}Grpc.getServiceDescriptor;
+import static io.grpc.stub.ServerCalls.asyncUnaryCall;
+import static io.grpc.stub.ServerCalls.asyncServerStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncClientStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncUnimplementedStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall;
+
+{{#deprecated}}
+    @java.lang.Deprecated
+{{/deprecated}}
+@javax.annotation.Generated(
+value = "by DubboGrpc generator",
+comments = "Source: {{protoName}}")
+public final class {{className}} {
+private {{className}}() {}
+
+public static class Dubbo{{serviceName}}Stub implements I{{serviceName}} {
+
+protected URL url;
+protected ReferenceConfigBase<?> referenceConfig;
+
+protected {{serviceName}}Grpc.{{serviceName}}BlockingStub blockingStub;
+protected {{serviceName}}Grpc.{{serviceName}}FutureStub futureStub;
+protected {{serviceName}}Grpc.{{serviceName}}Stub stub;
+
+public Dubbo{{serviceName}}Stub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
+this.url = url;
+this.referenceConfig = referenceConfig;
+
+blockingStub = {{serviceName}}Grpc.newBlockingStub(channel).build(channel, callOptions);
+futureStub = {{serviceName}}Grpc.newFutureStub(channel).build(channel, callOptions);
+stub = {{serviceName}}Grpc.newStub(channel).build(channel, callOptions);
+}
+
+{{#unaryMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{outputType}} {{methodName}}({{inputType}} request) {
+    return blockingStub
+    .withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS)
+    .{{methodName}}(request);
+    }
+
+    public com.google.common.util.concurrent.ListenableFuture<{{outputType}}> {{methodName}}Async({{inputType}} request) {
+    return futureStub
+    .withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS)
+    .{{methodName}}(request);
+    }
+
+    public void {{methodName}}({{inputType}} request, io.grpc.stub.StreamObserver<{{outputType}}> responseObserver){
+    stub
+    .withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS)
+    .{{methodName}}(request, responseObserver);
+    }
+
+{{/unaryMethods}}
+{{#serverStreamingMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public java.util.Iterator<{{outputType}}> {{methodName}}({{inputType}} request) {
+    return blockingStub
+    .withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS)
+    .{{methodName}}(request);
+    }
+
+    public void {{methodName}}({{inputType}} request, io.grpc.stub.StreamObserver<{{outputType}}> responseObserver) {
+    stub
+    .withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS)
+    .{{methodName}}(request, responseObserver);
+    }
+
+{{/serverStreamingMethods}}
+{{#biStreamingMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public io.grpc.stub.StreamObserver<{{inputType}}> {{methodName}}(io.grpc.stub.StreamObserver<{{outputType}}> responseObserver) {
+    return stub
+    .withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS)
+    .{{methodName}}(responseObserver);
+    }
+{{/biStreamingMethods}}
+}
+
+public static Dubbo{{serviceName}}Stub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
+return new Dubbo{{serviceName}}Stub(channel, callOptions, url, referenceConfig);
+}
+
+public interface I{{serviceName}} {
+{{#unaryMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    default public {{outputType}} {{methodName}}({{inputType}} request) {
+    throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
+    }
+
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    default public com.google.common.util.concurrent.ListenableFuture<{{outputType}}> {{methodName}}Async({{inputType}} request) {
+    throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
+    }
+
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public void {{methodName}}({{inputType}} request, io.grpc.stub.StreamObserver<{{outputType}}> responseObserver);
+
+{{/unaryMethods}}
+{{#serverStreamingMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    default public java.util.Iterator<{{outputType}}> {{methodName}}({{inputType}} request) {
+    throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
+    }
+
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public void {{methodName}}({{inputType}} request, io.grpc.stub.StreamObserver<{{outputType}}> responseObserver);
+
+{{/serverStreamingMethods}}
+{{#biStreamingMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public io.grpc.stub.StreamObserver<{{inputType}}> {{methodName}}(io.grpc.stub.StreamObserver<{{outputType}}> responseObserver);
+
+{{/biStreamingMethods}}
+}
+
+{{#javaDoc}}
+    {{{javaDoc}}}
+{{/javaDoc}}
+public static abstract class {{serviceName}}ImplBase implements io.grpc.BindableService, I{{serviceName}} {
+
+private I{{serviceName}} proxiedImpl;
+
+public final void setProxiedImpl(I{{serviceName}} proxiedImpl) {
+this.proxiedImpl = proxiedImpl;
+}
+
+{{#unaryMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    @java.lang.Override
+    public final {{outputType}} {{methodName}}({{inputType}} request) {
+    throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
+    }
+
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    @java.lang.Override
+    public final com.google.common.util.concurrent.ListenableFuture<{{outputType}}> {{methodName}}Async({{inputType}} request) {
+    throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
+    }
+
+{{/unaryMethods}}
+{{#serverStreamingMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    @java.lang.Override
+    public final java.util.Iterator<{{outputType}}> {{methodName}}({{inputType}} request) {
+    throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
+    }
+
+{{/serverStreamingMethods}}
+{{#methods}}
+    {{#isManyInput}}
+        public io.grpc.stub.StreamObserver<{{inputType}}> {{methodName}}(
+        io.grpc.stub.StreamObserver<{{outputType}}> responseObserver) {
+        return asyncUnimplementedStreamingCall({{packageName}}.{{serviceName}}Grpc.get{{methodNamePascalCase}}Method(), responseObserver);
+        }
+    {{/isManyInput}}{{^isManyInput}}
+        public void {{methodName}}({{inputType}} request,
+        io.grpc.stub.StreamObserver<{{outputType}}> responseObserver) {
+        asyncUnimplementedUnaryCall({{packageName}}.{{serviceName}}Grpc.get{{methodNamePascalCase}}Method(), responseObserver);
+        }
+    {{/isManyInput}}
+{{/methods}}
+
+@java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
+return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
+{{#methods}}
+    .addMethod(
+    {{packageName}}.{{serviceName}}Grpc.get{{methodNamePascalCase}}Method(),
+    {{grpcCallsMethodName}}(
+    new MethodHandlers<
+    {{inputType}},
+    {{outputType}}>(
+    proxiedImpl, METHODID_{{methodNameUpperUnderscore}})))
+{{/methods}}
+.build();
+}
+}
+{{#methods}}
+    private static final int METHODID_{{methodNameUpperUnderscore}} = {{methodNumber}};
+{{/methods}}
+
+private static final class MethodHandlers
+<Req, Resp> implements
+io.grpc.stub.ServerCalls.UnaryMethod
+<Req, Resp>,
+io.grpc.stub.ServerCalls.ServerStreamingMethod
+<Req, Resp>,
+io.grpc.stub.ServerCalls.ClientStreamingMethod
+<Req, Resp>,
+io.grpc.stub.ServerCalls.BidiStreamingMethod
+<Req, Resp> {
+private final I{{serviceName}} serviceImpl;
+private final int methodId;
+
+MethodHandlers(I{{serviceName}} serviceImpl, int methodId) {
+this.serviceImpl = serviceImpl;
+this.methodId = methodId;
+}
+
+@java.lang.Override
+@java.lang.SuppressWarnings("unchecked")
+public void invoke(Req request, io.grpc.stub.StreamObserver
+<Resp> responseObserver) {
+    switch (methodId) {
+    {{#methods}}
+        {{^isManyInput}}
+            case METHODID_{{methodNameUpperUnderscore}}:
+            serviceImpl.{{methodName}}(({{inputType}}) request,
+            (io.grpc.stub.StreamObserver<{{outputType}}>) responseObserver);
+            break;
+        {{/isManyInput}}
+    {{/methods}}
+    default:
+    throw new java.lang.AssertionError();
+    }
+    }
+
+    @java.lang.Override
+    @java.lang.SuppressWarnings("unchecked")
+    public io.grpc.stub.StreamObserver
+    <Req> invoke(io.grpc.stub.StreamObserver
+        <Resp> responseObserver) {
+            switch (methodId) {
+            {{#methods}}
+                {{#isManyInput}}
+                    case METHODID_{{methodNameUpperUnderscore}}:
+                    return (io.grpc.stub.StreamObserver
+                <Req>) serviceImpl.{{methodName}}(
+                    (io.grpc.stub.StreamObserver<{{outputType}}>) responseObserver);
+                {{/isManyInput}}
+            {{/methods}}
+            default:
+            throw new java.lang.AssertionError();
+            }
+            }
+            }
+
+            }
diff --git a/compiler/src/main/resources/DubboStub.mustache b/compiler/src/main/resources/DubboStub.mustache
new file mode 100644
index 0000000..06bd7b4
--- /dev/null
+++ b/compiler/src/main/resources/DubboStub.mustache
@@ -0,0 +1,53 @@
+{{#packageName}}
+    package {{packageName}};
+{{/packageName}}
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+{{#deprecated}}
+    @java.lang.Deprecated
+{{/deprecated}}
+@javax.annotation.Generated(
+value = "by Dubbo generator",
+comments = "Source: {{protoName}}")
+public final class {{className}} {
+private static final AtomicBoolean registered = new AtomicBoolean();
+
+private static Class<?> init() {
+Class<?> clazz = null;
+try {
+clazz = Class.forName({{serviceName}}Dubbo.class.getName());
+if (registered.compareAndSet(false, true)) {
+{{#methodTypes}}
+    org.apache.dubbo.common.serialize.protobuf.support.ProtobufUtils.marshaller(
+    {{.}}.getDefaultInstance());
+{{/methodTypes}}
+}
+} catch (ClassNotFoundException e) {
+// ignore
+}
+return clazz;
+}
+
+private {{serviceName}}Dubbo() {}
+
+public static final String SERVICE_NAME = "{{packageName}}.{{serviceName}}";
+
+/**
+* Code generated for Dubbo
+*/
+public interface I{{serviceName}} {
+
+static Class<?> clazz = init();
+
+{{#methods}}
+    {{outputType}} {{methodName}}({{inputType}} request);
+
+    CompletableFuture<{{outputType}}> {{methodName}}Async({{inputType}} request);
+
+{{/methods}}
+
+}
+
+}
diff --git a/compiler/src/main/resources/ReactorDubboGrpcStub.mustache b/compiler/src/main/resources/ReactorDubboGrpcStub.mustache
new file mode 100644
index 0000000..919f62e
--- /dev/null
+++ b/compiler/src/main/resources/ReactorDubboGrpcStub.mustache
@@ -0,0 +1,212 @@
+{{#packageName}}
+    package {{packageName}};
+{{/packageName}}
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.config.ReferenceConfigBase;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
+import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
+
+import static {{packageName}}.{{serviceName}}Grpc.getServiceDescriptor;
+import static io.grpc.stub.ServerCalls.asyncUnaryCall;
+import static io.grpc.stub.ServerCalls.asyncServerStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncClientStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
+
+
+{{#deprecated}}
+    @java.lang.Deprecated
+{{/deprecated}}
+@javax.annotation.Generated(
+value = "by ReactorDubboGrpc generator",
+comments = "Source: {{protoName}}")
+public final class {{className}} {
+private {{className}}() {}
+
+public static ReactorDubbo{{serviceName}}Stub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
+return new ReactorDubbo{{serviceName}}Stub(channel, callOptions, url, referenceConfig);
+}
+
+{{#javaDoc}}
+    {{{javaDoc}}}
+{{/javaDoc}}
+public static final class ReactorDubbo{{serviceName}}Stub implements IReactor{{serviceName}} {
+
+protected URL url;
+protected ReferenceConfigBase<?> referenceConfig;
+
+protected {{serviceName}}Grpc.{{serviceName}}Stub stub;
+
+public ReactorDubbo{{serviceName}}Stub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
+this.url = url;
+this.referenceConfig = referenceConfig;
+stub = {{serviceName}}Grpc.newStub(channel).build(channel, callOptions);
+}
+
+{{#methods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{#isManyOutput}}reactor.core.publisher.Flux{{/isManyOutput}}{{^isManyOutput}}reactor.core.publisher.Mono{{/isManyOutput}}<{{outputType}}> {{methodName}}({{#isManyInput}}reactor.core.publisher.Flux{{/isManyInput}}{{^isManyInput}}reactor.core.publisher.Mono{{/isManyInput}}<{{inputType}}> reactorRequest) {
+    {{serviceName}}Grpc.ChatStub localStub = stub.withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS);
+    return com.salesforce.reactorgrpc.stub.ClientCalls.{{reactiveCallsMethodName}}(reactorRequest, localStub::{{methodName}});
+    }
+
+{{/methods}}
+{{#unaryRequestMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{#isManyOutput}}reactor.core.publisher.Flux{{/isManyOutput}}{{^isManyOutput}}reactor.core.publisher.Mono{{/isManyOutput}}<{{outputType}}> {{methodName}}({{inputType}} reactorRequest) {
+    {{serviceName}}Grpc.ChatStub localStub = stub.withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS);
+    return com.salesforce.reactorgrpc.stub.ClientCalls.{{reactiveCallsMethodName}}(reactor.core.publisher.Mono.just(reactorRequest), localStub::{{methodName}});
+    }
+
+{{/unaryRequestMethods}}
+}
+
+public interface IReactor{{serviceName}} {
+{{#methods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{#isManyOutput}}reactor.core.publisher.Flux{{/isManyOutput}}{{^isManyOutput}}reactor.core.publisher.Mono{{/isManyOutput}}<{{outputType}}> {{methodName}}({{#isManyInput}}reactor.core.publisher.Flux{{/isManyInput}}{{^isManyInput}}reactor.core.publisher.Mono{{/isManyInput}}<{{inputType}}> reactorRequest);
+
+{{/methods}}
+{{#unaryRequestMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{#isManyOutput}}reactor.core.publisher.Flux{{/isManyOutput}}{{^isManyOutput}}reactor.core.publisher.Mono{{/isManyOutput}}<{{outputType}}> {{methodName}}({{inputType}} reactorRequest);
+
+{{/unaryRequestMethods}}
+}
+
+{{#javaDoc}}
+    {{{javaDoc}}}
+{{/javaDoc}}
+public static abstract class {{serviceName}}ImplBase implements IReactor{{serviceName}}, io.grpc.BindableService {
+
+private IReactor{{serviceName}} proxiedImpl;
+
+public final void setProxiedImpl(IReactor{{serviceName}} proxiedImpl) {
+this.proxiedImpl = proxiedImpl;
+}
+
+{{#unaryRequestMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public final {{#isManyOutput}}reactor.core.publisher.Flux{{/isManyOutput}}{{^isManyOutput}}reactor.core.publisher.Mono{{/isManyOutput}}<{{outputType}}> {{methodName}}({{inputType}} reactorRequest) {
+    throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
+    }
+
+{{/unaryRequestMethods}}
+{{#methods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{#isManyOutput}}reactor.core.publisher.Flux{{/isManyOutput}}{{^isManyOutput}}reactor.core.publisher.Mono{{/isManyOutput}}<{{outputType}}> {{methodName}}({{#isManyInput}}reactor.core.publisher.Flux{{/isManyInput}}{{^isManyInput}}reactor.core.publisher.Mono{{/isManyInput}}<{{inputType}}> request) {
+    throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+    }
+
+{{/methods}}
+@java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
+return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
+{{#methods}}
+    .addMethod(
+    {{packageName}}.{{serviceName}}Grpc.get{{methodNamePascalCase}}Method(),
+    {{grpcCallsMethodName}}(
+    new MethodHandlers<
+    {{inputType}},
+    {{outputType}}>(
+    proxiedImpl, METHODID_{{methodNameUpperUnderscore}})))
+{{/methods}}
+.build();
+}
+}
+
+{{#methods}}
+    private static final int METHODID_{{methodNameUpperUnderscore}} = {{methodNumber}};
+{{/methods}}
+
+private static final class MethodHandlers
+<Req, Resp> implements
+io.grpc.stub.ServerCalls.UnaryMethod
+<Req, Resp>,
+io.grpc.stub.ServerCalls.ServerStreamingMethod
+<Req, Resp>,
+io.grpc.stub.ServerCalls.ClientStreamingMethod
+<Req, Resp>,
+io.grpc.stub.ServerCalls.BidiStreamingMethod
+<Req, Resp> {
+private final IReactor{{serviceName}} serviceImpl;
+private final int methodId;
+
+MethodHandlers(IReactor{{serviceName}} serviceImpl, int methodId) {
+this.serviceImpl = serviceImpl;
+this.methodId = methodId;
+}
+
+@java.lang.Override
+@java.lang.SuppressWarnings("unchecked")
+public void invoke(Req request, io.grpc.stub.StreamObserver
+<Resp> responseObserver) {
+    switch (methodId) {
+    {{#methods}}
+        {{^isManyInput}}
+            case METHODID_{{methodNameUpperUnderscore}}:
+            com.salesforce.reactorgrpc.stub.ServerCalls.{{reactiveCallsMethodName}}(({{inputType}}) request,
+            (io.grpc.stub.StreamObserver<{{outputType}}>) responseObserver,
+            serviceImpl::{{methodName}});
+            break;
+        {{/isManyInput}}
+    {{/methods}}
+    default:
+    throw new java.lang.AssertionError();
+    }
+    }
+
+    @java.lang.Override
+    @java.lang.SuppressWarnings("unchecked")
+    public io.grpc.stub.StreamObserver
+    <Req> invoke(io.grpc.stub.StreamObserver
+        <Resp> responseObserver) {
+            switch (methodId) {
+            {{#methods}}
+                {{#isManyInput}}
+                    case METHODID_{{methodNameUpperUnderscore}}:
+                    return (io.grpc.stub.StreamObserver
+                <Req>) com.salesforce.reactorgrpc.stub.ServerCalls.{{reactiveCallsMethodName}}(
+                    (io.grpc.stub.StreamObserver<{{outputType}}>) responseObserver,
+                    serviceImpl::{{methodName}});
+                {{/isManyInput}}
+            {{/methods}}
+            default:
+            throw new java.lang.AssertionError();
+            }
+            }
+            }
+
+            }
diff --git a/compiler/src/main/resources/RxDubboGrpcStub.mustache b/compiler/src/main/resources/RxDubboGrpcStub.mustache
new file mode 100644
index 0000000..22c06b0
--- /dev/null
+++ b/compiler/src/main/resources/RxDubboGrpcStub.mustache
@@ -0,0 +1,246 @@
+{{#packageName}}
+    package {{packageName}};
+{{/packageName}}
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.config.ReferenceConfigBase;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
+import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
+
+import static {{packageName}}.{{serviceName}}Grpc.getServiceDescriptor;
+import static io.grpc.stub.ServerCalls.asyncUnaryCall;
+import static io.grpc.stub.ServerCalls.asyncServerStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncClientStreamingCall;
+import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
+
+
+{{#deprecated}}
+    @java.lang.Deprecated
+{{/deprecated}}
+@javax.annotation.Generated(
+value = "by RxDubboGrpc generator",
+comments = "Source: {{protoName}}")
+public final class {{className}} {
+private {{className}}() {}
+
+public static RxDubbo{{serviceName}}Stub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
+return new RxDubbo{{serviceName}}Stub(channel, callOptions, url, referenceConfig);
+}
+
+{{#javaDoc}}
+    {{{javaDoc}}}
+{{/javaDoc}}
+public static final class RxDubbo{{serviceName}}Stub implements IRx{{serviceName}} {
+
+protected URL url;
+protected ReferenceConfigBase<?> referenceConfig;
+
+protected {{serviceName}}Grpc.{{serviceName}}Stub stub;
+
+public RxDubbo{{serviceName}}Stub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
+this.url = url;
+this.referenceConfig = referenceConfig;
+stub = {{serviceName}}Grpc.newStub(channel).build(channel, callOptions);
+}
+
+{{#methods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{#isManyOutput}}io.reactivex.Flowable{{/isManyOutput}}{{^isManyOutput}}io.reactivex.Single{{/isManyOutput}}<{{outputType}}> {{methodName}}({{#isManyInput}}io.reactivex.Flowable{{/isManyInput}}{{^isManyInput}}io.reactivex.Single{{/isManyInput}}<{{inputType}}> rxRequest) {
+    return com.salesforce.rxgrpc.stub.ClientCalls.{{reactiveCallsMethodName}}(rxRequest,
+    {{^isManyInput}}
+        new com.salesforce.reactivegrpc.common.BiConsumer<{{inputType}}, io.grpc.stub.StreamObserver<{{outputType}}>>() {
+        @java.lang.Override
+        public void accept({{inputType}} request, io.grpc.stub.StreamObserver<{{outputType}}> observer) {
+        stub.withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS).{{methodNameCamelCase}}(request, observer);
+        }
+        });
+    {{/isManyInput}}
+    {{#isManyInput}}
+        new com.salesforce.reactivegrpc.common.Function
+        <io.grpc.stub.StreamObserver<{{outputType}}>, io.grpc.stub.StreamObserver<{{inputType}}>>() {
+        @java.lang.Override
+        public io.grpc.stub.StreamObserver<{{inputType}}> apply(io.grpc.stub.StreamObserver<{{outputType}}> observer) {
+        return stub.withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS).{{methodNameCamelCase}}(observer);
+        }
+        });
+    {{/isManyInput}}
+    }
+
+{{/methods}}
+{{#unaryRequestMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{#isManyOutput}}io.reactivex.Flowable{{/isManyOutput}}{{^isManyOutput}}io.reactivex.Single{{/isManyOutput}}<{{outputType}}> {{methodName}}({{inputType}} rxRequest) {
+    return com.salesforce.rxgrpc.stub.ClientCalls.{{reactiveCallsMethodName}}(io.reactivex.Single.just(rxRequest),
+    new com.salesforce.reactivegrpc.common.BiConsumer<{{inputType}}, io.grpc.stub.StreamObserver<{{outputType}}>>() {
+    @java.lang.Override
+    public void accept({{inputType}} request, io.grpc.stub.StreamObserver<{{outputType}}> observer) {
+    stub.withDeadlineAfter(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS).{{methodNameCamelCase}}(request, observer);
+    }
+    });
+    }
+
+{{/unaryRequestMethods}}
+}
+
+public interface IRx{{serviceName}} {
+{{#methods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{#isManyOutput}}io.reactivex.Flowable{{/isManyOutput}}{{^isManyOutput}}io.reactivex.Single{{/isManyOutput}}<{{outputType}}> {{methodName}}({{#isManyInput}}io.reactivex.Flowable{{/isManyInput}}{{^isManyInput}}io.reactivex.Single{{/isManyInput}}<{{inputType}}> rxRequest);
+
+{{/methods}}
+{{#unaryRequestMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{#isManyOutput}}io.reactivex.Flowable{{/isManyOutput}}{{^isManyOutput}}io.reactivex.Single{{/isManyOutput}}<{{outputType}}> {{methodName}}({{inputType}} rxRequest);
+
+{{/unaryRequestMethods}}
+}
+
+
+{{#javaDoc}}
+    {{{javaDoc}}}
+{{/javaDoc}}
+public static abstract class {{serviceName}}ImplBase implements IRx{{serviceName}}, io.grpc.BindableService {
+
+private IRx{{serviceName}} proxiedImpl;
+
+public final void setProxiedImpl(IRx{{serviceName}} proxiedImpl) {
+this.proxiedImpl = proxiedImpl;
+}
+{{#unaryRequestMethods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public final {{#isManyOutput}}io.reactivex.Flowable{{/isManyOutput}}{{^isManyOutput}}io.reactivex.Single{{/isManyOutput}}<{{outputType}}> {{methodName}}({{inputType}} rxRequest) {
+    throw new UnsupportedOperationException("No need to override this method, extend XxxImplBase and override all methods it allows.");
+    }
+
+{{/unaryRequestMethods}}
+{{#methods}}
+    {{#javaDoc}}
+        {{{javaDoc}}}
+    {{/javaDoc}}
+    {{#deprecated}}
+        @java.lang.Deprecated
+    {{/deprecated}}
+    public {{#isManyOutput}}io.reactivex.Flowable{{/isManyOutput}}{{^isManyOutput}}io.reactivex.Single{{/isManyOutput}}<{{outputType}}> {{methodNameCamelCase}}({{#isManyInput}}io.reactivex.Flowable{{/isManyInput}}{{^isManyInput}}io.reactivex.Single{{/isManyInput}}<{{inputType}}> request) {
+    throw new io.grpc.StatusRuntimeException(io.grpc.Status.UNIMPLEMENTED);
+    }
+
+{{/methods}}
+@java.lang.Override public final io.grpc.ServerServiceDefinition bindService() {
+return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor())
+{{#methods}}
+    .addMethod(
+    {{packageName}}.{{serviceName}}Grpc.get{{methodNamePascalCase}}Method(),
+    {{grpcCallsMethodName}}(
+    new MethodHandlers<
+    {{inputType}},
+    {{outputType}}>(
+    proxiedImpl, METHODID_{{methodNameUpperUnderscore}})))
+{{/methods}}
+.build();
+}
+}
+
+{{#methods}}
+    private static final int METHODID_{{methodNameUpperUnderscore}} = {{methodNumber}};
+{{/methods}}
+
+private static final class MethodHandlers
+<Req, Resp> implements
+io.grpc.stub.ServerCalls.UnaryMethod
+<Req, Resp>,
+io.grpc.stub.ServerCalls.ServerStreamingMethod
+<Req, Resp>,
+io.grpc.stub.ServerCalls.ClientStreamingMethod
+<Req, Resp>,
+io.grpc.stub.ServerCalls.BidiStreamingMethod
+<Req, Resp> {
+private final IRx{{serviceName}} serviceImpl;
+private final int methodId;
+
+MethodHandlers(IRx{{serviceName}} serviceImpl, int methodId) {
+this.serviceImpl = serviceImpl;
+this.methodId = methodId;
+}
+
+@java.lang.Override
+@java.lang.SuppressWarnings("unchecked")
+public void invoke(Req request, io.grpc.stub.StreamObserver
+<Resp> responseObserver) {
+    switch (methodId) {
+    {{#methods}}
+        {{^isManyInput}}
+            case METHODID_{{methodNameUpperUnderscore}}:
+            com.salesforce.rxgrpc.stub.ServerCalls.{{reactiveCallsMethodName}}(({{inputType}}) request,
+            (io.grpc.stub.StreamObserver<{{outputType}}>) responseObserver,
+            new com.salesforce.reactivegrpc.common.Function
+                <{{#isManyInput}}io.reactivex.Flowable{{/isManyInput}}{{^isManyInput}}io.reactivex.Single{{/isManyInput}}
+            <{{inputType}}>, {{#isManyOutput}}
+            io.reactivex.Flowable{{/isManyOutput}}{{^isManyOutput}}
+            io.reactivex.Single{{/isManyOutput}}<{{outputType}}>>() {
+            @java.lang.Override
+            public {{#isManyOutput}}
+            io.reactivex.Flowable{{/isManyOutput}}{{^isManyOutput}}
+            io.reactivex.Single{{/isManyOutput}}<{{outputType}}> apply({{#isManyInput}}
+            io.reactivex.Flowable{{/isManyInput}}{{^isManyInput}}
+            io.reactivex.Single{{/isManyInput}}<{{inputType}}> single) {
+            return serviceImpl.{{methodNameCamelCase}}(single);
+            }
+            });
+            break;
+        {{/isManyInput}}
+    {{/methods}}
+    default:
+    throw new java.lang.AssertionError();
+    }
+    }
+
+    @java.lang.Override
+    @java.lang.SuppressWarnings("unchecked")
+    public io.grpc.stub.StreamObserver
+    <Req> invoke(io.grpc.stub.StreamObserver
+        <Resp> responseObserver) {
+            switch (methodId) {
+            {{#methods}}
+                {{#isManyInput}}
+                    case METHODID_{{methodNameUpperUnderscore}}:
+                    return (io.grpc.stub.StreamObserver
+                <Req>) com.salesforce.rxgrpc.stub.ServerCalls.{{reactiveCallsMethodName}}(
+                    (io.grpc.stub.StreamObserver<{{outputType}}>) responseObserver,
+                    serviceImpl::{{methodNameCamelCase}});
+                {{/isManyInput}}
+            {{/methods}}
+            default:
+            throw new java.lang.AssertionError();
+            }
+            }
+            }
+
+            }
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java
index c30ce1d..cfc02d7 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java
@@ -26,7 +26,6 @@ import org.apache.dubbo.rpc.protocol.grpc.interceptors.ServerInterceptor;
 import org.apache.dubbo.rpc.protocol.grpc.interceptors.ServerTransportFilter;
 
 import io.grpc.CallOptions;
-import io.grpc.Deadline;
 import io.grpc.ManagedChannel;
 import io.grpc.ServerBuilder;
 import io.grpc.netty.GrpcSslContexts;
@@ -42,12 +41,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
-import java.util.concurrent.TimeUnit;
 
 import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
-import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
 import static org.apache.dubbo.remoting.Constants.DISPATCHER_KEY;
 import static org.apache.dubbo.remoting.Constants.SSL_CLIENT_CERT_PATH_KEY;
 import static org.apache.dubbo.remoting.Constants.SSL_CLIENT_KEY_PASSWORD_KEY;
@@ -152,9 +148,10 @@ public class GrpcOptionsUtils {
     }
 
     static CallOptions buildCallOptions(URL url) {
-        CallOptions callOptions = CallOptions.DEFAULT
-                .withDeadline(Deadline.after(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS));
-
+        // gRPC Deadline starts counting when it's created, so we need to create and add a new Deadline for each RPC call.
+//        CallOptions callOptions = CallOptions.DEFAULT
+//                .withDeadline(Deadline.after(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT), TimeUnit.MILLISECONDS));
+        CallOptions callOptions = CallOptions.DEFAULT;
         return getConfigurator()
                 .map(configurator -> configurator.configureCallOptions(callOptions, url))
                 .orElse(callOptions);
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 8a1188f..8381a3f 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
@@ -19,6 +19,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.config.ReferenceConfigBase;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
@@ -116,7 +117,8 @@ public class GrpcProtocol extends AbstractProxyProtocol {
 
         final Method dubboStubMethod;
         try {
-            dubboStubMethod = enclosingClass.getDeclaredMethod("getDubboStub", Channel.class, CallOptions.class);
+            dubboStubMethod = enclosingClass.getDeclaredMethod("getDubboStub", Channel.class, CallOptions.class,
+                    URL.class, ReferenceConfigBase.class);
         } catch (NoSuchMethodException e) {
             throw new IllegalArgumentException("Does not find getDubboStub in " + enclosingClass.getName() + ", please use the customized protoc-gen-dubbo-java to update the generated classes.");
         }
@@ -128,7 +130,12 @@ public class GrpcProtocol extends AbstractProxyProtocol {
 
         // CallOptions
         try {
-            @SuppressWarnings("unchecked") final T stub = (T) dubboStubMethod.invoke(null, channel, GrpcOptionsUtils.buildCallOptions(url));
+            @SuppressWarnings("unchecked") final T stub = (T) dubboStubMethod.invoke(null,
+                    channel,
+                    GrpcOptionsUtils.buildCallOptions(url),
+                    url,
+                    ApplicationModel.getConsumerModel(url.getServiceKey()).getReferenceConfig()
+            );
             final Invoker<T> target = proxyFactory.getInvoker(stub, type, url);
             GrpcInvoker<T> grpcInvoker = new GrpcInvoker<>(type, url, target, channel);
             invokers.add(grpcInvoker);
diff --git a/dubbo-serialization/dubbo-serialization-protobuf/pom.xml b/dubbo-serialization/dubbo-serialization-protobuf/pom.xml
index 4c81312..65eb7b7 100644
--- a/dubbo-serialization/dubbo-serialization-protobuf/pom.xml
+++ b/dubbo-serialization/dubbo-serialization-protobuf/pom.xml
@@ -29,8 +29,7 @@ limitations under the License.
     <description>The protobuf serialization module of dubbo project</description>
     <properties>
         <skip_maven_deploy>false</skip_maven_deploy>
-        <!-- /compiler/build.gradle -->
-        <proto_dubbo_plugin_version>1.19.0-SNAPSHOT</proto_dubbo_plugin_version>
+        <dubbo.compiler.version>0.0.1-SNAPSHOT</dubbo.compiler.version>
     </properties>
     <dependencies>
         <dependency>
@@ -61,24 +60,17 @@ limitations under the License.
                 <groupId>org.xolstice.maven.plugins</groupId>
                 <artifactId>protobuf-maven-plugin</artifactId>
                 <version>0.5.1</version>
+                <extensions>true</extensions>
                 <configuration>
                     <protocArtifact>com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier}</protocArtifact>
-                    <pluginId>grpc-java</pluginId>
-                    <pluginArtifact>
-                        org.apache.dubbo:protoc-gen-dubbo-java:${proto_dubbo_plugin_version}:exe:${os.detected.classifier}
-                    </pluginArtifact>
                     <outputDirectory>build/generated/source/proto/main/java</outputDirectory>
                     <clearOutputDirectory>false</clearOutputDirectory>
-                    <!-- supports 'dubbo' and 'grpc' -->
-                    <pluginParameter>dubbo</pluginParameter>
                 </configuration>
                 <executions>
                     <execution>
                         <goals>
                             <goal>compile</goal>
-                            <goal>compile-custom</goal>
                             <goal>test-compile</goal>
-                            <goal>test-compile-custom</goal>
                         </goals>
                     </execution>
                 </executions>