gRpc compiler refactor (#5416)
Refactor protobuf compiler support (gRPC and Dubbo), add Reactive gRPC support.
This commit is contained in:
parent
cd582c5c03
commit
a8800c8e71
6
LICENSE
6
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.
|
||||
9
NOTICE
9
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
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,2 +0,0 @@
|
|||
#Tue Oct 09 11:40:48 CST 2018
|
||||
gradle.version=4.9
|
||||
Binary file not shown.
|
|
@ -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",
|
||||
],
|
||||
)
|
||||
|
|
@ -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.
|
||||
|
|
@ -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')
|
||||
|
|
@ -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"
|
||||
Binary file not shown.
|
|
@ -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
|
||||
|
|
@ -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" "$@"
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
||||
|
|
@ -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("*");
|
||||
} else {
|
||||
result.push_back(c);
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
// Avoid "*/".
|
||||
if (prev == '*') {
|
||||
result.append("/");
|
||||
} else {
|
||||
result.push_back(c);
|
||||
}
|
||||
break;
|
||||
case '@':
|
||||
// '@' starts javadoc tags including the @deprecated tag, which will
|
||||
// cause a compile-time error if inserted before a declaration that
|
||||
// does not have a corresponding @Deprecated annotation.
|
||||
result.append("@");
|
||||
break;
|
||||
case '<':
|
||||
// Avoid interpretation as HTML.
|
||||
result.append("<");
|
||||
break;
|
||||
case '>':
|
||||
// Avoid interpretation as HTML.
|
||||
result.append(">");
|
||||
break;
|
||||
case '&':
|
||||
// Avoid interpretation as HTML.
|
||||
result.append("&");
|
||||
break;
|
||||
case '\\':
|
||||
// Java interprets Unicode escape sequences anywhere!
|
||||
result.append("\");
|
||||
break;
|
||||
default:
|
||||
result.push_back(c);
|
||||
break;
|
||||
}
|
||||
|
||||
prev = c;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
|
||||
template <typename DescriptorType>
|
||||
static string GrpcGetCommentsForDescriptor(const DescriptorType* descriptor) {
|
||||
SourceLocation location;
|
||||
if (descriptor->GetSourceLocation(&location)) {
|
||||
return location.leading_comments.empty() ?
|
||||
location.trailing_comments : location.leading_comments;
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
|
||||
static std::vector<string> GrpcGetDocLines(const string& comments) {
|
||||
if (!comments.empty()) {
|
||||
// TODO(kenton): Ideally we should parse the comment text as Markdown and
|
||||
// write it back as HTML, but this requires a Markdown parser. For now
|
||||
// we just use <pre> to get fixed-width text formatting.
|
||||
|
||||
// If the comment itself contains block comment start or end markers,
|
||||
// HTML-escape them so that they don't accidentally close the doc comment.
|
||||
string escapedComments = GrpcEscapeJavadoc(comments);
|
||||
|
||||
std::vector<string> lines = GrpcSplit(escapedComments, "\n");
|
||||
while (!lines.empty() && lines.back().empty()) {
|
||||
lines.pop_back();
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
return std::vector<string>();
|
||||
}
|
||||
|
||||
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
|
||||
template <typename DescriptorType>
|
||||
static std::vector<string> GrpcGetDocLinesForDescriptor(const DescriptorType* descriptor) {
|
||||
return GrpcGetDocLines(GrpcGetCommentsForDescriptor(descriptor));
|
||||
}
|
||||
|
||||
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
|
||||
static void GrpcWriteDocCommentBody(Printer* printer,
|
||||
const std::vector<string>& lines,
|
||||
bool surroundWithPreTag) {
|
||||
if (!lines.empty()) {
|
||||
if (surroundWithPreTag) {
|
||||
printer->Print(" * <pre>\n");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
// Most lines should start with a space. Watch out for lines that start
|
||||
// with a /, since putting that right after the leading asterisk will
|
||||
// close the comment.
|
||||
if (!lines[i].empty() && lines[i][0] == '/') {
|
||||
printer->Print(" * $line$\n", "line", lines[i]);
|
||||
} else {
|
||||
printer->Print(" *$line$\n", "line", lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (surroundWithPreTag) {
|
||||
printer->Print(" * </pre>\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
|
||||
static void GrpcWriteDocComment(Printer* printer, const string& comments) {
|
||||
printer->Print("/**\n");
|
||||
std::vector<string> lines = GrpcGetDocLines(comments);
|
||||
GrpcWriteDocCommentBody(printer, lines, false);
|
||||
printer->Print(" */\n");
|
||||
}
|
||||
|
||||
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
|
||||
static void GrpcWriteServiceDocComment(Printer* printer,
|
||||
const ServiceDescriptor* service) {
|
||||
// Deviating from protobuf to avoid extraneous docs
|
||||
// (see https://github.com/google/protobuf/issues/1406);
|
||||
printer->Print("/**\n");
|
||||
std::vector<string> lines = GrpcGetDocLinesForDescriptor(service);
|
||||
GrpcWriteDocCommentBody(printer, lines, true);
|
||||
printer->Print(" */\n");
|
||||
}
|
||||
|
||||
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
|
||||
void GrpcWriteMethodDocComment(Printer* printer,
|
||||
const MethodDescriptor* method) {
|
||||
// Deviating from protobuf to avoid extraneous docs
|
||||
// (see https://github.com/google/protobuf/issues/1406);
|
||||
printer->Print("/**\n");
|
||||
std::vector<string> lines = GrpcGetDocLinesForDescriptor(method);
|
||||
GrpcWriteDocCommentBody(printer, lines, true);
|
||||
printer->Print(" */\n");
|
||||
}
|
||||
|
||||
enum StubType {
|
||||
ASYNC_INTERFACE = 0,
|
||||
BLOCKING_CLIENT_INTERFACE = 1,
|
||||
FUTURE_CLIENT_INTERFACE = 2,
|
||||
BLOCKING_SERVER_INTERFACE = 3,
|
||||
ASYNC_CLIENT_IMPL = 4,
|
||||
BLOCKING_CLIENT_IMPL = 5,
|
||||
FUTURE_CLIENT_IMPL = 6,
|
||||
ABSTRACT_CLASS = 7,
|
||||
};
|
||||
|
||||
enum CallType {
|
||||
ASYNC_CALL = 0,
|
||||
BLOCKING_CALL = 1,
|
||||
FUTURE_CALL = 2
|
||||
};
|
||||
|
||||
static void PrintMarshallerStaticBlock(const ServiceDescriptor* service,
|
||||
std::map<string, string>* vars,
|
||||
Printer* p) {
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
const MethodDescriptor* method = service->method(i);
|
||||
(*vars)["input_type"] = google::protobuf::compiler::java::ClassName(method->input_type());
|
||||
(*vars)["output_type"] = google::protobuf::compiler::java::ClassName(method->output_type());
|
||||
p->Print(
|
||||
*vars,
|
||||
"private static final AtomicBoolean registered = new AtomicBoolean();\n\n");
|
||||
|
||||
p->Print(
|
||||
*vars,
|
||||
"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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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_
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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("*/", "*/").replace("*", "*"))
|
||||
.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +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.rpc.protocol.httpinvoker;
|
||||
|
||||
|
||||
/**
|
||||
* HttpService
|
||||
*/
|
||||
public interface HttpService {
|
||||
|
||||
String sayHello(String name);
|
||||
|
||||
String sayHello(String name, int times);
|
||||
|
||||
void timeOut(int millis);
|
||||
|
||||
String customException();
|
||||
|
||||
String getRemoteApplicationName();
|
||||
|
||||
}
|
||||
/*
|
||||
* 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";
|
||||
}
|
||||
}
|
||||
|
|
@ -14,15 +14,28 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.dubbo.rpc.protocol.http;
|
||||
package org.apache.dubbo.gen.grpc;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.apache.dubbo.gen.AbstractGenerator;
|
||||
|
||||
@Deprecated
|
||||
public class HttpRemoteInvocation extends org.apache.dubbo.rpc.protocol.httpinvoker.HttpRemoteInvocation {
|
||||
private static final long serialVersionUID = 1L;
|
||||
import com.salesforce.jprotoc.ProtocPlugin;
|
||||
|
||||
public HttpRemoteInvocation(MethodInvocation methodInvocation) {
|
||||
super(methodInvocation);
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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}}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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.{{serviceName}}Stub 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.{{serviceName}}Stub 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -51,8 +51,6 @@
|
|||
<exclude>**/*.jar</exclude>
|
||||
<exclude>**/mvnw*</exclude>
|
||||
<exclude>**/.flattened-pom.xml</exclude>
|
||||
<exclude>**/compiler/.gradle/**</exclude>
|
||||
<exclude>**/compiler/gradle/**</exclude>
|
||||
</excludes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-rpc</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<artifactId>dubbo-rpc-http-invoker</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>The http rpc module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-rpc-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-remoting-http</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-serialization-jdk</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -1,225 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.rpc.protocol.httpinvoker;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.Version;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.remoting.Constants;
|
||||
import org.apache.dubbo.remoting.http.HttpBinder;
|
||||
import org.apache.dubbo.remoting.http.HttpHandler;
|
||||
import org.apache.dubbo.remoting.http.HttpServer;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol;
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
import org.apache.dubbo.rpc.support.ProtocolUtils;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.remoting.RemoteAccessException;
|
||||
import org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor;
|
||||
import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean;
|
||||
import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter;
|
||||
import org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor;
|
||||
import org.springframework.remoting.support.RemoteInvocation;
|
||||
import org.springframework.remoting.support.RemoteInvocationFactory;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
|
||||
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
|
||||
|
||||
/**
|
||||
* HttpInvokerProtocol
|
||||
*/
|
||||
public class HttpInvokerProtocol extends AbstractProxyProtocol {
|
||||
|
||||
public static final int DEFAULT_PORT = 80;
|
||||
|
||||
private final Map<String, HttpServer> serverMap = new ConcurrentHashMap<String, HttpServer>();
|
||||
|
||||
private final Map<String, HttpInvokerServiceExporter> skeletonMap = new ConcurrentHashMap<String, HttpInvokerServiceExporter>();
|
||||
|
||||
private HttpBinder httpBinder;
|
||||
|
||||
public HttpInvokerProtocol() {
|
||||
super(RemoteAccessException.class);
|
||||
}
|
||||
|
||||
public void setHttpBinder(HttpBinder httpBinder) {
|
||||
this.httpBinder = httpBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultPort() {
|
||||
return DEFAULT_PORT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> Runnable doExport(final T impl, Class<T> type, URL url) throws RpcException {
|
||||
String addr = getAddr(url);
|
||||
HttpServer server = serverMap.get(addr);
|
||||
if (server == null) {
|
||||
server = httpBinder.bind(url, new InternalHandler());
|
||||
serverMap.put(addr, server);
|
||||
}
|
||||
final String path = url.getAbsolutePath();
|
||||
skeletonMap.put(path, createExporter(impl, type));
|
||||
|
||||
final String genericPath = path + "/" + GENERIC_KEY;
|
||||
|
||||
skeletonMap.put(genericPath, createExporter(impl, GenericService.class));
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
skeletonMap.remove(path);
|
||||
skeletonMap.remove(genericPath);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private <T> HttpInvokerServiceExporter createExporter(T impl, Class<?> type) {
|
||||
final HttpInvokerServiceExporter httpServiceExporter = new HttpInvokerServiceExporter();
|
||||
httpServiceExporter.setServiceInterface(type);
|
||||
httpServiceExporter.setService(impl);
|
||||
try {
|
||||
httpServiceExporter.afterPropertiesSet();
|
||||
} catch (Exception e) {
|
||||
throw new RpcException(e.getMessage(), e);
|
||||
}
|
||||
return httpServiceExporter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T doRefer(final Class<T> serviceType, final URL url) throws RpcException {
|
||||
final String generic = url.getParameter(GENERIC_KEY);
|
||||
final boolean isGeneric = ProtocolUtils.isGeneric(generic) || serviceType.equals(GenericService.class);
|
||||
|
||||
final HttpInvokerProxyFactoryBean httpProxyFactoryBean = new HttpInvokerProxyFactoryBean();
|
||||
httpProxyFactoryBean.setRemoteInvocationFactory(new RemoteInvocationFactory() {
|
||||
@Override
|
||||
public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) {
|
||||
RemoteInvocation invocation;
|
||||
/*
|
||||
package was renamed to 'org.apache.dubbo' in v2.7.0, so only provider versions after v2.7.0 can
|
||||
recognize org.apache.xxx.HttpRemoteInvocation'.
|
||||
*/
|
||||
if (Version.isRelease270OrHigher(url.getParameter(RELEASE_KEY))) {
|
||||
invocation = new HttpRemoteInvocation(methodInvocation);
|
||||
} else {
|
||||
/*
|
||||
The customized 'com.alibaba.dubbo.rpc.protocol.http.HttpRemoteInvocation' was firstly introduced
|
||||
in v2.6.3. The main purpose is to support transformation of attachments in HttpInvokerProtocol, see
|
||||
https://github.com/apache/dubbo/pull/1827. To guarantee interoperability with lower
|
||||
versions, we need to check if the provider is v2.6.3 or higher before sending customized
|
||||
HttpRemoteInvocation.
|
||||
*/
|
||||
if (Version.isRelease263OrHigher(url.getParameter(DUBBO_VERSION_KEY))) {
|
||||
invocation = new com.alibaba.dubbo.rpc.protocol.http.HttpRemoteInvocation(methodInvocation);
|
||||
} else {
|
||||
invocation = new RemoteInvocation(methodInvocation);
|
||||
}
|
||||
}
|
||||
if (isGeneric) {
|
||||
invocation.addAttribute(GENERIC_KEY, generic);
|
||||
}
|
||||
return invocation;
|
||||
}
|
||||
});
|
||||
|
||||
String key = url.toIdentityString();
|
||||
if (isGeneric) {
|
||||
key = key + "/" + GENERIC_KEY;
|
||||
}
|
||||
|
||||
httpProxyFactoryBean.setServiceUrl(key.replace("http-invoker","http"));
|
||||
httpProxyFactoryBean.setServiceInterface(serviceType);
|
||||
String client = url.getParameter(Constants.CLIENT_KEY);
|
||||
if (StringUtils.isEmpty(client) || "simple".equals(client)) {
|
||||
SimpleHttpInvokerRequestExecutor httpInvokerRequestExecutor = new SimpleHttpInvokerRequestExecutor() {
|
||||
@Override
|
||||
protected void prepareConnection(HttpURLConnection con,
|
||||
int contentLength) throws IOException {
|
||||
super.prepareConnection(con, contentLength);
|
||||
con.setReadTimeout(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT));
|
||||
con.setConnectTimeout(url.getParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT));
|
||||
}
|
||||
};
|
||||
httpProxyFactoryBean.setHttpInvokerRequestExecutor(httpInvokerRequestExecutor);
|
||||
} else if ("commons".equals(client)) {
|
||||
HttpComponentsHttpInvokerRequestExecutor httpInvokerRequestExecutor = new HttpComponentsHttpInvokerRequestExecutor();
|
||||
httpInvokerRequestExecutor.setReadTimeout(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT));
|
||||
httpInvokerRequestExecutor.setConnectTimeout(url.getParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT));
|
||||
httpProxyFactoryBean.setHttpInvokerRequestExecutor(httpInvokerRequestExecutor);
|
||||
} else {
|
||||
throw new IllegalStateException("Unsupported http protocol client " + client + ", only supported: simple, commons");
|
||||
}
|
||||
httpProxyFactoryBean.afterPropertiesSet();
|
||||
return (T) httpProxyFactoryBean.getObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getErrorCode(Throwable e) {
|
||||
if (e instanceof RemoteAccessException) {
|
||||
e = e.getCause();
|
||||
}
|
||||
if (e != null) {
|
||||
Class<?> cls = e.getClass();
|
||||
if (SocketTimeoutException.class.equals(cls)) {
|
||||
return RpcException.TIMEOUT_EXCEPTION;
|
||||
} else if (IOException.class.isAssignableFrom(cls)) {
|
||||
return RpcException.NETWORK_EXCEPTION;
|
||||
} else if (ClassNotFoundException.class.isAssignableFrom(cls)) {
|
||||
return RpcException.SERIALIZATION_EXCEPTION;
|
||||
}
|
||||
}
|
||||
return super.getErrorCode(e);
|
||||
}
|
||||
|
||||
private class InternalHandler implements HttpHandler {
|
||||
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException {
|
||||
String uri = request.getRequestURI();
|
||||
HttpInvokerServiceExporter skeleton = skeletonMap.get(uri);
|
||||
if (!"POST".equalsIgnoreCase(request.getMethod())) {
|
||||
response.setStatus(500);
|
||||
} else {
|
||||
RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort());
|
||||
try {
|
||||
skeleton.handleRequest(request, response);
|
||||
} catch (Throwable e) {
|
||||
throw new ServletException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dubbo.rpc.protocol.httpinvoker;
|
||||
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.remoting.support.RemoteInvocation;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
|
||||
|
||||
public class HttpRemoteInvocation extends RemoteInvocation {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String DUBBO_ATTACHMENTS_ATTR_NAME = "dubbo.attachments";
|
||||
|
||||
public HttpRemoteInvocation(MethodInvocation methodInvocation) {
|
||||
super(methodInvocation);
|
||||
addAttribute(DUBBO_ATTACHMENTS_ATTR_NAME, new HashMap<String, Object>(RpcContext.getContext().getAttachments()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object targetObject) throws NoSuchMethodException, IllegalAccessException,
|
||||
InvocationTargetException {
|
||||
RpcContext context = RpcContext.getContext();
|
||||
context.setAttachments((Map<String, Object>) getAttribute(DUBBO_ATTACHMENTS_ATTR_NAME));
|
||||
|
||||
String generic = (String) getAttribute(GENERIC_KEY);
|
||||
if (StringUtils.isNotEmpty(generic)) {
|
||||
context.setAttachment(GENERIC_KEY, generic);
|
||||
}
|
||||
try {
|
||||
return super.invoke(targetObject);
|
||||
} finally {
|
||||
context.setAttachments(null);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
http-invoker=org.apache.dubbo.rpc.protocol.httpinvoker.HttpInvokerProtocol
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.rpc.protocol.httpinvoker;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.beanutil.JavaBeanDescriptor;
|
||||
import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil;
|
||||
import org.apache.dubbo.common.extension.ExtensionLoader;
|
||||
import org.apache.dubbo.common.serialize.ObjectInput;
|
||||
import org.apache.dubbo.common.serialize.ObjectOutput;
|
||||
import org.apache.dubbo.common.serialize.Serialization;
|
||||
import org.apache.dubbo.common.serialize.nativejava.NativeJavaSerialization;
|
||||
import org.apache.dubbo.rpc.Exporter;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.Protocol;
|
||||
import org.apache.dubbo.rpc.ProxyFactory;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* HttpInvokerProtocolTest
|
||||
*/
|
||||
public class HttpInvokerProtocolTest {
|
||||
|
||||
@Test
|
||||
public void testHttpProtocol() {
|
||||
HttpServiceImpl server = new HttpServiceImpl();
|
||||
Assertions.assertFalse(server.isCalled());
|
||||
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
|
||||
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
|
||||
URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0");
|
||||
Exporter<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url));
|
||||
Invoker<HttpService> invoker = protocol.refer(HttpService.class, url);
|
||||
HttpService client = proxyFactory.getProxy(invoker);
|
||||
String result = client.sayHello("haha");
|
||||
Assertions.assertTrue(server.isCalled());
|
||||
Assertions.assertEquals("Hello, haha", result);
|
||||
invoker.destroy();
|
||||
exporter.unexport();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericInvoke() {
|
||||
HttpServiceImpl server = new HttpServiceImpl();
|
||||
Assertions.assertFalse(server.isCalled());
|
||||
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
|
||||
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
|
||||
URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0");
|
||||
Exporter<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url));
|
||||
Invoker<GenericService> invoker = protocol.refer(GenericService.class, url);
|
||||
GenericService client = proxyFactory.getProxy(invoker, true);
|
||||
String result = (String) client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"haha"});
|
||||
Assertions.assertTrue(server.isCalled());
|
||||
Assertions.assertEquals("Hello, haha", result);
|
||||
invoker.destroy();
|
||||
exporter.unexport();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericInvokeWithNativeJava() throws IOException, ClassNotFoundException {
|
||||
HttpServiceImpl server = new HttpServiceImpl();
|
||||
Assertions.assertFalse(server.isCalled());
|
||||
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
|
||||
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
|
||||
URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0&generic=nativejava");
|
||||
Exporter<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url));
|
||||
Invoker<GenericService> invoker = protocol.refer(GenericService.class, url);
|
||||
GenericService client = proxyFactory.getProxy(invoker);
|
||||
|
||||
Serialization serialization = new NativeJavaSerialization();
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
|
||||
ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream);
|
||||
objectOutput.writeObject("haha");
|
||||
objectOutput.flushBuffer();
|
||||
|
||||
Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{byteArrayOutputStream.toByteArray()});
|
||||
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream((byte[]) result);
|
||||
ObjectInput objectInput = serialization.deserialize(url, byteArrayInputStream);
|
||||
Assertions.assertTrue(server.isCalled());
|
||||
Assertions.assertEquals("Hello, haha", objectInput.readObject());
|
||||
invoker.destroy();
|
||||
exporter.unexport();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenericInvokeWithBean() {
|
||||
HttpServiceImpl server = new HttpServiceImpl();
|
||||
Assertions.assertFalse(server.isCalled());
|
||||
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
|
||||
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
|
||||
URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0&generic=bean");
|
||||
Exporter<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url));
|
||||
Invoker<GenericService> invoker = protocol.refer(GenericService.class, url);
|
||||
GenericService client = proxyFactory.getProxy(invoker);
|
||||
|
||||
JavaBeanDescriptor javaBeanDescriptor = JavaBeanSerializeUtil.serialize("haha");
|
||||
|
||||
Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{javaBeanDescriptor});
|
||||
Assertions.assertTrue(server.isCalled());
|
||||
Assertions.assertEquals("Hello, haha", JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) result));
|
||||
invoker.destroy();
|
||||
exporter.unexport();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverload() {
|
||||
HttpServiceImpl server = new HttpServiceImpl();
|
||||
Assertions.assertFalse(server.isCalled());
|
||||
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
|
||||
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
|
||||
URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0&hessian.overload.method=true&hessian2.request=false");
|
||||
Exporter<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url));
|
||||
Invoker<HttpService> invoker = protocol.refer(HttpService.class, url);
|
||||
HttpService client = proxyFactory.getProxy(invoker);
|
||||
String result = client.sayHello("haha");
|
||||
Assertions.assertEquals("Hello, haha", result);
|
||||
result = client.sayHello("haha", 1);
|
||||
Assertions.assertEquals("Hello, haha. ", result);
|
||||
invoker.destroy();
|
||||
exporter.unexport();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleClient() {
|
||||
HttpServiceImpl server = new HttpServiceImpl();
|
||||
Assertions.assertFalse(server.isCalled());
|
||||
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
|
||||
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
|
||||
URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0&client=simple");
|
||||
Exporter<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url));
|
||||
Invoker<HttpService> invoker = protocol.refer(HttpService.class, url);
|
||||
HttpService client = proxyFactory.getProxy(invoker);
|
||||
String result = client.sayHello("haha");
|
||||
Assertions.assertTrue(server.isCalled());
|
||||
Assertions.assertEquals("Hello, haha", result);
|
||||
invoker.destroy();
|
||||
exporter.unexport();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeOut() {
|
||||
HttpServiceImpl server = new HttpServiceImpl();
|
||||
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
|
||||
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
|
||||
URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0&timeout=10");
|
||||
Exporter<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url));
|
||||
Invoker<HttpService> invoker = protocol.refer(HttpService.class, url);
|
||||
HttpService client = proxyFactory.getProxy(invoker);
|
||||
try {
|
||||
client.timeOut(6000);
|
||||
fail();
|
||||
} catch (RpcException expected) {
|
||||
Assertions.assertTrue(expected.isTimeout());
|
||||
} finally {
|
||||
invoker.destroy();
|
||||
exporter.unexport();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomException() {
|
||||
HttpServiceImpl server = new HttpServiceImpl();
|
||||
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
|
||||
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
|
||||
URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0");
|
||||
Exporter<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url));
|
||||
Invoker<HttpService> invoker = protocol.refer(HttpService.class, url);
|
||||
HttpService client = proxyFactory.getProxy(invoker);
|
||||
try {
|
||||
client.customException();
|
||||
fail();
|
||||
} catch (HttpServiceImpl.MyException expected) {
|
||||
}
|
||||
invoker.destroy();
|
||||
exporter.unexport();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.dubbo.rpc.protocol.httpinvoker;
|
||||
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
|
||||
/**
|
||||
* HttpServiceImpl
|
||||
*/
|
||||
public class HttpServiceImpl implements HttpService {
|
||||
|
||||
private boolean called;
|
||||
|
||||
public String sayHello(String name) {
|
||||
called = true;
|
||||
return "Hello, " + name;
|
||||
}
|
||||
|
||||
public String sayHello(String name, int times) {
|
||||
called = true;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < times; i++) {
|
||||
sb.append("Hello, " + name + ". ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isCalled() {
|
||||
return called;
|
||||
}
|
||||
|
||||
public void timeOut(int millis) {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteApplicationName() {
|
||||
return RpcContext.getContext().getRemoteApplicationName();
|
||||
}
|
||||
|
||||
public String customException() {
|
||||
throw new MyException("custom exception");
|
||||
}
|
||||
|
||||
static class MyException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -3051041116483629056L;
|
||||
|
||||
public MyException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>dubbo-rpc</artifactId>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>dubbo-rpc-jsonrpc</artifactId>
|
||||
|
||||
<description>The JSON-RPC module of dubbo project</description>
|
||||
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-rpc-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-remoting-http</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.briandilley.jsonrpc4j</groupId>
|
||||
<artifactId>jsonrpc4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.portlet</groupId>
|
||||
<artifactId>portlet-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue