gRpc compiler refactor (#5416)

Refactor protobuf compiler support (gRPC and Dubbo), add Reactive gRPC support.
This commit is contained in:
ken.lj 2019-12-04 11:10:20 +08:00 committed by GitHub
parent cd582c5c03
commit a8800c8e71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 1455 additions and 4072 deletions

View File

@ -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
View File

@ -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

View File

@ -1,2 +0,0 @@
#Tue Oct 09 11:40:48 CST 2018
gradle.version=4.9

View File

@ -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",
],
)

View File

@ -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.

View File

@ -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')

View File

@ -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.

View File

@ -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

172
compiler/gradlew vendored
View File

@ -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" "$@"

84
compiler/gradlew.bat vendored
View File

@ -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

178
compiler/pom.xml Normal file
View File

@ -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>

View File

@ -1,580 +0,0 @@
#include "java_generator.h"
#include <algorithm>
#include <iostream>
#include <iterator>
#include <map>
#include <set>
#include <vector>
#include <google/protobuf/compiler/java/java_names.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>
// Stringify helpers used solely to cast GRPC_VERSION
#ifndef STR
#define STR(s) #s
#endif
#ifndef XSTR
#define XSTR(s) STR(s)
#endif
#ifndef FALLTHROUGH_INTENDED
#define FALLTHROUGH_INTENDED
#endif
namespace java_dubbo_generator {
using google::protobuf::FileDescriptor;
using google::protobuf::ServiceDescriptor;
using google::protobuf::MethodDescriptor;
using google::protobuf::Descriptor;
using google::protobuf::io::Printer;
using google::protobuf::SourceLocation;
using std::to_string;
// java keywords from: https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.9
static std::set<string> java_keywords = {
"abstract",
"assert",
"boolean",
"break",
"byte",
"case",
"catch",
"char",
"class",
"const",
"continue",
"default",
"do",
"double",
"else",
"enum",
"extends",
"final",
"finally",
"float",
"for",
"goto",
"if",
"implements",
"import",
"instanceof",
"int",
"interface",
"long",
"native",
"new",
"package",
"private",
"protected",
"public",
"return",
"short",
"static",
"strictfp",
"super",
"switch",
"synchronized",
"this",
"throw",
"throws",
"transient",
"try",
"void",
"volatile",
"while",
// additional ones added by us
"true",
"false",
};
// Adjust a method name prefix identifier to follow the JavaBean spec:
// - decapitalize the first letter
// - remove embedded underscores & capitalize the following letter
// Finally, if the result is a reserved java keyword, append an underscore.
static string MixedLower(const string& word) {
string w;
w += tolower(word[0]);
bool after_underscore = false;
for (size_t i = 1; i < word.length(); ++i) {
if (word[i] == '_') {
after_underscore = true;
} else {
w += after_underscore ? toupper(word[i]) : word[i];
after_underscore = false;
}
}
if (java_keywords.find(w) != java_keywords.end()) {
return w + "_";
}
return w;
}
// Converts to the identifier to the ALL_UPPER_CASE format.
// - An underscore is inserted where a lower case letter is followed by an
// upper case letter.
// - All letters are converted to upper case
static string ToAllUpperCase(const string& word) {
string w;
for (size_t i = 0; i < word.length(); ++i) {
w += toupper(word[i]);
if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) {
w += '_';
}
}
return w;
}
static inline string LowerMethodName(const MethodDescriptor* method) {
return MixedLower(method->name());
}
static inline string MethodPropertiesFieldName(const MethodDescriptor* method) {
return "METHOD_" + ToAllUpperCase(method->name());
}
static inline string MethodPropertiesGetterName(const MethodDescriptor* method) {
return MixedLower("get_" + method->name() + "_method");
}
static inline string MethodIdFieldName(const MethodDescriptor* method) {
return "METHODID_" + ToAllUpperCase(method->name());
}
static inline bool ShouldGenerateAsLite(const Descriptor* desc) {
return false;
}
static inline string MessageFullJavaName(bool nano, const Descriptor* desc) {
string name = google::protobuf::compiler::java::ClassName(desc);
if (nano && !ShouldGenerateAsLite(desc)) {
// XXX: Add "nano" to the original package
// (https://github.com/grpc/grpc-java/issues/900)
if (isupper(name[0])) {
// No java package specified.
return "nano." + name;
}
for (size_t i = 0; i < name.size(); ++i) {
if ((name[i] == '.') && (i < (name.size() - 1)) && isupper(name[i + 1])) {
return name.substr(0, i + 1) + "nano." + name.substr(i + 1);
}
}
}
return name;
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
template <typename ITR>
static void GrpcSplitStringToIteratorUsing(const string& full,
const char* delim,
ITR& result) {
// Optimize the common case where delim is a single character.
if (delim[0] != '\0' && delim[1] == '\0') {
char c = delim[0];
const char* p = full.data();
const char* end = p + full.size();
while (p != end) {
if (*p == c) {
++p;
} else {
const char* start = p;
while (++p != end && *p != c);
*result++ = string(start, p - start);
}
}
return;
}
string::size_type begin_index, end_index;
begin_index = full.find_first_not_of(delim);
while (begin_index != string::npos) {
end_index = full.find_first_of(delim, begin_index);
if (end_index == string::npos) {
*result++ = full.substr(begin_index);
return;
}
*result++ = full.substr(begin_index, (end_index - begin_index));
begin_index = full.find_first_not_of(delim, end_index);
}
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
static void GrpcSplitStringUsing(const string& full,
const char* delim,
std::vector<string>* result) {
std::back_insert_iterator< std::vector<string> > it(*result);
GrpcSplitStringToIteratorUsing(full, delim, it);
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
static std::vector<string> GrpcSplit(const string& full, const char* delim) {
std::vector<string> result;
GrpcSplitStringUsing(full, delim, &result);
return result;
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
static string GrpcEscapeJavadoc(const string& input) {
string result;
result.reserve(input.size() * 2);
char prev = '*';
for (string::size_type i = 0; i < input.size(); i++) {
char c = input[i];
switch (c) {
case '*':
// Avoid "/*".
if (prev == '/') {
result.append("&#42;");
} else {
result.push_back(c);
}
break;
case '/':
// Avoid "*/".
if (prev == '*') {
result.append("&#47;");
} else {
result.push_back(c);
}
break;
case '@':
// '@' starts javadoc tags including the @deprecated tag, which will
// cause a compile-time error if inserted before a declaration that
// does not have a corresponding @Deprecated annotation.
result.append("&#64;");
break;
case '<':
// Avoid interpretation as HTML.
result.append("&lt;");
break;
case '>':
// Avoid interpretation as HTML.
result.append("&gt;");
break;
case '&':
// Avoid interpretation as HTML.
result.append("&amp;");
break;
case '\\':
// Java interprets Unicode escape sequences anywhere!
result.append("&#92;");
break;
default:
result.push_back(c);
break;
}
prev = c;
}
return result;
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
template <typename DescriptorType>
static string GrpcGetCommentsForDescriptor(const DescriptorType* descriptor) {
SourceLocation location;
if (descriptor->GetSourceLocation(&location)) {
return location.leading_comments.empty() ?
location.trailing_comments : location.leading_comments;
}
return string();
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
static std::vector<string> GrpcGetDocLines(const string& comments) {
if (!comments.empty()) {
// TODO(kenton): Ideally we should parse the comment text as Markdown and
// write it back as HTML, but this requires a Markdown parser. For now
// we just use <pre> to get fixed-width text formatting.
// If the comment itself contains block comment start or end markers,
// HTML-escape them so that they don't accidentally close the doc comment.
string escapedComments = GrpcEscapeJavadoc(comments);
std::vector<string> lines = GrpcSplit(escapedComments, "\n");
while (!lines.empty() && lines.back().empty()) {
lines.pop_back();
}
return lines;
}
return std::vector<string>();
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
template <typename DescriptorType>
static std::vector<string> GrpcGetDocLinesForDescriptor(const DescriptorType* descriptor) {
return GrpcGetDocLines(GrpcGetCommentsForDescriptor(descriptor));
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
static void GrpcWriteDocCommentBody(Printer* printer,
const std::vector<string>& lines,
bool surroundWithPreTag) {
if (!lines.empty()) {
if (surroundWithPreTag) {
printer->Print(" * <pre>\n");
}
for (size_t i = 0; i < lines.size(); i++) {
// Most lines should start with a space. Watch out for lines that start
// with a /, since putting that right after the leading asterisk will
// close the comment.
if (!lines[i].empty() && lines[i][0] == '/') {
printer->Print(" * $line$\n", "line", lines[i]);
} else {
printer->Print(" *$line$\n", "line", lines[i]);
}
}
if (surroundWithPreTag) {
printer->Print(" * </pre>\n");
}
}
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
static void GrpcWriteDocComment(Printer* printer, const string& comments) {
printer->Print("/**\n");
std::vector<string> lines = GrpcGetDocLines(comments);
GrpcWriteDocCommentBody(printer, lines, false);
printer->Print(" */\n");
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
static void GrpcWriteServiceDocComment(Printer* printer,
const ServiceDescriptor* service) {
// Deviating from protobuf to avoid extraneous docs
// (see https://github.com/google/protobuf/issues/1406);
printer->Print("/**\n");
std::vector<string> lines = GrpcGetDocLinesForDescriptor(service);
GrpcWriteDocCommentBody(printer, lines, true);
printer->Print(" */\n");
}
// TODO(nmittler): Remove once protobuf includes javadoc methods in distribution.
void GrpcWriteMethodDocComment(Printer* printer,
const MethodDescriptor* method) {
// Deviating from protobuf to avoid extraneous docs
// (see https://github.com/google/protobuf/issues/1406);
printer->Print("/**\n");
std::vector<string> lines = GrpcGetDocLinesForDescriptor(method);
GrpcWriteDocCommentBody(printer, lines, true);
printer->Print(" */\n");
}
enum StubType {
ASYNC_INTERFACE = 0,
BLOCKING_CLIENT_INTERFACE = 1,
FUTURE_CLIENT_INTERFACE = 2,
BLOCKING_SERVER_INTERFACE = 3,
ASYNC_CLIENT_IMPL = 4,
BLOCKING_CLIENT_IMPL = 5,
FUTURE_CLIENT_IMPL = 6,
ABSTRACT_CLASS = 7,
};
enum CallType {
ASYNC_CALL = 0,
BLOCKING_CALL = 1,
FUTURE_CALL = 2
};
static void PrintMarshallerStaticBlock(const ServiceDescriptor* service,
std::map<string, string>* vars,
Printer* p) {
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* method = service->method(i);
(*vars)["input_type"] = google::protobuf::compiler::java::ClassName(method->input_type());
(*vars)["output_type"] = google::protobuf::compiler::java::ClassName(method->output_type());
p->Print(
*vars,
"private static final AtomicBoolean registered = new AtomicBoolean();\n\n");
p->Print(
*vars,
"private static Class<?> init() {\n"
" Class<?> clazz = null;\n"
" try {\n"
" clazz = Class.forName(DemoServiceDubbo.class.getName());\n"
" if (registered.compareAndSet(false, true)) {\n"
" $ProtobufUtils$.marshaller(\n"
" $input_type$.getDefaultInstance());\n"
" $ProtobufUtils$.marshaller(\n"
" $output_type$.getDefaultInstance());\n"
" }\n"
" } catch (ClassNotFoundException e) {\n"
" // ignore \n"
" }\n"
" return clazz;\n"
"}\n\n");
}
}
static void PrintDubboInterface(
const ServiceDescriptor* service,
std::map<string, string>* vars,
Printer* p, bool generate_nano) {
const string service_name = service->name();
(*vars)["service_name"] = service_name;
(*vars)["dubbo_interface"] = "I" + service_name;
p->Print(
"/**\n "
"* Code generated for Dubbo\n "
"*/\n"
);
p->Print(
*vars,
"public interface $dubbo_interface$ {\n\n"
" static Class<?> clazz = init();\n\n");
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* method = service->method(i);
(*vars)["input_type"] = MessageFullJavaName(generate_nano,
method->input_type());
(*vars)["output_type"] = MessageFullJavaName(generate_nano,
method->output_type());
(*vars)["lower_method_name"] = LowerMethodName(method);
// Simple RPC
p->Print(
*vars,
" $output_type$ $lower_method_name$($input_type$ request);\n\n");
// Simple Future RPC
p->Print(
*vars,
" $CompletableFuture$<$output_type$> $lower_method_name$Async(\n $input_type$ request);\n\n");
// p->Print(
// *vars,
// "default $CompletableFuture$<$output_type$> $lower_method_name$Async(\n"
// " $input_type$ request) {\n return CompletableFuture.completedFuture($lower_method_name$(request));\n}\n\n");
p->Outdent();
}
p->Outdent();
p->Print(" }\n\n");
}
static void PrintService(const ServiceDescriptor* service,
std::map<string, string>* vars,
Printer* p,
bool disable_version) {
(*vars)["service_name"] = service->name();
(*vars)["file_name"] = service->file()->name();
(*vars)["service_class_name"] = ServiceClassName(service);
(*vars)["grpc_version"] = "";
#ifdef GRPC_VERSION
if (!disable_version) {
(*vars)["grpc_version"] = " (version " XSTR(GRPC_VERSION) ")";
}
#endif
// TODO(nmittler): Replace with WriteServiceDocComment once included by protobuf distro.
GrpcWriteServiceDocComment(p, service);
p->Print(
*vars,
"@$Generated$(\n"
" value = \"by gRPC proto compiler$grpc_version$\",\n"
" comments = \"Source: $file_name$\")\n");
if (service->options().deprecated()) {
p->Print(*vars, "@$Deprecated$\n");
}
p->Print(
*vars,
"public final class $service_class_name$ {\n\n");
p->Indent();
PrintMarshallerStaticBlock(service, vars, p);
p->Print(
*vars,
"private $service_class_name$() {}\n\n");
p->Print(
*vars,
"public static final String SERVICE_NAME = "
"\"$Package$$service_name$\";\n\n");
PrintDubboInterface(service, vars, p, false);
p->Outdent();
p->Print("}\n");
}
void PrintImports(Printer* p) {
p->Print(
"import "
"java.util.concurrent.CompletableFuture;\n");
p->Print(
"import "
"java.util.concurrent.atomic.AtomicBoolean;\n");
}
void GenerateService(const ServiceDescriptor* service,
google::protobuf::io::ZeroCopyOutputStream* out,
ProtoFlavor flavor,
bool disable_version) {
// All non-generated classes must be referred by fully qualified names to
// avoid collision with generated classes.
std::map<string, string> vars;
vars["String"] = "java.lang.String";
vars["Deprecated"] = "java.lang.Deprecated";
vars["Override"] = "java.lang.Override";
vars["Iterator"] = "java.util.Iterator";
vars["Generated"] = "javax.annotation.Generated";
vars["CompletableFuture"] =
"java.util.concurrent.CompletableFuture";
vars["AtomicBoolean"] =
"java.util.concurrent.atomic.AtomicBoolean";
vars["ProtobufUtils"] =
"org.apache.dubbo.common.serialize.protobuf.support.ProtobufUtils";
Printer printer(out, '$');
string package_name = ServiceJavaPackage(service->file(),false);
if (!package_name.empty()) {
printer.Print(
"package $package_name$;\n\n",
"package_name", package_name);
}
PrintImports(&printer);
// Package string is used to fully qualify method names.
vars["Package"] = service->file()->package();
if (!vars["Package"].empty()) {
vars["Package"].append(".");
}
PrintService(service, &vars, &printer, false);
}
string ServiceJavaPackage(const FileDescriptor* file, bool nano) {
string result = google::protobuf::compiler::java::ClassName(file);
size_t last_dot_pos = result.find_last_of('.');
if (last_dot_pos != string::npos) {
result.resize(last_dot_pos);
} else {
result = "";
}
if (nano) {
if (!result.empty()) {
result += ".";
}
result += "nano";
}
return result;
}
string ServiceClassName(const google::protobuf::ServiceDescriptor* service) {
return service->name() + "Dubbo";
}
} // namespace java_dubbo_generator

File diff suppressed because it is too large Load Diff

View File

@ -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_

View File

@ -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);
}

View File

@ -0,0 +1,293 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.gen;
import com.google.common.base.Strings;
import com.google.common.html.HtmlEscapers;
import com.google.protobuf.DescriptorProtos.FileDescriptorProto;
import com.google.protobuf.DescriptorProtos.FileOptions;
import com.google.protobuf.DescriptorProtos.MethodDescriptorProto;
import com.google.protobuf.DescriptorProtos.ServiceDescriptorProto;
import com.google.protobuf.DescriptorProtos.SourceCodeInfo.Location;
import com.google.protobuf.compiler.PluginProtos;
import com.salesforce.jprotoc.Generator;
import com.salesforce.jprotoc.GeneratorException;
import com.salesforce.jprotoc.ProtoTypeMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public abstract class AbstractGenerator extends Generator {
private static final int SERVICE_NUMBER_OF_PATHS = 2;
private static final int METHOD_NUMBER_OF_PATHS = 4;
protected abstract String getClassPrefix();
protected abstract String getClassSuffix();
private String getServiceJavaDocPrefix() {
return " ";
}
private String getMethodJavaDocPrefix() {
return " ";
}
@Override
public List<PluginProtos.CodeGeneratorResponse.File> generateFiles(PluginProtos.CodeGeneratorRequest request) throws GeneratorException {
final ProtoTypeMap typeMap = ProtoTypeMap.of(request.getProtoFileList());
List<FileDescriptorProto> protosToGenerate = request.getProtoFileList().stream()
.filter(protoFile -> request.getFileToGenerateList().contains(protoFile.getName()))
.collect(Collectors.toList());
List<ServiceContext> services = findServices(protosToGenerate, typeMap);
return generateFiles(services);
}
private List<ServiceContext> findServices(List<FileDescriptorProto> protos, ProtoTypeMap typeMap) {
List<ServiceContext> contexts = new ArrayList<>();
protos.forEach(fileProto -> {
for (int serviceNumber = 0; serviceNumber < fileProto.getServiceCount(); serviceNumber++) {
ServiceContext serviceContext = buildServiceContext(
fileProto.getService(serviceNumber),
typeMap,
fileProto.getSourceCodeInfo().getLocationList(),
serviceNumber
);
serviceContext.protoName = fileProto.getName();
serviceContext.packageName = extractPackageName(fileProto);
contexts.add(serviceContext);
}
});
return contexts;
}
private String extractPackageName(FileDescriptorProto proto) {
FileOptions options = proto.getOptions();
if (options != null) {
String javaPackage = options.getJavaPackage();
if (!Strings.isNullOrEmpty(javaPackage)) {
return javaPackage;
}
}
return Strings.nullToEmpty(proto.getPackage());
}
private ServiceContext buildServiceContext(ServiceDescriptorProto serviceProto, ProtoTypeMap typeMap, List<Location> locations, int serviceNumber) {
ServiceContext serviceContext = new ServiceContext();
serviceContext.fileName = getClassPrefix() + serviceProto.getName() + getClassSuffix() + ".java";
serviceContext.className = getClassPrefix() + serviceProto.getName() + getClassSuffix();
serviceContext.serviceName = serviceProto.getName();
serviceContext.deprecated = serviceProto.getOptions() != null && serviceProto.getOptions().getDeprecated();
List<Location> allLocationsForService = locations.stream()
.filter(location ->
location.getPathCount() >= 2 &&
location.getPath(0) == FileDescriptorProto.SERVICE_FIELD_NUMBER &&
location.getPath(1) == serviceNumber
)
.collect(Collectors.toList());
Location serviceLocation = allLocationsForService.stream()
.filter(location -> location.getPathCount() == SERVICE_NUMBER_OF_PATHS)
.findFirst()
.orElseGet(Location::getDefaultInstance);
serviceContext.javaDoc = getJavaDoc(getComments(serviceLocation), getServiceJavaDocPrefix());
for (int methodNumber = 0; methodNumber < serviceProto.getMethodCount(); methodNumber++) {
MethodContext methodContext = buildMethodContext(
serviceProto.getMethod(methodNumber),
typeMap,
locations,
methodNumber
);
serviceContext.methods.add(methodContext);
serviceContext.methodTypes.add(methodContext.inputType);
serviceContext.methodTypes.add(methodContext.outputType);
}
return serviceContext;
}
private MethodContext buildMethodContext(MethodDescriptorProto methodProto, ProtoTypeMap typeMap, List<Location> locations, int methodNumber) {
MethodContext methodContext = new MethodContext();
methodContext.methodName = lowerCaseFirst(methodProto.getName());
methodContext.inputType = typeMap.toJavaTypeName(methodProto.getInputType());
methodContext.outputType = typeMap.toJavaTypeName(methodProto.getOutputType());
methodContext.deprecated = methodProto.getOptions() != null && methodProto.getOptions().getDeprecated();
methodContext.isManyInput = methodProto.getClientStreaming();
methodContext.isManyOutput = methodProto.getServerStreaming();
methodContext.methodNumber = methodNumber;
Location methodLocation = locations.stream()
.filter(location ->
location.getPathCount() == METHOD_NUMBER_OF_PATHS &&
location.getPath(METHOD_NUMBER_OF_PATHS - 1) == methodNumber
)
.findFirst()
.orElseGet(Location::getDefaultInstance);
methodContext.javaDoc = getJavaDoc(getComments(methodLocation), getMethodJavaDocPrefix());
if (!methodProto.getClientStreaming() && !methodProto.getServerStreaming()) {
methodContext.reactiveCallsMethodName = "oneToOne";
methodContext.grpcCallsMethodName = "asyncUnaryCall";
}
if (!methodProto.getClientStreaming() && methodProto.getServerStreaming()) {
methodContext.reactiveCallsMethodName = "oneToMany";
methodContext.grpcCallsMethodName = "asyncServerStreamingCall";
}
if (methodProto.getClientStreaming() && !methodProto.getServerStreaming()) {
methodContext.reactiveCallsMethodName = "manyToOne";
methodContext.grpcCallsMethodName = "asyncClientStreamingCall";
}
if (methodProto.getClientStreaming() && methodProto.getServerStreaming()) {
methodContext.reactiveCallsMethodName = "manyToMany";
methodContext.grpcCallsMethodName = "asyncBidiStreamingCall";
}
return methodContext;
}
private String lowerCaseFirst(String s) {
return Character.toLowerCase(s.charAt(0)) + s.substring(1);
}
private List<PluginProtos.CodeGeneratorResponse.File> generateFiles(List<ServiceContext> services) {
return services.stream()
.map(this::buildFile)
.collect(Collectors.toList());
}
private PluginProtos.CodeGeneratorResponse.File buildFile(ServiceContext context) {
String content = applyTemplate(getClassPrefix() + getClassSuffix() + "Stub.mustache", context);
return PluginProtos.CodeGeneratorResponse.File
.newBuilder()
.setName(absoluteFileName(context))
.setContent(content)
.build();
}
private String absoluteFileName(ServiceContext ctx) {
String dir = ctx.packageName.replace('.', '/');
if (Strings.isNullOrEmpty(dir)) {
return ctx.fileName;
} else {
return dir + "/" + ctx.fileName;
}
}
private String getComments(Location location) {
return location.getLeadingComments().isEmpty() ? location.getTrailingComments() : location.getLeadingComments();
}
private String getJavaDoc(String comments, String prefix) {
if (!comments.isEmpty()) {
StringBuilder builder = new StringBuilder("/**\n")
.append(prefix).append(" * <pre>\n");
Arrays.stream(HtmlEscapers.htmlEscaper().escape(comments).split("\n"))
.map(line -> line.replace("*/", "&#42;&#47;").replace("*", "&#42;"))
.forEach(line -> builder.append(prefix).append(" * ").append(line).append("\n"));
builder
.append(prefix).append(" * </pre>\n")
.append(prefix).append(" */");
return builder.toString();
}
return null;
}
/**
* Template class for proto Service objects.
*/
private class ServiceContext {
// CHECKSTYLE DISABLE VisibilityModifier FOR 8 LINES
public String fileName;
public String protoName;
public String packageName;
public String className;
public String serviceName;
public boolean deprecated;
public String javaDoc;
public List<MethodContext> methods = new ArrayList<>();
public Set<String> methodTypes = new HashSet<>();
public List<MethodContext> unaryRequestMethods() {
return methods.stream().filter(m -> !m.isManyInput).collect(Collectors.toList());
}
public List<MethodContext> unaryMethods() {
return methods.stream().filter(m -> (!m.isManyInput && !m.isManyOutput)).collect(Collectors.toList());
}
public List<MethodContext> serverStreamingMethods() {
return methods.stream().filter(m -> !m.isManyInput && m.isManyOutput).collect(Collectors.toList());
}
public List<MethodContext> biStreamingMethods() {
return methods.stream().filter(m -> m.isManyInput).collect(Collectors.toList());
}
}
/**
* Template class for proto RPC objects.
*/
private class MethodContext {
// CHECKSTYLE DISABLE VisibilityModifier FOR 10 LINES
public String methodName;
public String inputType;
public String outputType;
public boolean deprecated;
public boolean isManyInput;
public boolean isManyOutput;
public String reactiveCallsMethodName;
public String grpcCallsMethodName;
public int methodNumber;
public String javaDoc;
// This method mimics the upper-casing method ogf gRPC to ensure compatibility
// See https://github.com/grpc/grpc-java/blob/v1.8.0/compiler/src/java_plugin/cpp/java_generator.cpp#L58
public String methodNameUpperUnderscore() {
StringBuilder s = new StringBuilder();
for (int i = 0; i < methodName.length(); i++) {
char c = methodName.charAt(i);
s.append(Character.toUpperCase(c));
if ((i < methodName.length() - 1) && Character.isLowerCase(c) && Character.isUpperCase(methodName.charAt(i + 1))) {
s.append('_');
}
}
return s.toString();
}
public String methodNamePascalCase() {
String mn = methodName.replace("_", "");
return String.valueOf(Character.toUpperCase(mn.charAt(0))) + mn.substring(1);
}
public String methodNameCamelCase() {
String mn = methodName.replace("_", "");
return String.valueOf(Character.toLowerCase(mn.charAt(0))) + mn.substring(1);
}
}
}

View File

@ -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";
}
}

View File

@ -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";
}
}

View File

@ -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]);
}
}
}

View File

@ -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]);
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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}}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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>

View File

@ -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);

View File

@ -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);

View File

@ -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>

View File

@ -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);
}
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -1 +0,0 @@
http-invoker=org.apache.dubbo.rpc.protocol.httpinvoker.HttpInvokerProtocol

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -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>

View File

@ -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>