From d4c2852caf56746aa827530572cbcdc95450314b Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Fri, 30 Jun 2023 22:46:49 +0800 Subject: [PATCH 01/14] Prapare 3.3.0-beta.1 release --- dubbo-dependencies-bom/pom.xml | 2 +- .../dubbo-dependencies-zookeeper-curator5/pom.xml | 2 +- dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 5f72b4dfa6..2bd1ceb475 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -191,7 +191,7 @@ 2.0 1.5.0 1.23.0 - 3.3.0-beta.1-SNAPSHOT + 3.3.0-beta.1 diff --git a/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml b/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml index 41913dc5fd..6b09a1317b 100644 --- a/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml +++ b/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml @@ -32,7 +32,7 @@ pom - 3.3.0-beta.1-SNAPSHOT + 3.3.0-beta.1 1.5.0 5.1.0 3.8.1 diff --git a/dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml b/dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml index 678de29e88..8de4c660ac 100644 --- a/dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml +++ b/dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml @@ -32,7 +32,7 @@ pom - 3.3.0-beta.1-SNAPSHOT + 3.3.0-beta.1 1.5.0 4.3.0 3.4.14 diff --git a/pom.xml b/pom.xml index f8bee0e59f..016ff1c58a 100644 --- a/pom.xml +++ b/pom.xml @@ -137,7 +137,7 @@ 1.2.2 3.22.3 1.54.0 - 3.3.0-beta.1-SNAPSHOT + 3.3.0-beta.1 From 33a806330932d8e51df89513f2fc0ab382510b28 Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Fri, 30 Jun 2023 22:48:37 +0800 Subject: [PATCH 02/14] Update release test --- .github/workflows/release-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-test.yml b/.github/workflows/release-test.yml index 08fbec1abc..a6d7cccd78 100644 --- a/.github/workflows/release-test.yml +++ b/.github/workflows/release-test.yml @@ -41,7 +41,7 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: 8 + java-version: 17 - uses: actions/cache@v3 name: "Cache local Maven repository" with: @@ -132,7 +132,7 @@ jobs: fail-fast: false matrix: os: [ ubuntu-latest, windows-latest ] - jdk: [ 8, 11, 17, 19 ] + jdk: [ 17, 19 ] env: DISABLE_FILE_SYSTEM_TEST: true steps: @@ -169,7 +169,7 @@ jobs: fail-fast: false matrix: os: [ ubuntu-latest, windows-latest ] - jdk: [ 8, 11, 17, 19 ] + jdk: [ 17, 19 ] env: DISABLE_FILE_SYSTEM_TEST: true DUBBO_DEFAULT_SERIALIZATION: fastjson2 From 8bfdf1e38c8943fca68113b810e63aeb5e850303 Mon Sep 17 00:00:00 2001 From: icodening Date: Wed, 9 Aug 2023 14:00:25 +0800 Subject: [PATCH 03/14] unification HTTP server side (#12815) --- dubbo-distribution/dubbo-all/pom.xml | 20 + dubbo-remoting/dubbo-remoting-http12/pom.xml | 61 +++ .../http12/AbstractServerCallListener.java | 89 ++++ .../AbstractServerHttpChannelObserver.java | 151 ++++++ .../http12/BiStreamServerCallListener.java | 63 +++ .../remoting/http12/CompositeInputStream.java | 88 ++++ .../CustomizableHttpChannelObserver.java | 27 ++ .../remoting/http12/ErrorCodeHolder.java | 23 + .../dubbo/remoting/http12/ErrorResponse.java | 42 ++ .../http12/ErrorResponseCustomizer.java | 26 + .../http12/FlowControlStreamObserver.java | 43 ++ .../remoting/http12/HeadersCustomizer.java | 26 + .../dubbo/remoting/http12/HttpChannel.java | 34 ++ .../remoting/http12/HttpChannelHolder.java | 22 + .../remoting/http12/HttpChannelObserver.java | 25 + .../remoting/http12/HttpHeaderNames.java | 40 ++ .../dubbo/remoting/http12/HttpHeaders.java | 449 ++++++++++++++++++ .../remoting/http12/HttpInputMessage.java | 25 + .../dubbo/remoting/http12/HttpMetadata.java | 23 + .../remoting/http12/HttpOutputMessage.java | 36 ++ .../dubbo/remoting/http12/HttpStatus.java | 42 ++ .../http12/HttpTransportListener.java | 25 + .../remoting/http12/RequestMetadata.java | 25 + .../remoting/http12/ServerCallListener.java | 37 ++ .../ServerStreamServerCallListener.java | 53 +++ .../remoting/http12/TrailersCustomizer.java | 31 ++ .../http12/UnaryServerCallListener.java | 55 +++ .../http12/command/DataQueueCommand.java | 40 ++ .../http12/command/HeaderQueueCommand.java | 40 ++ .../command/HttpChannelQueueCommand.java | 36 ++ .../http12/command/HttpWriteQueue.java | 47 ++ .../remoting/http12/command/QueueCommand.java | 21 + .../http12/exception/DecodeException.java | 32 ++ .../http12/exception/EncodeException.java | 32 ++ .../http12/exception/HttpRequestTimeout.java | 42 ++ .../http12/exception/HttpStatusException.java | 40 ++ .../exception/IllegalPathException.java | 31 ++ .../exception/UnimplementedException.java | 31 ++ .../UnsupportedMediaTypeException.java | 31 ++ .../http12/h1/DefaultHttp1Request.java | 55 +++ .../http12/h1/DefaultHttp1Response.java | 45 ++ .../remoting/http12/h1/Http1InputMessage.java | 35 ++ .../remoting/http12/h1/Http1Metadata.java | 34 ++ .../http12/h1/Http1OutputMessage.java | 36 ++ .../remoting/http12/h1/Http1Request.java | 24 + .../http12/h1/Http1RequestMetadata.java | 56 +++ .../http12/h1/Http1ServerChannelObserver.java | 45 ++ .../h1/Http1ServerStreamChannelObserver.java | 49 ++ .../h1/Http1ServerTransportListener.java | 26 + .../Http1ServerTransportListenerFactory.java | 30 ++ .../h2/CancelableTransportListener.java | 27 ++ .../h2/DefaultHttp2StreamingDecoder.java | 53 +++ .../remoting/http12/h2/H2StreamChannel.java | 33 ++ .../h2/Http2CancelableStreamObserver.java | 29 ++ .../http12/h2/Http2ChannelDelegate.java | 66 +++ .../dubbo/remoting/http12/h2/Http2Header.java | 41 ++ .../remoting/http12/h2/Http2Headers.java | 36 ++ .../remoting/http12/h2/Http2InputMessage.java | 23 + .../http12/h2/Http2InputMessageFrame.java | 65 +++ .../http12/h2/Http2MetadataFrame.java | 57 +++ .../http12/h2/Http2OutputMessage.java | 32 ++ .../http12/h2/Http2OutputMessageFrame.java | 49 ++ .../http12/h2/Http2ServerChannelObserver.java | 96 ++++ .../Http2ServerTransportListenerFactory.java | 31 ++ .../remoting/http12/h2/Http2StreamFrame.java | 26 + .../http12/h2/Http2TransportListener.java | 23 + .../h2/command/Http2WriteQueueChannel.java | 58 +++ .../http12/h2/command/ResetQueueCommand.java | 42 ++ .../message/DefaultListeningDecoder.java | 49 ++ .../http12/message/HttpMessageCodec.java | 54 +++ .../remoting/http12/message/JsonCodec.java | 127 +++++ .../message/LengthFieldStreamingDecoder.java | 189 ++++++++ .../http12/message/ListeningDecoder.java | 43 ++ .../remoting/http12/message/MediaType.java | 66 +++ .../http12/message/MethodMetadata.java | 84 ++++ .../http12/message/StreamingDecoder.java | 23 + .../http12/netty4/HttpWriteQueueHandler.java | 42 ++ .../NettyHttpChannelFutureListener.java | 35 ++ .../http12/netty4/h1/NettyHttp1Channel.java | 66 +++ .../http12/netty4/h1/NettyHttp1Codec.java | 110 +++++ .../h1/NettyHttp1ConnectionHandler.java | 110 +++++ .../netty4/h2/NettyH2StreamChannel.java | 80 ++++ .../netty4/h2/NettyHttp2FrameCodec.java | 113 +++++ .../netty4/h2/NettyHttp2FrameHandler.java | 81 ++++ .../h2/NettyHttp2ProtocolSelectorHandler.java | 90 ++++ ...o.remoting.http12.message.HttpMessageCodec | 1 + dubbo-remoting/pom.xml | 1 + 87 files changed, 4590 insertions(+) create mode 100644 dubbo-remoting/dubbo-remoting-http12/pom.xml create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerCallListener.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/BiStreamServerCallListener.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/CompositeInputStream.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/CustomizableHttpChannelObserver.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorCodeHolder.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorResponse.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorResponseCustomizer.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/FlowControlStreamObserver.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HeadersCustomizer.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannel.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannelHolder.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannelObserver.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaderNames.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaders.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpInputMessage.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpMetadata.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpOutputMessage.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpStatus.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpTransportListener.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/RequestMetadata.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerCallListener.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerStreamServerCallListener.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/TrailersCustomizer.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/UnaryServerCallListener.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/DataQueueCommand.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HeaderQueueCommand.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HttpChannelQueueCommand.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HttpWriteQueue.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/QueueCommand.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/DecodeException.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/EncodeException.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/HttpRequestTimeout.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/HttpStatusException.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/IllegalPathException.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/UnimplementedException.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/UnsupportedMediaTypeException.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/DefaultHttp1Request.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/DefaultHttp1Response.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1InputMessage.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1Metadata.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1OutputMessage.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1Request.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1RequestMetadata.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerChannelObserver.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerStreamChannelObserver.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListener.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListenerFactory.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/CancelableTransportListener.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/DefaultHttp2StreamingDecoder.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/H2StreamChannel.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2CancelableStreamObserver.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ChannelDelegate.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Header.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Headers.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2InputMessage.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2InputMessageFrame.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2MetadataFrame.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2OutputMessage.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2OutputMessageFrame.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ServerChannelObserver.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ServerTransportListenerFactory.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2StreamFrame.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2TransportListener.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/command/Http2WriteQueueChannel.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/command/ResetQueueCommand.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/DefaultListeningDecoder.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodec.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/ListeningDecoder.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/MediaType.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/MethodMetadata.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/StreamingDecoder.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/HttpWriteQueueHandler.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/NettyHttpChannelFutureListener.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1Channel.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1Codec.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1ConnectionHandler.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyH2StreamChannel.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2FrameCodec.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2FrameHandler.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2ProtocolSelectorHandler.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index 838b31caee..3011ed31a8 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -482,6 +482,13 @@ compile true + + org.apache.dubbo + dubbo-remoting-http12 + ${project.version} + compile + true + org.apache.dubbo dubbo-remoting-netty @@ -720,6 +727,7 @@ org.apache.dubbo:dubbo-registry-zookeeper org.apache.dubbo:dubbo-remoting-api org.apache.dubbo:dubbo-remoting-http + org.apache.dubbo:dubbo-remoting-http12 org.apache.dubbo:dubbo-remoting-netty4 org.apache.dubbo:dubbo-remoting-netty org.apache.dubbo:dubbo-remoting-zookeeper-api @@ -1239,6 +1247,18 @@ META-INF/dubbo/internal/org.apache.dubbo.remoting.http.HttpBinder + + + META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec + + + + + META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory + + diff --git a/dubbo-remoting/dubbo-remoting-http12/pom.xml b/dubbo-remoting/dubbo-remoting-http12/pom.xml new file mode 100644 index 0000000000..514786699c --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + org.apache.dubbo + dubbo-remoting + ${revision} + ../pom.xml + + dubbo-remoting-http12 + jar + ${project.artifactId} + The http1/2 remoting module of dubbo project + + false + + + + org.apache.dubbo + dubbo-rpc-api + ${project.parent.version} + + + org.apache.dubbo + dubbo-common + ${project.parent.version} + + + org.apache.dubbo + dubbo-remoting-api + ${project.parent.version} + + + + io.netty + netty-transport + + + io.netty + netty-codec-http2 + + + + + diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerCallListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerCallListener.java new file mode 100644 index 0000000000..dfa8ac877e --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerCallListener.java @@ -0,0 +1,89 @@ +/* + * 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.remoting.http12; + +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.stream.StreamObserver; +import org.apache.dubbo.remoting.http12.exception.HttpRequestTimeout; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcInvocation; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_TIMEOUT_SERVER; + +public abstract class AbstractServerCallListener implements ServerCallListener { + + private static final ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(AbstractServerCallListener.class); + + protected final RpcInvocation invocation; + + protected final Invoker invoker; + + protected final StreamObserver responseObserver; + + public AbstractServerCallListener(RpcInvocation invocation, + Invoker invoker, + StreamObserver responseObserver) { + this.invocation = invocation; + this.invoker = invoker; + this.responseObserver = responseObserver; + } + + public void invoke() { + try { + final long stInMillis = System.currentTimeMillis(); + final Result response = invoker.invoke(invocation); + response.whenCompleteWithContext((r, t) -> { + if (t != null) { + responseObserver.onError(t); + return; + } + if (response.hasException()) { + doOnResponseHasException(response.getException()); + return; + } + final long cost = System.currentTimeMillis() - stInMillis; + Long timeout = (Long) invocation.get("timeout"); + if (timeout != null && timeout < cost) { + LOGGER.error(PROTOCOL_TIMEOUT_SERVER, "", "", String.format( + "Invoke timeout at server side, ignored to send response. service=%s method=%s cost=%s", + invocation.getTargetServiceUniqueName(), + invocation.getMethodName(), + cost)); + HttpRequestTimeout serverSideTimeout = HttpRequestTimeout.serverSide(); + responseObserver.onError(serverSideTimeout); + return; + } + onReturn(r.getValue()); + }); + } catch (Exception e) { + responseObserver.onError(e); + } finally { + RpcContext.removeCancellationContext(); + RpcContext.removeContext(); + } + } + + protected void doOnResponseHasException(Throwable t) { + responseObserver.onError(t); + } + + public abstract void onReturn(Object value); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java new file mode 100644 index 0000000000..5af04e629f --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java @@ -0,0 +1,151 @@ +/* + * 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.remoting.http12; + +import org.apache.dubbo.remoting.http12.exception.HttpStatusException; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; + +public abstract class AbstractServerHttpChannelObserver implements CustomizableHttpChannelObserver { + + private HeadersCustomizer headersCustomizer = HeadersCustomizer.NO_OP; + + private TrailersCustomizer trailersCustomizer = TrailersCustomizer.NO_OP; + + private ErrorResponseCustomizer errorResponseCustomizer = ErrorResponseCustomizer.NO_OP; + + private final HttpChannel httpChannel; + + private boolean headerSent; + + private HttpMessageCodec httpMessageCodec; + + public AbstractServerHttpChannelObserver(HttpChannel httpChannel) { + this.httpChannel = httpChannel; + } + + public void setHttpMessageCodec(HttpMessageCodec httpMessageCodec) { + this.httpMessageCodec = httpMessageCodec; + } + + @Override + public void setHeadersCustomizer(HeadersCustomizer headersCustomizer) { + this.headersCustomizer = headersCustomizer; + } + + @Override + public void setTrailersCustomizer(TrailersCustomizer trailersCustomizer) { + this.trailersCustomizer = trailersCustomizer; + } + + @Override + public void setErrorResponseCustomizer(ErrorResponseCustomizer errorResponseCustomizer) { + this.errorResponseCustomizer = errorResponseCustomizer; + } + + protected HeadersCustomizer getHeadersCustomizer() { + return headersCustomizer; + } + + protected TrailersCustomizer getTrailersCustomizer() { + return trailersCustomizer; + } + + @Override + public void onNext(Object data) { + try { + if (!headerSent) { + doSendHeaders(HttpStatus.OK.getStatusString()); + } + HttpOutputMessage outputMessage = encodeHttpOutputMessage(data); + preOutputMessage(outputMessage); + this.httpMessageCodec.encode(outputMessage.getBody(), data); + getHttpChannel().writeMessage(outputMessage); + postOutputMessage(outputMessage); + } catch (Throwable e) { + onError(e); + } + } + + protected void preOutputMessage(HttpOutputMessage outputMessage) throws Throwable { + + } + + protected void postOutputMessage(HttpOutputMessage outputMessage) throws Throwable { + + } + + protected abstract HttpMetadata encodeHttpMetadata(); + + protected HttpOutputMessage encodeHttpOutputMessage(Object data) { + return getHttpChannel().newOutputMessage(); + } + + protected HttpMetadata encodeTrailers(Throwable throwable) { + return null; + } + + @Override + public void onError(Throwable throwable) { + int httpStatusCode = HttpStatus.INTERNAL_SERVER_ERROR.getCode(); + if (throwable instanceof HttpStatusException) { + httpStatusCode = ((HttpStatusException) throwable).getStatusCode(); + } + if (!headerSent) { + doSendHeaders(String.valueOf(httpStatusCode)); + } + try { + ErrorResponse errorResponse = new ErrorResponse(); + errorResponse.setStatus(String.valueOf(httpStatusCode)); + errorResponse.setMessage(throwable.getMessage()); + this.errorResponseCustomizer.accept(errorResponse, throwable); + HttpOutputMessage httpOutputMessage = encodeHttpOutputMessage(errorResponse); + this.httpMessageCodec.encode(httpOutputMessage.getBody(), errorResponse); + getHttpChannel().writeMessage(httpOutputMessage); + } finally { + doOnCompleted(throwable); + } + } + + @Override + public void onCompleted() { + doOnCompleted(null); + } + + @Override + public HttpChannel getHttpChannel() { + return httpChannel; + } + + private void doSendHeaders(String statusCode) { + HttpMetadata httpMetadata = encodeHttpMetadata(); + httpMetadata.headers().set(HttpHeaderNames.STATUS.getName(), statusCode); + httpMetadata.headers().set(HttpHeaderNames.CONTENT_TYPE.getName(), httpMessageCodec.contentType().getName()); + this.headersCustomizer.accept(httpMetadata.headers()); + getHttpChannel().writeHeader(httpMetadata); + this.headerSent = true; + } + + protected void doOnCompleted(Throwable throwable) { + HttpMetadata httpMetadata = encodeTrailers(throwable); + if (httpMetadata == null) { + return; + } + this.trailersCustomizer.accept(httpMetadata.headers(), throwable); + getHttpChannel().writeHeader(httpMetadata); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/BiStreamServerCallListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/BiStreamServerCallListener.java new file mode 100644 index 0000000000..705031f98f --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/BiStreamServerCallListener.java @@ -0,0 +1,63 @@ +/* + * 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.remoting.http12; + +import org.apache.dubbo.common.stream.StreamObserver; +import org.apache.dubbo.remoting.http12.exception.HttpStatusException; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcInvocation; + +public class BiStreamServerCallListener extends AbstractServerCallListener { + + private StreamObserver requestObserver; + + public BiStreamServerCallListener(RpcInvocation invocation, + Invoker invoker, + FlowControlStreamObserver responseObserver) { + super(invocation, invoker, responseObserver); + invocation.setArguments(new Object[]{responseObserver}); + invoke(); + } + + @Override + @SuppressWarnings("all") + public void onReturn(Object value) { + this.requestObserver = (StreamObserver) value; + } + + @Override + public void onMessage(Object message) { + if (message instanceof Object[]) { + message = ((Object[]) message)[0]; + } + requestObserver.onNext(message); + if (((FlowControlStreamObserver) responseObserver).isAutoRequestN()) { + ((FlowControlStreamObserver) responseObserver).request(1); + } + } + + @Override + public void onCancel(long code) { + requestObserver.onError(new HttpStatusException((int) code)); + } + + @Override + public void onComplete() { + requestObserver.onCompleted(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/CompositeInputStream.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/CompositeInputStream.java new file mode 100644 index 0000000000..9b8b248eb0 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/CompositeInputStream.java @@ -0,0 +1,88 @@ +/* + * 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.remoting.http12; + +import org.apache.dubbo.remoting.http12.exception.DecodeException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class CompositeInputStream extends InputStream { + + private final Queue inputStreams = new ConcurrentLinkedQueue<>(); + + private int totalAvailable = 0; + + private int readIndex = 0; + + public void addInputStream(InputStream inputStream) { + this.inputStreams.offer(inputStream); + try { + this.totalAvailable += inputStream.available(); + } catch (IOException e) { + throw new DecodeException(e); + } + } + + @Override + public int read() throws IOException { + InputStream inputStream; + while ((inputStream = inputStreams.peek()) != null) { + int available = inputStream.available(); + if (available == 0) { + releaseHeadStream(); + continue; + } + int read = inputStream.read(); + if (read != -1) { + ++readIndex; + releaseIfNecessary(inputStream); + return read; + } + releaseHeadStream(); + } + return -1; + } + + @Override + public int available() { + return totalAvailable - readIndex; + } + + @Override + public void close() throws IOException { + InputStream inputStream; + while ((inputStream = inputStreams.poll()) != null) { + inputStream.close(); + } + } + + private void releaseHeadStream() throws IOException { + InputStream removeStream = inputStreams.remove(); + removeStream.close(); + } + + private void releaseIfNecessary(InputStream inputStream) throws IOException { + int available = inputStream.available(); + if (available == 0) { + inputStream.close(); + releaseHeadStream(); + } + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/CustomizableHttpChannelObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/CustomizableHttpChannelObserver.java new file mode 100644 index 0000000000..e43e8d9b49 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/CustomizableHttpChannelObserver.java @@ -0,0 +1,27 @@ +/* + * 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.remoting.http12; + +public interface CustomizableHttpChannelObserver extends HttpChannelObserver { + + void setHeadersCustomizer(HeadersCustomizer headersCustomizer); + + void setTrailersCustomizer(TrailersCustomizer trailersCustomizer); + + void setErrorResponseCustomizer(ErrorResponseCustomizer errorResponseCustomizer); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorCodeHolder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorCodeHolder.java new file mode 100644 index 0000000000..fa7361aa9c --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorCodeHolder.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12; + +public interface ErrorCodeHolder { + + long getErrorCode(); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorResponse.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorResponse.java new file mode 100644 index 0000000000..efe5c2bb4d --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorResponse.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12; + +import java.io.Serializable; + +public class ErrorResponse implements Serializable { + + private String status; + + private String message; + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorResponseCustomizer.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorResponseCustomizer.java new file mode 100644 index 0000000000..1d9a21c9fc --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorResponseCustomizer.java @@ -0,0 +1,26 @@ +/* + * 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.remoting.http12; + +import java.util.function.BiConsumer; + +@FunctionalInterface +public interface ErrorResponseCustomizer extends BiConsumer { + + ErrorResponseCustomizer NO_OP = (errorResponse, throwable) -> { + }; +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/FlowControlStreamObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/FlowControlStreamObserver.java new file mode 100644 index 0000000000..92bfd38e1e --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/FlowControlStreamObserver.java @@ -0,0 +1,43 @@ +/* + * 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.remoting.http12; + +import org.apache.dubbo.common.stream.StreamObserver; + +public interface FlowControlStreamObserver extends StreamObserver { + + /** + * Requests the peer to produce {@code count} more messages to be delivered to the 'inbound' + * {@link StreamObserver}. + * + *

This method is safe to call from multiple threads without external synchronization. + * + * @param count more messages + */ + void request(int count); + + boolean isAutoRequestN(); + + /** + * Swaps to manual flow control where no message will be delivered to {@link + * StreamObserver#onNext(Object)} unless it is {@link #request request()}ed. Since {@code + * request()} may not be called before the call is started, a number of initial requests may be + * specified. + */ + void disableAutoFlowControl(); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HeadersCustomizer.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HeadersCustomizer.java new file mode 100644 index 0000000000..a94823dd5d --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HeadersCustomizer.java @@ -0,0 +1,26 @@ +/* + * 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.remoting.http12; + +import java.util.function.Consumer; + +@FunctionalInterface +public interface HeadersCustomizer extends Consumer { + + HeadersCustomizer NO_OP = headers -> { + }; +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannel.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannel.java new file mode 100644 index 0000000000..8b9a9f2a2f --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannel.java @@ -0,0 +1,34 @@ +/* + * 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.remoting.http12; + +import java.net.SocketAddress; +import java.util.concurrent.CompletableFuture; + +public interface HttpChannel { + + CompletableFuture writeHeader(HttpMetadata httpMetadata); + + CompletableFuture writeMessage(HttpOutputMessage httpOutputMessage); + + HttpOutputMessage newOutputMessage(); + + SocketAddress remoteAddress(); + + void flush(); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannelHolder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannelHolder.java new file mode 100644 index 0000000000..f38149a3b0 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannelHolder.java @@ -0,0 +1,22 @@ +/* + * 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.remoting.http12; + +public interface HttpChannelHolder { + + HttpChannel getHttpChannel(); +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannelObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannelObserver.java new file mode 100644 index 0000000000..12b51b44e5 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpChannelObserver.java @@ -0,0 +1,25 @@ +/* + * 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.remoting.http12; + +import org.apache.dubbo.common.stream.StreamObserver; + +public interface HttpChannelObserver extends StreamObserver { + + HttpChannel getHttpChannel(); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaderNames.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaderNames.java new file mode 100644 index 0000000000..cdbf64fa58 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaderNames.java @@ -0,0 +1,40 @@ +/* + * 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.remoting.http12; + +public enum HttpHeaderNames { + + STATUS(":status"), + + CONTENT_TYPE("content-type"), + + CONTENT_LENGTH("content-length"), + + TRANSFER_ENCODING("transfer-encoding"), + + TE("te"); + + private final String name; + + HttpHeaderNames(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaders.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaders.java new file mode 100644 index 0000000000..9f6ddf8848 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaders.java @@ -0,0 +1,449 @@ +/* + * 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.remoting.http12; + +import java.io.Serializable; +import java.util.AbstractCollection; +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.Function; + +public class HttpHeaders implements Map>, Serializable, Cloneable { + + private final LinkedHashMap> targetMap; + + private final HashMap caseInsensitiveKeys; + + private final Locale locale; + + private transient volatile Set keySet; + + private transient volatile Collection> values; + + private transient volatile Set>> entrySet; + + public HttpHeaders() { + this.targetMap = new LinkedHashMap<>(); + this.caseInsensitiveKeys = new HashMap<>(); + this.locale = Locale.US; + } + + + // Implementation of java.util.Map + + @Override + public int size() { + return this.targetMap.size(); + } + + @Override + public boolean isEmpty() { + return this.targetMap.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return (key instanceof String && this.caseInsensitiveKeys.containsKey(convertKey((String) key))); + } + + @Override + public boolean containsValue(Object value) { + return this.targetMap.containsValue(value); + } + + @Override + public List get(Object key) { + if (key instanceof String) { + String caseInsensitiveKey = this.caseInsensitiveKeys.get(convertKey((String) key)); + if (caseInsensitiveKey != null) { + return this.targetMap.get(caseInsensitiveKey); + } + } + return null; + } + + public String getFirst(String name) { + List values = get(name); + if (values == null || values.isEmpty()) { + return null; + } + return values.get(0); + } + + public void set(String name, String value) { + List values = new ArrayList<>(); + values.add(value); + put(name, values); + } + + @Override + + public List getOrDefault(Object key, List defaultValue) { + if (key instanceof String) { + String caseInsensitiveKey = this.caseInsensitiveKeys.get(convertKey((String) key)); + if (caseInsensitiveKey != null) { + return this.targetMap.get(caseInsensitiveKey); + } + } + return defaultValue; + } + + @Override + public List put(String key, List value) { + String oldKey = this.caseInsensitiveKeys.put(convertKey(key), key); + List oldKeyValue = null; + if (oldKey != null && !oldKey.equals(key)) { + oldKeyValue = this.targetMap.remove(oldKey); + } + List oldValue = this.targetMap.put(key, value); + return (oldKeyValue != null ? oldKeyValue : oldValue); + } + + @Override + public void putAll(Map> map) { + if (map.isEmpty()) { + return; + } + map.forEach(this::put); + } + + @Override + + public List putIfAbsent(String key, List value) { + String oldKey = this.caseInsensitiveKeys.putIfAbsent(convertKey(key), key); + if (oldKey != null) { + List oldKeyValue = this.targetMap.get(oldKey); + if (oldKeyValue != null) { + return oldKeyValue; + } else { + key = oldKey; + } + } + return this.targetMap.putIfAbsent(key, value); + } + + @Override + + public List computeIfAbsent(String key, Function> mappingFunction) { + String oldKey = this.caseInsensitiveKeys.putIfAbsent(convertKey(key), key); + if (oldKey != null) { + List oldKeyValue = this.targetMap.get(oldKey); + if (oldKeyValue != null) { + return oldKeyValue; + } else { + key = oldKey; + } + } + return this.targetMap.computeIfAbsent(key, mappingFunction); + } + + @Override + + public List remove(Object key) { + if (key instanceof String) { + String caseInsensitiveKey = removeCaseInsensitiveKey((String) key); + if (caseInsensitiveKey != null) { + return this.targetMap.remove(caseInsensitiveKey); + } + } + return null; + } + + @Override + public void clear() { + this.caseInsensitiveKeys.clear(); + this.targetMap.clear(); + } + + @Override + public Set keySet() { + Set keySet = this.keySet; + if (keySet == null) { + keySet = new KeySet(this.targetMap.keySet()); + this.keySet = keySet; + } + return keySet; + } + + @Override + public Collection> values() { + Collection> values = this.values; + if (values == null) { + values = new Values(this.targetMap.values()); + this.values = values; + } + return values; + } + + @Override + public Set>> entrySet() { + Set>> entrySet = this.entrySet; + if (entrySet == null) { + entrySet = new EntrySet(this.targetMap.entrySet()); + this.entrySet = entrySet; + } + return entrySet; + } + + public Map toSingleValueMap() { + Map result = new HashMap<>(this.targetMap.size()); + for (String key : keySet()) { + result.put(key, getFirst(key)); + } + return result; + } + + @Override + public boolean equals(Object other) { + return (this == other || this.targetMap.equals(other)); + } + + @Override + public int hashCode() { + return this.targetMap.hashCode(); + } + + @Override + public String toString() { + return this.targetMap.toString(); + } + + + public Locale getLocale() { + return this.locale; + } + + protected String convertKey(String key) { + return key.toLowerCase(getLocale()); + } + + protected boolean removeEldestEntry(Map.Entry> eldest) { + return false; + } + + + private String removeCaseInsensitiveKey(String key) { + return this.caseInsensitiveKeys.remove(convertKey(key)); + } + + + private class KeySet extends AbstractSet { + + private final Set delegate; + + KeySet(Set delegate) { + this.delegate = delegate; + } + + @Override + public int size() { + return this.delegate.size(); + } + + @Override + public boolean contains(Object o) { + return this.delegate.contains(o); + } + + @Override + public Iterator iterator() { + return new KeySetIterator(); + } + + @Override + public boolean remove(Object o) { + return HttpHeaders.this.remove(o) != null; + } + + @Override + public void clear() { + HttpHeaders.this.clear(); + } + + @Override + public Spliterator spliterator() { + return this.delegate.spliterator(); + } + + @Override + public void forEach(Consumer action) { + this.delegate.forEach(action); + } + } + + + private class Values extends AbstractCollection> { + + private final Collection> delegate; + + Values(Collection> delegate) { + this.delegate = delegate; + } + + @Override + public int size() { + return this.delegate.size(); + } + + @Override + public boolean contains(Object o) { + return this.delegate.contains(o); + } + + @Override + public Iterator> iterator() { + return new ValuesIterator(); + } + + @Override + public void clear() { + HttpHeaders.this.clear(); + } + + @Override + public Spliterator> spliterator() { + return this.delegate.spliterator(); + } + + @Override + public void forEach(Consumer> action) { + this.delegate.forEach(action); + } + } + + + private class EntrySet extends AbstractSet>> { + + private final Set>> delegate; + + public EntrySet(Set>> delegate) { + this.delegate = delegate; + } + + @Override + public int size() { + return this.delegate.size(); + } + + @Override + public boolean contains(Object o) { + return this.delegate.contains(o); + } + + @Override + public Iterator>> iterator() { + return new EntrySetIterator(); + } + + @Override + @SuppressWarnings("unchecked") + public boolean remove(Object o) { + if (this.delegate.remove(o)) { + removeCaseInsensitiveKey(((Map.Entry>) o).getKey()); + return true; + } + return false; + } + + @Override + public void clear() { + this.delegate.clear(); + caseInsensitiveKeys.clear(); + } + + @Override + public Spliterator>> spliterator() { + return this.delegate.spliterator(); + } + + @Override + public void forEach(Consumer>> action) { + this.delegate.forEach(action); + } + } + + + private abstract class EntryIterator implements Iterator { + + private final Iterator>> delegate; + + + private Entry> last; + + public EntryIterator() { + this.delegate = targetMap.entrySet().iterator(); + } + + protected Entry> nextEntry() { + Entry> entry = this.delegate.next(); + this.last = entry; + return entry; + } + + @Override + public boolean hasNext() { + return this.delegate.hasNext(); + } + + @Override + public void remove() { + this.delegate.remove(); + if (this.last != null) { + removeCaseInsensitiveKey(this.last.getKey()); + this.last = null; + } + } + } + + + private class KeySetIterator extends EntryIterator { + + @Override + public String next() { + return nextEntry().getKey(); + } + } + + + private class ValuesIterator extends EntryIterator> { + + @Override + public List next() { + return nextEntry().getValue(); + } + } + + + private class EntrySetIterator extends EntryIterator>> { + + @Override + public Entry> next() { + return nextEntry(); + } + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpInputMessage.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpInputMessage.java new file mode 100644 index 0000000000..b80833764a --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpInputMessage.java @@ -0,0 +1,25 @@ +/* + * 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.remoting.http12; + +import java.io.InputStream; + +public interface HttpInputMessage { + + InputStream getBody(); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpMetadata.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpMetadata.java new file mode 100644 index 0000000000..c1fce4a759 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpMetadata.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12; + +public interface HttpMetadata { + + HttpHeaders headers(); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpOutputMessage.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpOutputMessage.java new file mode 100644 index 0000000000..ff8210ab4c --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpOutputMessage.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; + +public interface HttpOutputMessage { + + HttpOutputMessage EMPTY_MESSAGE = new HttpOutputMessage() { + + private final OutputStream INPUT_STREAM = new ByteArrayOutputStream(0); + + @Override + public OutputStream getBody() { + return INPUT_STREAM; + } + }; + + OutputStream getBody(); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpStatus.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpStatus.java new file mode 100644 index 0000000000..675737f2df --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpStatus.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12; + +public enum HttpStatus { + + OK(200), + REQUEST_TIMEOUT(408), + UNSUPPORTED_MEDIA_TYPE(415), + INTERNAL_SERVER_ERROR(500); + + private final int code; + + private final String statusString; + + HttpStatus(int code) { + this.code = code; + this.statusString = String.valueOf(code); + } + + public int getCode() { + return code; + } + + public String getStatusString() { + return statusString; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpTransportListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpTransportListener.java new file mode 100644 index 0000000000..e478a45f21 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpTransportListener.java @@ -0,0 +1,25 @@ +/* + * 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.remoting.http12; + +public interface HttpTransportListener

{ + + void onMetadata(HEADER metadata); + + void onData(MESSAGE message); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/RequestMetadata.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/RequestMetadata.java new file mode 100644 index 0000000000..7d3c773764 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/RequestMetadata.java @@ -0,0 +1,25 @@ +/* + * 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.remoting.http12; + +public interface RequestMetadata extends HttpMetadata { + + String method(); + + String path(); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerCallListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerCallListener.java new file mode 100644 index 0000000000..d5d076029f --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerCallListener.java @@ -0,0 +1,37 @@ +/* + * 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.remoting.http12; + +public interface ServerCallListener { + + /** + * Callback when a request message is received. + * + * @param message message received + */ + void onMessage(Object message); + + /** + * @param code when the call is canceled. + */ + void onCancel(long code); + + /** + * Request completed. + */ + void onComplete(); +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerStreamServerCallListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerStreamServerCallListener.java new file mode 100644 index 0000000000..e65478eb1f --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerStreamServerCallListener.java @@ -0,0 +1,53 @@ +/* + * 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.remoting.http12; + +import org.apache.dubbo.common.stream.StreamObserver; +import org.apache.dubbo.remoting.http12.exception.HttpStatusException; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcInvocation; + +public class ServerStreamServerCallListener extends AbstractServerCallListener { + + public ServerStreamServerCallListener(RpcInvocation invocation, Invoker invoker, + StreamObserver responseObserver) { + super(invocation, invoker, responseObserver); + } + + @Override + public void onReturn(Object value) { + } + + @Override + public void onMessage(Object message) { + if (message instanceof Object[]) { + message = ((Object[]) message)[0]; + } + invocation.setArguments(new Object[]{message, responseObserver}); + } + + @Override + public void onCancel(long code) { + responseObserver.onError(new HttpStatusException((int) code)); + } + + @Override + public void onComplete() { + invoke(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/TrailersCustomizer.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/TrailersCustomizer.java new file mode 100644 index 0000000000..a96290dd08 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/TrailersCustomizer.java @@ -0,0 +1,31 @@ +/* + * 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.remoting.http12; + +import java.util.function.BiConsumer; + +@FunctionalInterface +public interface TrailersCustomizer extends BiConsumer, HeadersCustomizer { + + TrailersCustomizer NO_OP = (headers, throwable) -> { + }; + + @Override + default void accept(HttpHeaders headers) { + this.accept(headers, null); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/UnaryServerCallListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/UnaryServerCallListener.java new file mode 100644 index 0000000000..e1a985803f --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/UnaryServerCallListener.java @@ -0,0 +1,55 @@ +/* + * 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.remoting.http12; + +import org.apache.dubbo.common.stream.StreamObserver; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcInvocation; + +public class UnaryServerCallListener extends AbstractServerCallListener { + + public UnaryServerCallListener(RpcInvocation invocation, + Invoker invoker, + StreamObserver responseObserver) { + super(invocation, invoker, responseObserver); + } + + @Override + public void onReturn(Object value) { + responseObserver.onNext(value); + responseObserver.onCompleted(); + } + + @Override + public void onMessage(Object message) { + if (message instanceof Object[]) { + invocation.setArguments((Object[]) message); + } else { + invocation.setArguments(new Object[]{message}); + } + } + + @Override + public void onCancel(long code) { + //ignore + } + + @Override + public void onComplete() { + invoke(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/DataQueueCommand.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/DataQueueCommand.java new file mode 100644 index 0000000000..8594dcb011 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/DataQueueCommand.java @@ -0,0 +1,40 @@ +/* + * 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.remoting.http12.command; + +import org.apache.dubbo.remoting.http12.HttpOutputMessage; + +public class DataQueueCommand extends HttpChannelQueueCommand { + + private final HttpOutputMessage httpOutputMessage; + + public DataQueueCommand(HttpOutputMessage httpMessage) { + this.httpOutputMessage = httpMessage; + } + + @Override + public void run() { + getHttpChannel().writeMessage(httpOutputMessage) + .whenComplete((unused, throwable) -> { + if (throwable != null) { + completeExceptionally(throwable); + } else { + complete(unused); + } + }); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HeaderQueueCommand.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HeaderQueueCommand.java new file mode 100644 index 0000000000..8464260cf9 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HeaderQueueCommand.java @@ -0,0 +1,40 @@ +/* + * 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.remoting.http12.command; + +import org.apache.dubbo.remoting.http12.HttpMetadata; + +public class HeaderQueueCommand extends HttpChannelQueueCommand { + + private final HttpMetadata httpMetadata; + + public HeaderQueueCommand(HttpMetadata httpMetadata) { + this.httpMetadata = httpMetadata; + } + + @Override + public void run() { + getHttpChannel().writeHeader(httpMetadata) + .whenComplete((unused, throwable) -> { + if (throwable != null) { + completeExceptionally(throwable); + } else { + complete(unused); + } + }); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HttpChannelQueueCommand.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HttpChannelQueueCommand.java new file mode 100644 index 0000000000..0d327d1282 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HttpChannelQueueCommand.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.command; + +import org.apache.dubbo.remoting.http12.HttpChannel; +import org.apache.dubbo.remoting.http12.HttpChannelHolder; + +import java.util.concurrent.CompletableFuture; + +public abstract class HttpChannelQueueCommand extends CompletableFuture implements QueueCommand, HttpChannelHolder { + + private HttpChannelHolder httpChannelHolder; + + public void setHttpChannel(HttpChannelHolder httpChannelHolder) { + this.httpChannelHolder = httpChannelHolder; + } + + public HttpChannel getHttpChannel() { + return httpChannelHolder.getHttpChannel(); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HttpWriteQueue.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HttpWriteQueue.java new file mode 100644 index 0000000000..f7a04cc0d4 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/HttpWriteQueue.java @@ -0,0 +1,47 @@ +/* + * 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.remoting.http12.command; + +import org.apache.dubbo.common.BatchExecutorQueue; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +public class HttpWriteQueue extends BatchExecutorQueue { + + private final Executor executor; + + public HttpWriteQueue(Executor executor) { + this.executor = executor; + } + + public CompletableFuture enqueue(HttpChannelQueueCommand cmd) { + this.enqueue(cmd, this.executor); + return cmd; + } + + @Override + protected void prepare(HttpChannelQueueCommand item) { + item.run(); + } + + @Override + protected void flush(HttpChannelQueueCommand item) { + item.run(); + item.getHttpChannel().flush(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/QueueCommand.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/QueueCommand.java new file mode 100644 index 0000000000..dceeaacd9c --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/command/QueueCommand.java @@ -0,0 +1,21 @@ +/* + * 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.remoting.http12.command; + +public interface QueueCommand extends Runnable { + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/DecodeException.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/DecodeException.java new file mode 100644 index 0000000000..af426da47d --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/DecodeException.java @@ -0,0 +1,32 @@ +/* + * 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.remoting.http12.exception; + +public class DecodeException extends HttpStatusException { + + public DecodeException() { + super(500); + } + + public DecodeException(String message) { + super(500, message); + } + + public DecodeException(Throwable cause) { + super(500, cause); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/EncodeException.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/EncodeException.java new file mode 100644 index 0000000000..83197f66d5 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/EncodeException.java @@ -0,0 +1,32 @@ +/* + * 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.remoting.http12.exception; + +public class EncodeException extends HttpStatusException { + + public EncodeException(String message) { + super(500, message); + } + + public EncodeException(String message, Throwable cause) { + super(500, message); + } + + public EncodeException(Throwable cause) { + super(500, cause); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/HttpRequestTimeout.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/HttpRequestTimeout.java new file mode 100644 index 0000000000..973369b6c8 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/HttpRequestTimeout.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.exception; + +import org.apache.dubbo.remoting.http12.HttpStatus; + +public class HttpRequestTimeout extends HttpStatusException { + + private final String side; + + private HttpRequestTimeout(String side) { + super(HttpStatus.REQUEST_TIMEOUT.getCode()); + this.side = side; + } + + public String getSide() { + return side; + } + + public static HttpRequestTimeout serverSide(){ + return new HttpRequestTimeout("server"); + } + + public static HttpRequestTimeout clientSide(){ + return new HttpRequestTimeout("client"); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/HttpStatusException.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/HttpStatusException.java new file mode 100644 index 0000000000..dd9104aa5f --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/HttpStatusException.java @@ -0,0 +1,40 @@ +/* + * 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.remoting.http12.exception; + +public class HttpStatusException extends RuntimeException { + + private final int statusCode; + + public HttpStatusException(int statusCode) { + this(statusCode, "Unknown Error"); + } + + public HttpStatusException(int statusCode, String message) { + super(message); + this.statusCode = statusCode; + } + + public HttpStatusException(int statusCode, Throwable cause) { + super(cause); + this.statusCode = statusCode; + } + + public int getStatusCode() { + return statusCode; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/IllegalPathException.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/IllegalPathException.java new file mode 100644 index 0000000000..96e36082af --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/IllegalPathException.java @@ -0,0 +1,31 @@ +/* + * 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.remoting.http12.exception; + +public class IllegalPathException extends RuntimeException{ + + public IllegalPathException() { + } + + public IllegalPathException(String message) { + super(message); + } + + public String getPath() { + return super.getMessage(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/UnimplementedException.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/UnimplementedException.java new file mode 100644 index 0000000000..7f5b8542bc --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/UnimplementedException.java @@ -0,0 +1,31 @@ +/* + * 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.remoting.http12.exception; + +public class UnimplementedException extends HttpStatusException { + + private final String unimplemented; + + public UnimplementedException(String unimplemented) { + super(500, "unimplemented " + unimplemented); + this.unimplemented = unimplemented; + } + + public String getUnimplemented() { + return unimplemented; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/UnsupportedMediaTypeException.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/UnsupportedMediaTypeException.java new file mode 100644 index 0000000000..58eb76bf34 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/exception/UnsupportedMediaTypeException.java @@ -0,0 +1,31 @@ +/* + * 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.remoting.http12.exception; + +public class UnsupportedMediaTypeException extends HttpStatusException { + + private final String mediaType; + + public UnsupportedMediaTypeException(String mediaType) { + super(415, "Unsupported Media Type '" + mediaType + "'"); + this.mediaType = mediaType; + } + + public String getMediaType() { + return mediaType; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/DefaultHttp1Request.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/DefaultHttp1Request.java new file mode 100644 index 0000000000..1bc610d84b --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/DefaultHttp1Request.java @@ -0,0 +1,55 @@ +/* + * 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.remoting.http12.h1; + +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpInputMessage; +import org.apache.dubbo.remoting.http12.RequestMetadata; + +import java.io.InputStream; + +public class DefaultHttp1Request implements Http1Request { + + private final RequestMetadata httpMetadata; + + private final HttpInputMessage httpInputMessage; + + public DefaultHttp1Request(RequestMetadata httpMetadata, HttpInputMessage httpInputMessage) { + this.httpMetadata = httpMetadata; + this.httpInputMessage = httpInputMessage; + } + + @Override + public InputStream getBody() { + return httpInputMessage.getBody(); + } + + @Override + public HttpHeaders headers() { + return httpMetadata.headers(); + } + + @Override + public String method() { + return httpMetadata.method(); + } + + @Override + public String path() { + return httpMetadata.path(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/DefaultHttp1Response.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/DefaultHttp1Response.java new file mode 100644 index 0000000000..4f345b6cbe --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/DefaultHttp1Response.java @@ -0,0 +1,45 @@ +/* + * 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.remoting.http12.h1; + +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpInputMessage; +import org.apache.dubbo.remoting.http12.HttpMetadata; + +import java.io.InputStream; + +public class DefaultHttp1Response implements HttpMetadata, HttpInputMessage { + + private final HttpMetadata httpMetadata; + + private final HttpInputMessage httpInputMessage; + + public DefaultHttp1Response(HttpMetadata httpMetadata, HttpInputMessage httpInputMessage) { + this.httpMetadata = httpMetadata; + this.httpInputMessage = httpInputMessage; + } + + @Override + public InputStream getBody() { + return httpInputMessage.getBody(); + } + + @Override + public HttpHeaders headers() { + return httpMetadata.headers(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1InputMessage.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1InputMessage.java new file mode 100644 index 0000000000..3267de831b --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1InputMessage.java @@ -0,0 +1,35 @@ +/* + * 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.remoting.http12.h1; + +import org.apache.dubbo.remoting.http12.HttpInputMessage; + +import java.io.InputStream; + +public class Http1InputMessage implements HttpInputMessage { + + private final InputStream body; + + public Http1InputMessage(InputStream body) { + this.body = body; + } + + @Override + public InputStream getBody() { + return body; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1Metadata.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1Metadata.java new file mode 100644 index 0000000000..2aebae3d43 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1Metadata.java @@ -0,0 +1,34 @@ +/* + * 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.remoting.http12.h1; + +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpMetadata; + +public class Http1Metadata implements HttpMetadata { + + private final HttpHeaders headers; + + public Http1Metadata(HttpHeaders headers) { + this.headers = headers; + } + + @Override + public HttpHeaders headers() { + return headers; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1OutputMessage.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1OutputMessage.java new file mode 100644 index 0000000000..42cf7a1ee5 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1OutputMessage.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.h1; + +import org.apache.dubbo.remoting.http12.HttpOutputMessage; + +import java.io.OutputStream; + +public class Http1OutputMessage implements HttpOutputMessage { + + private final OutputStream outputStream; + + public Http1OutputMessage(OutputStream outputStream) { + this.outputStream = outputStream; + } + + @Override + public OutputStream getBody() { + return outputStream; + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1Request.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1Request.java new file mode 100644 index 0000000000..2b3c3cbabf --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1Request.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.h1; + +import org.apache.dubbo.remoting.http12.HttpInputMessage; +import org.apache.dubbo.remoting.http12.RequestMetadata; + +public interface Http1Request extends RequestMetadata, HttpInputMessage { + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1RequestMetadata.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1RequestMetadata.java new file mode 100644 index 0000000000..39175ddbe4 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1RequestMetadata.java @@ -0,0 +1,56 @@ +/* + * 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.remoting.http12.h1; + +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.RequestMetadata; + +public class Http1RequestMetadata implements RequestMetadata { + + private HttpHeaders headers; + + private String method; + + private String path; + + public void setHeaders(HttpHeaders headers) { + this.headers = headers; + } + + public void setMethod(String method) { + this.method = method; + } + + public void setPath(String path) { + this.path = path; + } + + @Override + public HttpHeaders headers() { + return headers; + } + + @Override + public String method() { + return method; + } + + @Override + public String path() { + return path; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerChannelObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerChannelObserver.java new file mode 100644 index 0000000000..d2fceb8d9a --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerChannelObserver.java @@ -0,0 +1,45 @@ +/* + * 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.remoting.http12.h1; + +import org.apache.dubbo.remoting.http12.AbstractServerHttpChannelObserver; +import org.apache.dubbo.remoting.http12.HttpChannel; +import org.apache.dubbo.remoting.http12.HttpChannelObserver; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpOutputMessage; + +public class Http1ServerChannelObserver extends AbstractServerHttpChannelObserver implements HttpChannelObserver { + + public Http1ServerChannelObserver(HttpChannel httpChannel) { + super(httpChannel); + } + + @Override + protected HttpMetadata encodeHttpMetadata() { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.set(HttpHeaderNames.TRANSFER_ENCODING.getName(), "chunked"); + return new Http1Metadata(httpHeaders); + } + + @Override + protected void doOnCompleted(Throwable throwable) { + super.doOnCompleted(throwable); + this.getHttpChannel().writeMessage(HttpOutputMessage.EMPTY_MESSAGE); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerStreamChannelObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerStreamChannelObserver.java new file mode 100644 index 0000000000..063b971df3 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerStreamChannelObserver.java @@ -0,0 +1,49 @@ +/* + * 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.remoting.http12.h1; + +import org.apache.dubbo.remoting.http12.HttpChannel; +import org.apache.dubbo.remoting.http12.HttpOutputMessage; + +import java.io.IOException; + +public class Http1ServerStreamChannelObserver extends Http1ServerChannelObserver { + + private static final String SERVER_SENT_EVENT_DATA_PREFIX = "data:"; + private static final String SERVER_SENT_EVENT_LF = "\n\n"; + + private static final byte[] SERVER_SENT_EVENT_DATA_PREFIX_BYTES = SERVER_SENT_EVENT_DATA_PREFIX.getBytes(); + private static final byte[] SERVER_SENT_EVENT_LF_BYTES = SERVER_SENT_EVENT_LF.getBytes(); + + public Http1ServerStreamChannelObserver(HttpChannel httpChannel) { + super(httpChannel); + } + + @Override + protected void preOutputMessage(HttpOutputMessage httpMessage) throws IOException { + HttpOutputMessage httpOutputMessage = this.getHttpChannel().newOutputMessage(); + httpOutputMessage.getBody().write(SERVER_SENT_EVENT_DATA_PREFIX_BYTES, 0, SERVER_SENT_EVENT_DATA_PREFIX_BYTES.length); + this.getHttpChannel().writeMessage(httpOutputMessage); + } + + @Override + protected void postOutputMessage(HttpOutputMessage httpMessage) throws IOException { + HttpOutputMessage httpOutputMessage = this.getHttpChannel().newOutputMessage(); + httpOutputMessage.getBody().write(SERVER_SENT_EVENT_LF_BYTES, 0, SERVER_SENT_EVENT_LF_BYTES.length); + this.getHttpChannel().writeMessage(httpOutputMessage); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListener.java new file mode 100644 index 0000000000..eb816afb02 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListener.java @@ -0,0 +1,26 @@ +/* + * 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.remoting.http12.h1; + +import org.apache.dubbo.remoting.http12.HttpChannelHolder; +import org.apache.dubbo.remoting.http12.HttpInputMessage; +import org.apache.dubbo.remoting.http12.HttpTransportListener; +import org.apache.dubbo.remoting.http12.RequestMetadata; + +public interface Http1ServerTransportListener extends HttpTransportListener, HttpChannelHolder { + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListenerFactory.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListenerFactory.java new file mode 100644 index 0000000000..1e8f7de276 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListenerFactory.java @@ -0,0 +1,30 @@ +/* + * 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.remoting.http12.h1; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.remoting.http12.HttpChannel; +import org.apache.dubbo.rpc.model.FrameworkModel; + +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface Http1ServerTransportListenerFactory { + + Http1ServerTransportListener newInstance(HttpChannel httpChannel, URL url, FrameworkModel frameworkModel); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/CancelableTransportListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/CancelableTransportListener.java new file mode 100644 index 0000000000..3f842e0818 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/CancelableTransportListener.java @@ -0,0 +1,27 @@ +/* + * 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.remoting.http12.h2; + +import org.apache.dubbo.remoting.http12.HttpInputMessage; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpTransportListener; + +public interface CancelableTransportListener
extends HttpTransportListener { + + void cancelByRemote(long errorCode); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/DefaultHttp2StreamingDecoder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/DefaultHttp2StreamingDecoder.java new file mode 100644 index 0000000000..b43d2d1732 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/DefaultHttp2StreamingDecoder.java @@ -0,0 +1,53 @@ +/* + * 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.remoting.http12.h2; + +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.message.DefaultListeningDecoder; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.remoting.http12.message.StreamingDecoder; + +import java.io.InputStream; + +public class DefaultHttp2StreamingDecoder implements StreamingDecoder { + + private final DefaultListeningDecoder delegate; + + public DefaultHttp2StreamingDecoder(HttpMessageCodec httpMessageCodec, Class[] targetTypes) { + this.delegate = new DefaultListeningDecoder(httpMessageCodec, targetTypes); + } + + @Override + public void decode(InputStream inputStream) throws DecodeException { + delegate.decode(inputStream); + } + + @Override + public void close() { + delegate.close(); + } + + @Override + public void setListener(Listener listener) { + delegate.setListener(listener); + } + + @Override + public void request(int numMessages) { + //no op + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/H2StreamChannel.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/H2StreamChannel.java new file mode 100644 index 0000000000..005043dcf3 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/H2StreamChannel.java @@ -0,0 +1,33 @@ +/* + * 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.remoting.http12.h2; + +import org.apache.dubbo.remoting.http12.HttpChannel; + +import java.util.concurrent.CompletableFuture; + +public interface H2StreamChannel extends HttpChannel { + + CompletableFuture writeResetFrame(long errorCode); + + @Override + default Http2OutputMessage newOutputMessage() { + return this.newOutputMessage(false); + } + + Http2OutputMessage newOutputMessage(boolean endStream); +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2CancelableStreamObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2CancelableStreamObserver.java new file mode 100644 index 0000000000..55131626e0 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2CancelableStreamObserver.java @@ -0,0 +1,29 @@ +/* + * 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.remoting.http12.h2; + +import org.apache.dubbo.common.stream.StreamObserver; +import org.apache.dubbo.rpc.CancellationContext; + +public interface Http2CancelableStreamObserver extends StreamObserver { + + void setCancellationContext(CancellationContext cancellationContext); + + CancellationContext getCancellationContext(); + + void cancel(Throwable throwable); +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ChannelDelegate.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ChannelDelegate.java new file mode 100644 index 0000000000..9c5aaea104 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ChannelDelegate.java @@ -0,0 +1,66 @@ +/* + * 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.remoting.http12.h2; + +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpOutputMessage; + +import java.net.SocketAddress; +import java.util.concurrent.CompletableFuture; + +public class Http2ChannelDelegate implements H2StreamChannel { + + private final H2StreamChannel h2StreamChannel; + + public Http2ChannelDelegate(H2StreamChannel h2StreamChannel) { + this.h2StreamChannel = h2StreamChannel; + } + + public H2StreamChannel getH2StreamChannel() { + return h2StreamChannel; + } + + @Override + public CompletableFuture writeHeader(HttpMetadata httpMetadata) { + return h2StreamChannel.writeHeader(httpMetadata); + } + + @Override + public CompletableFuture writeMessage(HttpOutputMessage httpOutputMessage) { + return h2StreamChannel.writeMessage(httpOutputMessage); + } + + @Override + public SocketAddress remoteAddress() { + return h2StreamChannel.remoteAddress(); + } + + @Override + public void flush() { + h2StreamChannel.flush(); + } + + @Override + public CompletableFuture writeResetFrame(long errorCode) { + return h2StreamChannel.writeResetFrame(errorCode); + } + + @Override + public Http2OutputMessage newOutputMessage(boolean endStream) { + return h2StreamChannel.newOutputMessage(endStream); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Header.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Header.java new file mode 100644 index 0000000000..b0308e2edf --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Header.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.h2; + +import org.apache.dubbo.remoting.http12.RequestMetadata; + +public interface Http2Header extends RequestMetadata, Http2StreamFrame { + + @Override + default String method() { + return headers().getFirst(Http2Headers.METHOD.getName()); + } + + @Override + default String path() { + return headers().getFirst(Http2Headers.PATH.getName()); + } + + default String status() { + return headers().getFirst(Http2Headers.STATUS.getName()); + } + + @Override + default String name() { + return "HEADER"; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Headers.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Headers.java new file mode 100644 index 0000000000..4a2c885e18 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Headers.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.h2; + +public enum Http2Headers { + + PATH(":path"), + + METHOD(":method"), + + STATUS(":status"); + + private final String name; + + Http2Headers(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2InputMessage.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2InputMessage.java new file mode 100644 index 0000000000..640b13c049 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2InputMessage.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.h2; + +import org.apache.dubbo.remoting.http12.HttpInputMessage; + +public interface Http2InputMessage extends HttpInputMessage, Http2StreamFrame { + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2InputMessageFrame.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2InputMessageFrame.java new file mode 100644 index 0000000000..e73955c96e --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2InputMessageFrame.java @@ -0,0 +1,65 @@ +/* + * 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.remoting.http12.h2; + +import java.io.InputStream; + +public class Http2InputMessageFrame implements Http2InputMessage { + + private int id; + + private final InputStream body; + + private final boolean endStream; + + public Http2InputMessageFrame(InputStream body) { + this(body, false); + } + + public Http2InputMessageFrame(boolean endStream) { + this(null, endStream); + } + + public Http2InputMessageFrame(InputStream body, boolean endStream) { + this.body = body; + this.endStream = endStream; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public InputStream getBody() { + return body; + } + + @Override + public String name() { + return "DATA"; + } + + @Override + public int id() { + return id; + } + + @Override + public boolean isEndStream() { + return endStream; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2MetadataFrame.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2MetadataFrame.java new file mode 100644 index 0000000000..2081b9f169 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2MetadataFrame.java @@ -0,0 +1,57 @@ +/* + * 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.remoting.http12.h2; + +import org.apache.dubbo.remoting.http12.HttpHeaders; + +public class Http2MetadataFrame implements Http2Header { + + private final int streamId; + + private final HttpHeaders headers; + + private final boolean endStream; + + public Http2MetadataFrame(HttpHeaders headers) { + this(headers, false); + } + + public Http2MetadataFrame(HttpHeaders headers, boolean endStream) { + this(-1, headers, endStream); + } + + public Http2MetadataFrame(int streamId, HttpHeaders headers, boolean endStream) { + this.streamId = streamId; + this.headers = headers; + this.endStream = endStream; + } + + @Override + public HttpHeaders headers() { + return headers; + } + + @Override + public int id() { + return streamId; + } + + @Override + public boolean isEndStream() { + return endStream; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2OutputMessage.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2OutputMessage.java new file mode 100644 index 0000000000..75f34bcb84 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2OutputMessage.java @@ -0,0 +1,32 @@ +/* + * 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.remoting.http12.h2; + +import org.apache.dubbo.remoting.http12.HttpOutputMessage; + +public interface Http2OutputMessage extends HttpOutputMessage, Http2StreamFrame { + + @Override + default String name() { + return "DATA"; + } + + @Override + default int id() { + return -1; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2OutputMessageFrame.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2OutputMessageFrame.java new file mode 100644 index 0000000000..15c87eb413 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2OutputMessageFrame.java @@ -0,0 +1,49 @@ +/* + * 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.remoting.http12.h2; + +import java.io.OutputStream; + +public class Http2OutputMessageFrame implements Http2OutputMessage { + + private final OutputStream body; + + private final boolean endStream; + + public Http2OutputMessageFrame(OutputStream body) { + this(body, false); + } + + public Http2OutputMessageFrame(boolean endStream) { + this(null, endStream); + } + + public Http2OutputMessageFrame(OutputStream body, boolean endStream) { + this.body = body; + this.endStream = endStream; + } + + @Override + public OutputStream getBody() { + return body; + } + + @Override + public boolean isEndStream() { + return endStream; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ServerChannelObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ServerChannelObserver.java new file mode 100644 index 0000000000..ce9187c265 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ServerChannelObserver.java @@ -0,0 +1,96 @@ +/* + * 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.remoting.http12.h2; + +import org.apache.dubbo.remoting.http12.AbstractServerHttpChannelObserver; +import org.apache.dubbo.remoting.http12.ErrorCodeHolder; +import org.apache.dubbo.remoting.http12.FlowControlStreamObserver; +import org.apache.dubbo.remoting.http12.HttpChannelObserver; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.message.StreamingDecoder; +import org.apache.dubbo.rpc.CancellationContext; + +public class Http2ServerChannelObserver extends AbstractServerHttpChannelObserver implements HttpChannelObserver, FlowControlStreamObserver, Http2CancelableStreamObserver { + + private CancellationContext cancellationContext; + + private StreamingDecoder streamingDecoder; + + private boolean autoRequestN = true; + + public Http2ServerChannelObserver(H2StreamChannel h2StreamChannel) { + super(h2StreamChannel); + } + + public void setStreamingDecoder(StreamingDecoder streamingDecoder) { + this.streamingDecoder = streamingDecoder; + } + + @Override + protected HttpMetadata encodeHttpMetadata() { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.set(HttpHeaderNames.TE.getName(), "trailers"); + return new Http2MetadataFrame(httpHeaders); + } + + @Override + protected HttpMetadata encodeTrailers(Throwable throwable) { + return new Http2MetadataFrame(new HttpHeaders(), true); + } + + @Override + public H2StreamChannel getHttpChannel() { + return (H2StreamChannel) super.getHttpChannel(); + } + + @Override + public void setCancellationContext(CancellationContext cancellationContext) { + this.cancellationContext = cancellationContext; + } + + @Override + public CancellationContext getCancellationContext() { + return cancellationContext; + } + + @Override + public void cancel(Throwable throwable) { + long errorCode = 0; + if (throwable instanceof ErrorCodeHolder) { + errorCode = ((ErrorCodeHolder) throwable).getErrorCode(); + } + getHttpChannel().writeResetFrame(errorCode); + this.cancellationContext.cancel(throwable); + } + + @Override + public void request(int count) { + this.streamingDecoder.request(count); + } + + @Override + public void disableAutoFlowControl() { + this.autoRequestN = false; + } + + @Override + public boolean isAutoRequestN() { + return autoRequestN; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ServerTransportListenerFactory.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ServerTransportListenerFactory.java new file mode 100644 index 0000000000..5b7308d932 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2ServerTransportListenerFactory.java @@ -0,0 +1,31 @@ +/* + * 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.remoting.http12.h2; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.rpc.model.FrameworkModel; + +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface Http2ServerTransportListenerFactory { + + Http2TransportListener newInstance(H2StreamChannel streamChannel, URL url, FrameworkModel frameworkModel); + + boolean supportContentType(String contentType); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2StreamFrame.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2StreamFrame.java new file mode 100644 index 0000000000..d57f754c4b --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2StreamFrame.java @@ -0,0 +1,26 @@ +/* + * 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.remoting.http12.h2; + +public interface Http2StreamFrame { + + int id(); + + String name(); + + boolean isEndStream(); +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2TransportListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2TransportListener.java new file mode 100644 index 0000000000..00bfbc6554 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2TransportListener.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.h2; + +import org.apache.dubbo.remoting.http12.HttpChannelHolder; + +public interface Http2TransportListener extends CancelableTransportListener, HttpChannelHolder { + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/command/Http2WriteQueueChannel.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/command/Http2WriteQueueChannel.java new file mode 100644 index 0000000000..ee2225599c --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/command/Http2WriteQueueChannel.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.h2.command; + +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpOutputMessage; +import org.apache.dubbo.remoting.http12.command.DataQueueCommand; +import org.apache.dubbo.remoting.http12.command.HeaderQueueCommand; +import org.apache.dubbo.remoting.http12.command.HttpWriteQueue; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2ChannelDelegate; + +import java.util.concurrent.CompletableFuture; + +public class Http2WriteQueueChannel extends Http2ChannelDelegate { + + private final HttpWriteQueue httpWriteQueue; + + public Http2WriteQueueChannel(H2StreamChannel h2StreamChannel, HttpWriteQueue httpWriteQueue) { + super(h2StreamChannel); + this.httpWriteQueue = httpWriteQueue; + } + + @Override + public CompletableFuture writeHeader(HttpMetadata httpMetadata) { + HeaderQueueCommand cmd = new HeaderQueueCommand(httpMetadata); + cmd.setHttpChannel(this::getH2StreamChannel); + return httpWriteQueue.enqueue(cmd); + } + + @Override + public CompletableFuture writeMessage(HttpOutputMessage httpOutputMessage) { + DataQueueCommand cmd = new DataQueueCommand(httpOutputMessage); + cmd.setHttpChannel(this::getH2StreamChannel); + return httpWriteQueue.enqueue(cmd); + } + + @Override + public CompletableFuture writeResetFrame(long errorCode) { + ResetQueueCommand cmd = new ResetQueueCommand(errorCode); + cmd.setHttpChannel(this::getH2StreamChannel); + return this.httpWriteQueue.enqueue(cmd); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/command/ResetQueueCommand.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/command/ResetQueueCommand.java new file mode 100644 index 0000000000..7fabddb7cf --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/command/ResetQueueCommand.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.h2.command; + +import org.apache.dubbo.remoting.http12.command.HttpChannelQueueCommand; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; + +public class ResetQueueCommand extends HttpChannelQueueCommand { + + private final long errorCode; + + public ResetQueueCommand(long errorCode) { + this.errorCode = errorCode; + } + + @Override + public void run() { + ((H2StreamChannel) getHttpChannel()) + .writeResetFrame(errorCode) + .whenComplete((unused, throwable) -> { + if (throwable != null) { + completeExceptionally(throwable); + } else { + complete(unused); + } + }); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/DefaultListeningDecoder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/DefaultListeningDecoder.java new file mode 100644 index 0000000000..dc57c7bf84 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/DefaultListeningDecoder.java @@ -0,0 +1,49 @@ +/* + * 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.remoting.http12.message; + +import java.io.InputStream; + +public class DefaultListeningDecoder implements ListeningDecoder { + + private final HttpMessageCodec httpMessageCodec; + + private final Class[] targetTypes; + + private Listener listener; + + public DefaultListeningDecoder(HttpMessageCodec httpMessageCodec, Class[] targetTypes) { + this.httpMessageCodec = httpMessageCodec; + this.targetTypes = targetTypes; + } + + @Override + public void setListener(Listener listener) { + this.listener = listener; + } + + @Override + public void decode(InputStream inputStream) { + Object[] decode = this.httpMessageCodec.decode(inputStream, targetTypes); + this.listener.onMessage(decode); + } + + @Override + public void close() { + this.listener.onClose(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodec.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodec.java new file mode 100644 index 0000000000..5437d9af47 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodec.java @@ -0,0 +1,54 @@ +/* + * 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.remoting.http12.message; + +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.exception.EncodeException; + +import java.io.InputStream; +import java.io.OutputStream; + +/** + * for http body codec + */ +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface HttpMessageCodec { + + void encode(OutputStream outputStream, Object data) throws EncodeException; + + default void encode(OutputStream outputStream, Object[] data) throws EncodeException { + //default encode first data + this.encode(outputStream, data[0]); + } + + Object decode(InputStream inputStream, Class targetType) throws DecodeException; + + default Object[] decode(InputStream inputStream, Class[] targetTypes) throws DecodeException { + //default decode first target type + return new Object[]{this.decode(inputStream, targetTypes[0])}; + } + + MediaType contentType(); + + default boolean support(String contentType) { + MediaType mediaType = this.contentType(); + return mediaType.getName().startsWith(contentType); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java new file mode 100644 index 0000000000..fb6a6f6faa --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java @@ -0,0 +1,127 @@ +/* + * 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.remoting.http12.message; + +import com.alibaba.fastjson2.JSONObject; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.utils.JsonUtils; +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.exception.EncodeException; + +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +/** + * body is json + */ +@Activate +public class JsonCodec implements HttpMessageCodec { + + public static final HttpMessageCodec INSTANCE = new JsonCodec(); + + @Override + public MediaType contentType() { + return MediaType.APPLICATION_JSON_VALUE; + } + + @Override + public void encode(OutputStream outputStream, Object unSerializedBody) throws EncodeException { + try { + try { + String jsonString = JsonUtils.toJson(unSerializedBody); + outputStream.write(jsonString.getBytes(StandardCharsets.UTF_8)); + } finally { + outputStream.flush(); + } + } catch (Throwable e) { + throw new EncodeException(e); + } + } + + @Override + public void encode(OutputStream outputStream, Object[] data) throws EncodeException { + try { + try { + String jsonString = JsonUtils.toJson(data); + outputStream.write(jsonString.getBytes(StandardCharsets.UTF_8)); + } finally { + outputStream.flush(); + } + } catch (Throwable e) { + throw new EncodeException(e); + } + } + + @Override + public Object decode(InputStream body, Class targetType) throws DecodeException { + try { + try { + int len; + byte[] data = new byte[4096]; + StringBuilder builder = new StringBuilder(4096); + while ((len = body.read(data)) != -1) { + builder.append(new String(data, 0, len)); + } + return JsonUtils.toJavaObject(builder.toString(), targetType); + } finally { + body.close(); + } + } catch (Throwable e) { + throw new DecodeException(e); + } + } + + @Override + public Object[] decode(InputStream dataInputStream, Class[] targetTypes) throws DecodeException { + List result = new ArrayList<>(); + try { + try { + if (targetTypes.length == 1) { + return new Object[]{this.decode(dataInputStream, targetTypes[0])}; + } + int len; + byte[] data = new byte[4096]; + StringBuilder builder = new StringBuilder(4096); + while ((len = dataInputStream.read(data)) != -1) { + builder.append(new String(data, 0, len)); + } + String jsonString = builder.toString(); + List jsonObjects = JsonUtils.toJavaList(jsonString, Object.class); + + for (int i = 0; i < targetTypes.length; i++) { + Object jsonObject = jsonObjects.get(i); + Class type = targetTypes[i]; + if (jsonObject instanceof JSONObject) { + Object o = ((JSONObject) jsonObject).toJavaObject(type); + result.add(o); + } else { + result.add(jsonObject); + } + } + return result.toArray(); + } finally { + dataInputStream.close(); + } + } catch (Throwable e) { + throw new DecodeException(e); + } + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java new file mode 100644 index 0000000000..dc2d57d948 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java @@ -0,0 +1,189 @@ +/* + * 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.remoting.http12.message; + +import org.apache.dubbo.remoting.http12.CompositeInputStream; +import org.apache.dubbo.remoting.http12.exception.DecodeException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class LengthFieldStreamingDecoder implements StreamingDecoder { + + private long pendingDeliveries; + + private boolean inDelivery = false; + + private boolean closing; + + private boolean closed; + + private DecodeState state = DecodeState.HEADER; + + private final CompositeInputStream accumulate = new CompositeInputStream(); + + private final Class[] targetTypes; + + private HttpMessageCodec httpMessageCodec; + + private Listener listener; + + private final int lengthFieldOffset; + + private final int lengthFieldLength; + + private int requiredLength; + + public LengthFieldStreamingDecoder(Class[] targetTypes) { + this(4, targetTypes); + } + + public LengthFieldStreamingDecoder(int lengthFieldLength, Class[] targetTypes) { + this(0, lengthFieldLength, targetTypes); + } + + public LengthFieldStreamingDecoder(int lengthFieldOffset, int lengthFieldLength, Class[] targetTypes) { + this.lengthFieldOffset = lengthFieldOffset; + this.lengthFieldLength = lengthFieldLength; + this.targetTypes = targetTypes; + this.requiredLength = lengthFieldOffset + lengthFieldLength; + } + + public void setHttpMessageCodec(HttpMessageCodec httpMessageCodec) { + this.httpMessageCodec = httpMessageCodec; + } + + @Override + public final void decode(InputStream inputStream) throws DecodeException { + if (closing || closed) { + // ignored + return; + } + accumulate.addInputStream(inputStream); + deliver(); + } + + @Override + public final void request(int numMessages) { + pendingDeliveries += numMessages; + deliver(); + } + + @Override + public final void close() { + closing = true; + deliver(); + } + + @Override + public final void setListener(Listener listener) { + this.listener = listener; + } + + private void deliver() { + // We can have reentrancy here when using a direct executor, triggered by calls to + // request more messages. This is safe as we simply loop until pendingDelivers = 0 + if (inDelivery) { + return; + } + inDelivery = true; + try { + // Process the uncompressed bytes. + while (pendingDeliveries > 0 && hasEnoughBytes()) { + switch (state) { + case HEADER: + processHeader(); + break; + case PAYLOAD: + // Read the body and deliver the message. + processBody(); + + // Since we've delivered a message, decrement the number of pending + // deliveries remaining. + pendingDeliveries--; + break; + default: + throw new AssertionError("Invalid state: " + state); + } + } + if (closing) { + if (!closed) { + closed = true; + accumulate.close(); + listener.onClose(); + } + } + } catch (IOException e) { + throw new DecodeException(e); + } finally { + inDelivery = false; + } + } + + private void processHeader() throws IOException { + processOffset(accumulate, lengthFieldOffset); + byte[] lengthBytes = new byte[lengthFieldLength]; + accumulate.read(lengthBytes); + requiredLength = bytesToInt(lengthBytes); + + // Continue reading the frame body. + state = DecodeState.PAYLOAD; + } + + protected void processOffset(InputStream inputStream, int lengthFieldOffset) throws IOException { + //default skip offset + skipOffset(inputStream, lengthFieldOffset); + } + + private void skipOffset(InputStream inputStream, int lengthFieldOffset) throws IOException { + if (lengthFieldOffset != 0) { + return; + } + inputStream.read(new byte[lengthFieldOffset]); + } + + private void processBody() throws IOException { + byte[] rawMessage = readRawMessage(accumulate, requiredLength); + InputStream inputStream = new ByteArrayInputStream(rawMessage); + Object[] decodeParameters = httpMessageCodec.decode(inputStream, targetTypes); + this.listener.onMessage(decodeParameters); + + // Done with this frame, begin processing the next header. + state = DecodeState.HEADER; + requiredLength = lengthFieldOffset + lengthFieldLength; + } + + protected byte[] readRawMessage(InputStream inputStream, int length) throws IOException { + byte[] data = new byte[length]; + inputStream.read(data, 0, length); + return data; + } + + private boolean hasEnoughBytes() { + return requiredLength - accumulate.available() <= 0; + } + + protected static int bytesToInt(byte[] bytes) { + return (bytes[0] << 24) & 0xFF | (bytes[1] << 16) & 0xFF | (bytes[2] << 8) & 0xFF | (bytes[3]) & 0xFF; + } + + private enum DecodeState { + HEADER, + PAYLOAD + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/ListeningDecoder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/ListeningDecoder.java new file mode 100644 index 0000000000..2765827a33 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/ListeningDecoder.java @@ -0,0 +1,43 @@ +/* + * 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.remoting.http12.message; + +import org.apache.dubbo.remoting.http12.exception.DecodeException; + +import java.io.InputStream; + +public interface ListeningDecoder { + + void decode(InputStream inputStream) throws DecodeException; + + void close(); + + void setListener(Listener listener); + + interface Listener { + + /** + * call on decode finish + * @param message decoded object + */ + void onMessage(Object message); + + default void onClose() { + + } + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/MediaType.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/MediaType.java new file mode 100644 index 0000000000..b04c024804 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/MediaType.java @@ -0,0 +1,66 @@ +/* + * 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.remoting.http12.message; + + +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.Map; + +public class MediaType { + + public static final MediaType ALL_VALUE = new MediaType("*", "*"); + + public static final MediaType APPLICATION_JSON_VALUE = new MediaType("application", "json"); + + public static final MediaType TEXT_EVENT_STREAM_VALUE = new MediaType("text", "event-stream"); + + private final String name; + + private final String type; + + private final String subType; + + private final Charset charset; + + public MediaType(String type, String subType) { + this(type, subType, Collections.singletonMap("charset", "UTF-8")); + } + + public MediaType(String type, String subType, Map parameters) { + this.type = type; + this.subType = subType; + this.name = type + "/" + subType; + this.charset = Charset.forName(parameters.getOrDefault("charset", "UTF-8")); + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public String getSubType() { + return subType; + } + + public Charset getCharset() { + return charset; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/MethodMetadata.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/MethodMetadata.java new file mode 100644 index 0000000000..09f572ed74 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/MethodMetadata.java @@ -0,0 +1,84 @@ +/* + * 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.remoting.http12.message; + +import org.apache.dubbo.rpc.model.MethodDescriptor; +import org.apache.dubbo.rpc.model.ReflectionMethodDescriptor; +import org.apache.dubbo.rpc.model.StubMethodDescriptor; + +import java.lang.reflect.ParameterizedType; + +public class MethodMetadata { + + private final Class[] actualRequestTypes; + + private final Class actualResponseType; + + private MethodMetadata(Class[] actualRequestTypes, Class actualResponseType) { + this.actualRequestTypes = actualRequestTypes; + this.actualResponseType = actualResponseType; + } + + public Class[] getActualRequestTypes() { + return actualRequestTypes; + } + + public Class getActualResponseType() { + return actualResponseType; + } + + public static MethodMetadata fromMethodDescriptor(MethodDescriptor method) { + if (method instanceof ReflectionMethodDescriptor) { + return doResolveReflection((ReflectionMethodDescriptor) method); + } + if (method instanceof StubMethodDescriptor) { + return doResolveStub((StubMethodDescriptor) method); + } + throw new IllegalStateException("Can not reach here"); + } + + private static MethodMetadata doResolveStub(StubMethodDescriptor method) { + Class[] actualRequestTypes = method.getParameterClasses(); + Class actualResponseType = method.getReturnClass(); + return new MethodMetadata(actualRequestTypes, actualResponseType); + } + + private static MethodMetadata doResolveReflection(ReflectionMethodDescriptor method) { + Class[] actualRequestTypes; + Class actualResponseType; + switch (method.getRpcType()) { + case CLIENT_STREAM: + case BI_STREAM: + actualRequestTypes = new Class[]{ + (Class) ((ParameterizedType) method.getMethod() + .getGenericReturnType()).getActualTypeArguments()[0]}; + actualResponseType = (Class) ((ParameterizedType) method.getMethod() + .getGenericParameterTypes()[0]).getActualTypeArguments()[0]; + return new MethodMetadata(actualRequestTypes, actualResponseType); + case SERVER_STREAM: + actualRequestTypes = new Class[]{method.getMethod().getParameterTypes()[0]}; + actualResponseType = (Class) ((ParameterizedType) method.getMethod() + .getGenericParameterTypes()[1]).getActualTypeArguments()[0]; + return new MethodMetadata(actualRequestTypes, actualResponseType); + case UNARY: + actualRequestTypes = method.getParameterClasses(); + actualResponseType = (Class) method.getReturnTypes()[0]; + return new MethodMetadata(actualRequestTypes, actualResponseType); + } + throw new IllegalStateException("Can not reach here"); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/StreamingDecoder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/StreamingDecoder.java new file mode 100644 index 0000000000..212b68a6ac --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/StreamingDecoder.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.message; + +public interface StreamingDecoder extends ListeningDecoder { + + void request(int numMessages); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/HttpWriteQueueHandler.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/HttpWriteQueueHandler.java new file mode 100644 index 0000000000..e292aada05 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/HttpWriteQueueHandler.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12.netty4; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.EventLoop; +import org.apache.dubbo.remoting.http12.command.HttpWriteQueue; + +public class HttpWriteQueueHandler extends ChannelInboundHandlerAdapter { + + private HttpWriteQueue writeQueue; + + @Override + public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + EventLoop eventLoop = ctx.channel().eventLoop(); + this.writeQueue = new HttpWriteQueue(eventLoop); + } + + @Override + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { + this.writeQueue = null; + } + + public HttpWriteQueue getWriteQueue() { + return writeQueue; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/NettyHttpChannelFutureListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/NettyHttpChannelFutureListener.java new file mode 100644 index 0000000000..279f851260 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/NettyHttpChannelFutureListener.java @@ -0,0 +1,35 @@ +/* + * 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.remoting.http12.netty4; + +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; + +import java.util.concurrent.CompletableFuture; + +public class NettyHttpChannelFutureListener extends CompletableFuture implements ChannelFutureListener { + + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (!future.isSuccess()) { + Throwable cause = future.cause(); + this.completeExceptionally(cause); + } else { + this.complete(null); + } + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1Channel.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1Channel.java new file mode 100644 index 0000000000..030a7da084 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1Channel.java @@ -0,0 +1,66 @@ +/* + * 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.remoting.http12.netty4.h1; + +import io.netty.buffer.ByteBufOutputStream; +import io.netty.channel.Channel; +import org.apache.dubbo.remoting.http12.HttpChannel; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpOutputMessage; +import org.apache.dubbo.remoting.http12.h1.Http1OutputMessage; +import org.apache.dubbo.remoting.http12.netty4.NettyHttpChannelFutureListener; + +import java.net.SocketAddress; +import java.util.concurrent.CompletableFuture; + +public class NettyHttp1Channel implements HttpChannel { + + private final Channel channel; + + public NettyHttp1Channel(Channel channel) { + this.channel = channel; + } + + @Override + public CompletableFuture writeHeader(HttpMetadata httpMetadata) { + NettyHttpChannelFutureListener nettyHttpChannelFutureListener = new NettyHttpChannelFutureListener(); + this.channel.writeAndFlush(httpMetadata).addListener(nettyHttpChannelFutureListener); + return nettyHttpChannelFutureListener; + } + + @Override + public CompletableFuture writeMessage(HttpOutputMessage httpOutputMessage) { + NettyHttpChannelFutureListener nettyHttpChannelFutureListener = new NettyHttpChannelFutureListener(); + this.channel.writeAndFlush(httpOutputMessage).addListener(nettyHttpChannelFutureListener); + return nettyHttpChannelFutureListener; + } + + @Override + public HttpOutputMessage newOutputMessage() { + return new Http1OutputMessage(new ByteBufOutputStream(channel.alloc().buffer())); + } + + @Override + public SocketAddress remoteAddress() { + return channel.remoteAddress(); + } + + @Override + public void flush() { + + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1Codec.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1Codec.java new file mode 100644 index 0000000000..b8425cd623 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1Codec.java @@ -0,0 +1,110 @@ +/* + * 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.remoting.http12.netty4.h1; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.DefaultHttpResponse; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.netty.handler.codec.http.HttpVersion; +import io.netty.handler.codec.http.LastHttpContent; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpOutputMessage; +import org.apache.dubbo.remoting.http12.h1.DefaultHttp1Request; +import org.apache.dubbo.remoting.http12.h1.Http1InputMessage; +import org.apache.dubbo.remoting.http12.h1.Http1Request; +import org.apache.dubbo.remoting.http12.h1.Http1RequestMetadata; + +import java.io.OutputStream; +import java.util.List; +import java.util.Map; + +public class NettyHttp1Codec extends ChannelDuplexHandler { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //decode FullHttpRequest + if (msg instanceof FullHttpRequest) { + FullHttpRequest fullHttpRequest = (FullHttpRequest) msg; + HttpHeaders headers = fullHttpRequest.headers(); + Http1RequestMetadata http1RequestMetadata = new Http1RequestMetadata(); + http1RequestMetadata.setPath(fullHttpRequest.uri()); + http1RequestMetadata.setMethod(fullHttpRequest.method().name()); + org.apache.dubbo.remoting.http12.HttpHeaders httpHeaders = new org.apache.dubbo.remoting.http12.HttpHeaders(); + for (Map.Entry header : headers) { + String key = header.getKey(); + httpHeaders.set(key, header.getValue()); + } + http1RequestMetadata.setHeaders(httpHeaders); + Http1Request http1Request = new DefaultHttp1Request(http1RequestMetadata, new Http1InputMessage(new ByteBufInputStream(fullHttpRequest.content(), true))); + super.channelRead(ctx, http1Request); + return; + } + super.channelRead(ctx, msg); + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + if (msg instanceof HttpMetadata) { + doWriteHeader(ctx, ((HttpMetadata) msg), promise); + return; + } + if (msg instanceof HttpOutputMessage) { + doWriteMessage(ctx, ((HttpOutputMessage) msg), promise); + return; + } + super.write(ctx, msg, promise); + } + + private void doWriteHeader(ChannelHandlerContext ctx, HttpMetadata msg, ChannelPromise promise) { + //process status + List statusHeaders = msg.headers().remove(HttpHeaderNames.STATUS.getName()); + HttpResponseStatus status = HttpResponseStatus.OK; + if (!(statusHeaders == null || statusHeaders.isEmpty())) { + status = HttpResponseStatus.valueOf(Integer.parseInt(statusHeaders.get(0))); + } + //process normal headers + DefaultHttpResponse defaultHttpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status); + HttpHeaders headers = defaultHttpResponse.headers(); + for (Map.Entry> entry : msg.headers().entrySet()) { + headers.set(entry.getKey(), entry.getValue()); + } + ctx.writeAndFlush(defaultHttpResponse, promise); + } + + private void doWriteMessage(ChannelHandlerContext ctx, HttpOutputMessage msg, ChannelPromise promise) { + if (HttpOutputMessage.EMPTY_MESSAGE == msg) { + ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT, promise); + return; + } + OutputStream body = msg.getBody(); + if (body instanceof ByteBufOutputStream) { + ByteBuf buffer = ((ByteBufOutputStream) body).buffer(); + ctx.writeAndFlush(buffer, promise); + return; + } + throw new IllegalArgumentException("HttpOutputMessage body must be 'io.netty.buffer.ByteBufOutputStream'"); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1ConnectionHandler.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1ConnectionHandler.java new file mode 100644 index 0000000000..84ddeda1bb --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1ConnectionHandler.java @@ -0,0 +1,110 @@ +/* + * 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.remoting.http12.netty4.h1; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.threadpool.ThreadPool; +import org.apache.dubbo.common.utils.Assert; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.exception.UnsupportedMediaTypeException; +import org.apache.dubbo.remoting.http12.h1.Http1Request; +import org.apache.dubbo.remoting.http12.h1.Http1ServerChannelObserver; +import org.apache.dubbo.remoting.http12.h1.Http1ServerTransportListener; +import org.apache.dubbo.remoting.http12.h1.Http1ServerTransportListenerFactory; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.rpc.model.FrameworkModel; + +import java.util.List; +import java.util.concurrent.Executor; + +public class NettyHttp1ConnectionHandler extends SimpleChannelInboundHandler { + + private Http1ServerTransportListenerFactory http1ServerTransportListenerFactory; + + private final FrameworkModel frameworkModel; + + private final URL url; + + private final Executor executor; + + private Http1ServerChannelObserver errorResponseObserver; + + public NettyHttp1ConnectionHandler(URL url, FrameworkModel frameworkModel) { + this.url = url; + this.frameworkModel = frameworkModel; + this.executor = url.getOrDefaultFrameworkModel().getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url); + } + + public NettyHttp1ConnectionHandler(URL url, + FrameworkModel frameworkModel, + Http1ServerTransportListenerFactory http1ServerTransportListenerFactory) { + this.url = url; + this.frameworkModel = frameworkModel; + this.executor = url.getOrDefaultFrameworkModel().getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url); + this.http1ServerTransportListenerFactory = http1ServerTransportListenerFactory; + } + + public void setHttp1ServerTransportListenerFactory(Http1ServerTransportListenerFactory http1ServerTransportListenerFactory) { + this.http1ServerTransportListenerFactory = http1ServerTransportListenerFactory; + } + + protected void channelRead0(ChannelHandlerContext ctx, Http1Request http1Request) { + //process h1 request + Http1ServerTransportListener http1TransportListener = initTransportListenerIfNecessary(ctx, http1Request); + executor.execute(() -> { + try { + http1TransportListener.onMetadata(http1Request); + http1TransportListener.onData(http1Request); + } catch (Exception e) { + errorResponseObserver.onError(e); + } + }); + } + + private Http1ServerTransportListener initTransportListenerIfNecessary(ChannelHandlerContext ctx, Http1Request http1Request) { + //each h1 request create http1TransportListener instance + Http1ServerTransportListenerFactory http1ServerTransportListenerFactory = this.http1ServerTransportListenerFactory; + Assert.notNull(http1ServerTransportListenerFactory, "http1ServerTransportListenerFactory must be not null."); + Http1ServerTransportListener http1TransportListener = http1ServerTransportListenerFactory.newInstance(new NettyHttp1Channel(ctx.channel()), url, frameworkModel); + + HttpHeaders headers = http1Request.headers(); + String contentType = headers.getFirst(HttpHeaderNames.CONTENT_TYPE.getName()); + if (!StringUtils.hasText(contentType)) { + throw new UnsupportedMediaTypeException(contentType); + } + HttpMessageCodec codec = findSuitableCodec(contentType, frameworkModel.getExtensionLoader(HttpMessageCodec.class).getActivateExtensions()); + if (codec == null) { + throw new UnsupportedMediaTypeException(contentType); + } + this.errorResponseObserver = new Http1ServerChannelObserver(new NettyHttp1Channel(ctx.channel())); + this.errorResponseObserver.setHttpMessageCodec(codec); + return http1TransportListener; + } + + private static HttpMessageCodec findSuitableCodec(String contentType, List candidates) { + for (HttpMessageCodec codec : candidates) { + if (codec.support(contentType)) { + return codec; + } + } + return null; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyH2StreamChannel.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyH2StreamChannel.java new file mode 100644 index 0000000000..f315b13100 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyH2StreamChannel.java @@ -0,0 +1,80 @@ +/* + * 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.remoting.http12.netty4.h2; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.handler.codec.http2.DefaultHttp2ResetFrame; +import io.netty.handler.codec.http2.Http2StreamChannel; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpOutputMessage; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2OutputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2OutputMessageFrame; +import org.apache.dubbo.remoting.http12.netty4.NettyHttpChannelFutureListener; + +import java.net.SocketAddress; +import java.util.concurrent.CompletableFuture; + +public class NettyH2StreamChannel implements H2StreamChannel { + + private final Http2StreamChannel http2StreamChannel; + + public NettyH2StreamChannel(Http2StreamChannel http2StreamChannel) { + this.http2StreamChannel = http2StreamChannel; + } + + @Override + public CompletableFuture writeHeader(HttpMetadata httpMetadata) { + //WriteQueue.enqueue header frame + NettyHttpChannelFutureListener nettyHttpChannelFutureListener = new NettyHttpChannelFutureListener(); + http2StreamChannel.write(httpMetadata).addListener(nettyHttpChannelFutureListener); + return nettyHttpChannelFutureListener; + } + + @Override + public CompletableFuture writeMessage(HttpOutputMessage httpOutputMessage) { + NettyHttpChannelFutureListener nettyHttpChannelFutureListener = new NettyHttpChannelFutureListener(); + http2StreamChannel.write(httpOutputMessage).addListener(nettyHttpChannelFutureListener); + return nettyHttpChannelFutureListener; + } + + @Override + public Http2OutputMessage newOutputMessage(boolean endStream) { + ByteBuf buffer = http2StreamChannel.alloc().buffer(); + ByteBufOutputStream outputStream = new ByteBufOutputStream(buffer); + return new Http2OutputMessageFrame(outputStream, endStream); + } + + @Override + public SocketAddress remoteAddress() { + return this.http2StreamChannel.remoteAddress(); + } + + @Override + public void flush() { + this.http2StreamChannel.flush(); + } + + @Override + public CompletableFuture writeResetFrame(long errorCode) { + DefaultHttp2ResetFrame resetFrame = new DefaultHttp2ResetFrame(errorCode); + NettyHttpChannelFutureListener nettyHttpChannelFutureListener = new NettyHttpChannelFutureListener(); + http2StreamChannel.write(resetFrame).addListener(nettyHttpChannelFutureListener); + return nettyHttpChannelFutureListener; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2FrameCodec.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2FrameCodec.java new file mode 100644 index 0000000000..3cf80e1b51 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2FrameCodec.java @@ -0,0 +1,113 @@ +/* + * 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.remoting.http12.netty4.h2; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http2.DefaultHttp2DataFrame; +import io.netty.handler.codec.http2.DefaultHttp2Headers; +import io.netty.handler.codec.http2.DefaultHttp2HeadersFrame; +import io.netty.handler.codec.http2.Http2DataFrame; +import io.netty.handler.codec.http2.Http2Headers; +import io.netty.handler.codec.http2.Http2HeadersFrame; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.h2.Http2Header; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessageFrame; +import org.apache.dubbo.remoting.http12.h2.Http2MetadataFrame; +import org.apache.dubbo.remoting.http12.h2.Http2OutputMessage; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; +import java.util.Map; + +public class NettyHttp2FrameCodec extends ChannelDuplexHandler { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + if (msg instanceof Http2HeadersFrame) { + Http2Header http2Header = onHttp2HeadersFrame(((Http2HeadersFrame) msg)); + super.channelRead(ctx, http2Header); + } else if (msg instanceof Http2DataFrame) { + Http2InputMessage http2Message = onHttp2DataFrame(((Http2DataFrame) msg)); + super.channelRead(ctx, http2Message); + } else { + super.channelRead(ctx, msg); + } + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + if (msg instanceof Http2Header) { + Http2Header http2Header = (Http2Header) msg; + Http2HeadersFrame http2HeadersFrame = encodeHttp2HeadersFrame(http2Header); + super.write(ctx, http2HeadersFrame, promise); + } else if (msg instanceof Http2OutputMessage) { + Http2OutputMessage http2OutputMessage = (Http2OutputMessage) msg; + Http2DataFrame http2DataFrame = encodeHttp2DataFrame(ctx, http2OutputMessage); + super.write(ctx, http2DataFrame, promise); + } else { + super.write(ctx, msg, promise); + } + } + + private Http2Header onHttp2HeadersFrame(Http2HeadersFrame headersFrame) { + Http2Headers headers = headersFrame.headers(); + boolean endStream = headersFrame.isEndStream(); + HttpHeaders head = new HttpHeaders(); + for (Map.Entry header : headers) { + head.set(header.getKey().toString(), header.getValue().toString()); + } + return new Http2MetadataFrame(headersFrame.stream().id(), head, endStream); + } + + private Http2InputMessage onHttp2DataFrame(Http2DataFrame dataFrame) { + ByteBuf content = dataFrame.content(); + Http2InputMessageFrame message = new Http2InputMessageFrame(new ByteBufInputStream(content, true), dataFrame.isEndStream()); + message.setId(dataFrame.stream().id()); + return message; + } + + private Http2HeadersFrame encodeHttp2HeadersFrame(Http2Header http2Header) { + HttpHeaders headers = http2Header.headers(); + DefaultHttp2Headers http2Headers = new DefaultHttp2Headers(); + for (Map.Entry> entry : headers.entrySet()) { + String name = entry.getKey(); + List value = entry.getValue(); + http2Headers.set(name, value); + } + return new DefaultHttp2HeadersFrame(http2Headers, http2Header.isEndStream()); + } + + private Http2DataFrame encodeHttp2DataFrame(ChannelHandlerContext ctx, Http2OutputMessage outputMessage) throws IOException { + OutputStream body = outputMessage.getBody(); + if (body == null) { + return new DefaultHttp2DataFrame(outputMessage.isEndStream()); + } + if (body instanceof ByteBufOutputStream) { + ByteBuf buffer = ((ByteBufOutputStream) body).buffer(); + return new DefaultHttp2DataFrame(buffer, outputMessage.isEndStream()); + } + throw new IllegalArgumentException("Http2OutputMessage body must be ByteBufOutputStream"); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2FrameHandler.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2FrameHandler.java new file mode 100644 index 0000000000..05e0cbed97 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2FrameHandler.java @@ -0,0 +1,81 @@ +/* + * 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.remoting.http12.netty4.h2; + +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http2.Http2ResetFrame; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.http12.HttpStatus; +import org.apache.dubbo.remoting.http12.exception.HttpStatusException; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2Header; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2TransportListener; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_FAILED_RESPONSE; + +public class NettyHttp2FrameHandler extends ChannelDuplexHandler { + + private static final ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger( + NettyHttp2FrameHandler.class); + + private final H2StreamChannel h2StreamChannel; + + private final Http2TransportListener transportListener; + + public NettyHttp2FrameHandler(H2StreamChannel h2StreamChannel, Http2TransportListener transportListener) { + this.h2StreamChannel = h2StreamChannel; + this.transportListener = transportListener; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + if (msg instanceof Http2Header) { + transportListener.onMetadata((Http2Header) msg); + } else if (msg instanceof Http2InputMessage) { + transportListener.onData((Http2InputMessage) msg); + } else { + super.channelRead(ctx, msg); + } + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + //reset frame + if (evt instanceof Http2ResetFrame) { + long errorCode = ((Http2ResetFrame) evt).errorCode(); + transportListener.cancelByRemote(errorCode); + } else { + super.userEventTriggered(ctx, evt); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (LOGGER.isWarnEnabled()) { + LOGGER.warn(PROTOCOL_FAILED_RESPONSE, "", "", "Exception in processing triple message", cause); + } + int statusCode = HttpStatus.INTERNAL_SERVER_ERROR.getCode(); + if (cause instanceof HttpStatusException) { + statusCode = ((HttpStatusException) cause).getStatusCode(); + } + h2StreamChannel.writeResetFrame(statusCode); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2ProtocolSelectorHandler.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2ProtocolSelectorHandler.java new file mode 100644 index 0000000000..09dbf9f2fc --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h2/NettyHttp2ProtocolSelectorHandler.java @@ -0,0 +1,90 @@ +/* + * 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.remoting.http12.netty4.h2; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http2.Http2StreamChannel; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.command.HttpWriteQueue; +import org.apache.dubbo.remoting.http12.exception.UnsupportedMediaTypeException; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory; +import org.apache.dubbo.remoting.http12.h2.command.Http2WriteQueueChannel; +import org.apache.dubbo.remoting.http12.netty4.HttpWriteQueueHandler; +import org.apache.dubbo.rpc.model.FrameworkModel; + +import java.util.Set; + +public class NettyHttp2ProtocolSelectorHandler extends SimpleChannelInboundHandler { + + private Http2ServerTransportListenerFactory defaultHttp2ServerTransportListenerFactory; + + private final URL url; + + private final FrameworkModel frameworkModel; + + public NettyHttp2ProtocolSelectorHandler(URL url, FrameworkModel frameworkModel) { + this.url = url; + this.frameworkModel = frameworkModel; + } + + public NettyHttp2ProtocolSelectorHandler(URL url, FrameworkModel frameworkModel, Http2ServerTransportListenerFactory defaultHttp2ServerTransportListenerFactory) { + this.url = url; + this.frameworkModel = frameworkModel; + this.defaultHttp2ServerTransportListenerFactory = defaultHttp2ServerTransportListenerFactory; + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, HttpMetadata metadata) { + HttpHeaders headers = metadata.headers(); + String contentType = headers.getFirst(HttpHeaderNames.CONTENT_TYPE.getName()); + //415 + if (!StringUtils.hasText(contentType)) { + throw new UnsupportedMediaTypeException(contentType); + } + Http2ServerTransportListenerFactory factory = adaptHttp2ServerTransportListenerFactory(contentType); + if (factory == null) { + throw new UnsupportedMediaTypeException(contentType); + } + H2StreamChannel h2StreamChannel = new NettyH2StreamChannel((Http2StreamChannel) ctx.channel()); + HttpWriteQueueHandler writeQueueHandler = ctx.channel().parent().pipeline().get(HttpWriteQueueHandler.class); + if (writeQueueHandler != null) { + HttpWriteQueue writeQueue = writeQueueHandler.getWriteQueue(); + h2StreamChannel = new Http2WriteQueueChannel(h2StreamChannel, writeQueue); + } + ChannelPipeline pipeline = ctx.pipeline(); + pipeline.addLast(new NettyHttp2FrameHandler(h2StreamChannel, factory.newInstance(h2StreamChannel, url, frameworkModel))); + pipeline.remove(this); + ctx.fireChannelRead(metadata); + } + + private Http2ServerTransportListenerFactory adaptHttp2ServerTransportListenerFactory(String contentType) { + Set http2ServerTransportListenerFactories = frameworkModel.getExtensionLoader(Http2ServerTransportListenerFactory.class).getSupportedExtensionInstances(); + for (Http2ServerTransportListenerFactory factory : http2ServerTransportListenerFactories) { + if (factory.supportContentType(contentType)) { + return factory; + } + } + return defaultHttp2ServerTransportListenerFactory; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec b/dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec new file mode 100644 index 0000000000..10f9ef3dd9 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec @@ -0,0 +1 @@ +json=org.apache.dubbo.remoting.http12.message.JsonCodec diff --git a/dubbo-remoting/pom.xml b/dubbo-remoting/pom.xml index c89503cb7e..f50a4a97ea 100644 --- a/dubbo-remoting/pom.xml +++ b/dubbo-remoting/pom.xml @@ -38,6 +38,7 @@ dubbo-remoting-zookeeper dubbo-remoting-zookeeper-curator5 dubbo-remoting-netty4 + dubbo-remoting-http12 From 56de12127b62362b3572a27c556f687bff3cfc0a Mon Sep 17 00:00:00 2001 From: Ken Liu Date: Wed, 16 Aug 2023 16:25:08 +0800 Subject: [PATCH 04/14] Revert "Add Dubbo Annotation Processor (Add deprecated method warn when called by user, #10850) (#11513)" (#12871) This reverts commit 0b6f2e4a8d045e137ce2b440e7fdd79941c57ec5. --- .licenserc.yaml | 1 - NOTICE | 2 +- dubbo-annotation-processor/pom.xml | 165 ------- .../AnnotationProcessingHandler.java | 44 -- .../AnnotationProcessorContext.java | 139 ------ .../DispatchingAnnotationProcessor.java | 162 ------- .../annotation/handler/DeprecatedHandler.java | 110 ----- .../dubbo/annotation/permit/Permit.java | 429 ------------------ .../dubbo/annotation/permit/dummy/Child.java | 33 -- .../annotation/permit/dummy/GrandChild.java | 43 -- .../dubbo/annotation/permit/dummy/Parent.java | 36 -- .../annotation/permit/dummy/package-info.java | 32 -- .../dubbo/annotation/permit/package-info.java | 32 -- .../dubbo/annotation/util/ASTUtils.java | 111 ----- .../dubbo/annotation/util/FileUtils.java | 155 ------- .../javax.annotation.processing.Processor | 1 - .../src/main/resources/handlers.cfg | 17 - .../dubbo/annotation/RealInvocationTest.java | 64 --- .../dubbo/annotation/TestingCommons.java | 71 --- .../DeprecatedMethodInvocationCounter.java | 36 -- .../dubbo/eci/extractor/JavassistUtils.java | 151 ------ .../apache/dubbo/eci/util/ReflectUtils.java | 51 --- .../org/testing/dm/TestConstructorMethod.java | 28 -- .../dm/TestConstructorMethodParentClass.java | 27 -- .../dm/TestConstructorMethodSubClass.java | 30 -- .../org/testing/dm/TestDeprecatedMethod.java | 26 -- .../dm/TestInterfaceDeprecatedMethod.java | 24 - dubbo-build-tools/pom.xml | 8 +- .../DeprecatedMethodInvocationCounter.java | 83 ---- ...catedMethodInvocationCounterConstants.java | 35 -- .../common/constants/LoggerCodeConstants.java | 5 - ...DeprecatedMethodInvocationCounterTest.java | 59 --- dubbo-config/dubbo-config-api/pom.xml | 1 - .../dubbo-metadata-processor/pom.xml | 13 - .../org/apache/dubbo/dependency/FileTest.java | 2 - pom.xml | 11 +- 36 files changed, 6 insertions(+), 2231 deletions(-) delete mode 100644 dubbo-annotation-processor/pom.xml delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessingHandler.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessorContext.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/DispatchingAnnotationProcessor.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/handler/DeprecatedHandler.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/Permit.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Child.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/GrandChild.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Parent.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/package-info.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/package-info.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/ASTUtils.java delete mode 100644 dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/FileUtils.java delete mode 100644 dubbo-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor delete mode 100644 dubbo-annotation-processor/src/main/resources/handlers.cfg delete mode 100644 dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/RealInvocationTest.java delete mode 100644 dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/TestingCommons.java delete mode 100644 dubbo-annotation-processor/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java delete mode 100644 dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/extractor/JavassistUtils.java delete mode 100644 dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/util/ReflectUtils.java delete mode 100644 dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethod.java delete mode 100644 dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodParentClass.java delete mode 100644 dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodSubClass.java delete mode 100644 dubbo-annotation-processor/src/test/resources/org/testing/dm/TestDeprecatedMethod.java delete mode 100644 dubbo-annotation-processor/src/test/resources/org/testing/dm/TestInterfaceDeprecatedMethod.java delete mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java delete mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/constants/DeprecatedMethodInvocationCounterConstants.java delete mode 100644 dubbo-common/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounterTest.java diff --git a/.licenserc.yaml b/.licenserc.yaml index 0e8b7409d8..3935786a0e 100644 --- a/.licenserc.yaml +++ b/.licenserc.yaml @@ -101,7 +101,6 @@ header: - 'dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java' - 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboMergingDigest.java' - 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboAbstractTDigest.java' - - 'dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/**' - 'dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/FormattingTuple.java' - 'dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/MessageFormatter.java' diff --git a/NOTICE b/NOTICE index b862c0f833..fb9cb50141 100644 --- a/NOTICE +++ b/NOTICE @@ -4,7 +4,7 @@ Copyright 2018-2023 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). -This product contains code from the Netty Project: +This product contains code form the Netty Project: The Netty Project ================= diff --git a/dubbo-annotation-processor/pom.xml b/dubbo-annotation-processor/pom.xml deleted file mode 100644 index 8a89f1bf74..0000000000 --- a/dubbo-annotation-processor/pom.xml +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - 4.0.0 - - org.apache.dubbo - dubbo-annotation-processor - 1.0.0 - - - 8 - 8 - UTF-8 - - - true - true - true - true - - true - - 5.9.0 - 3.29.2-GA - - - jar - - - - - org.junit.jupiter - junit-jupiter-engine - ${junit_jupiter_version} - test - - - - org.junit.jupiter - junit-jupiter-api - ${junit_jupiter_version} - test - - - - org.junit.jupiter - junit-jupiter-params - ${junit_jupiter_version} - test - - - - org.javassist - javassist - ${javassist_version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.10.1 - - none - true - - - - - - - - default-profile-in-jdk-8 - - - ${java.home}/../lib/tools.jar - - (, 9) - - - ${java.home}/../lib/tools.jar - - - - - javac - javac - 1.0 - system - ${toolsjar} - - - - - - legacy-apple-jdk-profile - - false - - ${java.home}/../Classes/classes.jar - - (, 9) - - - - ${java.home}/../Classes/classes.jar - - - - - javac - javac - 1.0 - system - ${toolsjar} - - - - - - add-export-greater-than-9 - - false - [9, ) - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.10.1 - - true - none - - - - - - - - diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessingHandler.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessingHandler.java deleted file mode 100644 index 4830e32704..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessingHandler.java +++ /dev/null @@ -1,44 +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.annotation; - -import javax.lang.model.element.Element; -import java.lang.annotation.Annotation; -import java.util.Set; - -/** - * Represents an annotation processing handler, which is invoked by DispatchingAnnotationProcessor. - */ -public interface AnnotationProcessingHandler { - - /** - * Set the annotations that this handler will handle. - * - * @return annotations to handle - */ - Set> getAnnotationsToHandle(); - - /** - * Formal processing method. - * - * @param elements the elements that annotated by the annotations of getAnnotationsToHandle() - * @param annotationProcessorContext the annotation processor context object (Javac object encapsulation) - */ - void process(Set elements, - AnnotationProcessorContext annotationProcessorContext); -} diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessorContext.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessorContext.java deleted file mode 100644 index 958385aba6..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessorContext.java +++ /dev/null @@ -1,139 +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.annotation; - -import com.sun.source.util.Trees; -import com.sun.tools.javac.api.JavacTrees; -import com.sun.tools.javac.processing.JavacProcessingEnvironment; -import com.sun.tools.javac.tree.TreeMaker; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.Names; - -import javax.annotation.processing.ProcessingEnvironment; -import java.lang.reflect.Method; -import java.util.Objects; - -/** - * The Context Object of Annotation Processor, which stores objects related to javac. - */ -public class AnnotationProcessorContext { - private JavacProcessingEnvironment javacProcessingEnvironment; - private JavacTrees javacTrees; - private TreeMaker treeMaker; - private Names names; - private Context javacContext; - private Trees trees; - - private AnnotationProcessorContext() { } - - private static T jbUnwrap(Class iface, T wrapper) { - T unwrapped = null; - try { - final Class apiWrappers = wrapper.getClass().getClassLoader().loadClass("org.jetbrains.jps.javac.APIWrappers"); - final Method unwrapMethod = apiWrappers.getDeclaredMethod("unwrap", Class.class, Object.class); - unwrapped = iface.cast(unwrapMethod.invoke(null, iface, wrapper)); - } catch (Throwable ignored) { - } - - return unwrapped != null ? unwrapped : wrapper; - } - - public static AnnotationProcessorContext fromProcessingEnvironment(ProcessingEnvironment processingEnv) { - AnnotationProcessorContext apContext = new AnnotationProcessorContext(); - - Object procEnvToUnwrap = processingEnv.getClass() == JavacProcessingEnvironment.class ? - processingEnv : jbUnwrap(JavacProcessingEnvironment.class, processingEnv); - - JavacProcessingEnvironment jcProcessingEnvironment = (JavacProcessingEnvironment) procEnvToUnwrap; - - Context context = jcProcessingEnvironment.getContext(); - - apContext.javacProcessingEnvironment = jcProcessingEnvironment; - - apContext.javacContext = context; - apContext.javacTrees = JavacTrees.instance(jcProcessingEnvironment); - apContext.treeMaker = TreeMaker.instance(context); - apContext.names = Names.instance(context); - - apContext.trees = Trees.instance(jcProcessingEnvironment); - - return apContext; - } - - // Auto-generated methods. - - public JavacTrees getJavacTrees() { - return javacTrees; - } - - public TreeMaker getTreeMaker() { - return treeMaker; - } - - public Names getNames() { - return names; - } - - public Context getJavacContext() { - return javacContext; - } - - public Trees getTrees() { - return trees; - } - - public JavacProcessingEnvironment getJavacProcessingEnvironment() { - return javacProcessingEnvironment; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - AnnotationProcessorContext context = (AnnotationProcessorContext) o; - - if (!Objects.equals(javacTrees, context.javacTrees)) return false; - if (!Objects.equals(treeMaker, context.treeMaker)) return false; - if (!Objects.equals(names, context.names)) return false; - if (!Objects.equals(javacContext, context.javacContext)) - return false; - return Objects.equals(trees, context.trees); - } - - @Override - public int hashCode() { - int result = javacTrees != null ? javacTrees.hashCode() : 0; - result = 31 * result + (treeMaker != null ? treeMaker.hashCode() : 0); - result = 31 * result + (names != null ? names.hashCode() : 0); - result = 31 * result + (javacContext != null ? javacContext.hashCode() : 0); - result = 31 * result + (trees != null ? trees.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "AnnotationProcessorContext{" + - "javacTrees=" + javacTrees + - ", treeMaker=" + treeMaker + - ", names=" + names + - ", javacContext=" + javacContext + - ", trees=" + trees + - '}'; - } -} diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/DispatchingAnnotationProcessor.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/DispatchingAnnotationProcessor.java deleted file mode 100644 index 8c11d72eff..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/DispatchingAnnotationProcessor.java +++ /dev/null @@ -1,162 +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.annotation; - -import org.apache.dubbo.annotation.permit.Permit; -import org.apache.dubbo.annotation.util.FileUtils; - -import com.sun.tools.javac.code.Symbol; -import com.sun.tools.javac.processing.JavacRoundEnvironment; - -import javax.annotation.processing.AbstractProcessor; -import javax.annotation.processing.ProcessingEnvironment; -import javax.annotation.processing.RoundEnvironment; -import javax.annotation.processing.SupportedAnnotationTypes; -import javax.lang.model.SourceVersion; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.tools.Diagnostic; -import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Dispatching annotation processor, which uses a file to locate handlers and invoke them. - */ -@SupportedAnnotationTypes("*") -public class DispatchingAnnotationProcessor extends AbstractProcessor { - - private static Set handlers; - - private static Set loadHandlers() { - List classNames = FileUtils.loadConfigurationFileInResources("handlers.cfg"); - Set tempHandlers = new HashSet<>(); - - for (String clsName : classNames) { - try { - Class cls = (Class) Class.forName(clsName); - AnnotationProcessingHandler r = cls.getConstructor().newInstance(); - - tempHandlers.add(r); - - } catch (InstantiationException | NoSuchMethodException | InvocationTargetException | - IllegalAccessException | ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - return Collections.unmodifiableSet(tempHandlers); - } - - private AnnotationProcessorContext apContext; - - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - Permit.addOpens(); - super.init(processingEnv); - - if (processingEnv.getClass().getName().startsWith("org.eclipse.jdt.")) { - // Don't run on ECJ, since this processor is javac based. - processingEnv - .getMessager() - .printMessage(Diagnostic.Kind.WARNING, "The Annotation processor doesn't support ECJ."); - - return; - } - - if (handlers == null) { - handlers = loadHandlers(); - } - - apContext = AnnotationProcessorContext.fromProcessingEnvironment(processingEnv); - } - - @Override - public boolean process(Set annotations, RoundEnvironment roundEnv) { - - if (processingEnv.getClass().getName().startsWith("org.eclipse.jdt.")) { - // Don't run on ECJ, since this processor is javac based. - return false; - } - - for (AnnotationProcessingHandler i : handlers) { - Set elements = new HashSet<>(16); - - for (Class annotationClass : i.getAnnotationsToHandle()) { - elements.addAll(getElementsAnnotatedWith(annotationClass, roundEnv)); - } - - i.process(elements, apContext); - } - - return false; - } - - /** - * A hack to make comment only .java file pass the compilation by skipping package symbol scan. - * - * @param annotationClass the annotation class to find - * @param roundEnvironment the javac's round environment - * @return the elements annotated with specified annotation - */ - private Set getElementsAnnotatedWith(Class annotationClass, RoundEnvironment roundEnvironment) { - - TypeElement a = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName()); - - // Detect the Javac's version. - if (Integer.parseInt(SourceVersion.latest().name().split("_")[1]) > 8) { - return roundEnvironment.getElementsAnnotatedWith(a); - } - - Set result = Collections.emptySet(); - - try { - Class annotationSetScannerClass = Class.forName("com.sun.tools.javac.processing.JavacRoundEnvironment$AnnotationSetScanner"); - Constructor scannerConstructor = Permit.getConstructor(annotationSetScannerClass, JavacRoundEnvironment.class, Set.class); - Object scanner = scannerConstructor.newInstance(roundEnvironment, result); - - Set rootElements1 = roundEnvironment - .getRootElements() - .stream() - .filter(x -> x.getClass() != Symbol.PackageSymbol.class) - .collect(Collectors.toSet()); - - for (Element element : rootElements1) { - Method scanningMethod = Permit.getMethod(annotationSetScannerClass, "scan", Element.class, TypeElement.class); - result = (Set) scanningMethod.invoke(scanner, element, a); - } - - } catch (InstantiationException | NoSuchMethodException | ClassNotFoundException | InvocationTargetException | - IllegalAccessException e) { - throw new RuntimeException(e); - } - - return result; - } - - @Override - public SourceVersion getSupportedSourceVersion() { - return SourceVersion.latestSupported(); - } -} diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/handler/DeprecatedHandler.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/handler/DeprecatedHandler.java deleted file mode 100644 index c87cb8f6c9..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/handler/DeprecatedHandler.java +++ /dev/null @@ -1,110 +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.annotation.handler; - -import org.apache.dubbo.annotation.AnnotationProcessingHandler; -import org.apache.dubbo.annotation.AnnotationProcessorContext; -import org.apache.dubbo.annotation.util.ASTUtils; - -import com.sun.tools.javac.code.Symbol; -import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.tree.TreeTranslator; - -import javax.lang.model.element.Element; -import java.lang.annotation.Annotation; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * Handles @Deprecated annotation and adds logger warn call to the methods that are annotated with it. - */ -public class DeprecatedHandler implements AnnotationProcessingHandler { - - @Override - public Set> getAnnotationsToHandle() { - return new HashSet<>( - Collections.singletonList(Deprecated.class) - ); - } - - @Override - public void process(Set elements, AnnotationProcessorContext apContext) { - for (Element element : elements) { - // Only interested in methods. - if (!(element instanceof Symbol.MethodSymbol)) { - continue; - } - - Symbol.ClassSymbol classSymbol = (Symbol.ClassSymbol) element.getEnclosingElement(); - - ASTUtils.addImportStatement(apContext, classSymbol, "org.apache.dubbo.common", "DeprecatedMethodInvocationCounter"); - - JCTree methodTree = apContext.getJavacTrees().getTree(element); - - methodTree.accept(new TreeTranslator() { - @Override - public void visitMethodDef(JCTree.JCMethodDecl jcMethodDecl) { - - JCTree.JCBlock block = jcMethodDecl.body; - - if (block == null) { - // No method body. (i.e. interface method declaration.) - return; - } - - ASTUtils.insertStatementToHeadOfMethod(block, jcMethodDecl, generateCounterStatement(apContext, classSymbol, jcMethodDecl)); - } - }); - } - } - - /** - * Generate an expression statement like this: - * DeprecatedMethodInvocationCounter.onDeprecatedMethodCalled("...."); - * - * @param originalMethodDecl the method declaration that will add logger statement - * @param apContext annotation processor context - * @param classSymbol the enclosing class that will be the logger's name - * @return generated expression statement - */ - private JCTree.JCExpressionStatement generateCounterStatement(AnnotationProcessorContext apContext, - Symbol.ClassSymbol classSymbol, - JCTree.JCMethodDecl originalMethodDecl) { - - JCTree.JCExpression fullStatement = apContext.getTreeMaker().Apply( - com.sun.tools.javac.util.List.nil(), - - apContext.getTreeMaker().Select( - apContext.getTreeMaker().Ident(apContext.getNames().fromString("DeprecatedMethodInvocationCounter")), - apContext.getNames().fromString("onDeprecatedMethodCalled") - ), - - com.sun.tools.javac.util.List.of( - apContext.getTreeMaker().Literal(getMethodDefinition(classSymbol, originalMethodDecl)) - ) - ); - - return apContext.getTreeMaker().Exec(fullStatement); - } - - private String getMethodDefinition(Symbol.ClassSymbol classSymbol, JCTree.JCMethodDecl originalMethodDecl) { - return classSymbol.getQualifiedName() + "." - + originalMethodDecl.name.toString() + "(" + originalMethodDecl.params.toString() + ")"; - } -} diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/Permit.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/Permit.java deleted file mode 100644 index 3d5c941764..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/Permit.java +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Authored by Project Lombok and licensed by MIT License, which is attached below: - * - * Copyright (C) 2018-2021 The Project Lombok Authors. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * 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. - */ - -package org.apache.dubbo.annotation.permit; - -import org.apache.dubbo.annotation.permit.dummy.Parent; - -import sun.misc.Unsafe; - -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -// sunapi suppresses javac's warning about using Unsafe; 'all' suppresses eclipse's warning about the unspecified 'sunapi' key. Leave them both. -// Yes, javac's definition of the word 'all' is quite contrary to what the dictionary says it means. 'all' does NOT include 'sunapi' according to javac. -@SuppressWarnings({"sunapi", "all"}) -public class Permit { - private Permit() { - } - - - private static final long ACCESSIBLE_OVERRIDE_FIELD_OFFSET; - private static final IllegalAccessException INIT_ERROR; - private static final sun.misc.Unsafe UNSAFE = (sun.misc.Unsafe) reflectiveStaticFieldAccess(sun.misc.Unsafe.class, "theUnsafe"); - - static { - Field f; - long g; - Throwable ex; - - try { - g = getOverrideFieldOffset(); - ex = null; - } catch (Throwable t) { - f = null; - g = -1L; - ex = t; - } - - ACCESSIBLE_OVERRIDE_FIELD_OFFSET = g; - if (ex == null) INIT_ERROR = null; - else if (ex instanceof IllegalAccessException) INIT_ERROR = (IllegalAccessException) ex; - else { - INIT_ERROR = new IllegalAccessException("Cannot initialize Unsafe-based permit"); - INIT_ERROR.initCause(ex); - } - } - - public static T setAccessible(T accessor) { - if (INIT_ERROR == null) { - UNSAFE.putBoolean(accessor, ACCESSIBLE_OVERRIDE_FIELD_OFFSET, true); - } else { - accessor.setAccessible(true); - } - - return accessor; - } - - private static long getOverrideFieldOffset() throws Throwable { - Field f = null; - Throwable saved = null; - try { - f = AccessibleObject.class.getDeclaredField("override"); - } catch (Throwable t) { - saved = t; - } - - if (f != null) { - return UNSAFE.objectFieldOffset(f); - } - // The below seems very risky, but for all AccessibleObjects in java today it does work, and starting with JDK12, making the field accessible is no longer possible. - try { - return UNSAFE.objectFieldOffset(Fake.class.getDeclaredField("override")); - } catch (Throwable t) { - throw saved; - } - } - - static class Fake { - boolean override; - Object accessCheckCache; - } - - public static Method getMethod(Class c, String mName, Class... parameterTypes) throws NoSuchMethodException { - Method m = null; - Class oc = c; - while (c != null) { - try { - m = c.getDeclaredMethod(mName, parameterTypes); - break; - } catch (NoSuchMethodException e) { - } - c = c.getSuperclass(); - } - - if (m == null) throw new NoSuchMethodException(oc.getName() + " :: " + mName + "(args)"); - return setAccessible(m); - } - - public static Method permissiveGetMethod(Class c, String mName, Class... parameterTypes) { - try { - return getMethod(c, mName, parameterTypes); - } catch (Exception ignore) { - return null; - } - } - - public static Field getField(Class c, String fName) throws NoSuchFieldException { - Field f = null; - Class oc = c; - while (c != null) { - try { - f = c.getDeclaredField(fName); - break; - } catch (NoSuchFieldException e) { - } - c = c.getSuperclass(); - } - - if (f == null) throw new NoSuchFieldException(oc.getName() + " :: " + fName); - - return setAccessible(f); - } - - public static Field permissiveGetField(Class c, String fName) { - try { - return getField(c, fName); - } catch (Exception ignore) { - return null; - } - } - - public static T permissiveReadField(Class type, Field f, Object instance) { - try { - return type.cast(f.get(instance)); - } catch (Exception ignore) { - return null; - } - } - - public static Constructor getConstructor(Class c, Class... parameterTypes) throws NoSuchMethodException { - return setAccessible(c.getDeclaredConstructor(parameterTypes)); - } - - private static Object reflectiveStaticFieldAccess(Class c, String fName) { - try { - Field f = c.getDeclaredField(fName); - f.setAccessible(true); - return f.get(null); - } catch (Exception e) { - return null; - } - } - - public static boolean isDebugReflection() { - return !"false".equals(System.getProperty("lombok.debug.reflection", "false")); - } - - public static void handleReflectionDebug(Throwable t, Throwable initError) { - if (!isDebugReflection()) return; - - System.err.println("** LOMBOK REFLECTION exception: " + t.getClass() + ": " + (t.getMessage() == null ? "(no message)" : t.getMessage())); - t.printStackTrace(System.err); - if (initError != null) { - System.err.println("*** ADDITIONALLY, exception occurred setting up reflection: "); - initError.printStackTrace(System.err); - } - } - - public static Object invoke(Method m, Object receiver, Object... args) throws IllegalAccessException, InvocationTargetException { - return invoke(null, m, receiver, args); - } - - public static Object invoke(Throwable initError, Method m, Object receiver, Object... args) throws IllegalAccessException, InvocationTargetException { - try { - return m.invoke(receiver, args); - } catch (IllegalAccessException e) { - handleReflectionDebug(e, initError); - throw e; - } catch (RuntimeException e) { - handleReflectionDebug(e, initError); - throw e; - } catch (Error e) { - handleReflectionDebug(e, initError); - throw e; - } - } - - public static Object invokeSneaky(Method m, Object receiver, Object... args) { - return invokeSneaky(null, m, receiver, args); - } - - public static Object invokeSneaky(Throwable initError, Method m, Object receiver, Object... args) { - try { - return m.invoke(receiver, args); - } catch (NoClassDefFoundError e) { - handleReflectionDebug(e, initError); - //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly - //do anything useful here. - return null; - } catch (NullPointerException e) { - handleReflectionDebug(e, initError); - //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly - //do anything useful here. - return null; - } catch (IllegalAccessException e) { - handleReflectionDebug(e, initError); - throw sneakyThrow(e); - } catch (InvocationTargetException e) { - throw sneakyThrow(e.getCause()); - } catch (RuntimeException e) { - handleReflectionDebug(e, initError); - throw e; - } catch (Error e) { - handleReflectionDebug(e, initError); - throw e; - } - } - - public static T newInstance(Constructor c, Object... args) throws IllegalAccessException, InvocationTargetException, InstantiationException { - return newInstance(null, c, args); - } - - public static T newInstance(Throwable initError, Constructor c, Object... args) throws IllegalAccessException, InvocationTargetException, InstantiationException { - try { - return c.newInstance(args); - } catch (IllegalAccessException e) { - handleReflectionDebug(e, initError); - throw e; - } catch (InstantiationException e) { - handleReflectionDebug(e, initError); - throw e; - } catch (RuntimeException e) { - handleReflectionDebug(e, initError); - throw e; - } catch (Error e) { - handleReflectionDebug(e, initError); - throw e; - } - } - - public static T newInstanceSneaky(Constructor c, Object... args) { - return newInstanceSneaky(null, c, args); - } - - public static T newInstanceSneaky(Throwable initError, Constructor c, Object... args) { - try { - return c.newInstance(args); - } catch (NoClassDefFoundError e) { - handleReflectionDebug(e, initError); - //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly - //do anything useful here. - return null; - } catch (NullPointerException e) { - handleReflectionDebug(e, initError); - //ignore, we don't have access to the correct ECJ classes, so lombok can't possibly - //do anything useful here. - return null; - } catch (IllegalAccessException e) { - handleReflectionDebug(e, initError); - throw sneakyThrow(e); - } catch (InstantiationException e) { - handleReflectionDebug(e, initError); - throw sneakyThrow(e); - } catch (InvocationTargetException e) { - throw sneakyThrow(e.getCause()); - } catch (RuntimeException e) { - handleReflectionDebug(e, initError); - throw e; - } catch (Error e) { - handleReflectionDebug(e, initError); - throw e; - } - } - - public static Object get(Field f, Object receiver) throws IllegalAccessException { - try { - return f.get(receiver); - } catch (IllegalAccessException e) { - handleReflectionDebug(e, null); - throw e; - } catch (RuntimeException e) { - handleReflectionDebug(e, null); - throw e; - } catch (Error e) { - handleReflectionDebug(e, null); - throw e; - } - } - - public static void set(Field f, Object receiver, Object newValue) throws IllegalAccessException { - try { - f.set(receiver, newValue); - } catch (IllegalAccessException e) { - handleReflectionDebug(e, null); - throw e; - } catch (RuntimeException e) { - handleReflectionDebug(e, null); - throw e; - } catch (Error e) { - handleReflectionDebug(e, null); - throw e; - } - } - - public static void reportReflectionProblem(Throwable initError, String msg) { - if (!isDebugReflection()) return; - System.err.println("** LOMBOK REFLECTION issue: " + msg); - if (initError != null) { - System.err.println("*** ADDITIONALLY, exception occurred setting up reflection: "); - initError.printStackTrace(System.err); - } - } - - public static RuntimeException sneakyThrow(Throwable t) { - if (t == null) throw new NullPointerException("t"); - return Permit.sneakyThrow0(t); - } - - @SuppressWarnings("unchecked") - private static T sneakyThrow0(Throwable t) throws T { - throw (T) t; - } - - private static Object getJdkCompilerModule() { - /* call public api: ModuleLayer.boot().findModule("jdk.compiler").get(); - but use reflection because we don't want this code to crash on jdk1.7 and below. - In that case, none of this stuff was needed in the first place, so we just exit via - the catch block and do nothing. - */ - - try { - Class cModuleLayer = Class.forName("java.lang.ModuleLayer"); - Method mBoot = cModuleLayer.getDeclaredMethod("boot"); - Object bootLayer = mBoot.invoke(null); - Class cOptional = Class.forName("java.util.Optional"); - Method mFindModule = cModuleLayer.getDeclaredMethod("findModule", String.class); - Object oCompilerO = mFindModule.invoke(bootLayer, "jdk.compiler"); - return cOptional.getDeclaredMethod("get").invoke(oCompilerO); - } catch (Exception e) { - return null; - } - } - - private static Object getOwnModule() { - try { - Method m = Permit.getMethod(Class.class, "getModule"); - return m.invoke(Permit.class); - } catch (Exception e) { - return null; - } - } - - private static long getFirstFieldOffset(Unsafe unsafe) { - try { - return unsafe.objectFieldOffset(Parent.class.getDeclaredField("first")); - } catch (NoSuchFieldException e) { - // can't happen. - throw new RuntimeException(e); - } catch (SecurityException e) { - // can't happen - throw new RuntimeException(e); - } - } - - public static void addOpens() { - Class cModule; - try { - cModule = Class.forName("java.lang.Module"); - } catch (ClassNotFoundException e) { - return; //jdk8-; this is not needed. - } - - Unsafe unsafe = UNSAFE; - - Object jdkCompilerModule = getJdkCompilerModule(); - Object ownModule = getOwnModule(); - String[] allPkgs = { - "com.sun.tools.javac.code", - "com.sun.tools.javac.comp", - "com.sun.tools.javac.file", - "com.sun.tools.javac.main", - "com.sun.tools.javac.model", - "com.sun.tools.javac.parser", - "com.sun.tools.javac.processing", - "com.sun.tools.javac.tree", - "com.sun.tools.javac.util", - "com.sun.tools.javac.jvm", - "com.sun.tools.javac.api" - }; - - try { - Method m = cModule.getDeclaredMethod("implAddOpens", String.class, cModule); - long firstFieldOffset = getFirstFieldOffset(unsafe); - unsafe.putBooleanVolatile(m, firstFieldOffset, true); - for (String p : allPkgs) m.invoke(jdkCompilerModule, p, ownModule); - } catch (Exception ignore) {} - - try { - Method m = cModule.getDeclaredMethod("implAddExports", String.class, cModule); - long firstFieldOffset = getFirstFieldOffset(unsafe); - unsafe.putBooleanVolatile(m, firstFieldOffset, true); - for (String p : allPkgs) m.invoke(jdkCompilerModule, p, ownModule); - } catch (Exception ignore) {} - } -} diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Child.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Child.java deleted file mode 100644 index 46c647bedc..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Child.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Authored by Project Lombok and licensed by MIT License, which is attached below: - * - * Copyright (C) 2018-2021 The Project Lombok Authors. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * 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. - */ - -package org.apache.dubbo.annotation.permit.dummy; - -@SuppressWarnings("all") -public abstract class Child extends Parent { - private transient volatile boolean foo; - private transient volatile Object[] bar; - private transient volatile Object baz; - -} diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/GrandChild.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/GrandChild.java deleted file mode 100644 index c2bf737629..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/GrandChild.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Authored by Project Lombok and licensed by MIT License, which is attached below: - * - * Copyright (C) 2018-2021 The Project Lombok Authors. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * 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. - */ - -package org.apache.dubbo.annotation.permit.dummy; - -@SuppressWarnings("all") -public final class GrandChild extends Child { - private Class a; - private int b; - private String c; - private Class d; - private Class[] e; - private Class[] f; - private int g; - private transient String h; - private transient Object i; - private byte[] j; - private byte[] k; - private byte[] l; - private volatile Object m; - private Object n; -} diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Parent.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Parent.java deleted file mode 100644 index 53cb8c8ce5..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Parent.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Authored by Project Lombok and licensed by MIT License, which is attached below: - * - * Copyright (C) 2018-2021 The Project Lombok Authors. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * 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. - */ - -package org.apache.dubbo.annotation.permit.dummy; - -import java.io.OutputStream; - -@SuppressWarnings("all") -public class Parent { - boolean first; - static final Object staticObj = OutputStream.class; - volatile Object second; - private static volatile boolean staticSecond; - private static volatile boolean staticThird; -} diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/package-info.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/package-info.java deleted file mode 100644 index dcbf5a58a0..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/package-info.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Authored by Project Lombok and licensed by MIT License, which is attached below: - * - * Copyright (C) 2018-2021 The Project Lombok Authors. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * 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 package recreates the type hierarchy of {@code java.lang.reflect.AccessibleObject} and friends (such as {@code java.lang.reflect.Method}); - * its purpose is to allow us to ask {@code sun.misc.internal.Unsafe} about the exact offset of the {@code override} field of {@code AccessibleObject}; - * asking about that field directly doesn't work after jdk14, presumably because the fields of AO are expressly hidden somehow. - *

- * NB: It's usually 12, on the vast majority of OS, VM, and architecture combos. - */ -package org.apache.dubbo.annotation.permit.dummy; diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/package-info.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/package-info.java deleted file mode 100644 index 95b72451c6..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/package-info.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Authored by Project Lombok and licensed by MIT License, which is attached below: - * - * Copyright (C) 2018-2021 The Project Lombok Authors. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * 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 is a reduced copy of the nqzero Permit-reflect project. - * https://github.com/nqzero/permit-reflect - *

- * Many thanks to nqzero. The permit-reflect project is, like lombok itself, licensed under the MIT license. - * See https://github.com/nqzero/permit-reflect/blob/master/License for license info. - */ -package org.apache.dubbo.annotation.permit; diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/ASTUtils.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/ASTUtils.java deleted file mode 100644 index bfd463785f..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/ASTUtils.java +++ /dev/null @@ -1,111 +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.annotation.util; - -import org.apache.dubbo.annotation.AnnotationProcessorContext; - -import com.sun.source.util.TreePath; -import com.sun.tools.javac.code.Symbol; -import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.util.ListBuffer; - -import java.util.List; - -/** - * Some utils about AST manipulating. - */ -public final class ASTUtils { - - private ASTUtils() { - throw new UnsupportedOperationException("No instance of 'ASTUtils' for you! "); - } - - public static void addImportStatement(AnnotationProcessorContext apContext, - Symbol.ClassSymbol classSymbol, - String packageName, - String className) { - - JCTree.JCImport jcImport = apContext.getTreeMaker().Import( - apContext.getTreeMaker().Select( - apContext.getTreeMaker().Ident(apContext.getNames().fromString(packageName)), - apContext.getNames().fromString(className) - ), false); - - TreePath treePath = apContext.getTrees().getPath(classSymbol); - TreePath parentPath = treePath.getParentPath(); - JCTree.JCCompilationUnit compilationUnit = (JCTree.JCCompilationUnit) parentPath.getCompilationUnit(); - - List imports = compilationUnit.getImports(); - if (imports.stream().noneMatch(x -> x.qualid.toString().contains(packageName + "." + className))) { - - compilationUnit.accept(new JCTree.Visitor() { - @Override - public void visitTopLevel(JCTree.JCCompilationUnit that) { - - List defs = compilationUnit.defs; - - ListBuffer newDefs = new ListBuffer<>(); - - newDefs.add(defs.get(0)); - newDefs.add(jcImport); - newDefs.addAll(defs.subList(1, defs.size())); - - compilationUnit.defs = newDefs.toList(); - } - }); - } - } - - /** - * Insert statement to head of the method. - * - * @param block the method body - * @param originalMethodDecl the method declaration that will add logger statement - * @param fullExpressionStatement the statement to insert. - */ - public static void insertStatementToHeadOfMethod(JCTree.JCBlock block, - JCTree.JCMethodDecl originalMethodDecl, - JCTree.JCStatement fullExpressionStatement) { - - boolean isConstructor = originalMethodDecl.name.toString().equals(""); - ListBuffer statements = new ListBuffer<>(); - - // In constructor, super(...) or this(...) should be the first statement. - - if (isConstructor && !block.stats.isEmpty()) { - - boolean startsWithSuper = block.stats.get(0).toString().startsWith("super("); - boolean startsWithThis = block.stats.get(0).toString().startsWith("this("); - - if (startsWithSuper || startsWithThis) { - statements.add(block.stats.get(0)); - statements.add(fullExpressionStatement); - statements.addAll(block.stats.subList(1, block.stats.size())); - } else { - statements.add(fullExpressionStatement); - statements.addAll(block.stats); - } - - } else { - statements.add(fullExpressionStatement); - statements.addAll(block.stats); - } - - block.stats = statements.toList(); - } -} diff --git a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/FileUtils.java b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/FileUtils.java deleted file mode 100644 index 66a897913a..0000000000 --- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/FileUtils.java +++ /dev/null @@ -1,155 +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.annotation.util; - -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.FileChannel; -import java.nio.channels.ReadableByteChannel; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.Scanner; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * Utilities of iterating file. - */ -public final class FileUtils { - - private static final Pattern WINDOWS_PATH_PATTERN = Pattern.compile("file:/\\w:/.*"); - - - private FileUtils() { - throw new UnsupportedOperationException("No instance of FileUtils for you! "); - } - - public static List getAllClassFilePaths(String rootPath) { - List targetFolders; - - try (Stream filesStream = Files.walk(Paths.get(rootPath))) { - targetFolders = filesStream.filter(x -> !x.toFile().isFile()) - .filter(x -> x.toString().contains("classes") && !x.toString().contains("test-classes")) - .filter(x -> x.toString().contains("\\org\\apache\\dubbo".replace('\\', File.separatorChar))) - .collect(Collectors.toList()); - - return targetFolders; - - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public static byte[] openFileAsByteArray(String filePath) { - try (FileChannel fileChannel = FileChannel.open(Paths.get(filePath))) { - - ByteBuffer byteBuffer = ByteBuffer.allocate((int) fileChannel.size()); - fileChannel.read(byteBuffer); - - return byteBuffer.array(); - - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public static String openFileAsString(String filePath) { - return new String(openFileAsByteArray(filePath)); - } - - public static String getSourceFilePathFromClassFilePath(String classFilePath) { - - String classesPathString = "\\target\\classes\\".replace("\\", File.separator); - String sourcesPathString = "\\src\\main\\java\\".replace("\\", File.separator); - - String sourceFilePathByReplace = classFilePath.replace(classesPathString, sourcesPathString) - .replace(".class", ".java"); - - // Inner classes. - if (sourceFilePathByReplace.lastIndexOf('$') != -1) { - int dollarCharIndex = sourceFilePathByReplace.lastIndexOf('$'); - String outerClassPath = sourceFilePathByReplace.substring(0, dollarCharIndex); - - return outerClassPath + ".java"; - } - - return sourceFilePathByReplace; - } - - public static List loadConfigurationFileInResources(String path) { - - ReadableByteChannel resourceReadableByteChannel = Channels.newChannel( - Objects.requireNonNull(FileUtils.class.getClassLoader().getResourceAsStream(path))); - - List lines = new ArrayList<>(); - - try (Scanner scanner = new Scanner(resourceReadableByteChannel)) { - - while (scanner.hasNextLine()) { - String line = scanner.nextLine().trim(); - - if (!line.startsWith("#") && !line.isEmpty()) { - lines.add(line); - } - } - - return lines; - } - } - - /** - *

Get absolute path of resource. - * - *

Retained for testing. It won't work in JAR. - * - * @param path relative path of resources folder. - * @return absolute path of resource - */ - public static String getResourceFilePath(String path) { - String resourceFilePath = FileUtils.class.getClassLoader().getResource(path).toString(); - - if (WINDOWS_PATH_PATTERN.matcher(resourceFilePath).matches()) { - resourceFilePath = resourceFilePath.replace("file:/", ""); - } else { - resourceFilePath = resourceFilePath.replace("file:", ""); - } - - return resourceFilePath; - } - - public static List getAllFilesInDirectory(Path targetFolder) { - - try (Stream classFilesStream = Files.walk(targetFolder)) { - - return classFilesStream - .filter(x -> x.toFile().isFile()) - .collect(Collectors.toList()); - - } catch (IOException e) { - return Collections.emptyList(); - } - } -} diff --git a/dubbo-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/dubbo-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor deleted file mode 100644 index fe51e15be0..0000000000 --- a/dubbo-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ /dev/null @@ -1 +0,0 @@ -org.apache.dubbo.annotation.DispatchingAnnotationProcessor diff --git a/dubbo-annotation-processor/src/main/resources/handlers.cfg b/dubbo-annotation-processor/src/main/resources/handlers.cfg deleted file mode 100644 index bcdca71445..0000000000 --- a/dubbo-annotation-processor/src/main/resources/handlers.cfg +++ /dev/null @@ -1,17 +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. - -org.apache.dubbo.annotation.handler.DeprecatedHandler diff --git a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/RealInvocationTest.java b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/RealInvocationTest.java deleted file mode 100644 index 9544990ffe..0000000000 --- a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/RealInvocationTest.java +++ /dev/null @@ -1,64 +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.annotation; - -import org.apache.dubbo.annotation.util.FileUtils; -import org.apache.dubbo.eci.extractor.JavassistUtils; - -import javassist.bytecode.ClassFile; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Real invocation test of DispatchingAnnotationProcessor (and DeprecatedHandler). - */ -class RealInvocationTest { - - /** - * [File name, Should the counter exist in the class file? ] - */ - private static final Map FILES = new HashMap<>(5, 1); - - static { - FILES.put("TestConstructorMethod.java", true); - FILES.put("TestDeprecatedMethod.java", true); - FILES.put("TestInterfaceDeprecatedMethod.java", false); - FILES.put("TestConstructorMethodParentClass.java", false); - FILES.put("TestConstructorMethodSubClass.java", true); - } - - @Test - void test() { - - for (Map.Entry i : FILES.entrySet()) { - String filePath = FileUtils.getResourceFilePath("org/testing/dm/" + i.getKey()); - - Assertions.assertTrue(TestingCommons.compileTheSource(filePath), "Compile failed! "); - - String classFilePath = filePath.replace(".java", ".class"); - ClassFile classFile = JavassistUtils.openClassFile(classFilePath); - List stringItems = JavassistUtils.getConstPoolStringItems(classFile.getConstPool()); - - Assertions.assertEquals(i.getValue(), stringItems.contains("org/apache/dubbo/common/DeprecatedMethodInvocationCounter")); - } - } -} diff --git a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/TestingCommons.java b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/TestingCommons.java deleted file mode 100644 index cca11f56e6..0000000000 --- a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/TestingCommons.java +++ /dev/null @@ -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.annotation; - -import javax.tools.JavaCompiler; -import javax.tools.JavaFileObject; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.Locale; - -import static java.util.Arrays.asList; - -/** - * Common code of annotation processor testing. - */ -public final class TestingCommons { - private TestingCommons() { - throw new UnsupportedOperationException("No instance of TestingCommons for you! "); - } - - private static class ObjectHolders { - static final JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); - - static final StandardJavaFileManager javaFileManager = javaCompiler.getStandardFileManager( - null, - Locale.ROOT, - StandardCharsets.UTF_8 - ); - } - - public static boolean compileTheSource(String filePath) { - - - JavaCompiler.CompilationTask compilationTask = ObjectHolders.javaCompiler.getTask( - null, - ObjectHolders.javaFileManager, - null, - asList("-parameters", "-Xlint:unchecked", "-nowarn", "-Xlint:deprecation"), - null, - getSourceFileJavaFileObject(filePath) - ); - - compilationTask.setProcessors( - Collections.singletonList(new DispatchingAnnotationProcessor()) - ); - - return compilationTask.call(); - } - - private static Iterable getSourceFileJavaFileObject(String filePath) { - - return ObjectHolders.javaFileManager.getJavaFileObjects(filePath); - } -} diff --git a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java deleted file mode 100644 index cc34299c81..0000000000 --- a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.dubbo.common; - -/** - * Reduced mock of Deprecated method invocation counter. - */ -public final class DeprecatedMethodInvocationCounter { - private DeprecatedMethodInvocationCounter() { - throw new UnsupportedOperationException("No instance of DeprecatedMethodInvocationCounter for you! "); - } - - /** - * Invoked by (modified) deprecated method. - * - * @param methodDefinition filled by annotation processor. (like 'org.apache.dubbo.common.URL.getServiceName()') - */ - public static void onDeprecatedMethodCalled(String methodDefinition) { - // Intended to be empty. - } -} diff --git a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/extractor/JavassistUtils.java b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/extractor/JavassistUtils.java deleted file mode 100644 index 3a2475591a..0000000000 --- a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/extractor/JavassistUtils.java +++ /dev/null @@ -1,151 +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.eci.extractor; - -import org.apache.dubbo.annotation.util.FileUtils; - -import javassist.bytecode.ClassFile; -import javassist.bytecode.ConstPool; - -import java.io.ByteArrayInputStream; -import java.io.DataInputStream; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Utilities of Javassist. - */ -public class JavassistUtils { - private static final Map stringFieldCache = new HashMap<>(2, 1); - - private static Method getItemMethodCache = null; - - private JavassistUtils() { - throw new UnsupportedOperationException("No instance of JavassistUtils for you! "); - } - - public static ClassFile openClassFile(String classFilePath) { - try { - byte[] clsB = FileUtils.openFileAsByteArray(classFilePath); - return new ClassFile(new DataInputStream(new ByteArrayInputStream(clsB))); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - static List getConstPoolItems(ConstPool cp) { - List objects = new ArrayList<>(cp.getSize()); - - for (int i = 0; i < cp.getSize(); i++) { - objects.add(getConstPoolItem(cp, i)); - } - - return objects; - } - - /** - * Calls ConstPool.getItem() method reflectively. - * - * @param cp The ConstPool object. - * @param index The index of items. - * @return The XXXInfo Object. Since it's invisible, return Object instead. - */ - static Object getConstPoolItem(ConstPool cp, int index) { - - if (getItemMethodCache == null) { - Class cpc = ConstPool.class; - Method getItemMethod; - try { - getItemMethod = cpc.getDeclaredMethod("getItem", int.class); - getItemMethod.setAccessible(true); - - getItemMethodCache = getItemMethod; - - } catch (NoSuchMethodException e) { - throw new RuntimeException("Javassist internal method changed.", e); - } - } - - try { - return getItemMethodCache.invoke(cp, index); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException("Javassist internal method changed.", e); - } - } - - public static List getConstPoolStringItems(ConstPool cp) { - List objects = getConstPoolItems(cp); - List stringItems = new ArrayList<>(cp.getSize()); - - for (Object item : objects) { - - Field stringField; - - if (item != null) { - stringField = getStringFieldInConstPoolItems(item); - - if (stringField == null) { - continue; - } - - Object fieldData; - - try { - fieldData = stringField.get(item); - } catch (IllegalAccessException e) { - throw new RuntimeException("Javassist internal field changed.", e); - } - - if (fieldData.getClass() == String.class) { - stringItems.add((String) fieldData); - } - } - } - - return stringItems; - } - - /** - * Obtain the 'string' field in Utf8Info and StringInfo. - * - * @param item The instance of Utf8Info and StringInfo. - * @return 'string' field's value - */ - static Field getStringFieldInConstPoolItems(Object item) { - if (stringFieldCache.containsKey(item.getClass())) { - return stringFieldCache.get(item.getClass()); - } else { - try { - Field stringField = item.getClass().getDeclaredField("string"); - stringField.setAccessible(true); - stringFieldCache.put(item.getClass(), stringField); - - return stringField; - } catch (NoSuchFieldException ignored) { - } - } - - return null; - } -} diff --git a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/util/ReflectUtils.java b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/util/ReflectUtils.java deleted file mode 100644 index 681bdc0441..0000000000 --- a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/util/ReflectUtils.java +++ /dev/null @@ -1,51 +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.eci.util; - -import java.lang.reflect.Field; - -/** - * Tools of reflective operations. - */ -public final class ReflectUtils { - private ReflectUtils() { - throw new UnsupportedOperationException("No instance of ReflectUtils for you! "); - } - - /** - * Searches (a private) field in super classes recursively. - * - * @param cls the actual type - * @param name the field name - * @return the corresponding Field object, or null if the field does not exist. - */ - public static Field getDeclaredFieldRecursively(Class cls, String name) { - try { - Field indexField = cls.getDeclaredField(name); - indexField.setAccessible(true); - - return indexField; - } catch (NoSuchFieldException e) { - if (cls == Object.class) { - return null; - } - - return getDeclaredFieldRecursively(cls.getSuperclass(), name); - } - } -} diff --git a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethod.java b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethod.java deleted file mode 100644 index c705ca8d13..0000000000 --- a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethod.java +++ /dev/null @@ -1,28 +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.testing.dm; - -public class TestConstructorMethod { - @Deprecated - TestConstructorMethod() { - this("1"); - } - - TestConstructorMethod(String s) { - } -} diff --git a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodParentClass.java b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodParentClass.java deleted file mode 100644 index 8e14e67c51..0000000000 --- a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodParentClass.java +++ /dev/null @@ -1,27 +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.testing.dm; - -public class TestConstructorMethodParentClass { - - public TestConstructorMethodParentClass() { - } - - public TestConstructorMethodParentClass(String s) { - } -} diff --git a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodSubClass.java b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodSubClass.java deleted file mode 100644 index 3b71626c9b..0000000000 --- a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodSubClass.java +++ /dev/null @@ -1,30 +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.testing.dm; - -public class TestConstructorMethodSubClass extends TestConstructorMethodParentClass { - - @Deprecated - public TestConstructorMethodSubClass(int i) { - super(); - } - - public TestConstructorMethodSubClass(String s) { - super(s); - } -} diff --git a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestDeprecatedMethod.java b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestDeprecatedMethod.java deleted file mode 100644 index 6360c3e137..0000000000 --- a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestDeprecatedMethod.java +++ /dev/null @@ -1,26 +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.testing.dm; - -public class TestDeprecatedMethod { - - @Deprecated - public void m1() { - System.out.println("M1! "); - } -} diff --git a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestInterfaceDeprecatedMethod.java b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestInterfaceDeprecatedMethod.java deleted file mode 100644 index a2ce7af598..0000000000 --- a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestInterfaceDeprecatedMethod.java +++ /dev/null @@ -1,24 +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.testing.dm; - -public interface TestInterfaceDeprecatedMethod { - - @Deprecated - public void m1(); -} diff --git a/dubbo-build-tools/pom.xml b/dubbo-build-tools/pom.xml index 5c3b83e2dd..28bae806b1 100644 --- a/dubbo-build-tools/pom.xml +++ b/dubbo-build-tools/pom.xml @@ -13,8 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> - 4.0.0 @@ -24,7 +24,7 @@ jar - true + true - + \ No newline at end of file diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java deleted file mode 100644 index b4245c5bfa..0000000000 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.dubbo.common; - -import org.apache.dubbo.common.constants.DeprecatedMethodInvocationCounterConstants; -import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; -import org.apache.dubbo.common.logger.LoggerFactory; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.LongAdder; - -/** - * Deprecated method invocation counter, which is used by annotation processor. - *

- * If an IDE says it is unused, just ignore it. - */ -public final class DeprecatedMethodInvocationCounter { - private DeprecatedMethodInvocationCounter() { - throw new UnsupportedOperationException("No instance of DeprecatedMethodInvocationCounter for you! "); - } - - private static final ConcurrentHashMap COUNTERS = new ConcurrentHashMap<>(); - - private static final ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(DeprecatedMethodInvocationCounter.class); - - /** - * Invoked by (modified) deprecated method. - * - * @param methodDefinition filled by annotation processor. (like 'org.apache.dubbo.common.URL.getServiceName()') - */ - public static void onDeprecatedMethodCalled(String methodDefinition) { - if (!hasThisMethodInvoked(methodDefinition)) { - LOGGER.warn( - DeprecatedMethodInvocationCounterConstants.ERROR_CODE, - DeprecatedMethodInvocationCounterConstants.POSSIBLE_CAUSE, - DeprecatedMethodInvocationCounterConstants.EXTENDED_MESSAGE, - DeprecatedMethodInvocationCounterConstants.LOGGER_MESSAGE_PREFIX + methodDefinition - ); - } - - increaseInvocationCount(methodDefinition); - } - - private static void increaseInvocationCount(String methodDefinition) { - COUNTERS.computeIfAbsent(methodDefinition, k -> new LongAdder()); - LongAdder adder = COUNTERS.get(methodDefinition); - - adder.increment(); - } - - public static boolean hasThisMethodInvoked(String methodDefinition) { - return COUNTERS.containsKey(methodDefinition); - } - - public static Map getInvocationRecord() { - // Perform a deep-copy to avoid concurrent issues. - HashMap copyOfCounters = new HashMap<>(); - - for (Map.Entry entry : COUNTERS.entrySet()) { - copyOfCounters.put(entry.getKey(), entry.getValue().intValue()); - } - - return Collections.unmodifiableMap(copyOfCounters); - } -} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/DeprecatedMethodInvocationCounterConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/DeprecatedMethodInvocationCounterConstants.java deleted file mode 100644 index f747568491..0000000000 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/DeprecatedMethodInvocationCounterConstants.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.dubbo.common.constants; - -/** - * Constants of Deprecated Method Invocation Counter. - */ -public final class DeprecatedMethodInvocationCounterConstants { - private DeprecatedMethodInvocationCounterConstants() { - throw new UnsupportedOperationException("No instance of DeprecatedMethodInvocationCounterConstants for you! "); - } - - public static final String ERROR_CODE = LoggerCodeConstants.COMMON_DEPRECATED_METHOD_INVOKED; - - public static final String POSSIBLE_CAUSE = "invocation of deprecated method"; - - public static final String EXTENDED_MESSAGE = ""; - - public static final String LOGGER_MESSAGE_PREFIX = "Deprecated method invoked. The method is "; -} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java index fb66b5a8c9..7a598ddddf 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java @@ -94,11 +94,6 @@ public interface LoggerCodeConstants { String COMMON_NOT_FOUND_TRACER_DEPENDENCY = "0-29"; - /** - * Used in annotation processor to indicate a deprecated method is invoked. - */ - String COMMON_DEPRECATED_METHOD_INVOKED = "0-99"; - // Registry module String REGISTRY_ADDRESS_INVALID = "1-1"; diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounterTest.java deleted file mode 100644 index b1ad0943a7..0000000000 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounterTest.java +++ /dev/null @@ -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.common; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Map; - -/** - * Tests of DeprecatedMethodInvocationCounter. - */ -class DeprecatedMethodInvocationCounterTest { - - private static final String METHOD_DEFINITION = "org.apache.dubbo.common.URL.getServiceName()"; - - @Test - void testRealInvocation() { - Assertions.assertFalse(DeprecatedMethodInvocationCounter.hasThisMethodInvoked(METHOD_DEFINITION)); - - // Invoke a deprecated method. - URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path#index?version=1.0.0&id=org.apache.dubbo.config.RegistryConfig#0"); - - // Not a typo, intentionally invoke twice. - invokeDeprecatedMethod(url); - invokeDeprecatedMethod(url); - - Assertions.assertTrue(DeprecatedMethodInvocationCounter.hasThisMethodInvoked(METHOD_DEFINITION)); - - Map record = DeprecatedMethodInvocationCounter.getInvocationRecord(); - Assertions.assertEquals(2, record.get(METHOD_DEFINITION)); - } - - private void invokeDeprecatedMethod(URL url) { - try { - Method m = URL.class.getMethod("getServiceName"); - m.invoke(url); - } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { - throw new RuntimeException(e); - } - } -} diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml index d21d6e5f54..3b00dbb1a0 100644 --- a/dubbo-config/dubbo-config-api/pom.xml +++ b/dubbo-config/dubbo-config-api/pom.xml @@ -259,6 +259,5 @@ test - diff --git a/dubbo-metadata/dubbo-metadata-processor/pom.xml b/dubbo-metadata/dubbo-metadata-processor/pom.xml index 0945a6d434..859d057abc 100644 --- a/dubbo-metadata/dubbo-metadata-processor/pom.xml +++ b/dubbo-metadata/dubbo-metadata-processor/pom.xml @@ -161,17 +161,4 @@ test - - - - - org.apache.maven.plugins - maven-compiler-plugin - - true - none - - - - diff --git a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java index 806e7090b2..aa0a264b36 100644 --- a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java +++ b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java @@ -51,7 +51,6 @@ class FileTest { ignoredModules.add(Pattern.compile("dubbo-parent")); ignoredModules.add(Pattern.compile("dubbo-core-spi")); ignoredModules.add(Pattern.compile("dubbo-demo.*")); - ignoredModules.add(Pattern.compile("dubbo-annotation-processor")); ignoredArtifacts.add(Pattern.compile("dubbo-demo.*")); ignoredArtifacts.add(Pattern.compile("dubbo-test.*")); @@ -67,7 +66,6 @@ class FileTest { ignoredModulesInDubboAll.add(Pattern.compile("dubbo-native.*")); ignoredModulesInDubboAll.add(Pattern.compile("dubbo-config-spring6.*")); ignoredModulesInDubboAll.add(Pattern.compile(".*spring-boot.*")); - ignoredModulesInDubboAll.add(Pattern.compile("dubbo-annotation-processor.*")); ignoredModulesInDubboAll.add(Pattern.compile("dubbo-maven-plugin")); } diff --git a/pom.xml b/pom.xml index 5801f45d56..8bcf596193 100644 --- a/pom.xml +++ b/pom.xml @@ -125,7 +125,6 @@ 1.5.0 3.3.0 3.1.0 - 1.0.0 1.7.1 0.6.1 @@ -141,7 +140,6 @@ - dubbo-annotation-processor dubbo-common dubbo-container dubbo-compiler @@ -184,14 +182,6 @@ - - - org.apache.dubbo - dubbo-annotation-processor - ${dubbo_annotation_processor_version} - true - - org.junit.jupiter @@ -726,6 +716,7 @@ ${maven_compiler_version} + -proc:none -parameters true From 8e55dae8f990785e0d4b9c9ca1d149e445248d6e Mon Sep 17 00:00:00 2001 From: Ken Liu Date: Wed, 30 Aug 2023 21:48:57 +0800 Subject: [PATCH 05/14] Feature improvement, only register one url for port unification. (#12528) --- .../common/constants/CommonConstants.java | 8 ++- .../common/deploy/ApplicationDeployer.java | 4 +- .../dubbo/common/deploy/ModuleDeployer.java | 4 ++ .../dubbo/config/ApplicationConfig.java | 9 +++ .../apache/dubbo/config/ServiceConfig.java | 17 +++++- .../InternalServiceConfigBuilder.java | 60 ++++++++++--------- .../deploy/DefaultApplicationDeployer.java | 22 ++++--- .../config/deploy/DefaultModuleDeployer.java | 16 +++++ .../config/utils/ConfigValidationUtils.java | 3 +- .../dubbo/config/ReferenceConfigTest.java | 2 +- .../dubbo/config/ServiceConfigTest.java | 9 +-- ...ryCenterExportMetadataIntegrationTest.java | 11 +--- ...ryCenterExportMetadataIntegrationTest.java | 11 +--- ...erviceURLParamsMetadataCustomizerTest.java | 6 +- .../utils/ConfigValidationUtilsTest.java | 5 +- dubbo-config/pom.xml | 15 ++++- .../apache/dubbo/metadata/MetadataInfo.java | 8 ++- .../client/ServiceDiscoveryRegistry.java | 1 + .../ServiceDiscoveryRegistryDirectory.java | 10 ++++ .../ServiceInstanceMetadataUtils.java | 25 ++++---- .../integration/RegistryDirectory.java | 37 ++++++++++++ .../registry/support/FailbackRegistry.java | 18 +++++- .../api/pu/AbstractPortUnificationServer.java | 20 ++++++- .../netty4/PortUnificationServerTest.java | 21 ++++++- dubbo-test/dubbo-dependencies-all/pom.xml | 10 ++-- .../org/apache/dubbo/dependency/FileTest.java | 2 + 26 files changed, 262 insertions(+), 92 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java index fcf113302f..f2ab8011d5 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java @@ -641,7 +641,13 @@ public interface CommonConstants { String REST_SERVICE_DEPLOYER_URL_ATTRIBUTE_KEY = "restServiceDeployerAttributeKey"; - String SERVICE_DEPLOYER_ATTRIBUTE_KEY = "serviceDeployer"; String RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY = "resteasyNettyHttpRequest"; + String SERVICE_DEPLOYER_ATTRIBUTE_KEY = "serviceDeployer"; + + String RESTEASY_NETTY_HTTP_REQUEST_ATTRIBUTE_KEY = "resteasyNettyHttpRequest"; String DUBBO_MANUAL_REGISTER_KEY = "dubbo.application.manual-register"; + + String EXT_PROTOCOL = "ext.protocol"; + + String IS_EXTRA = "isExtra"; } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ApplicationDeployer.java b/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ApplicationDeployer.java index 0b0b9d4509..84dbe70410 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ApplicationDeployer.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ApplicationDeployer.java @@ -48,7 +48,9 @@ public interface ApplicationDeployer extends Deployer { /** * Register application instance and start internal services */ - void prepareApplicationInstance(); + void prepareApplicationInstance(ModuleModel moduleModel); + + void exportMetadataService(); /** * Register application instance and start internal services diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ModuleDeployer.java b/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ModuleDeployer.java index 80d36d2d9c..b628e9b5ce 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ModuleDeployer.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ModuleDeployer.java @@ -50,4 +50,8 @@ public interface ModuleDeployer extends Deployer { * Whether start in background, do not await finish */ boolean isBackground(); + + boolean hasRegistryInteraction(); + + ApplicationDeployer getApplicationDeployer(); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java index de4cc47a5e..35703ef3f1 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java @@ -33,6 +33,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_PROTOCOL_KEY; @@ -82,6 +83,8 @@ public class ApplicationConfig extends AbstractConfig { private static final long serialVersionUID = 5508512956753757169L; + private static final String DEFAULT_NAME_PREFIX = "DUBBO_APP_"; + /** * Application name */ @@ -747,6 +750,12 @@ public class ApplicationConfig extends AbstractConfig { public void refresh() { super.refresh(); appendEnvironmentProperties(); + if (StringUtils.isEmpty(getName())) { + String defaultName = DEFAULT_NAME_PREFIX + UUID.randomUUID(); + this.setName(defaultName); + LOGGER.info("No application name was set, '" + defaultName + "' will be used as the default application name," + + " it's highly recommended to set a unique and customized name for it can be critical for some service governance features."); + } } private void appendEnvironmentProperties() { diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java index 3e6b767b52..c4bccea4c3 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java @@ -76,6 +76,8 @@ import static org.apache.dubbo.common.constants.CommonConstants.DUBBO; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_IP_TO_BIND; import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_MANAGEMENT_MODE_ISOLATION; import static org.apache.dubbo.common.constants.CommonConstants.EXPORTER_LISTENER_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.EXT_PROTOCOL; +import static org.apache.dubbo.common.constants.CommonConstants.IS_EXTRA; import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE; import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY; @@ -366,7 +368,17 @@ public class ServiceConfig extends ServiceConfigBase { mapServiceName(url, serviceNameMapping, scheduledExecutor); } }); + onExported(); + + if (hasRegistrySpecified()) { + getScopeModel().getDeployer().getApplicationDeployer().exportMetadataService(); + } + } + + public boolean hasRegistrySpecified() { + return CollectionUtils.isNotEmpty(this.getRegistries()) + || CollectionUtils.isNotEmpty(getScopeModel().getApplicationModel().getApplicationConfigManager().getRegistries()); } protected void mapServiceName(URL url, ServiceNameMapping serviceNameMapping, ScheduledExecutorService scheduledExecutor) { @@ -740,14 +752,13 @@ public class ServiceConfig extends ServiceConfigBase { // export to remote if the config is not local (export to local only when config is local) if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) { // export to extra protocol is used in remote export - String extProtocol = url.getParameter("ext.protocol", ""); + String extProtocol = url.getParameter(EXT_PROTOCOL, ""); List protocols = new ArrayList<>(); if (StringUtils.isNotBlank(extProtocol)) { // export original url url = URLBuilder.from(url). addParameter(IS_PU_SERVER_KEY, Boolean.TRUE.toString()). - removeParameter("ext.protocol"). build(); } @@ -765,6 +776,8 @@ public class ServiceConfig extends ServiceConfigBase { if (StringUtils.isNotBlank(protocol)) { URL localUrl = URLBuilder.from(url). setProtocol(protocol). + addParameter(IS_EXTRA, Boolean.TRUE.toString()). + removeParameter(EXT_PROTOCOL). build(); localUrl = exportRemote(localUrl, registryURLs, registerType); if (!isGeneric(generic) && !getScopeModel().isInternal()) { diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/InternalServiceConfigBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/InternalServiceConfigBuilder.java index 5a2dbdbaf6..a54bc775a3 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/InternalServiceConfigBuilder.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/InternalServiceConfigBuilder.java @@ -51,7 +51,7 @@ import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY; public class InternalServiceConfigBuilder { private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass()); - private static final Set UNACCEPTABLE_PROTOCOL = Stream.of("rest", "grpc").collect(Collectors.toSet()); + private static final Set ACCEPTABLE_PROTOCOL = Stream.of("dubbo", "tri", "injvm").collect(Collectors.toSet()); private final ApplicationModel applicationModel; private String protocol; @@ -112,19 +112,20 @@ public class InternalServiceConfigBuilder { */ private String getRelatedOrDefaultProtocol() { String protocol = ""; - // - List moduleModels = applicationModel.getPubModuleModels(); - protocol = moduleModels.stream() - .map(ModuleModel::getConfigManager) - .map(ModuleConfigManager::getConsumers) - .filter(CollectionUtils::isNotEmpty) - .flatMap(Collection::stream) - .map(ConsumerConfig::getProtocol) - .filter(StringUtils::isNotEmpty) - .filter(p -> !UNACCEPTABLE_PROTOCOL.contains(p)) - .findFirst() - .orElse(""); + // + if (StringUtils.isEmpty(protocol)) { + Collection protocols = applicationModel.getApplicationConfigManager().getProtocols(); + if (CollectionUtils.isNotEmpty(protocols)) { + protocol = protocols.stream() + .map(ProtocolConfig::getName) + .filter(StringUtils::isNotEmpty) + .filter(p -> ACCEPTABLE_PROTOCOL.contains(p)) + .findFirst() + .orElse(""); + } + } // + List moduleModels = applicationModel.getPubModuleModels(); if (StringUtils.isEmpty(protocol)) { Stream providerConfigStream = moduleModels.stream() .map(ModuleModel::getConfigManager) @@ -145,22 +146,10 @@ public class InternalServiceConfigBuilder { } }) .filter(StringUtils::isNotEmpty) - .filter(p -> !UNACCEPTABLE_PROTOCOL.contains(p)) + .filter(p -> ACCEPTABLE_PROTOCOL.contains(p)) .findFirst() .orElse(""); } - // - if (StringUtils.isEmpty(protocol)) { - Collection protocols = applicationModel.getApplicationConfigManager().getProtocols(); - if (CollectionUtils.isNotEmpty(protocols)) { - protocol = protocols.stream() - .map(ProtocolConfig::getName) - .filter(StringUtils::isNotEmpty) - .filter(p -> !UNACCEPTABLE_PROTOCOL.contains(p)) - .findFirst() - .orElse(""); - } - } // if (StringUtils.isEmpty(protocol)) { protocol = getApplicationConfig().getProtocol(); @@ -171,7 +160,18 @@ public class InternalServiceConfigBuilder { } } } - return StringUtils.isNotEmpty(protocol) && !UNACCEPTABLE_PROTOCOL.contains(protocol) ? protocol : DUBBO_PROTOCOL; + // + protocol = moduleModels.stream() + .map(ModuleModel::getConfigManager) + .map(ModuleConfigManager::getConsumers) + .filter(CollectionUtils::isNotEmpty) + .flatMap(Collection::stream) + .map(ConsumerConfig::getProtocol) + .filter(StringUtils::isNotEmpty) + .filter(p -> ACCEPTABLE_PROTOCOL.contains(p)) + .findFirst() + .orElse(""); + return StringUtils.isNotEmpty(protocol) && ACCEPTABLE_PROTOCOL.contains(protocol) ? protocol : DUBBO_PROTOCOL; } public InternalServiceConfigBuilder protocol(String protocol) { @@ -254,7 +254,11 @@ public class InternalServiceConfigBuilder { logger.info("Using " + this.protocol + " protocol to export "+interfaceClass.getName()+" service on port " + protocolConfig.getPort()); applicationModel.getApplicationConfigManager().getProtocol(this.protocol) - .ifPresent(protocolConfig::mergeProtocol); + .ifPresent(p -> { + protocolConfig.mergeProtocol(p); + // clear extra protocols possibly merged from global ProtocolConfig + protocolConfig.setExtProtocol(null); + }); ApplicationConfig applicationConfig = getApplicationConfig(); diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java index d4a3da0cee..3e194f6557 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java @@ -183,13 +183,13 @@ public class DefaultApplicationDeployer extends AbstractDeployer listener : listeners) { diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java index 5694c890dc..281415d7d5 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java @@ -87,6 +87,9 @@ public class DefaultModuleDeployer extends AbstractDeployer impleme private Boolean background; private Boolean exportAsync; private Boolean referAsync; + + private boolean registryInteracted; + private CompletableFuture exportFuture; private CompletableFuture referFuture; @@ -439,6 +442,10 @@ public class DefaultModuleDeployer extends AbstractDeployer impleme exportedServices.add(sc); } } + + if (serviceConfig.hasRegistrySpecified()) { + registryInteracted = true; + } } private void registerServiceInternal(ServiceConfigBase sc) { @@ -578,4 +585,13 @@ public class DefaultModuleDeployer extends AbstractDeployer impleme this.initialize(); } + @Override + public boolean hasRegistryInteraction() { + return registryInteracted; + } + + @Override + public ApplicationDeployer getApplicationDeployer() { + return applicationDeployer; + } } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java index 1f92b894ad..e8f1f9fbf3 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java @@ -100,7 +100,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_SE import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY; import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY; import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; -import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CLASS_NOT_FOUND; import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_PARAMETER_FORMAT_ERROR; import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_ALL; import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_INSTANCE; @@ -464,7 +463,7 @@ public class ConfigValidationUtils { try { ClassUtils.forName("org.apache.dubbo.qos.protocol.QosProtocolWrapper"); } catch (ClassNotFoundException e) { - logger.warn(COMMON_CLASS_NOT_FOUND, "", "", "No QosProtocolWrapper class was found. Please check the dependency of dubbo-qos whether was imported correctly.", e); + logger.info("QosProtocolWrapper not found, qos will not be enabled, please check if 'dubbo-qos' dependency was imported correctly."); } } } diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java index 5412f39e22..db3478e1a2 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java @@ -37,7 +37,6 @@ import org.apache.dubbo.rpc.Protocol; import org.apache.dubbo.rpc.ProxyFactory; import org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder; import org.apache.dubbo.rpc.cluster.support.registry.ZoneAwareClusterInvoker; -//import org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker; import org.apache.dubbo.rpc.cluster.support.wrapper.ScopeClusterInvoker; import org.apache.dubbo.rpc.listener.ListenerInvokerWrapper; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -1041,6 +1040,7 @@ class ReferenceConfigTest { referenceConfig1.setRegistry(new RegistryConfig(zkUrl1)); referenceConfig1.setScopeModel(moduleModel); referenceConfig1.setScope("remote"); + referenceConfig1.setTimeout(30000); Object object1 = referenceConfig1.get(); java.lang.reflect.Method callBean1 = object1.getClass().getDeclaredMethod("call", requestClazzOrigin); diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java index fe5a0ad643..467fd63d5e 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java @@ -186,8 +186,9 @@ class ServiceConfigTest { assertThat(url.getParameters(), hasKey(METHODS_KEY)); assertThat(url.getParameters().get(METHODS_KEY), containsString("echo")); assertThat(url.getParameters(), hasEntry(SIDE_KEY, PROVIDER)); - // export MetadataService and DemoService in "mockprotocol2" protocol. - Mockito.verify(protocolDelegate, times(2)).export(Mockito.any(Invoker.class)); + // export DemoService in "mockprotocol2" protocol. + Mockito.verify(protocolDelegate, times(1)).export(Mockito.any(Invoker.class)); + // MetadataService will be exported on either dubbo or triple (the only two default acceptable protocol) } @Test @@ -351,8 +352,8 @@ class ServiceConfigTest { assertThat(url.getParameters(), hasKey(METHODS_KEY)); assertThat(url.getParameters().get(METHODS_KEY), containsString("echo")); assertThat(url.getParameters(), hasEntry(SIDE_KEY, PROVIDER)); - // export MetadataService and DemoService in "mockprotocol2" protocol. - Mockito.verify(protocolDelegate, times(2)).export(Mockito.any(Invoker.class)); + // export DemoService in "mockprotocol2" protocol (MetadataService will be not exported if no registry specified) + Mockito.verify(protocolDelegate, times(1)).export(Mockito.any(Invoker.class)); } @Test diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/integration/multiple/exportmetadata/MultipleRegistryCenterExportMetadataIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/integration/multiple/exportmetadata/MultipleRegistryCenterExportMetadataIntegrationTest.java index 28a644bff7..8f25f3c195 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/integration/multiple/exportmetadata/MultipleRegistryCenterExportMetadataIntegrationTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/integration/multiple/exportmetadata/MultipleRegistryCenterExportMetadataIntegrationTest.java @@ -39,7 +39,6 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.List; -import java.util.stream.Collectors; import static org.apache.dubbo.rpc.Constants.SCOPE_LOCAL; @@ -159,13 +158,9 @@ class MultipleRegistryCenterExportMetadataIntegrationTest implements Integration // 1. Metadata Service exporter with Injvm protocol // 2. MultipleRegistryCenterExportMetadataService exporter with Injvm protocol Assertions.assertEquals(exporterListener.getExportedExporters().size(), 2); - List> injvmExporters = exporterListener.getExportedExporters() - .stream() - .filter( - exporter -> PROTOCOL_NAME.equalsIgnoreCase(exporter.getInvoker().getUrl().getProtocol()) - ).collect(Collectors.toList()); + List> injvmExporters = exporterListener.getExportedExporters(); // Make sure there two injvmExporters - Assertions.assertEquals(injvmExporters.size(), 2); + Assertions.assertEquals(2, injvmExporters.size()); } @AfterEach @@ -178,4 +173,4 @@ class MultipleRegistryCenterExportMetadataIntegrationTest implements Integration serviceListener = null; logger.info(getClass().getSimpleName() + " testcase is ending..."); } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/integration/single/exportmetadata/SingleRegistryCenterExportMetadataIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/integration/single/exportmetadata/SingleRegistryCenterExportMetadataIntegrationTest.java index 3178b2e7e9..e64a671f52 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/integration/single/exportmetadata/SingleRegistryCenterExportMetadataIntegrationTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/integration/single/exportmetadata/SingleRegistryCenterExportMetadataIntegrationTest.java @@ -39,7 +39,6 @@ import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.List; -import java.util.stream.Collectors; import static org.apache.dubbo.rpc.Constants.SCOPE_LOCAL; @@ -155,13 +154,9 @@ class SingleRegistryCenterExportMetadataIntegrationTest implements IntegrationTe // 1. Metadata Service exporter with Injvm protocol // 2. SingleRegistryCenterExportMetadataService exporter with Injvm protocol Assertions.assertEquals(exporterListener.getExportedExporters().size(), 2); - List> injvmExporters = exporterListener.getExportedExporters() - .stream() - .filter( - exporter -> PROTOCOL_NAME.equalsIgnoreCase(exporter.getInvoker().getUrl().getProtocol()) - ).collect(Collectors.toList()); + List> injvmExporters = exporterListener.getExportedExporters(); // Make sure there are 2 injvmExporters - Assertions.assertEquals(injvmExporters.size(), 2); + Assertions.assertEquals(2, injvmExporters.size()); } @AfterEach @@ -174,4 +169,4 @@ class SingleRegistryCenterExportMetadataIntegrationTest implements IntegrationTe serviceListener = null; logger.info(getClass().getSimpleName() + " testcase is ending..."); } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/MetadataServiceURLParamsMetadataCustomizerTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/MetadataServiceURLParamsMetadataCustomizerTest.java index f8361128d5..a6c6622aa1 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/MetadataServiceURLParamsMetadataCustomizerTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/MetadataServiceURLParamsMetadataCustomizerTest.java @@ -69,7 +69,7 @@ class MetadataServiceURLParamsMetadataCustomizerTest { } @Test - void test() { + void test() throws InterruptedException { DubboBootstrap providerBootstrap = DubboBootstrap.newInstance(); ServiceConfig serviceConfig = new ServiceConfig<>(); serviceConfig.setInterface(DemoService.class); @@ -90,8 +90,10 @@ class MetadataServiceURLParamsMetadataCustomizerTest { ApplicationModel applicationModel = providerBootstrap.getApplicationModel(); MetadataServiceURLParamsMetadataCustomizer customizer = new MetadataServiceURLParamsMetadataCustomizer(); - customizer.customize(instance, applicationModel); + Thread.sleep(5000);// wait for service delay export + + customizer.customize(instance, applicationModel); String val = instance.getMetadata().get(METADATA_SERVICE_URL_PARAMS_PROPERTY_NAME); Assertions.assertNotNull(val); diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java index bd059ffb2a..0570638276 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java @@ -30,9 +30,8 @@ import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; -import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CLASS_NOT_FOUND; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -109,7 +108,7 @@ class ConfigValidationUtilsTest { config.setQosEnable(true); mock.validateApplicationConfig(config); - verify(loggerMock).warn(eq(COMMON_CLASS_NOT_FOUND), eq(""), eq(""), eq("No QosProtocolWrapper class was found. Please check the dependency of dubbo-qos whether was imported correctly."), any()); + verify(loggerMock).info(anyString()); } private void injectField(Field field, Object newValue) throws Exception { diff --git a/dubbo-config/pom.xml b/dubbo-config/pom.xml index 8fe60edd83..532486994d 100644 --- a/dubbo-config/pom.xml +++ b/dubbo-config/pom.xml @@ -32,7 +32,6 @@ dubbo-config-api dubbo-config-spring - dubbo-config-spring6 @@ -49,4 +48,18 @@ test + + + + spring6 + + [17,) + + + dubbo-config-api + dubbo-config-spring + dubbo-config-spring6 + + + diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java index f2b2bed500..26665790d4 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java @@ -50,6 +50,7 @@ import java.util.stream.Collectors; import static org.apache.dubbo.common.constants.CommonConstants.DOT_SEPARATOR; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_CHAR_SEPARATOR; +import static org.apache.dubbo.common.constants.CommonConstants.IS_EXTRA; import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY; import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; import static org.apache.dubbo.metadata.RevisionResolver.EMPTY_REVISION; @@ -240,7 +241,12 @@ public class MetadataInfo implements Serializable { } Set subServices = subscribedServices.get(serviceKeyWithoutProtocol); if (CollectionUtils.isNotEmpty(subServices)) { - return subServices.iterator().next(); + List validServices = subServices.stream().filter(serviceInfo -> StringUtils.isEmpty(serviceInfo.getParameter(IS_EXTRA))).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(validServices)) { + return validServices.iterator().next(); + } else { + return subServices.iterator().next(); + } } return null; } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java index 95a196466e..fbc8f0e792 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java @@ -127,6 +127,7 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry { return factory.getServiceDiscovery(registryURL); } + @Override protected boolean shouldRegister(URL providerURL) { String side = providerURL.getSide(); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java index d5168aaf7c..6c151a19a5 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java @@ -31,6 +31,7 @@ import org.apache.dubbo.common.utils.Assert; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.ConcurrentHashMapUtils; import org.apache.dubbo.common.utils.NetUtils; +import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.metadata.MetadataInfo; import org.apache.dubbo.registry.AddressListener; import org.apache.dubbo.registry.Constants; @@ -70,6 +71,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.DISABLED_KEY; import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; import static org.apache.dubbo.common.constants.CommonConstants.INSTANCE_REGISTER_MODE; +import static org.apache.dubbo.common.constants.CommonConstants.IS_EXTRA; import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_FAILED_DESTROY_INVOKER; @@ -389,6 +391,14 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory { .getMatchedServiceInfos(consumerProtocolServiceKey) .stream() .filter(serviceInfo -> serviceInfo.getPort() <= 0 || serviceInfo.getPort() == port) + // special filter for extra protocols. + .filter(serviceInfo -> { + if (StringUtils.isNotEmpty(consumerProtocolServiceKey.getProtocol())) {// if consumer side protocol is specified, use all the protocols we got in hand now directly + return true; + } else {// if consumer side protocol is not specified, remove all extra protocols + return StringUtils.isEmpty(serviceInfo.getParameter(IS_EXTRA)); + } + }) .map(MetadataInfo.ServiceInfo::getProtocolServiceKey) .collect(Collectors.toList()); diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java index fbb858aac0..9604fd8350 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java @@ -21,6 +21,7 @@ import org.apache.dubbo.common.constants.RegistryConstants; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.JsonUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.metadata.MetadataInfo; @@ -203,19 +204,21 @@ public class ServiceInstanceMetadataUtils { } public static void registerMetadataAndInstance(ApplicationModel applicationModel) { - LOGGER.info("Start registering instance address to registry."); RegistryManager registryManager = applicationModel.getBeanFactory().getBean(RegistryManager.class); // register service instance - List serviceDiscoveries = registryManager.getServiceDiscoveries(); - for (ServiceDiscovery serviceDiscovery : serviceDiscoveries) { - MetricsEventBus.post(RegistryEvent.toRegisterEvent(applicationModel, - Collections.singletonList(getServiceDiscoveryName(serviceDiscovery))), - () -> { - // register service instance - serviceDiscoveries.forEach(ServiceDiscovery::register); - return null; - } - ); + if (CollectionUtils.isNotEmpty(registryManager.getServiceDiscoveries())) { + LOGGER.info("Start registering instance address to registry."); + List serviceDiscoveries = registryManager.getServiceDiscoveries(); + for (ServiceDiscovery serviceDiscovery : serviceDiscoveries) { + MetricsEventBus.post(RegistryEvent.toRegisterEvent(applicationModel, + Collections.singletonList(getServiceDiscoveryName(serviceDiscovery))), + () -> { + // register service instance + serviceDiscoveries.forEach(ServiceDiscovery::register); + return null; + } + ); + } } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java index cf33c533f1..c9f0fa7d1b 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java @@ -61,10 +61,12 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR; import static org.apache.dubbo.common.constants.CommonConstants.DISABLED_KEY; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL; import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_REGISTER_MODE; +import static org.apache.dubbo.common.constants.CommonConstants.EXT_PROTOCOL; import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_FAILED_INIT_SERIALIZATION_OPTIMIZER; @@ -413,6 +415,11 @@ public class RegistryDirectory extends DynamicDirectory { } URL url = mergeUrl(providerUrl); + // get the effective protocol that this consumer should consume based on consumer side protocol configuration and available protocols in address pool. + String effectiveProtocol = getEffectiveProtocol(queryProtocols, url); + if (!effectiveProtocol.equals(url.getProtocol())) { + url = url.setProtocol(effectiveProtocol); + } // Cache key is url that does not merge with consumer side parameters, // regardless of how the consumer combines parameters, @@ -453,6 +460,36 @@ public class RegistryDirectory extends DynamicDirectory { return newUrlInvokerMap; } + /** + * Get the protocol to consume by matching the consumer acceptable protocols and the available provider protocols. + *

+ * Only one protocol will be used if consumer set to accept multiple protocols, for example, dubbo.consumer.protocol='tri,rest'. + * + * @param queryProtocols consumer side protocols. + * @param url provider url that have extra protocols specified. + * @return the protocol to consume. + */ + private String getEffectiveProtocol(String queryProtocols, URL url) { + String protocol = url.getProtocol(); + if (StringUtils.isNotEmpty(queryProtocols)) { + String[] acceptProtocols = queryProtocols.split(COMMA_SEPARATOR); + String acceptedProtocol = acceptProtocols[0]; + if (!acceptedProtocol.equals(url.getProtocol())) { + String extProtocols = url.getParameter(EXT_PROTOCOL); + if (StringUtils.isNotEmpty(extProtocols)) { + String[] extProtocolsArr = extProtocols.split(COMMA_SEPARATOR); + for (String p : extProtocolsArr) { + if (p.equalsIgnoreCase(acceptedProtocol)) { + protocol = acceptedProtocol; + break; + } + } + } + } + } + return protocol; + } + private boolean checkProtocolValid(String queryProtocols, URL providerUrl) { // If protocol is configured at the reference side, only the matching protocol is selected if (queryProtocols != null && queryProtocols.length() > 0) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/FailbackRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/FailbackRegistry.java index 84613f74fe..c216f58b2c 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/FailbackRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/FailbackRegistry.java @@ -36,8 +36,9 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.TimeUnit; -import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_NOTIFY_EVENT; +import static org.apache.dubbo.common.constants.CommonConstants.IS_EXTRA; import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_NOTIFY_EVENT; import static org.apache.dubbo.registry.Constants.DEFAULT_REGISTRY_RETRY_PERIOD; import static org.apache.dubbo.registry.Constants.REGISTRY_RETRY_PERIOD_KEY; @@ -195,8 +196,7 @@ public abstract class FailbackRegistry extends AbstractRegistry { @Override public void register(URL url) { - if (!acceptable(url)) { - logger.info("URL " + url + " will not be registered to Registry. Registry " + this.getUrl() + " does not accept service of this protocol type."); + if (!shouldRegister(url)) { return; } super.register(url); @@ -227,6 +227,18 @@ public abstract class FailbackRegistry extends AbstractRegistry { } } + protected boolean shouldRegister(URL providerURL) { + // extra protocol url must not be registered for interface based service discovery + if (providerURL.getParameter(IS_EXTRA, false)) { + return false; + } + if (!acceptable(providerURL)) { + logger.info("URL " + providerURL + " will not be registered to Registry. Registry " + this.getUrl() + " does not accept service of this protocol type."); + return false; + } + return true; + } + @Override public void reExportRegister(URL url) { if (!acceptable(url)) { diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/pu/AbstractPortUnificationServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/pu/AbstractPortUnificationServer.java index 9a6ac624c6..c2b564b324 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/pu/AbstractPortUnificationServer.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/pu/AbstractPortUnificationServer.java @@ -17,15 +17,22 @@ package org.apache.dubbo.remoting.api.pu; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.remoting.ChannelHandler; import org.apache.dubbo.remoting.RemotingException; import org.apache.dubbo.remoting.api.WireProtocol; import org.apache.dubbo.remoting.transport.AbstractServer; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR; +import static org.apache.dubbo.common.constants.CommonConstants.EXT_PROTOCOL; + public abstract class AbstractPortUnificationServer extends AbstractServer { private final List protocols; @@ -44,7 +51,18 @@ public abstract class AbstractPortUnificationServer extends AbstractServer { public AbstractPortUnificationServer(URL url, ChannelHandler handler) throws RemotingException { super(url, handler); - this.protocols = url.getOrDefaultFrameworkModel().getExtensionLoader(WireProtocol.class).getActivateExtension(url, new String[0]); + ExtensionLoader loader = url.getOrDefaultFrameworkModel().getExtensionLoader(WireProtocol.class); + List extProtocols = new ArrayList<>(); + // load main protocol + extProtocols.add(loader.getExtension(url.getProtocol())); + // load extra protocols + String extraProtocols = url.getParameter(EXT_PROTOCOL); + if (StringUtils.isNotEmpty(extraProtocols)) { + Arrays.stream(extraProtocols.split(COMMA_SEPARATOR)).forEach(p -> { + extProtocols.add(loader.getExtension(p)); + }); + } + this.protocols = extProtocols; } public List getProtocols() { diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java index 0f5268da89..da9264a346 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java @@ -18,25 +18,43 @@ package org.apache.dubbo.remoting.transport.netty4; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.extension.ExtensionDirector; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.threadpool.manager.DefaultExecutorRepository; +import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.config.context.ModuleConfigManager; +import org.apache.dubbo.remoting.Channel; import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.remoting.api.ProtocolDetector; +import org.apache.dubbo.remoting.api.WireProtocol; +import org.apache.dubbo.remoting.api.pu.AbstractPortUnificationServer; +import org.apache.dubbo.remoting.api.pu.ChannelOperator; import org.apache.dubbo.remoting.api.pu.DefaultPuHandler; +import org.apache.dubbo.remoting.api.ssl.ContextOperator; import org.apache.dubbo.rpc.model.ApplicationModel; import org.apache.dubbo.rpc.model.ModuleModel; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; + +import java.net.InetSocketAddress; +import java.util.Collection; +import java.util.concurrent.Executors; import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_MANAGEMENT_MODE_DEFAULT; +import static org.apache.dubbo.common.constants.CommonConstants.EXT_PROTOCOL; class PortUnificationServerTest { @Test void testBind() throws RemotingException { int port = NetUtils.getAvailablePort(); - URL url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar"); + URL url = URL.valueOf("empty://127.0.0.1:" + port + "?foo=bar&" + EXT_PROTOCOL + "=tri"); ApplicationModel applicationModel = ApplicationModel.defaultModel(); ApplicationConfig applicationConfig = new ApplicationConfig("provider-app"); applicationConfig.setExecutorManagementMode(EXECUTOR_MANAGEMENT_MODE_DEFAULT); @@ -52,6 +70,7 @@ class PortUnificationServerTest { final NettyPortUnificationServer server = new NettyPortUnificationServer(url, new DefaultPuHandler()); server.bind(); Assertions.assertTrue(server.isBound()); + Assertions.assertEquals(2, server.getProtocols().size()); server.close(); } } diff --git a/dubbo-test/dubbo-dependencies-all/pom.xml b/dubbo-test/dubbo-dependencies-all/pom.xml index 0216003790..2a5f1a3e1d 100644 --- a/dubbo-test/dubbo-dependencies-all/pom.xml +++ b/dubbo-test/dubbo-dependencies-all/pom.xml @@ -72,11 +72,11 @@ dubbo-config-spring ${project.version} - - org.apache.dubbo - dubbo-config-spring6 - ${project.version} - + + + + + diff --git a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java index aa0a264b36..66c13236b6 100644 --- a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java +++ b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java @@ -51,6 +51,8 @@ class FileTest { ignoredModules.add(Pattern.compile("dubbo-parent")); ignoredModules.add(Pattern.compile("dubbo-core-spi")); ignoredModules.add(Pattern.compile("dubbo-demo.*")); + ignoredModules.add(Pattern.compile("dubbo-annotation-processor")); + ignoredModules.add(Pattern.compile("dubbo-config-spring6")); ignoredArtifacts.add(Pattern.compile("dubbo-demo.*")); ignoredArtifacts.add(Pattern.compile("dubbo-test.*")); From 059b75c53389bc0d4a0af2b611fa861baee31921 Mon Sep 17 00:00:00 2001 From: icodening Date: Fri, 1 Sep 2023 09:43:04 +0800 Subject: [PATCH 06/14] [feat.] new triple protocol implement (#12873) --- .artifacts | 1 + dubbo-distribution/dubbo-all/pom.xml | 12 + dubbo-distribution/dubbo-bom/pom.xml | 5 + .../reactive/calls/ReactorServerCalls.java | 3 +- .../AbstractServerHttpChannelObserver.java | 4 + .../h1/Http1ServerTransportListener.java | 3 +- .../http12/h2/Http2TransportListener.java | 4 +- .../http12/message/HttpMessageCodec.java | 4 +- .../message/HttpMessageCodecFactory.java | 39 ++ .../http12/message/JsonCodecFactory.java | 35 ++ .../message/LengthFieldStreamingDecoder.java | 45 +- .../http12/message/StreamingDecoder.java | 49 +- .../h1/NettyHttp1ConnectionHandler.java | 16 +- ...ing.http12.message.HttpMessageCodecFactory | 1 + dubbo-rpc/dubbo-rpc-triple/pom.xml | 5 + .../tri/ReflectionPackableMethod.java | 7 +- .../rpc/protocol/tri/TripleHttp2Protocol.java | 113 +++-- .../rpc/protocol/tri/compressor/Bzip2.java | 14 +- .../protocol/tri/compressor/Compressor.java | 4 + .../rpc/protocol/tri/compressor/Gzip.java | 11 + .../rpc/protocol/tri/compressor/Identity.java | 7 + .../rpc/protocol/tri/compressor/Snappy.java | 7 +- .../tri/h12}/AbstractServerCallListener.java | 27 +- .../h12/AbstractServerTransportListener.java | 479 ++++++++++++++++++ .../protocol/tri/h12/AttachmentHolder.java | 26 + .../tri/h12}/BiStreamServerCallListener.java | 3 +- .../protocol/tri/h12/CompressibleCodec.java | 71 +++ .../tri/h12/DefaultHttpMessageListener.java | 43 ++ .../protocol/tri/h12/HttpMessageListener.java | 24 + .../protocol/tri/h12}/ServerCallListener.java | 2 +- .../tri/h12/ServerCallToObserverAdapter.java | 25 + .../h12}/ServerStreamServerCallListener.java | 2 +- .../tri/h12/TripleProtocolDetector.java | 87 ++++ .../tri/h12}/UnaryServerCallListener.java | 28 +- .../tri/h12/grpc/GrpcCompositeCodec.java | 124 +++++ .../h12/grpc/GrpcCompositeCodecFactory.java | 50 ++ .../tri/h12/grpc/GrpcHeaderNames.java | 36 ++ .../GrpcHttp2ServerTransportListener.java | 216 ++++++++ ...pcHttp2ServerTransportListenerFactory.java | 38 ++ .../tri/h12/grpc/GrpcStreamingDecoder.java | 61 +++ .../rpc/protocol/tri/h12/grpc/GrpcUtils.java | 54 ++ .../h12/grpc/ProtobufHttpMessageCodec.java | 57 +++ .../grpc/StreamingHttpMessageListener.java | 36 +- .../tri/h12/grpc/WrapperHttpMessageCodec.java | 143 ++++++ .../DefaultHttp11ServerTransportListener.java | 122 +++++ ...tHttp11ServerTransportListenerFactory.java | 33 ++ .../GenericHttp2ServerTransportListener.java | 223 ++++++++ ...icHttp2ServerTransportListenerFactory.java | 40 ++ .../Http2ServerCallToObserverAdapter.java | 40 ++ .../h12/http2/Http2ServerStreamObserver.java | 77 +++ .../rpc/protocol/tri/stream/StreamUtils.java | 53 +- .../TripleIsolationExecutorSupport.java | 18 +- .../TripleServerConnectionHandler.java | 13 +- ...p12.h2.Http2ServerTransportListenerFactory | 1 + ...o.remoting.http12.message.HttpMessageCodec | 2 + ...ing.http12.message.HttpMessageCodecFactory | 1 + dubbo-test/dubbo-dependencies-all/pom.xml | 5 + 57 files changed, 2511 insertions(+), 138 deletions(-) create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodecFactory.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodecFactory.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory rename {dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12 => dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12}/AbstractServerCallListener.java (70%) create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AttachmentHolder.java rename {dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12 => dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12}/BiStreamServerCallListener.java (95%) create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/CompressibleCodec.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/DefaultHttpMessageListener.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/HttpMessageListener.java rename {dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12 => dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12}/ServerCallListener.java (96%) create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerCallToObserverAdapter.java rename {dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12 => dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12}/ServerStreamServerCallListener.java (97%) create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/TripleProtocolDetector.java rename {dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12 => dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12}/UnaryServerCallListener.java (64%) create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodecFactory.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHeaderNames.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListener.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListenerFactory.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcStreamingDecoder.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcUtils.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/ProtobufHttpMessageCodec.java rename dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/DefaultHttp2StreamingDecoder.java => dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/StreamingHttpMessageListener.java (50%) create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/WrapperHttpMessageCodec.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListener.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListenerFactory.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListener.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListenerFactory.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerCallToObserverAdapter.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerStreamObserver.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory diff --git a/.artifacts b/.artifacts index be912a56f7..7b113ce8ab 100644 --- a/.artifacts +++ b/.artifacts @@ -85,6 +85,7 @@ dubbo-registry-zookeeper dubbo-remoting dubbo-remoting-api dubbo-remoting-http +dubbo-remoting-http12 dubbo-remoting-netty dubbo-remoting-netty4 dubbo-remoting-zookeeper-api diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index d0ff531c7e..be8bdbf11b 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -1261,12 +1261,24 @@ META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec + + + META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory + + META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory + + + META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.h1.Http1ServerTransportListenerFactory + + diff --git a/dubbo-distribution/dubbo-bom/pom.xml b/dubbo-distribution/dubbo-bom/pom.xml index 9757c56352..0978c711e1 100644 --- a/dubbo-distribution/dubbo-bom/pom.xml +++ b/dubbo-distribution/dubbo-bom/pom.xml @@ -501,6 +501,11 @@ dubbo-remoting-http ${project.version} + + org.apache.dubbo + dubbo-remoting-http12 + ${project.version} + org.apache.dubbo dubbo-remoting-netty diff --git a/dubbo-plugin/dubbo-reactive/src/main/java/org/apache/dubbo/reactive/calls/ReactorServerCalls.java b/dubbo-plugin/dubbo-reactive/src/main/java/org/apache/dubbo/reactive/calls/ReactorServerCalls.java index 33c54d1496..e9ce9bd41d 100644 --- a/dubbo-plugin/dubbo-reactive/src/main/java/org/apache/dubbo/reactive/calls/ReactorServerCalls.java +++ b/dubbo-plugin/dubbo-reactive/src/main/java/org/apache/dubbo/reactive/calls/ReactorServerCalls.java @@ -21,7 +21,6 @@ import org.apache.dubbo.common.stream.StreamObserver; import org.apache.dubbo.reactive.ServerTripleReactorPublisher; import org.apache.dubbo.reactive.ServerTripleReactorSubscriber; import org.apache.dubbo.rpc.protocol.tri.observer.CallStreamObserver; -import org.apache.dubbo.rpc.protocol.tri.observer.ServerCallToObserverAdapter; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -72,7 +71,7 @@ public final class ReactorServerCalls { try { Flux response = func.apply(Mono.just(request)); ServerTripleReactorSubscriber subscriber = response.subscribeWith(new ServerTripleReactorSubscriber<>()); - subscriber.subscribe((ServerCallToObserverAdapter) responseObserver); + subscriber.subscribe((CallStreamObserver) responseObserver); } catch (Throwable throwable) { responseObserver.onError(throwable); } diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java index 5af04e629f..3e0b2a9b75 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java @@ -41,6 +41,10 @@ public abstract class AbstractServerHttpChannelObserver implements CustomizableH this.httpMessageCodec = httpMessageCodec; } + protected HttpMessageCodec getHttpMessageCodec() { + return httpMessageCodec; + } + @Override public void setHeadersCustomizer(HeadersCustomizer headersCustomizer) { this.headersCustomizer = headersCustomizer; diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListener.java index eb816afb02..9e41598f42 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListener.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListener.java @@ -16,11 +16,10 @@ */ package org.apache.dubbo.remoting.http12.h1; -import org.apache.dubbo.remoting.http12.HttpChannelHolder; import org.apache.dubbo.remoting.http12.HttpInputMessage; import org.apache.dubbo.remoting.http12.HttpTransportListener; import org.apache.dubbo.remoting.http12.RequestMetadata; -public interface Http1ServerTransportListener extends HttpTransportListener, HttpChannelHolder { +public interface Http1ServerTransportListener extends HttpTransportListener { } diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2TransportListener.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2TransportListener.java index 00bfbc6554..19faa32e4d 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2TransportListener.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2TransportListener.java @@ -16,8 +16,6 @@ */ package org.apache.dubbo.remoting.http12.h2; -import org.apache.dubbo.remoting.http12.HttpChannelHolder; - -public interface Http2TransportListener extends CancelableTransportListener, HttpChannelHolder { +public interface Http2TransportListener extends CancelableTransportListener { } diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodec.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodec.java index 5437d9af47..65c3ad65e9 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodec.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodec.java @@ -34,14 +34,14 @@ public interface HttpMessageCodec { default void encode(OutputStream outputStream, Object[] data) throws EncodeException { //default encode first data - this.encode(outputStream, data[0]); + this.encode(outputStream, data == null || data.length == 0 ? null : data[0]); } Object decode(InputStream inputStream, Class targetType) throws DecodeException; default Object[] decode(InputStream inputStream, Class[] targetTypes) throws DecodeException { //default decode first target type - return new Object[]{this.decode(inputStream, targetTypes[0])}; + return new Object[]{this.decode(inputStream, targetTypes == null || targetTypes.length == 0 ? null : targetTypes[0])}; } MediaType contentType(); diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodecFactory.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodecFactory.java new file mode 100644 index 0000000000..80978b6a98 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodecFactory.java @@ -0,0 +1,39 @@ +/* + * 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.remoting.http12.message; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.rpc.model.FrameworkModel; + +/** + * for http body codec + */ +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface HttpMessageCodecFactory { + + HttpMessageCodec createCodec(URL url, FrameworkModel frameworkModel); + + MediaType contentType(); + + default boolean support(String contentType) { + MediaType mediaType = this.contentType(); + return mediaType.getName().startsWith(contentType); + } + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodecFactory.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodecFactory.java new file mode 100644 index 0000000000..8f7d2f356c --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodecFactory.java @@ -0,0 +1,35 @@ +/* + * 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.remoting.http12.message; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.rpc.model.FrameworkModel; + +@Activate +public class JsonCodecFactory implements HttpMessageCodecFactory { + + @Override + public HttpMessageCodec createCodec(URL url, FrameworkModel frameworkModel) { + return new JsonCodec(); + } + + @Override + public MediaType contentType() { + return MediaType.APPLICATION_JSON_VALUE; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java index dc2d57d948..67da0dea90 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java @@ -20,6 +20,7 @@ import org.apache.dubbo.remoting.http12.CompositeInputStream; import org.apache.dubbo.remoting.http12.exception.DecodeException; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -37,11 +38,7 @@ public class LengthFieldStreamingDecoder implements StreamingDecoder { private final CompositeInputStream accumulate = new CompositeInputStream(); - private final Class[] targetTypes; - - private HttpMessageCodec httpMessageCodec; - - private Listener listener; + private FragmentListener listener; private final int lengthFieldOffset; @@ -49,25 +46,22 @@ public class LengthFieldStreamingDecoder implements StreamingDecoder { private int requiredLength; - public LengthFieldStreamingDecoder(Class[] targetTypes) { - this(4, targetTypes); + private InputStream dataHeader = new ByteArrayInputStream(new byte[0]); + + public LengthFieldStreamingDecoder() { + this(4); } - public LengthFieldStreamingDecoder(int lengthFieldLength, Class[] targetTypes) { - this(0, lengthFieldLength, targetTypes); + public LengthFieldStreamingDecoder(int lengthFieldLength) { + this(0, lengthFieldLength); } - public LengthFieldStreamingDecoder(int lengthFieldOffset, int lengthFieldLength, Class[] targetTypes) { + public LengthFieldStreamingDecoder(int lengthFieldOffset, int lengthFieldLength) { this.lengthFieldOffset = lengthFieldOffset; this.lengthFieldLength = lengthFieldLength; - this.targetTypes = targetTypes; this.requiredLength = lengthFieldOffset + lengthFieldLength; } - public void setHttpMessageCodec(HttpMessageCodec httpMessageCodec) { - this.httpMessageCodec = httpMessageCodec; - } - @Override public final void decode(InputStream inputStream) throws DecodeException { if (closing || closed) { @@ -91,7 +85,7 @@ public class LengthFieldStreamingDecoder implements StreamingDecoder { } @Override - public final void setListener(Listener listener) { + public final void setFragmentListener(FragmentListener listener) { this.listener = listener; } @@ -136,10 +130,16 @@ public class LengthFieldStreamingDecoder implements StreamingDecoder { } private void processHeader() throws IOException { - processOffset(accumulate, lengthFieldOffset); + ByteArrayOutputStream bos = new ByteArrayOutputStream(lengthFieldOffset + lengthFieldLength); + byte[] offsetData = new byte[lengthFieldOffset]; + int ignore = accumulate.read(offsetData); + bos.write(offsetData); + processOffset(new ByteArrayInputStream(offsetData), lengthFieldOffset); byte[] lengthBytes = new byte[lengthFieldLength]; - accumulate.read(lengthBytes); + ignore = accumulate.read(lengthBytes); + bos.write(lengthBytes); requiredLength = bytesToInt(lengthBytes); + this.dataHeader = new ByteArrayInputStream(bos.toByteArray()); // Continue reading the frame body. state = DecodeState.PAYLOAD; @@ -154,20 +154,23 @@ public class LengthFieldStreamingDecoder implements StreamingDecoder { if (lengthFieldOffset != 0) { return; } - inputStream.read(new byte[lengthFieldOffset]); + int ignore = inputStream.read(new byte[lengthFieldOffset]); } private void processBody() throws IOException { byte[] rawMessage = readRawMessage(accumulate, requiredLength); InputStream inputStream = new ByteArrayInputStream(rawMessage); - Object[] decodeParameters = httpMessageCodec.decode(inputStream, targetTypes); - this.listener.onMessage(decodeParameters); + invokeListener(inputStream); // Done with this frame, begin processing the next header. state = DecodeState.HEADER; requiredLength = lengthFieldOffset + lengthFieldLength; } + protected void invokeListener(InputStream inputStream) { + this.listener.onFragmentMessage(dataHeader, inputStream); + } + protected byte[] readRawMessage(InputStream inputStream, int length) throws IOException { byte[] data = new byte[length]; inputStream.read(data, 0, length); diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/StreamingDecoder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/StreamingDecoder.java index 212b68a6ac..f1b1b2e046 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/StreamingDecoder.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/StreamingDecoder.java @@ -16,8 +16,55 @@ */ package org.apache.dubbo.remoting.http12.message; -public interface StreamingDecoder extends ListeningDecoder { +import org.apache.dubbo.remoting.http12.exception.DecodeException; + +import java.io.InputStream; + +public interface StreamingDecoder { void request(int numMessages); + void decode(InputStream inputStream) throws DecodeException; + + void close(); + + void setFragmentListener(FragmentListener listener); + + interface FragmentListener { + + /** + * @param rawMessage raw message + */ + void onFragmentMessage(InputStream rawMessage); + + /** + * @param rawMessage raw message + */ + default void onFragmentMessage(InputStream dataHeader, InputStream rawMessage){ + onFragmentMessage(rawMessage); + } + + default void onClose() { + + } + } + + class DefaultFragmentListener implements FragmentListener { + + private final ListeningDecoder listeningDecoder; + + public DefaultFragmentListener(ListeningDecoder listeningDecoder) { + this.listeningDecoder = listeningDecoder; + } + + @Override + public void onFragmentMessage(InputStream rawMessage) { + listeningDecoder.decode(rawMessage); + } + + @Override + public void onClose() { + this.listeningDecoder.close(); + } + } } diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1ConnectionHandler.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1ConnectionHandler.java index 84ddeda1bb..9385a30564 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1ConnectionHandler.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/netty4/h1/NettyHttp1ConnectionHandler.java @@ -29,7 +29,7 @@ import org.apache.dubbo.remoting.http12.h1.Http1Request; import org.apache.dubbo.remoting.http12.h1.Http1ServerChannelObserver; import org.apache.dubbo.remoting.http12.h1.Http1ServerTransportListener; import org.apache.dubbo.remoting.http12.h1.Http1ServerTransportListenerFactory; -import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory; import org.apache.dubbo.rpc.model.FrameworkModel; import java.util.List; @@ -90,19 +90,19 @@ public class NettyHttp1ConnectionHandler extends SimpleChannelInboundHandler candidates) { - for (HttpMessageCodec codec : candidates) { - if (codec.support(contentType)) { - return codec; + private static HttpMessageCodecFactory findSuitableCodec(String contentType, List candidates) { + for (HttpMessageCodecFactory factory : candidates) { + if (factory.support(contentType)) { + return factory; } } return null; diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory b/dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory new file mode 100644 index 0000000000..f72f51f4b6 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory @@ -0,0 +1 @@ +json=org.apache.dubbo.remoting.http12.message.JsonCodecFactory diff --git a/dubbo-rpc/dubbo-rpc-triple/pom.xml b/dubbo-rpc/dubbo-rpc-triple/pom.xml index 1c28453239..a09ac23906 100644 --- a/dubbo-rpc/dubbo-rpc-triple/pom.xml +++ b/dubbo-rpc/dubbo-rpc-triple/pom.xml @@ -37,6 +37,11 @@ dubbo-rpc-api ${project.parent.version} + + org.apache.dubbo + dubbo-remoting-http12 + ${project.parent.version} + org.apache.dubbo dubbo-remoting-netty4 diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ReflectionPackableMethod.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ReflectionPackableMethod.java index da3e67dfa4..161c19f1a3 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ReflectionPackableMethod.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/ReflectionPackableMethod.java @@ -17,18 +17,17 @@ package org.apache.dubbo.rpc.protocol.tri; +import com.google.protobuf.Message; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.serialize.MultipleSerialization; import org.apache.dubbo.common.stream.StreamObserver; import org.apache.dubbo.config.Constants; -import org.apache.dubbo.remoting.utils.UrlUtils; import org.apache.dubbo.remoting.transport.CodecSupport; +import org.apache.dubbo.remoting.utils.UrlUtils; import org.apache.dubbo.rpc.model.MethodDescriptor; import org.apache.dubbo.rpc.model.Pack; import org.apache.dubbo.rpc.model.PackableMethod; - -import com.google.protobuf.Message; import org.apache.dubbo.rpc.model.UnPack; import org.apache.dubbo.rpc.model.WrapperUnPack; @@ -140,7 +139,7 @@ public class ReflectionPackableMethod implements PackableMethod { * * @return true if the request and response object is not generated by protobuf */ - static boolean needWrap(MethodDescriptor methodDescriptor, Class[] parameterClasses, + public static boolean needWrap(MethodDescriptor methodDescriptor, Class[] parameterClasses, Class returnClass) { String methodName = methodDescriptor.getMethodName(); // generic call must be wrapped diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java index 8daa1f600f..3937921e5e 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java @@ -19,7 +19,10 @@ package org.apache.dubbo.rpc.protocol.tri; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; +import io.netty.handler.codec.http.HttpObjectAggregator; +import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http2.Http2FrameCodec; +import io.netty.handler.codec.http2.Http2FrameCodecBuilder; import io.netty.handler.codec.http2.Http2FrameLogger; import io.netty.handler.codec.http2.Http2MultiplexHandler; import io.netty.handler.codec.http2.Http2Settings; @@ -31,22 +34,25 @@ import org.apache.dubbo.common.config.Configuration; import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; import org.apache.dubbo.remoting.ChannelHandler; import org.apache.dubbo.remoting.api.AbstractWireProtocol; import org.apache.dubbo.remoting.api.pu.ChannelHandlerPretender; import org.apache.dubbo.remoting.api.pu.ChannelOperator; import org.apache.dubbo.remoting.api.ssl.ContextOperator; +import org.apache.dubbo.remoting.http12.netty4.HttpWriteQueueHandler; +import org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1Codec; +import org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1ConnectionHandler; +import org.apache.dubbo.remoting.http12.netty4.h2.NettyHttp2FrameCodec; +import org.apache.dubbo.remoting.http12.netty4.h2.NettyHttp2ProtocolSelectorHandler; import org.apache.dubbo.rpc.HeaderFilter; -import org.apache.dubbo.rpc.executor.ExecutorSupport; import org.apache.dubbo.rpc.model.FrameworkModel; import org.apache.dubbo.rpc.model.ScopeModelAware; +import org.apache.dubbo.rpc.protocol.tri.h12.TripleProtocolDetector; +import org.apache.dubbo.rpc.protocol.tri.h12.http1.DefaultHttp11ServerTransportListenerFactory; +import org.apache.dubbo.rpc.protocol.tri.h12.http2.GenericHttp2ServerTransportListenerFactory; import org.apache.dubbo.rpc.protocol.tri.transport.TripleClientHandler; -import org.apache.dubbo.rpc.protocol.tri.transport.TripleCommandOutBoundHandler; -import org.apache.dubbo.rpc.protocol.tri.transport.TripleHttp2FrameServerHandler; import org.apache.dubbo.rpc.protocol.tri.transport.TripleServerConnectionHandler; import org.apache.dubbo.rpc.protocol.tri.transport.TripleTailHandler; -import org.apache.dubbo.rpc.protocol.tri.transport.TripleWriteQueue; import java.util.ArrayList; import java.util.Collections; @@ -80,7 +86,7 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo private FrameworkModel frameworkModel; public TripleHttp2Protocol() { - super(new Http2ProtocolDetector()); + super(new TripleProtocolDetector()); } @Override @@ -94,8 +100,61 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo super.close(); } + @Override + public void configClientPipeline(URL url, ChannelOperator operator, ContextOperator contextOperator) { + Configuration config = ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultApplicationModel()); + final Http2FrameCodec codec = Http2FrameCodecBuilder.forClient() + .gracefulShutdownTimeoutMillis(10000) + .initialSettings(new Http2Settings().headerTableSize( + config.getInt(H2_SETTINGS_HEADER_TABLE_SIZE_KEY, DEFAULT_SETTING_HEADER_LIST_SIZE)) + .pushEnabled(config.getBoolean(H2_SETTINGS_ENABLE_PUSH_KEY, false)) + .maxConcurrentStreams( + config.getInt(H2_SETTINGS_MAX_CONCURRENT_STREAMS_KEY, Integer.MAX_VALUE)) + .initialWindowSize( + config.getInt(H2_SETTINGS_INITIAL_WINDOW_SIZE_KEY, DEFAULT_WINDOW_INIT_SIZE)) + .maxFrameSize(config.getInt(H2_SETTINGS_MAX_FRAME_SIZE_KEY, DEFAULT_MAX_FRAME_SIZE)) + .maxHeaderListSize(config.getInt(H2_SETTINGS_MAX_HEADER_LIST_SIZE_KEY, + DEFAULT_MAX_HEADER_LIST_SIZE))) + .frameLogger(CLIENT_LOGGER) + .build(); +// codec.connection().local().flowController().frameWriter(codec.encoder().frameWriter()); + final Http2MultiplexHandler handler = new Http2MultiplexHandler( + new TripleClientHandler(frameworkModel)); + List handlers = new ArrayList<>(); + handlers.add(new ChannelHandlerPretender(codec)); + handlers.add(new ChannelHandlerPretender(handler)); + handlers.add(new ChannelHandlerPretender(new TripleTailHandler())); + operator.configChannelHandler(handlers); + } + @Override public void configServerProtocolHandler(URL url, ChannelOperator operator) { + String httpVersion = operator.detectResult().getAttribute(TripleProtocolDetector.HTTP_VERSION); + List channelHandlerPretenders = new ArrayList<>(); + try { + //h1 + if (TripleProtocolDetector.HttpVersion.HTTP1.getVersion().equals(httpVersion)) { + configurerHttp1Handlers(url, channelHandlerPretenders); + return; + } + + //h2 + if (TripleProtocolDetector.HttpVersion.HTTP2.getVersion().equals(httpVersion)) { + configurerHttp2Handlers(url, channelHandlerPretenders); + } + } finally { + operator.configChannelHandler(channelHandlerPretenders); + } + } + + private void configurerHttp1Handlers(URL url, List handlers) { + handlers.add(new ChannelHandlerPretender(new HttpServerCodec())); + handlers.add(new ChannelHandlerPretender(new HttpObjectAggregator(Integer.MAX_VALUE))); + handlers.add(new ChannelHandlerPretender(new NettyHttp1Codec())); + handlers.add(new ChannelHandlerPretender(new NettyHttp1ConnectionHandler(url, frameworkModel, DefaultHttp11ServerTransportListenerFactory.INSTANCE))); + } + + private void configurerHttp2Handlers(URL url, List handlers) { Configuration config = ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultApplicationModel()); final List headFilters; if (filtersLoader != null) { @@ -117,55 +176,19 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo DEFAULT_MAX_HEADER_LIST_SIZE))) .frameLogger(SERVER_LOGGER) .build(); - ExecutorSupport executorSupport = ExecutorRepository.getInstance(url.getOrDefaultApplicationModel()).getExecutorSupport(url); - codec.connection().local().flowController().frameWriter(codec.encoder().frameWriter()); - TripleWriteQueue writeQueue = new TripleWriteQueue(); final Http2MultiplexHandler handler = new Http2MultiplexHandler( new ChannelInitializer() { @Override protected void initChannel(Http2StreamChannel ch) { final ChannelPipeline p = ch.pipeline(); - p.addLast(new TripleCommandOutBoundHandler()); - p.addLast(new TripleHttp2FrameServerHandler(frameworkModel, executorSupport, - headFilters, ch, writeQueue)); + p.addLast(new NettyHttp2FrameCodec()); + p.addLast(new NettyHttp2ProtocolSelectorHandler(url, frameworkModel, GenericHttp2ServerTransportListenerFactory.INSTANCE)); } }); - List handlers = new ArrayList<>(); + handlers.add(new ChannelHandlerPretender(new HttpWriteQueueHandler())); handlers.add(new ChannelHandlerPretender(codec)); handlers.add(new ChannelHandlerPretender(new FlushConsolidationHandler(64, true))); handlers.add(new ChannelHandlerPretender(new TripleServerConnectionHandler())); handlers.add(new ChannelHandlerPretender(handler)); - handlers.add(new ChannelHandlerPretender(new TripleTailHandler())); - operator.configChannelHandler(handlers); - - - } - - @Override - public void configClientPipeline(URL url, ChannelOperator operator, ContextOperator contextOperator) { - Configuration config = ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultApplicationModel()); - final Http2FrameCodec codec = TripleHttp2FrameCodecBuilder.forClient() - .customizeConnection((connection) -> connection.remote().flowController(new TriHttp2RemoteFlowController(connection, url.getOrDefaultApplicationModel()))) - .gracefulShutdownTimeoutMillis(10000) - .initialSettings(new Http2Settings().headerTableSize( - config.getInt(H2_SETTINGS_HEADER_TABLE_SIZE_KEY, DEFAULT_SETTING_HEADER_LIST_SIZE)) - .pushEnabled(config.getBoolean(H2_SETTINGS_ENABLE_PUSH_KEY, false)) - .maxConcurrentStreams( - config.getInt(H2_SETTINGS_MAX_CONCURRENT_STREAMS_KEY, Integer.MAX_VALUE)) - .initialWindowSize( - config.getInt(H2_SETTINGS_INITIAL_WINDOW_SIZE_KEY, DEFAULT_WINDOW_INIT_SIZE)) - .maxFrameSize(config.getInt(H2_SETTINGS_MAX_FRAME_SIZE_KEY, DEFAULT_MAX_FRAME_SIZE)) - .maxHeaderListSize(config.getInt(H2_SETTINGS_MAX_HEADER_LIST_SIZE_KEY, - DEFAULT_MAX_HEADER_LIST_SIZE))) - .frameLogger(CLIENT_LOGGER) - .build(); - codec.connection().local().flowController().frameWriter(codec.encoder().frameWriter()); - final Http2MultiplexHandler handler = new Http2MultiplexHandler( - new TripleClientHandler(frameworkModel)); - List handlers = new ArrayList<>(); - handlers.add(new ChannelHandlerPretender(codec)); - handlers.add(new ChannelHandlerPretender(handler)); - handlers.add(new ChannelHandlerPretender(new TripleTailHandler())); - operator.configChannelHandler(handlers); } } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Bzip2.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Bzip2.java index dbc54be92c..5a53cb3f71 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Bzip2.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Bzip2.java @@ -17,13 +17,14 @@ package org.apache.dubbo.rpc.protocol.tri.compressor; -import org.apache.dubbo.rpc.RpcException; - import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream; import org.apache.commons.io.output.ByteArrayOutputStream; +import org.apache.dubbo.rpc.RpcException; import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.OutputStream; /** @@ -59,6 +60,15 @@ public class Bzip2 implements Compressor, DeCompressor { return out.toByteArray(); } + @Override + public OutputStream decorate(OutputStream outputStream) { + try { + return new BZip2CompressorOutputStream(outputStream); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + @Override public byte[] decompress(byte[] payloadByteArr) { if (null == payloadByteArr || 0 == payloadByteArr.length) { diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Compressor.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Compressor.java index 35d7ab80fb..73a33f3fd9 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Compressor.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Compressor.java @@ -22,6 +22,8 @@ import org.apache.dubbo.common.extension.SPI; import org.apache.dubbo.rpc.Constants; import org.apache.dubbo.rpc.model.FrameworkModel; +import java.io.OutputStream; + /** * compress payload for grpc request, and decompress response payload Configure it in files, * pictures or other configurations that exist in the system properties Configure {@link @@ -51,4 +53,6 @@ public interface Compressor extends MessageEncoding { */ byte[] compress(byte[] payloadByteArr); + OutputStream decorate(OutputStream outputStream); + } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Gzip.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Gzip.java index 371b650bae..168bc627aa 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Gzip.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Gzip.java @@ -21,6 +21,8 @@ import org.apache.dubbo.rpc.RpcException; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -52,6 +54,15 @@ public class Gzip implements Compressor, DeCompressor { return byteOutStream.toByteArray(); } + @Override + public OutputStream decorate(OutputStream outputStream) { + try { + return new GZIPOutputStream(outputStream); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + @Override public byte[] decompress(byte[] payloadByteArr) throws RpcException { if (null == payloadByteArr || 0 == payloadByteArr.length) { diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Identity.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Identity.java index 3d3d32d788..ee6d16a671 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Identity.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Identity.java @@ -17,6 +17,8 @@ package org.apache.dubbo.rpc.protocol.tri.compressor; +import java.io.OutputStream; + /** * Default compressor *

@@ -38,6 +40,11 @@ public class Identity implements Compressor, DeCompressor { return payloadByteArr; } + @Override + public OutputStream decorate(OutputStream outputStream) { + return outputStream; + } + @Override public byte[] decompress(byte[] payloadByteArr) { return payloadByteArr; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Snappy.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Snappy.java index be5b11fe81..2d1e9b08c2 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Snappy.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/compressor/Snappy.java @@ -20,6 +20,7 @@ package org.apache.dubbo.rpc.protocol.tri.compressor; import org.apache.dubbo.rpc.RpcException; import java.io.IOException; +import java.io.OutputStream; /** * snappy compressor, Provide high-speed compression speed and reasonable compression ratio @@ -40,7 +41,6 @@ public class Snappy implements Compressor, DeCompressor { if (null == payloadByteArr || 0 == payloadByteArr.length) { return new byte[0]; } - try { return org.xerial.snappy.Snappy.compress(payloadByteArr); } catch (IOException e) { @@ -48,6 +48,11 @@ public class Snappy implements Compressor, DeCompressor { } } + @Override + public OutputStream decorate(OutputStream outputStream) { + return outputStream; + } + @Override public byte[] decompress(byte[] payloadByteArr) { if (null == payloadByteArr || 0 == payloadByteArr.length) { diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerCallListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerCallListener.java similarity index 70% rename from dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerCallListener.java rename to dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerCallListener.java index dfa8ac877e..2ae592501c 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerCallListener.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerCallListener.java @@ -14,17 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.remoting.http12; +package org.apache.dubbo.rpc.protocol.tri.h12; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.stream.StreamObserver; import org.apache.dubbo.remoting.http12.exception.HttpRequestTimeout; +import org.apache.dubbo.remoting.http12.h2.Http2CancelableStreamObserver; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum; +import org.apache.dubbo.rpc.protocol.tri.call.AbstractServerCall; +import java.net.InetSocketAddress; + +import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY; import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_TIMEOUT_SERVER; public abstract class AbstractServerCallListener implements ServerCallListener { @@ -46,16 +52,31 @@ public abstract class AbstractServerCallListener implements ServerCallListener { } public void invoke() { + if (responseObserver instanceof Http2CancelableStreamObserver) { + RpcContext.restoreCancellationContext(((Http2CancelableStreamObserver) responseObserver).getCancellationContext()); + } + InetSocketAddress remoteAddress = (InetSocketAddress) invocation.getAttributes() + .remove(AbstractServerCall.REMOTE_ADDRESS_KEY); + RpcContext.getServiceContext().setRemoteAddress(remoteAddress); + String remoteApp = (String) invocation.getAttributes() + .remove(TripleHeaderEnum.CONSUMER_APP_NAME_KEY); + if (null != remoteApp) { + RpcContext.getServiceContext().setRemoteApplicationName(remoteApp); + invocation.setAttachmentIfAbsent(REMOTE_APPLICATION_KEY, remoteApp); + } try { final long stInMillis = System.currentTimeMillis(); final Result response = invoker.invoke(invocation); response.whenCompleteWithContext((r, t) -> { + if (responseObserver instanceof AttachmentHolder) { + ((AttachmentHolder) responseObserver).setResponseAttachments(response.getObjectAttachments()); + } if (t != null) { responseObserver.onError(t); return; } if (response.hasException()) { - doOnResponseHasException(response.getException()); + onResponseException(response.getException()); return; } final long cost = System.currentTimeMillis() - stInMillis; @@ -80,7 +101,7 @@ public abstract class AbstractServerCallListener implements ServerCallListener { } } - protected void doOnResponseHasException(Throwable t) { + protected void onResponseException(Throwable t) { responseObserver.onError(t); } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java new file mode 100644 index 0000000000..a294d61e2a --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java @@ -0,0 +1,479 @@ +/* + * 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.tri.h12; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.JsonUtils; +import org.apache.dubbo.remoting.http12.HttpChannel; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpInputMessage; +import org.apache.dubbo.remoting.http12.HttpStatus; +import org.apache.dubbo.remoting.http12.HttpTransportListener; +import org.apache.dubbo.remoting.http12.RequestMetadata; +import org.apache.dubbo.remoting.http12.exception.HttpStatusException; +import org.apache.dubbo.remoting.http12.exception.IllegalPathException; +import org.apache.dubbo.remoting.http12.exception.UnimplementedException; +import org.apache.dubbo.remoting.http12.exception.UnsupportedMediaTypeException; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory; +import org.apache.dubbo.remoting.http12.message.MethodMetadata; +import org.apache.dubbo.rpc.HeaderFilter; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.PathResolver; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.TriRpcStatus; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.MethodDescriptor; +import org.apache.dubbo.rpc.model.ProviderModel; +import org.apache.dubbo.rpc.model.ServiceDescriptor; +import org.apache.dubbo.rpc.protocol.tri.TripleConstant; +import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum; +import org.apache.dubbo.rpc.protocol.tri.TripleProtocol; +import org.apache.dubbo.rpc.protocol.tri.stream.StreamUtils; +import org.apache.dubbo.rpc.service.ServiceDescriptorInternalCache; +import org.apache.dubbo.rpc.stub.StubSuppliers; + +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.Executor; +import java.util.function.Supplier; + +import static org.apache.dubbo.common.constants.CommonConstants.HEADER_FILTER_KEY; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR; +import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_FAILED_PARSE; + +public abstract class AbstractServerTransportListener
implements HttpTransportListener { + + private static final ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(AbstractServerTransportListener.class); + + private final PathResolver pathResolver; + + private final FrameworkModel frameworkModel; + + private final URL url; + + private final HttpChannel httpChannel; + + private final List headerFilters; + + private HttpMessageCodec httpMessageCodec; + + private Invoker invoker; + + private ServiceDescriptor serviceDescriptor; + + private MethodDescriptor methodDescriptor; + + private RpcInvocation rpcInvocation; + + private MethodMetadata methodMetadata; + + private HEADER httpMetadata; + + private Executor executor; + + private boolean hasStub; + + private HttpMessageListener httpMessageListener; + + public AbstractServerTransportListener(FrameworkModel frameworkModel, URL url, HttpChannel httpChannel) { + this.frameworkModel = frameworkModel; + this.url = url; + this.httpChannel = httpChannel; + this.pathResolver = frameworkModel.getExtensionLoader(PathResolver.class).getDefaultExtension(); + this.headerFilters = frameworkModel.getExtensionLoader(HeaderFilter.class).getActivateExtension(url, HEADER_FILTER_KEY); + } + + protected Executor initializeExecutor(HEADER metadata) { + //default direct executor + return Runnable::run; + } + + @Override + public void onMetadata(HEADER metadata) { + try { + this.executor = initializeExecutor(metadata); + } catch (Throwable throwable) { + onError(throwable); + return; + } + if (this.executor == null) { + onError(new NullPointerException("initializeExecutor return null")); + return; + } + executor.execute(() -> { + try { + doOnMetadata(metadata); + } catch (Throwable throwable) { + onError(throwable); + } + }); + } + + protected void doOnMetadata(HEADER metadata) { + onPrepareMetadata(metadata); + this.httpMetadata = metadata; + String path = metadata.path(); + HttpHeaders headers = metadata.headers(); + //1.check necessary header + String contentType = headers.getFirst(HttpHeaderNames.CONTENT_TYPE.getName()); + if (contentType == null) { + throw new UnsupportedMediaTypeException("'" + HttpHeaderNames.CONTENT_TYPE.getName() + "' must be not null."); + } + + //2. check service + String[] parts = path.split("/"); + if (parts.length != 3) { + throw new IllegalPathException(path); + } + String serviceName = parts[1]; + this.hasStub = pathResolver.hasNativeStub(path); + this.invoker = getInvoker(metadata, serviceName); + if (invoker == null) { + throw new UnimplementedException(serviceName); + } + HttpMessageCodec httpMessageCodec = determineHttpMessageCodec(contentType); + if (httpMessageCodec == null) { + throw new UnsupportedMediaTypeException(contentType); + } + this.httpMessageCodec = httpMessageCodec; + this.serviceDescriptor = findServiceDescriptor(invoker, serviceName, hasStub); + setHttpMessageListener(newHttpMessageListener()); + onMetadataCompletion(metadata); + } + + protected abstract HttpMessageListener newHttpMessageListener(); + + @Override + public void onData(MESSAGE message) { + this.executor.execute(() -> { + try { + doOnData(message); + } catch (Throwable e) { + onError(e); + } + }); + } + + protected void doOnData(MESSAGE message) { + //decode message + onPrepareData(message); + InputStream body = message.getBody(); + httpMessageListener.onMessage(body); + onDataCompletion(message); + } + + protected void onPrepareMetadata(HEADER header) { + //default no op + } + + protected void onMetadataCompletion(HEADER metadata) { + //default no op + } + + protected void onPrepareData(MESSAGE message) { + //default no op + } + + protected void onDataCompletion(MESSAGE message) { + //default no op + } + + protected void onError(Throwable throwable) { + //default rethrow + if (throwable instanceof RuntimeException) { + throw ((RuntimeException) throwable); + } + if (throwable instanceof InvocationTargetException) { + Throwable targetException = ((InvocationTargetException) throwable).getTargetException(); + if (targetException instanceof RuntimeException) { + throw (RuntimeException) targetException; + } else if (targetException instanceof Error) { + throw (Error) targetException; + } + } + throw new HttpStatusException(HttpStatus.INTERNAL_SERVER_ERROR.getCode(), throwable); + } + + private Invoker getInvoker(HEADER metadata, String serviceName) { + HttpHeaders headers = metadata.headers(); + final String version = + headers.containsKey(TripleHeaderEnum.SERVICE_VERSION.getHeader()) ? headers.get( + TripleHeaderEnum.SERVICE_VERSION.getHeader()).toString() : null; + final String group = + headers.containsKey(TripleHeaderEnum.SERVICE_GROUP.getHeader()) ? headers.get( + TripleHeaderEnum.SERVICE_GROUP.getHeader()).toString() : null; + final String key = URL.buildKey(serviceName, group, version); + Invoker invoker = pathResolver.resolve(key); + if (invoker == null && TripleProtocol.RESOLVE_FALLBACK_TO_DEFAULT) { + invoker = pathResolver.resolve(URL.buildKey(serviceName, group, "1.0.0")); + } + if (invoker == null && TripleProtocol.RESOLVE_FALLBACK_TO_DEFAULT) { + invoker = pathResolver.resolve(serviceName); + } + return invoker; + } + + + protected HttpMessageCodec determineHttpMessageCodec(String contentType) { + for (HttpMessageCodecFactory httpMessageCodecFactory : frameworkModel.getExtensionLoader(HttpMessageCodecFactory.class).getActivateExtensions()) { + if (httpMessageCodecFactory.support(contentType)) { + return httpMessageCodecFactory.createCodec(invoker.getUrl(), frameworkModel); + } + } + return null; + } + + private static ServiceDescriptor findServiceDescriptor(Invoker invoker, String serviceName, boolean hasStub) throws UnimplementedException { + ServiceDescriptor result; + if (hasStub) { + result = getStubServiceDescriptor(invoker.getUrl(), serviceName); + } else { + result = getReflectionServiceDescriptor(invoker.getUrl()); + } + if (result == null) { + throw new UnimplementedException("service:" + serviceName); + } + return result; + } + + protected static MethodDescriptor findMethodDescriptor(ServiceDescriptor serviceDescriptor, String originalMethodName, boolean hasStub) throws UnimplementedException { + MethodDescriptor result; + if (hasStub) { + result = serviceDescriptor.getMethods(originalMethodName).get(0); + } else { + result = findReflectionMethodDescriptor(serviceDescriptor, originalMethodName); + } + return result; + } + + protected RpcInvocation buildRpcInvocation(Invoker invoker, + ServiceDescriptor serviceDescriptor, + MethodDescriptor methodDescriptor) { + final URL url = invoker.getUrl(); + RpcInvocation inv = new RpcInvocation(url.getServiceModel(), + methodDescriptor.getMethodName(), + serviceDescriptor.getInterfaceName(), url.getProtocolServiceKey(), + methodDescriptor.getParameterClasses(), + new Object[0]); + inv.setTargetServiceUniqueName(url.getServiceKey()); + inv.setReturnTypes(methodDescriptor.getReturnTypes()); + Map headers = getHttpMetadata().headers().toSingleValueMap(); + Map requestMetadata = headersToMap(headers, () -> { + return Optional.ofNullable(headers.get(TripleHeaderEnum.TRI_HEADER_CONVERT.getHeader())) + .map(CharSequence::toString) + .orElse(null); + }); + inv.setObjectAttachments(StreamUtils.toAttachments(requestMetadata)); + + inv.put("tri.remote.address", httpChannel.remoteAddress()); + //customizer RpcInvocation + headerFilters.forEach(f -> f.invoke(invoker, inv)); + return inv; + } + + protected static ServiceDescriptor getStubServiceDescriptor(URL url, String serviceName) { + ServiceDescriptor serviceDescriptor; + if (url.getServiceModel() != null) { + serviceDescriptor = url + .getServiceModel() + .getServiceModel(); + } else { + serviceDescriptor = StubSuppliers.getServiceDescriptor(serviceName); + } + return serviceDescriptor; + } + + protected static ServiceDescriptor getReflectionServiceDescriptor(URL url) { + ProviderModel providerModel = (ProviderModel) url.getServiceModel(); + if (providerModel == null || providerModel.getServiceModel() == null) { + return null; + } + return providerModel.getServiceModel(); + } + + protected static boolean isEcho(String methodName) { + return CommonConstants.$ECHO.equals(methodName); + } + + protected static boolean isGeneric(String methodName) { + return CommonConstants.$INVOKE.equals(methodName) || CommonConstants.$INVOKE_ASYNC.equals( + methodName); + } + + protected static MethodDescriptor findReflectionMethodDescriptor(ServiceDescriptor serviceDescriptor, String methodName) { + MethodDescriptor methodDescriptor = null; + if (isGeneric(methodName)) { + // There should be one and only one + methodDescriptor = ServiceDescriptorInternalCache.genericService() + .getMethods(methodName).get(0); + } else if (isEcho(methodName)) { + // There should be one and only one + return ServiceDescriptorInternalCache.echoService().getMethods(methodName) + .get(0); + } else { + List methodDescriptors = serviceDescriptor.getMethods(methodName); + // try lower-case method + if (CollectionUtils.isEmpty(methodDescriptors)) { + final String lowerMethod = + Character.toLowerCase(methodName.charAt(0)) + methodName.substring(1); + methodDescriptors = serviceDescriptor.getMethods(lowerMethod); + } + if (CollectionUtils.isEmpty(methodDescriptors)) { + return null; + } + // In most cases there is only one method + if (methodDescriptors.size() == 1) { + methodDescriptor = methodDescriptors.get(0); + } + // generated unary method ,use unary type + // Response foo(Request) + // void foo(Request,StreamObserver) + if (methodDescriptors.size() == 2) { + if (methodDescriptors.get(1).getRpcType() == MethodDescriptor.RpcType.SERVER_STREAM) { + methodDescriptor = methodDescriptors.get(0); + } else if (methodDescriptors.get(0).getRpcType() == MethodDescriptor.RpcType.SERVER_STREAM) { + methodDescriptor = methodDescriptors.get(1); + } + } + } + return methodDescriptor; + } + + protected FrameworkModel getFrameworkModel() { + return frameworkModel; + } + + protected HEADER getHttpMetadata() { + return httpMetadata; + } + + protected Invoker getInvoker() { + return invoker; + } + + protected ServiceDescriptor getServiceDescriptor() { + return serviceDescriptor; + } + + protected MethodDescriptor getMethodDescriptor() { + return methodDescriptor; + } + + public void setServiceDescriptor(ServiceDescriptor serviceDescriptor) { + this.serviceDescriptor = serviceDescriptor; + } + + public void setMethodDescriptor(MethodDescriptor methodDescriptor) { + this.methodDescriptor = methodDescriptor; + } + + public void setMethodMetadata(MethodMetadata methodMetadata) { + this.methodMetadata = methodMetadata; + } + + protected RpcInvocation getRpcInvocation() { + return rpcInvocation; + } + + public void setRpcInvocation(RpcInvocation rpcInvocation) { + this.rpcInvocation = rpcInvocation; + } + + protected MethodMetadata getMethodMetadata() { + return methodMetadata; + } + + protected HttpMessageCodec getHttpMessageCodec() { + return httpMessageCodec; + } + + protected void setHttpMessageListener(HttpMessageListener httpMessageListener) { + this.httpMessageListener = httpMessageListener; + } + + protected HttpMessageListener getHttpMessageListener() { + return httpMessageListener; + } + + protected PathResolver getPathResolver() { + return pathResolver; + } + + protected final URL getUrl() { + return url; + } + + public boolean isHasStub() { + return hasStub; + } + + protected Map headersToMap(Map headers, Supplier convertUpperHeaderSupplier) { + if (headers == null) { + return Collections.emptyMap(); + } + Map attachments = new HashMap<>(headers.size()); + for (Map.Entry header : headers.entrySet()) { + String key = header.getKey(); + if (key.endsWith(TripleConstant.HEADER_BIN_SUFFIX) + && key.length() > TripleConstant.HEADER_BIN_SUFFIX.length()) { + try { + String realKey = key.substring(0, + key.length() - TripleConstant.HEADER_BIN_SUFFIX.length()); + byte[] value = StreamUtils.decodeASCIIByte(header.getValue()); + attachments.put(realKey, value); + } catch (Exception e) { + LOGGER.error(PROTOCOL_FAILED_PARSE, "", "", "Failed to parse response attachment key=" + key, e); + } + } else { + attachments.put(key, header.getValue()); + } + } + + // try converting upper key + Object obj = convertUpperHeaderSupplier.get(); + if (obj == null) { + return attachments; + } + if (obj instanceof String) { + String json = TriRpcStatus.decodeMessage((String) obj); + Map map = JsonUtils.toJavaObject(json, Map.class); + for (Map.Entry entry : map.entrySet()) { + Object val = attachments.remove(entry.getKey()); + if (val != null) { + attachments.put(entry.getValue(), val); + } + } + } else { + // If convertUpperHeaderSupplier does not return String, just fail... + // Internal invocation, use INTERNAL_ERROR instead. + + LOGGER.error(INTERNAL_ERROR, "wrong internal invocation", "", "Triple convertNoLowerCaseHeader error, obj is not String"); + } + return attachments; + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AttachmentHolder.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AttachmentHolder.java new file mode 100644 index 0000000000..be0e488096 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AttachmentHolder.java @@ -0,0 +1,26 @@ +/* + * 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.tri.h12; + +import java.util.Map; + +public interface AttachmentHolder { + + void setResponseAttachments(Map attachments); + + Map getResponseAttachments(); +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/BiStreamServerCallListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/BiStreamServerCallListener.java similarity index 95% rename from dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/BiStreamServerCallListener.java rename to dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/BiStreamServerCallListener.java index 705031f98f..0ffd8d7ca7 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/BiStreamServerCallListener.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/BiStreamServerCallListener.java @@ -15,9 +15,10 @@ * limitations under the License. */ -package org.apache.dubbo.remoting.http12; +package org.apache.dubbo.rpc.protocol.tri.h12; import org.apache.dubbo.common.stream.StreamObserver; +import org.apache.dubbo.remoting.http12.FlowControlStreamObserver; import org.apache.dubbo.remoting.http12.exception.HttpStatusException; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcInvocation; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/CompressibleCodec.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/CompressibleCodec.java new file mode 100644 index 0000000000..7da92bd17f --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/CompressibleCodec.java @@ -0,0 +1,71 @@ +/* + * 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.tri.h12; + +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.exception.EncodeException; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.remoting.http12.message.MediaType; +import org.apache.dubbo.rpc.protocol.tri.compressor.Compressor; + +import java.io.InputStream; +import java.io.OutputStream; + +public class CompressibleCodec implements HttpMessageCodec { + + private final HttpMessageCodec delegate; + + private Compressor compressor = Compressor.NONE; + + public CompressibleCodec(HttpMessageCodec delegate) { + this.delegate = delegate; + } + + public void setCompressor(Compressor compressor) { + this.compressor = compressor; + } + + @Override + public void encode(OutputStream outputStream, Object data) throws EncodeException { + delegate.encode(compressor.decorate(outputStream), data); + } + + @Override + public Object decode(InputStream inputStream, Class targetType) throws DecodeException { + return delegate.decode(inputStream, targetType); + } + + @Override + public void encode(OutputStream outputStream, Object[] data) throws EncodeException { + delegate.encode(outputStream, data); + } + + @Override + public Object[] decode(InputStream inputStream, Class[] targetTypes) throws DecodeException { + return delegate.decode(inputStream, targetTypes); + } + + @Override + public boolean support(String contentType) { + return delegate.support(contentType); + } + + @Override + public MediaType contentType() { + return delegate.contentType(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/DefaultHttpMessageListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/DefaultHttpMessageListener.java new file mode 100644 index 0000000000..0ecab54e4f --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/DefaultHttpMessageListener.java @@ -0,0 +1,43 @@ +/* + * 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.tri.h12; + +import org.apache.dubbo.remoting.http12.message.ListeningDecoder; + +import java.io.InputStream; + +public class DefaultHttpMessageListener implements HttpMessageListener { + + private ListeningDecoder listeningDecoder; + + public DefaultHttpMessageListener() { + + } + + public DefaultHttpMessageListener(ListeningDecoder listeningDecoder) { + this.listeningDecoder = listeningDecoder; + } + + public void setListeningDecoder(ListeningDecoder listeningDecoder) { + this.listeningDecoder = listeningDecoder; + } + + @Override + public void onMessage(InputStream inputStream) { + listeningDecoder.decode(inputStream); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/HttpMessageListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/HttpMessageListener.java new file mode 100644 index 0000000000..810af9bded --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/HttpMessageListener.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.tri.h12; + +import java.io.InputStream; + +public interface HttpMessageListener { + + void onMessage(InputStream inputStream); +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerCallListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerCallListener.java similarity index 96% rename from dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerCallListener.java rename to dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerCallListener.java index d5d076029f..55616bdd82 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerCallListener.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerCallListener.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.remoting.http12; +package org.apache.dubbo.rpc.protocol.tri.h12; public interface ServerCallListener { diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerCallToObserverAdapter.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerCallToObserverAdapter.java new file mode 100644 index 0000000000..b463971087 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerCallToObserverAdapter.java @@ -0,0 +1,25 @@ +/* + * 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.tri.h12; + +import org.apache.dubbo.rpc.protocol.tri.ServerStreamObserver; + +public interface ServerCallToObserverAdapter extends ServerStreamObserver { + + void setExceptionCode(int exceptionCode); + +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerStreamServerCallListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerStreamServerCallListener.java similarity index 97% rename from dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerStreamServerCallListener.java rename to dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerStreamServerCallListener.java index e65478eb1f..5a0e60969a 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ServerStreamServerCallListener.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerStreamServerCallListener.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.dubbo.remoting.http12; +package org.apache.dubbo.rpc.protocol.tri.h12; import org.apache.dubbo.common.stream.StreamObserver; import org.apache.dubbo.remoting.http12.exception.HttpStatusException; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/TripleProtocolDetector.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/TripleProtocolDetector.java new file mode 100644 index 0000000000..c6c7128ab1 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/TripleProtocolDetector.java @@ -0,0 +1,87 @@ +/* + * 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.tri.h12; + +import io.netty.handler.codec.http2.Http2CodecUtil; +import org.apache.dubbo.remoting.api.ProtocolDetector; +import org.apache.dubbo.remoting.buffer.ByteBufferBackedChannelBuffer; +import org.apache.dubbo.remoting.buffer.ChannelBuffer; +import org.apache.dubbo.remoting.buffer.ChannelBuffers; + +import static java.lang.Math.min; + +public class TripleProtocolDetector implements ProtocolDetector { + + public static final String HTTP_VERSION = "HTTP_VERSION"; + + private final ChannelBuffer clientPrefaceString = new ByteBufferBackedChannelBuffer( + Http2CodecUtil.connectionPrefaceBuf().nioBuffer()); + + @Override + public Result detect(ChannelBuffer in) { + //http1 + if (in.readableBytes() < 2) { + return Result.needMoreData(); + } + byte[] magics = new byte[5]; + in.getBytes(in.readerIndex(), magics, 0, 5); + if (isHttp(magics)) { + Result recognized = Result.recognized(); + recognized.setAttribute(HTTP_VERSION, HttpVersion.HTTP1.getVersion()); + return recognized; + } + in.resetReaderIndex(); + + //http2 + int prefaceLen = clientPrefaceString.readableBytes(); + int bytesRead = min(in.readableBytes(), prefaceLen); + if (bytesRead == 0 || !ChannelBuffers.prefixEquals(in, clientPrefaceString, bytesRead)) { + return Result.unrecognized(); + } + if (bytesRead == prefaceLen) { + Result recognized = Result.recognized(); + recognized.setAttribute(HTTP_VERSION, HttpVersion.HTTP2.getVersion()); + return recognized; + } + return Result.needMoreData(); + } + + private static boolean isHttp(byte[] magic) { + if (magic[0] == 'G' && magic[1] == 'E' && magic[2] == 'T') { + return true; + } + if (magic[0] == 'P' && magic[1] == 'O' && magic[2] == 'S' && magic[3] == 'T') { + return true; + } + return false; + } + + public static enum HttpVersion { + HTTP1("http1"), + HTTP2("http2"); + + private final String version; + + HttpVersion(String version) { + this.version = version; + } + + public String getVersion() { + return version; + } + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/UnaryServerCallListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/UnaryServerCallListener.java similarity index 64% rename from dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/UnaryServerCallListener.java rename to dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/UnaryServerCallListener.java index e1a985803f..f933020ddd 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/UnaryServerCallListener.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/UnaryServerCallListener.java @@ -14,20 +14,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.remoting.http12; +package org.apache.dubbo.rpc.protocol.tri.h12; import org.apache.dubbo.common.stream.StreamObserver; import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.TriRpcStatus; public class UnaryServerCallListener extends AbstractServerCallListener { + private boolean applyCustomizeException = false; + public UnaryServerCallListener(RpcInvocation invocation, Invoker invoker, StreamObserver responseObserver) { super(invocation, invoker, responseObserver); } + public void setApplyCustomizeException(boolean applyCustomizeException) { + this.applyCustomizeException = applyCustomizeException; + } + @Override public void onReturn(Object value) { responseObserver.onNext(value); @@ -43,6 +51,24 @@ public class UnaryServerCallListener extends AbstractServerCallListener { } } + @Override + protected void onResponseException(Throwable t) { + if (applyCustomizeException) { + TriRpcStatus status = TriRpcStatus.getStatus(t); + int exceptionCode = status.code.code; + if (exceptionCode == TriRpcStatus.UNKNOWN.code.code) { + exceptionCode = RpcException.BIZ_EXCEPTION; + } + if (responseObserver instanceof ServerCallToObserverAdapter) { + ((ServerCallToObserverAdapter) responseObserver).setExceptionCode(exceptionCode); + } + onReturn(t); + } else { + super.onResponseException(t); + } + + } + @Override public void onCancel(long code) { //ignore diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java new file mode 100644 index 0000000000..5ff1b1da21 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java @@ -0,0 +1,124 @@ +/* + * 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.tri.h12.grpc; + +import com.google.protobuf.Message; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.exception.EncodeException; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.remoting.http12.message.MediaType; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * compatible low version. + * version < 3.3 + * + * @since 3.3 + */ +@Activate +public class GrpcCompositeCodec implements HttpMessageCodec { + + private static final MediaType MEDIA_TYPE = new MediaType("application", "grpc"); + + private final ProtobufHttpMessageCodec protobufHttpMessageCodec; + + private final WrapperHttpMessageCodec wrapperHttpMessageCodec; + + public GrpcCompositeCodec(ProtobufHttpMessageCodec protobufHttpMessageCodec, + WrapperHttpMessageCodec wrapperHttpMessageCodec) { + this.protobufHttpMessageCodec = protobufHttpMessageCodec; + this.wrapperHttpMessageCodec = wrapperHttpMessageCodec; + } + + public void setEncodeTypes(Class[] encodeTypes) { + this.wrapperHttpMessageCodec.setEncodeTypes(encodeTypes); + } + + public void setDecodeTypes(Class[] decodeTypes) { + this.wrapperHttpMessageCodec.setDecodeTypes(decodeTypes); + } + + + @Override + public void encode(OutputStream outputStream, Object data) throws EncodeException { + //protobuf + //TODO int compressed = Identity.MESSAGE_ENCODING.equals(requestMetadata.compressor.getMessageEncoding()) ? 0 : 1; + try { + int compressed = 0; + outputStream.write(compressed); + if (data instanceof Message) { + int serializedSize = ((Message) data).getSerializedSize(); + //write length + writeLength(outputStream, serializedSize); + protobufHttpMessageCodec.encode(outputStream, data); + return; + } + //wrapper + wrapperHttpMessageCodec.encode(outputStream, data); + } catch (IOException e) { + throw new EncodeException(e); + } + } + + @Override + public Object decode(InputStream inputStream, Class targetType) throws DecodeException { + if (isProtobuf(targetType)) { + return protobufHttpMessageCodec.decode(inputStream, targetType); + } + return wrapperHttpMessageCodec.decode(inputStream, targetType); + } + + @Override + public Object[] decode(InputStream inputStream, Class[] targetTypes) throws DecodeException { + if (targetTypes.length > 1) { + return wrapperHttpMessageCodec.decode(inputStream, targetTypes); + } + return HttpMessageCodec.super.decode(inputStream, targetTypes); + } + + private boolean isProtobuf(Class targetType) { + if (targetType == null) { + return false; + } + return Message.class.isAssignableFrom(targetType); + } + + private static void writeLength(OutputStream outputStream, int length) { + try { + outputStream.write(((length >> 24) & 0xFF)); + outputStream.write(((length >> 16) & 0xFF)); + outputStream.write(((length >> 8) & 0xFF)); + outputStream.write((length & 0xFF)); + } catch (IOException e) { + throw new EncodeException(e); + } + } + + @Override + public MediaType contentType() { + return MEDIA_TYPE; + } + + @Override + public boolean support(String contentType) { + return contentType.startsWith(MEDIA_TYPE.getName()); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodecFactory.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodecFactory.java new file mode 100644 index 0000000000..792fde774d --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodecFactory.java @@ -0,0 +1,50 @@ +/* + * 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.tri.h12.grpc; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory; +import org.apache.dubbo.remoting.http12.message.MediaType; +import org.apache.dubbo.remoting.utils.UrlUtils; +import org.apache.dubbo.rpc.model.FrameworkModel; + +@Activate +public class GrpcCompositeCodecFactory implements HttpMessageCodecFactory { + + private static final MediaType MEDIA_TYPE = new MediaType("application", "grpc"); + + @Override + public HttpMessageCodec createCodec(URL url, FrameworkModel frameworkModel) { + final String serializeName = UrlUtils.serializationOrDefault(url); + WrapperHttpMessageCodec wrapperHttpMessageCodec = new WrapperHttpMessageCodec(url, frameworkModel); + wrapperHttpMessageCodec.setSerializeType(serializeName); + ProtobufHttpMessageCodec protobufHttpMessageCodec = new ProtobufHttpMessageCodec(); + return new GrpcCompositeCodec(protobufHttpMessageCodec, wrapperHttpMessageCodec); + } + + @Override + public MediaType contentType() { + return MEDIA_TYPE; + } + + @Override + public boolean support(String contentType) { + return contentType.startsWith(MEDIA_TYPE.getName()); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHeaderNames.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHeaderNames.java new file mode 100644 index 0000000000..030cb53259 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHeaderNames.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.tri.h12.grpc; + +public enum GrpcHeaderNames { + + GRPC_STATUS("grpc-status"), + GRPC_MESSAGE("grpc-message"), + GRPC_ENCODING("grpc-encoding"), + GRPC_TIMEOUT("grpc-timeout"), + ; + + private final String name; + + GrpcHeaderNames(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListener.java new file mode 100644 index 0000000000..19f1680ef1 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListener.java @@ -0,0 +1,216 @@ +/* + * 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.tri.h12.grpc; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.exception.UnimplementedException; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2Header; +import org.apache.dubbo.remoting.http12.h2.Http2TransportListener; +import org.apache.dubbo.remoting.http12.message.MethodMetadata; +import org.apache.dubbo.remoting.http12.message.StreamingDecoder; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.MethodDescriptor; +import org.apache.dubbo.rpc.model.ServiceDescriptor; +import org.apache.dubbo.rpc.protocol.tri.TripleCustomerProtocolWapper; +import org.apache.dubbo.rpc.protocol.tri.call.AbstractServerCall; +import org.apache.dubbo.rpc.protocol.tri.compressor.DeCompressor; +import org.apache.dubbo.rpc.protocol.tri.compressor.Identity; +import org.apache.dubbo.rpc.protocol.tri.h12.HttpMessageListener; +import org.apache.dubbo.rpc.protocol.tri.h12.http2.GenericHttp2ServerTransportListener; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_FAILED_PARSE; + +public class GrpcHttp2ServerTransportListener extends GenericHttp2ServerTransportListener implements Http2TransportListener { + + private static final ErrorTypeAwareLogger LOGGER = LoggerFactory.getErrorTypeAwareLogger(AbstractServerCall.class); + + public GrpcHttp2ServerTransportListener(H2StreamChannel h2StreamChannel, URL url, FrameworkModel frameworkModel) { + super(h2StreamChannel, url, frameworkModel); + initialize(); + } + + private void initialize() { + getServerChannelObserver().setTrailersCustomizer(this::grpcTrailersCustomize); + } + + private void grpcTrailersCustomize(HttpHeaders httpHeaders, Throwable throwable) { + httpHeaders.set(GrpcHeaderNames.GRPC_STATUS.getName(), "0"); + if (throwable != null) { + httpHeaders.set(GrpcHeaderNames.GRPC_MESSAGE.getName(), throwable.getMessage()); + } + } + + @Override + protected RpcInvocation buildRpcInvocation(Invoker invoker, ServiceDescriptor serviceDescriptor, MethodDescriptor methodDescriptor) { + RpcInvocation rpcInvocation = super.buildRpcInvocation(invoker, serviceDescriptor, methodDescriptor); + HttpHeaders headers = getHttpMetadata().headers(); + String timeoutString = headers.getFirst(GrpcHeaderNames.GRPC_TIMEOUT.getName()); + try { + if (Objects.nonNull(timeoutString)) { + Long timeout = GrpcUtils.parseTimeoutToMills(timeoutString); + rpcInvocation.put("timeout", timeout); + } + } catch (Throwable t) { + LOGGER.warn(PROTOCOL_FAILED_PARSE, "", "", String.format("Failed to parse request timeout set from:%s, service=%s " + + "method=%s", timeoutString, serviceDescriptor.getInterfaceName(), getMethodDescriptor().getMethodName())); + } + return rpcInvocation; + } + + @Override + protected StreamingDecoder newStreamingDecoder() { + return new GrpcStreamingDecoder(); + } + + @Override + protected HttpMessageListener newHttpMessageListener() { + Http2Header httpMetadata = getHttpMetadata(); + boolean hasStub = getPathResolver().hasNativeStub(httpMetadata.path()); + if (hasStub) { + return GrpcHttp2ServerTransportListener.super.newHttpMessageListener(); + } + return new LazyFindMethodListener(); + } + + @Override + protected void onMetadataCompletion(Http2Header metadata) { + super.onMetadataCompletion(metadata); + processGrpcHeaders(metadata); + } + + private void processGrpcHeaders(Http2Header metadata) { + String messageEncoding = metadata.headers().getFirst(GrpcHeaderNames.GRPC_ENCODING.getName()); + if (null != messageEncoding) { + if (!Identity.MESSAGE_ENCODING.equals(messageEncoding)) { + DeCompressor compressor = DeCompressor.getCompressor(getFrameworkModel(), + messageEncoding); + if (null == compressor) { + throw new UnimplementedException(GrpcHeaderNames.GRPC_ENCODING.getName() + " '" + messageEncoding + "'"); + } + getStreamingDecoder().setDeCompressor(compressor); + } + } + } + + @Override + protected GrpcStreamingDecoder getStreamingDecoder() { + return (GrpcStreamingDecoder) super.getStreamingDecoder(); + } + + private class LazyFindMethodListener implements HttpMessageListener { + + private final StreamingDecoder streamingDecoder; + + private LazyFindMethodListener() { + this.streamingDecoder = new GrpcStreamingDecoder(); + this.streamingDecoder.setFragmentListener(new DetermineMethodDescriptorListener()); + this.streamingDecoder.request(Integer.MAX_VALUE); + } + + @Override + public void onMessage(InputStream inputStream) { + streamingDecoder.decode(inputStream); + } + } + + private class DetermineMethodDescriptorListener implements StreamingDecoder.FragmentListener { + + @Override + public void onFragmentMessage(InputStream rawMessage) { + + } + + @Override + public void onClose() { + getStreamingDecoder().close(); + } + + @Override + public void onFragmentMessage(InputStream dataHeader, InputStream rawMessage) { + try { + ByteArrayOutputStream merge = new ByteArrayOutputStream(dataHeader.available() + rawMessage.available()); + transferToOutputStream(merge, dataHeader); + ByteArrayOutputStream bos = new ByteArrayOutputStream(rawMessage.available()); + transferToOutputStream(bos, rawMessage); + byte[] data = bos.toByteArray(); + MethodDescriptor methodDescriptor = getMethodDescriptor(); + if (methodDescriptor == null) { + Http2Header httpMetadata = getHttpMetadata(); + String path = httpMetadata.path(); + String[] parts = path.split("/"); + String originalMethodName = parts[2]; + methodDescriptor = findReflectionMethodDescriptor(getServiceDescriptor(), originalMethodName); + if (methodDescriptor == null) { + List methodDescriptors = getServiceDescriptor().getMethods(originalMethodName); + final TripleCustomerProtocolWapper.TripleRequestWrapper request; + request = TripleCustomerProtocolWapper.TripleRequestWrapper.parseFrom(data); + final String[] paramTypes = request.getArgTypes() + .toArray(new String[request.getArgs().size()]); + // wrapper mode the method can overload so maybe list + for (MethodDescriptor descriptor : methodDescriptors) { + // params type is array + if (Arrays.equals(descriptor.getCompatibleParamSignatures(), paramTypes)) { + methodDescriptor = descriptor; + break; + } + } + if (methodDescriptor == null) { + throw new UnimplementedException("method:" + originalMethodName); + } + } + setMethodDescriptor(methodDescriptor); + setMethodMetadata(MethodMetadata.fromMethodDescriptor(methodDescriptor)); + setRpcInvocation(buildRpcInvocation(getInvoker(), getServiceDescriptor(), methodDescriptor)); + //replace decoder + HttpMessageListener httpMessageListener = GrpcHttp2ServerTransportListener.super.newHttpMessageListener(); + GrpcCompositeCodec grpcCompositeCodec = (GrpcCompositeCodec) getHttpMessageCodec(); + grpcCompositeCodec.setEncodeTypes(new Class[]{getMethodMetadata().getActualResponseType()}); + grpcCompositeCodec.setDecodeTypes(getMethodMetadata().getActualRequestTypes()); + setHttpMessageListener(httpMessageListener); + } + transferToOutputStream(merge, new ByteArrayInputStream(data)); + getHttpMessageListener().onMessage(new ByteArrayInputStream(merge.toByteArray())); + } catch (IOException e) { + throw new DecodeException(e); + } + } + + private void transferToOutputStream(OutputStream out, InputStream inputStream) throws IOException { + byte[] bytes = new byte[1024]; + int len; + while ((len = inputStream.read(bytes)) != -1) { + out.write(bytes, 0, len); + } + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListenerFactory.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListenerFactory.java new file mode 100644 index 0000000000..cdcd42489e --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListenerFactory.java @@ -0,0 +1,38 @@ +/* + * 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.tri.h12.grpc; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory; +import org.apache.dubbo.remoting.http12.h2.Http2TransportListener; +import org.apache.dubbo.rpc.model.FrameworkModel; + +public class GrpcHttp2ServerTransportListenerFactory implements Http2ServerTransportListenerFactory { + + public static final String CONTENT_TYPE = "application/grpc"; + + @Override + public Http2TransportListener newInstance(H2StreamChannel streamChannel, URL url, FrameworkModel frameworkModel) { + return new GrpcHttp2ServerTransportListener(streamChannel, url, frameworkModel); + } + + @Override + public boolean supportContentType(String contentType) { + return contentType.startsWith(CONTENT_TYPE); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcStreamingDecoder.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcStreamingDecoder.java new file mode 100644 index 0000000000..d0bc805afc --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcStreamingDecoder.java @@ -0,0 +1,61 @@ +/* + * 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.tri.h12.grpc; + +import org.apache.dubbo.remoting.http12.message.LengthFieldStreamingDecoder; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.protocol.tri.compressor.DeCompressor; + +import java.io.IOException; +import java.io.InputStream; + +public class GrpcStreamingDecoder extends LengthFieldStreamingDecoder { + + private static final int COMPRESSED_FLAG_MASK = 1; + private static final int RESERVED_MASK = 0xFE; + + private boolean compressedFlag; + + private DeCompressor deCompressor = DeCompressor.NONE; + + public GrpcStreamingDecoder() { + super(1, 4); + } + + public void setDeCompressor(DeCompressor deCompressor) { + this.deCompressor = deCompressor; + } + + @Override + protected void processOffset(InputStream inputStream, int lengthFieldOffset) throws IOException { + int type = inputStream.read(); + if ((type & RESERVED_MASK) != 0) { + throw new RpcException("gRPC frame header malformed: reserved bits not zero"); + } + compressedFlag = (type & COMPRESSED_FLAG_MASK) != 0; + } + + @Override + protected byte[] readRawMessage(InputStream inputStream, int length) throws IOException { + byte[] rawMessage = super.readRawMessage(inputStream, length); + return compressedFlag ? deCompressedMessage(rawMessage) : rawMessage; + } + + private byte[] deCompressedMessage(byte[] rawMessage) { + return deCompressor.decompress(rawMessage); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcUtils.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcUtils.java new file mode 100644 index 0000000000..2689824a6f --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcUtils.java @@ -0,0 +1,54 @@ +/* + * 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.tri.h12.grpc; + +import org.apache.dubbo.common.utils.StringUtils; + +import java.util.concurrent.TimeUnit; + +public class GrpcUtils { + + private GrpcUtils() { + + } + + public static Long parseTimeoutToMills(String timeoutVal) { + if (StringUtils.isEmpty(timeoutVal) || StringUtils.isContains(timeoutVal, "null")) { + return null; + } + long value = Long.parseLong(timeoutVal.substring(0, timeoutVal.length() - 1)); + char unit = timeoutVal.charAt(timeoutVal.length() - 1); + switch (unit) { + case 'n': + return TimeUnit.NANOSECONDS.toMillis(value); + case 'u': + return TimeUnit.MICROSECONDS.toMillis(value); + case 'm': + return value; + case 'S': + return TimeUnit.SECONDS.toMillis(value); + case 'M': + return TimeUnit.MINUTES.toMillis(value); + case 'H': + return TimeUnit.HOURS.toMillis(value); + default: + // invalid timeout config + return null; + } + } + +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/ProtobufHttpMessageCodec.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/ProtobufHttpMessageCodec.java new file mode 100644 index 0000000000..1d6fce91df --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/ProtobufHttpMessageCodec.java @@ -0,0 +1,57 @@ +/* + * 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.tri.h12.grpc; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.exception.EncodeException; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.remoting.http12.message.MediaType; +import org.apache.dubbo.rpc.protocol.tri.SingleProtobufUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +@Activate(onClass = "com.google.protobuf.Message") +public class ProtobufHttpMessageCodec implements HttpMessageCodec { + + private static final MediaType MEDIA_TYPE = new MediaType("application", "x-protobuf"); + + @Override + public void encode(OutputStream outputStream, Object data) throws EncodeException { + try { + SingleProtobufUtils.serialize(data, outputStream); + } catch (IOException e) { + throw new EncodeException(e); + } + } + + @Override + public Object decode(InputStream inputStream, Class targetType) throws DecodeException { + try { + return SingleProtobufUtils.deserialize(inputStream, targetType); + } catch (IOException e) { + throw new DecodeException(e); + } + } + + @Override + public MediaType contentType() { + return MEDIA_TYPE; + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/DefaultHttp2StreamingDecoder.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/StreamingHttpMessageListener.java similarity index 50% rename from dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/DefaultHttp2StreamingDecoder.java rename to dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/StreamingHttpMessageListener.java index b43d2d1732..bbcac87d43 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/DefaultHttp2StreamingDecoder.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/StreamingHttpMessageListener.java @@ -14,40 +14,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.remoting.http12.h2; +package org.apache.dubbo.rpc.protocol.tri.h12.grpc; -import org.apache.dubbo.remoting.http12.exception.DecodeException; -import org.apache.dubbo.remoting.http12.message.DefaultListeningDecoder; -import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; import org.apache.dubbo.remoting.http12.message.StreamingDecoder; +import org.apache.dubbo.rpc.protocol.tri.h12.HttpMessageListener; import java.io.InputStream; -public class DefaultHttp2StreamingDecoder implements StreamingDecoder { +public class StreamingHttpMessageListener implements HttpMessageListener { - private final DefaultListeningDecoder delegate; + private StreamingDecoder streamingDecoder; - public DefaultHttp2StreamingDecoder(HttpMessageCodec httpMessageCodec, Class[] targetTypes) { - this.delegate = new DefaultListeningDecoder(httpMessageCodec, targetTypes); + public StreamingHttpMessageListener() { + } + + public StreamingHttpMessageListener(StreamingDecoder streamingDecoder) { + this.streamingDecoder = streamingDecoder; } @Override - public void decode(InputStream inputStream) throws DecodeException { - delegate.decode(inputStream); - } - - @Override - public void close() { - delegate.close(); - } - - @Override - public void setListener(Listener listener) { - delegate.setListener(listener); - } - - @Override - public void request(int numMessages) { - //no op + public void onMessage(InputStream inputStream) { + streamingDecoder.decode(inputStream); } } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/WrapperHttpMessageCodec.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/WrapperHttpMessageCodec.java new file mode 100644 index 0000000000..21a7a428f6 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/WrapperHttpMessageCodec.java @@ -0,0 +1,143 @@ +/* + * 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.tri.h12.grpc; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.dubbo.common.serialize.MultipleSerialization; +import org.apache.dubbo.config.Constants; +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.exception.EncodeException; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.remoting.http12.message.MediaType; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.protocol.tri.TripleCustomerProtocolWapper; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +public class WrapperHttpMessageCodec implements HttpMessageCodec { + + private static final MediaType MEDIA_TYPE = new MediaType("application", "triple+wrapper"); + + private static final String DEFAULT_SERIALIZE_TYPE = "fastjson2"; + + private final MultipleSerialization serialization; + + private final URL url; + + private Class[] encodeTypes; + + private Class[] decodeTypes; + + private String serializeType = DEFAULT_SERIALIZE_TYPE; + + public WrapperHttpMessageCodec(URL url, FrameworkModel frameworkModel) { + this.url = url; + this.serialization = frameworkModel + .getExtensionLoader(MultipleSerialization.class) + .getExtension(url.getParameter(Constants.MULTI_SERIALIZATION_KEY, + CommonConstants.DEFAULT_KEY)); + } + + public void setSerializeType(String serializeType) { + this.serializeType = serializeType; + } + + public void setEncodeTypes(Class[] encodeTypes) { + this.encodeTypes = encodeTypes; + } + + public void setDecodeTypes(Class[] decodeTypes) { + this.decodeTypes = decodeTypes; + } + + @Override + public void encode(OutputStream outputStream, Object data) throws EncodeException { + try { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + serialization.serialize(url, serializeType, encodeTypes[0], data, bos); + byte[] encoded = TripleCustomerProtocolWapper.TripleResponseWrapper.Builder.newBuilder() + .setSerializeType(serializeType) + .setType(encodeTypes[0].getName()) + .setData(bos.toByteArray()) + .build() + .toByteArray(); + writeLength(outputStream, encoded.length); + outputStream.write(encoded); + } catch (IOException e) { + throw new EncodeException(e); + } + } + + @Override + public void encode(OutputStream outputStream, Object[] data) throws EncodeException { + //TODO + } + + @Override + public Object decode(InputStream inputStream, Class targetType) throws DecodeException { + Object[] decode = this.decode(inputStream, new Class[]{targetType}); + if (decode == null || decode.length == 0) { + return null; + } + return decode[0]; + } + + @Override + public Object[] decode(InputStream inputStream, Class[] targetTypes) throws DecodeException { + try { + int len; + byte[] data = new byte[4096]; + ByteArrayOutputStream bos = new ByteArrayOutputStream(4096); + while ((len = inputStream.read(data)) != -1) { + bos.write(data, 0, len); + } + TripleCustomerProtocolWapper.TripleRequestWrapper wrapper = TripleCustomerProtocolWapper.TripleRequestWrapper.parseFrom( + bos.toByteArray()); + setSerializeType(wrapper.getSerializeType()); + Object[] ret = new Object[wrapper.getArgs().size()]; + for (int i = 0; i < wrapper.getArgs().size(); i++) { + ByteArrayInputStream in = new ByteArrayInputStream( + wrapper.getArgs().get(i)); + try { + ret[i] = this.serialization.deserialize(url, wrapper.getSerializeType(), targetTypes[i], in); + } catch (ClassNotFoundException e) { + throw new DecodeException(e); + } + } + return ret; + } catch (IOException e) { + throw new DecodeException(e); + } + } + + @Override + public MediaType contentType() { + return MEDIA_TYPE; + } + + private static void writeLength(OutputStream outputStream, int length) throws IOException { + outputStream.write(((length >> 24) & 0xFF)); + outputStream.write(((length >> 16) & 0xFF)); + outputStream.write(((length >> 8) & 0xFF)); + outputStream.write((length & 0xFF)); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListener.java new file mode 100644 index 0000000000..e8c880753e --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListener.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.tri.h12.http1; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.stream.StreamObserver; +import org.apache.dubbo.remoting.http12.HttpChannel; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpInputMessage; +import org.apache.dubbo.remoting.http12.RequestMetadata; +import org.apache.dubbo.remoting.http12.h1.Http1ServerChannelObserver; +import org.apache.dubbo.remoting.http12.h1.Http1ServerStreamChannelObserver; +import org.apache.dubbo.remoting.http12.h1.Http1ServerTransportListener; +import org.apache.dubbo.remoting.http12.message.DefaultListeningDecoder; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.remoting.http12.message.ListeningDecoder; +import org.apache.dubbo.remoting.http12.message.MediaType; +import org.apache.dubbo.remoting.http12.message.MethodMetadata; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.MethodDescriptor; +import org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener; +import org.apache.dubbo.rpc.protocol.tri.h12.DefaultHttpMessageListener; +import org.apache.dubbo.rpc.protocol.tri.h12.HttpMessageListener; +import org.apache.dubbo.rpc.protocol.tri.h12.ServerCallListener; +import org.apache.dubbo.rpc.protocol.tri.h12.ServerStreamServerCallListener; +import org.apache.dubbo.rpc.protocol.tri.h12.UnaryServerCallListener; + +public class DefaultHttp11ServerTransportListener extends AbstractServerTransportListener implements Http1ServerTransportListener { + + private final HttpChannel httpChannel; + + private final URL url; + + public DefaultHttp11ServerTransportListener(HttpChannel httpChannel, URL url, FrameworkModel frameworkModel) { + super(frameworkModel, url, httpChannel); + this.url = url; + this.httpChannel = httpChannel; + } + + private ServerCallListener startListener(RpcInvocation invocation, + MethodDescriptor methodDescriptor, + Invoker invoker) { + switch (methodDescriptor.getRpcType()) { + case UNARY: + Http1ServerChannelObserver http1ChannelObserver = new Http1ServerChannelObserver(httpChannel); + http1ChannelObserver.setHttpMessageCodec(getHttpMessageCodec()); + return new AutoCompleteUnaryServerCallListener(invocation, invoker, http1ChannelObserver); + case SERVER_STREAM: + Http1ServerChannelObserver serverStreamChannelObserver = new Http1ServerStreamChannelObserver(httpChannel); + serverStreamChannelObserver.setHttpMessageCodec(getHttpMessageCodec()); + serverStreamChannelObserver.setHeadersCustomizer((headers) -> headers.set(HttpHeaderNames.CONTENT_TYPE.getName(), MediaType.TEXT_EVENT_STREAM_VALUE.getName())); + return new AutoCompleteServerStreamServerCallListener(invocation, invoker, serverStreamChannelObserver); + default: + throw new UnsupportedOperationException("HTTP1.x only support unary and server-stream"); + } + } + + @Override + protected HttpMessageListener newHttpMessageListener() { + RequestMetadata httpMetadata = getHttpMetadata(); + String path = httpMetadata.path(); + String[] parts = path.split("/"); + String originalMethodName = parts[2]; + boolean hasStub = getPathResolver().hasNativeStub(path); + MethodDescriptor methodDescriptor = findMethodDescriptor(getServiceDescriptor(), originalMethodName, hasStub); + MethodMetadata methodMetadata = MethodMetadata.fromMethodDescriptor(methodDescriptor); + RpcInvocation rpcInvocation = buildRpcInvocation(getInvoker(), getServiceDescriptor(), methodDescriptor); + setRpcInvocation(rpcInvocation); + HttpMessageCodec httpMessageCodec = getHttpMessageCodec(); + ListeningDecoder listeningDecoder = newListeningDecoder(httpMessageCodec, methodMetadata.getActualRequestTypes()); + return new DefaultHttpMessageListener(listeningDecoder); + } + + private ListeningDecoder newListeningDecoder(HttpMessageCodec codec, Class[] actualRequestTypes) { + DefaultListeningDecoder defaultListeningDecoder = new DefaultListeningDecoder(codec, actualRequestTypes); + ServerCallListener serverCallListener = startListener(getRpcInvocation(), getMethodDescriptor(), getInvoker()); + defaultListeningDecoder.setListener(serverCallListener::onMessage); + return defaultListeningDecoder; + } + + private static class AutoCompleteUnaryServerCallListener extends UnaryServerCallListener { + + public AutoCompleteUnaryServerCallListener(RpcInvocation invocation, Invoker invoker, StreamObserver responseObserver) { + super(invocation, invoker, responseObserver); + } + + @Override + public void onMessage(Object message) { + super.onMessage(message); + super.onComplete(); + } + } + + private static class AutoCompleteServerStreamServerCallListener extends ServerStreamServerCallListener { + + public AutoCompleteServerStreamServerCallListener(RpcInvocation invocation, Invoker invoker, StreamObserver responseObserver) { + super(invocation, invoker, responseObserver); + } + + @Override + public void onMessage(Object message) { + super.onMessage(message); + super.onComplete(); + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListenerFactory.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListenerFactory.java new file mode 100644 index 0000000000..cddeb4182e --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListenerFactory.java @@ -0,0 +1,33 @@ +/* + * 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.tri.h12.http1; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.http12.HttpChannel; +import org.apache.dubbo.remoting.http12.h1.Http1ServerTransportListener; +import org.apache.dubbo.remoting.http12.h1.Http1ServerTransportListenerFactory; +import org.apache.dubbo.rpc.model.FrameworkModel; + +public class DefaultHttp11ServerTransportListenerFactory implements Http1ServerTransportListenerFactory { + + public static final Http1ServerTransportListenerFactory INSTANCE = new DefaultHttp11ServerTransportListenerFactory(); + + @Override + public Http1ServerTransportListener newInstance(HttpChannel httpChannel, URL url, FrameworkModel frameworkModel) { + return new DefaultHttp11ServerTransportListener(httpChannel, url, frameworkModel); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListener.java new file mode 100644 index 0000000000..8c325fab2a --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListener.java @@ -0,0 +1,223 @@ +/* + * 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.tri.h12.http2; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; +import org.apache.dubbo.common.threadpool.serial.SerializingExecutor; +import org.apache.dubbo.remoting.http12.RequestMetadata; +import org.apache.dubbo.remoting.http12.exception.HttpStatusException; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2Header; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2ServerChannelObserver; +import org.apache.dubbo.remoting.http12.h2.Http2TransportListener; +import org.apache.dubbo.remoting.http12.message.DefaultListeningDecoder; +import org.apache.dubbo.remoting.http12.message.JsonCodec; +import org.apache.dubbo.remoting.http12.message.LengthFieldStreamingDecoder; +import org.apache.dubbo.remoting.http12.message.ListeningDecoder; +import org.apache.dubbo.remoting.http12.message.MethodMetadata; +import org.apache.dubbo.remoting.http12.message.StreamingDecoder; +import org.apache.dubbo.rpc.CancellationContext; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.executor.ExecutorSupport; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.MethodDescriptor; +import org.apache.dubbo.rpc.protocol.tri.ReflectionPackableMethod; +import org.apache.dubbo.rpc.protocol.tri.h12.AbstractServerTransportListener; +import org.apache.dubbo.rpc.protocol.tri.h12.BiStreamServerCallListener; +import org.apache.dubbo.rpc.protocol.tri.h12.HttpMessageListener; +import org.apache.dubbo.rpc.protocol.tri.h12.ServerCallListener; +import org.apache.dubbo.rpc.protocol.tri.h12.ServerStreamServerCallListener; +import org.apache.dubbo.rpc.protocol.tri.h12.UnaryServerCallListener; +import org.apache.dubbo.rpc.protocol.tri.h12.grpc.StreamingHttpMessageListener; + +import java.util.concurrent.Executor; + +public class GenericHttp2ServerTransportListener extends AbstractServerTransportListener implements Http2TransportListener { + + private final Http2ServerChannelObserver serverChannelObserver; + + private final H2StreamChannel h2StreamChannel; + + private final ExecutorSupport executorSupport; + + private final StreamingDecoder streamingDecoder; + + private ServerCallListener serverCallListener; + + public GenericHttp2ServerTransportListener(H2StreamChannel h2StreamChannel, URL url, FrameworkModel frameworkModel) { + super(frameworkModel, url, h2StreamChannel); + this.h2StreamChannel = h2StreamChannel; + this.executorSupport = ExecutorRepository.getInstance(url.getOrDefaultApplicationModel()).getExecutorSupport(url); + this.streamingDecoder = newStreamingDecoder(); + this.serverChannelObserver = new Http2ServerCallToObserverAdapter(frameworkModel, h2StreamChannel); + this.serverChannelObserver.setHttpMessageCodec(JsonCodec.INSTANCE); + this.serverChannelObserver.setStreamingDecoder(streamingDecoder); + } + + @Override + protected Executor initializeExecutor(Http2Header metadata) { + Executor executor = executorSupport.getExecutor(metadata); + return new SerializingExecutor(executor); + } + + private ServerCallListener startListener(RpcInvocation invocation, + MethodDescriptor methodDescriptor, + Invoker invoker) { + Http2ServerChannelObserver responseObserver = getServerChannelObserver(); + CancellationContext cancellationContext = RpcContext.getCancellationContext(); + responseObserver.setCancellationContext(cancellationContext); + switch (methodDescriptor.getRpcType()) { + case UNARY: + Http2Header httpMetadata = getHttpMetadata(); + boolean hasStub = getPathResolver().hasNativeStub(httpMetadata.path()); + boolean applyCustomizeException = false; + if (!hasStub) { + applyCustomizeException = ReflectionPackableMethod.needWrap(methodDescriptor, getMethodMetadata().getActualRequestTypes(), getMethodMetadata().getActualResponseType()); + } + UnaryServerCallListener unaryServerCallListener = startUnary(invocation, invoker, responseObserver); + unaryServerCallListener.setApplyCustomizeException(applyCustomizeException); + return unaryServerCallListener; + case SERVER_STREAM: + return startServerStreaming(invocation, invoker, responseObserver); + case BI_STREAM: + case CLIENT_STREAM: + return startBiStreaming(invocation, invoker, responseObserver); + default: + throw new IllegalStateException("Can not reach here"); + } + } + + public Http2ServerChannelObserver getServerChannelObserver() { + return serverChannelObserver; + } + + @Override + public void cancelByRemote(long errorCode) { + this.serverChannelObserver.cancel(new HttpStatusException((int) errorCode)); + this.serverCallListener.onCancel(errorCode); + } + + protected StreamingDecoder newStreamingDecoder() { + //default lengthFieldLength = 4 + return new LengthFieldStreamingDecoder(); + } + + protected void doOnMetadata(Http2Header metadata) { + if (metadata.isEndStream()) { + return; + } + super.doOnMetadata(metadata); + } + + @Override + protected HttpMessageListener newHttpMessageListener() { + RequestMetadata httpMetadata = getHttpMetadata(); + String path = httpMetadata.path(); + String[] parts = path.split("/"); + String originalMethodName = parts[2]; + MethodDescriptor methodDescriptor = getMethodDescriptor(); + if (methodDescriptor == null) { + methodDescriptor = findMethodDescriptor(getServiceDescriptor(), originalMethodName, isHasStub()); + setMethodDescriptor(methodDescriptor); + } + MethodMetadata methodMetadata = getMethodMetadata(); + if (methodMetadata == null) { + methodMetadata = MethodMetadata.fromMethodDescriptor(getMethodDescriptor()); + setMethodMetadata(methodMetadata); + } + RpcInvocation rpcInvocation = getRpcInvocation(); + if (rpcInvocation == null) { + setRpcInvocation(buildRpcInvocation(getInvoker(), getServiceDescriptor(), methodDescriptor)); + } + initializeServerCallListener(); + DefaultListeningDecoder defaultListeningDecoder = new DefaultListeningDecoder(getHttpMessageCodec(), getMethodMetadata().getActualRequestTypes()); + defaultListeningDecoder.setListener(new Http2StreamingDecodeListener(serverCallListener)); + streamingDecoder.setFragmentListener(new StreamingDecoder.DefaultFragmentListener(defaultListeningDecoder)); + getServerChannelObserver().setStreamingDecoder(streamingDecoder); + return new StreamingHttpMessageListener(streamingDecoder); + } + + @Override + protected void onMetadataCompletion(Http2Header metadata) { + super.onMetadataCompletion(metadata); + this.serverChannelObserver.setHttpMessageCodec(getHttpMessageCodec()); + this.serverChannelObserver.request(1); + } + + @Override + protected void onDataCompletion(Http2InputMessage message) { + if (message.isEndStream()) { + serverCallListener.onComplete(); + } + } + + @Override + protected void onError(Throwable throwable) { + serverChannelObserver.onError(throwable); + } + + protected StreamingDecoder getStreamingDecoder() { + return this.streamingDecoder; + } + + private static class Http2StreamingDecodeListener implements ListeningDecoder.Listener { + + private final ServerCallListener serverCallListener; + + private Http2StreamingDecodeListener(ServerCallListener serverCallListener) { + this.serverCallListener = serverCallListener; + } + + @Override + public void onMessage(Object message) { + this.serverCallListener.onMessage(message); + } + + @Override + public void onClose() { + this.serverCallListener.onComplete(); + } + } + + private void initializeServerCallListener() { + if (serverCallListener == null) { + this.serverCallListener = startListener(getRpcInvocation(), getMethodDescriptor(), getInvoker()); + } + } + + private UnaryServerCallListener startUnary(RpcInvocation invocation, + Invoker invoker, + Http2ServerChannelObserver responseObserver) { + return new UnaryServerCallListener(invocation, invoker, responseObserver); + } + + private ServerStreamServerCallListener startServerStreaming(RpcInvocation invocation, Invoker invoker, Http2ServerChannelObserver responseObserver) { + return new ServerStreamServerCallListener(invocation, invoker, responseObserver); + } + + private BiStreamServerCallListener startBiStreaming(RpcInvocation invocation, Invoker invoker, Http2ServerChannelObserver responseObserver) { + return new BiStreamServerCallListener(invocation, invoker, responseObserver); + } + + protected ServerCallListener getServerCallListener() { + return serverCallListener; + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListenerFactory.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListenerFactory.java new file mode 100644 index 0000000000..f6e6841311 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListenerFactory.java @@ -0,0 +1,40 @@ +/* + * 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.tri.h12.http2; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory; +import org.apache.dubbo.remoting.http12.h2.Http2TransportListener; +import org.apache.dubbo.rpc.model.FrameworkModel; + +public class GenericHttp2ServerTransportListenerFactory implements Http2ServerTransportListenerFactory { + + public static final Http2ServerTransportListenerFactory INSTANCE = new GenericHttp2ServerTransportListenerFactory(); + + @Override + public Http2TransportListener newInstance(H2StreamChannel streamChannel, + URL url, + FrameworkModel frameworkModel) { + return new GenericHttp2ServerTransportListener(streamChannel, url, frameworkModel); + } + + @Override + public boolean supportContentType(String contentType) { + return true; + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerCallToObserverAdapter.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerCallToObserverAdapter.java new file mode 100644 index 0000000000..932f94563b --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerCallToObserverAdapter.java @@ -0,0 +1,40 @@ +/* + * 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.tri.h12.http2; + +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.protocol.tri.h12.ServerCallToObserverAdapter; + +public class Http2ServerCallToObserverAdapter extends Http2ServerStreamObserver implements ServerCallToObserverAdapter { + + private int exceptionCode; + + public Http2ServerCallToObserverAdapter(FrameworkModel frameworkModel, H2StreamChannel h2StreamChannel) { + super(frameworkModel, h2StreamChannel); + setHeadersCustomizer((headers) -> { + if (exceptionCode != 0) { + headers.set("tri-exception-code", String.valueOf(exceptionCode)); + } + }); + } + + @Override + public void setExceptionCode(int exceptionCode) { + this.exceptionCode = exceptionCode; + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerStreamObserver.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerStreamObserver.java new file mode 100644 index 0000000000..03dab446f3 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/Http2ServerStreamObserver.java @@ -0,0 +1,77 @@ +/* + * 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.tri.h12.http2; + +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2ServerChannelObserver; +import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.protocol.tri.ServerStreamObserver; +import org.apache.dubbo.rpc.protocol.tri.TripleProtocol; +import org.apache.dubbo.rpc.protocol.tri.compressor.Compressor; +import org.apache.dubbo.rpc.protocol.tri.h12.AttachmentHolder; +import org.apache.dubbo.rpc.protocol.tri.h12.CompressibleCodec; +import org.apache.dubbo.rpc.protocol.tri.stream.StreamUtils; + +import java.util.Map; + +public class Http2ServerStreamObserver extends Http2ServerChannelObserver implements ServerStreamObserver, AttachmentHolder { + + private final FrameworkModel frameworkModel; + + private HttpMessageCodec httpMessageCodec; + + private Map attachments; + + public Http2ServerStreamObserver(FrameworkModel frameworkModel, H2StreamChannel h2StreamChannel) { + super(h2StreamChannel); + this.frameworkModel = frameworkModel; + } + + @Override + public void setCompression(String compression) { + CompressibleCodec compressibleCodec = new CompressibleCodec(httpMessageCodec); + compressibleCodec.setCompressor(Compressor.getCompressor(frameworkModel, compression)); + super.setHttpMessageCodec(compressibleCodec); + } + + @Override + public void setHttpMessageCodec(HttpMessageCodec httpMessageCodec) { + super.setHttpMessageCodec(httpMessageCodec); + this.httpMessageCodec = httpMessageCodec; + } + + @Override + public void setResponseAttachments(Map attachments) { + this.attachments = attachments; + } + + @Override + public Map getResponseAttachments() { + return this.attachments; + } + + @Override + protected HttpMetadata encodeTrailers(Throwable throwable) { + HttpMetadata httpMetadata = super.encodeTrailers(throwable); + HttpHeaders headers = httpMetadata.headers(); + StreamUtils.convertAttachment(headers, attachments, TripleProtocol.CONVERT_NO_LOWER_HEADER); + return httpMetadata; + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/stream/StreamUtils.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/stream/StreamUtils.java index 07def88303..8df63eab78 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/stream/StreamUtils.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/stream/StreamUtils.java @@ -17,16 +17,16 @@ package org.apache.dubbo.rpc.protocol.tri.stream; +import io.netty.handler.codec.http2.DefaultHttp2Headers; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.JsonUtils; import org.apache.dubbo.common.utils.LRU2Cache; +import org.apache.dubbo.remoting.http12.HttpHeaders; import org.apache.dubbo.rpc.TriRpcStatus; import org.apache.dubbo.rpc.protocol.tri.TripleConstant; import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum; -import io.netty.handler.codec.http2.DefaultHttp2Headers; - import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.Collections; @@ -115,6 +115,38 @@ public class StreamUtils { } } + public static void convertAttachment(HttpHeaders headers, + Map attachments, + boolean needConvertHeaderKey) { + if (attachments == null) { + return; + } + Map needConvertKey = new HashMap<>(); + for (Map.Entry entry : attachments.entrySet()) { + String key = lruHeaderMap.get(entry.getKey()); + if (key == null) { + final String lowerCaseKey = entry.getKey().toLowerCase(Locale.ROOT); + lruHeaderMap.put(entry.getKey(), lowerCaseKey); + key = lowerCaseKey; + } + if (TripleHeaderEnum.containsExcludeAttachments(key)) { + continue; + } + final Object v = entry.getValue(); + if (v == null) { + continue; + } + if (needConvertHeaderKey && !key.equals(entry.getKey())) { + needConvertKey.put(key, entry.getKey()); + } + convertSingleAttachment(headers, key, v); + } + if (!needConvertKey.isEmpty()) { + String needConvertJson = JsonUtils.toJson(needConvertKey); + headers.set(TripleHeaderEnum.TRI_HEADER_CONVERT.getHeader(), TriRpcStatus.encodeMessage(needConvertJson)); + } + } + public static void convertAttachment(DefaultHttp2Headers headers, Map attachments) { @@ -145,5 +177,22 @@ public class StreamUtils { } } + private static void convertSingleAttachment(HttpHeaders headers, String key, Object v) { + try { + if (v instanceof String || v instanceof Number || v instanceof Boolean) { + String str = v.toString(); + headers.set(key, str); + } else if (v instanceof byte[]) { + String str = encodeBase64ASCII((byte[]) v); + headers.set(key + TripleConstant.HEADER_BIN_SUFFIX, str); + } else { + LOGGER.warn(PROTOCOL_UNSUPPORTED, "", "", "Unsupported attachment k: " + key + " class: " + v.getClass().getName()); + } + } catch (Throwable t) { + LOGGER.warn(PROTOCOL_UNSUPPORTED, "", "", "Meet exception when convert single attachment key:" + key + " value=" + v, + t); + } + } + } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/transport/TripleIsolationExecutorSupport.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/transport/TripleIsolationExecutorSupport.java index a2f08ee9f5..a00de30f5a 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/transport/TripleIsolationExecutorSupport.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/transport/TripleIsolationExecutorSupport.java @@ -20,10 +20,11 @@ import org.apache.dubbo.common.ServiceKey; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.h2.Http2Header; import org.apache.dubbo.rpc.executor.AbstractIsolationExecutorSupport; import org.apache.dubbo.rpc.protocol.tri.TripleHeaderEnum; -import io.netty.handler.codec.http2.Http2Headers; public class TripleIsolationExecutorSupport extends AbstractIsolationExecutorSupport { private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(TripleIsolationExecutorSupport.class); @@ -34,18 +35,19 @@ public class TripleIsolationExecutorSupport extends AbstractIsolationExecutorSup @Override protected ServiceKey getServiceKey(Object data) { - if (!(data instanceof Http2Headers)) { + if (!(data instanceof Http2Header)) { return null; } - Http2Headers headers = (Http2Headers) data; - String path = headers.path().toString(); + Http2Header http2Metadata = (Http2Header) data; + HttpHeaders headers = http2Metadata.headers(); + String path = http2Metadata.path(); String[] parts = path.split("/"); // path like /{interfaceName}/{methodName} String interfaceName = parts[1]; - String version = headers.contains(TripleHeaderEnum.SERVICE_VERSION.getHeader()) ? - headers.get(TripleHeaderEnum.SERVICE_VERSION.getHeader()).toString() : null; - String group = headers.contains(TripleHeaderEnum.SERVICE_GROUP.getHeader()) ? - headers.get(TripleHeaderEnum.SERVICE_GROUP.getHeader()).toString() : null; + String version = headers.containsKey(TripleHeaderEnum.SERVICE_VERSION.getHeader()) ? + headers.getFirst(TripleHeaderEnum.SERVICE_VERSION.getHeader()) : null; + String group = headers.containsKey(TripleHeaderEnum.SERVICE_GROUP.getHeader()) ? + headers.getFirst(TripleHeaderEnum.SERVICE_GROUP.getHeader()) : null; return new ServiceKey(interfaceName, version, group); } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/transport/TripleServerConnectionHandler.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/transport/TripleServerConnectionHandler.java index 9703cb287b..5750470384 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/transport/TripleServerConnectionHandler.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/transport/TripleServerConnectionHandler.java @@ -17,17 +17,16 @@ package org.apache.dubbo.rpc.protocol.tri.transport; -import io.netty.handler.codec.http2.DefaultHttp2ResetFrame; -import io.netty.handler.codec.http2.Http2Error; -import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; -import org.apache.dubbo.common.logger.LoggerFactory; - import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http2.DefaultHttp2ResetFrame; import io.netty.handler.codec.http2.Http2ChannelDuplexHandler; +import io.netty.handler.codec.http2.Http2Error; import io.netty.handler.codec.http2.Http2GoAwayFrame; import io.netty.handler.codec.http2.Http2PingFrame; import io.netty.util.ReferenceCountUtil; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; import java.io.IOException; import java.net.SocketException; @@ -74,6 +73,10 @@ public class TripleServerConnectionHandler extends Http2ChannelDuplexHandler { super.channelInactive(ctx); //reset all active stream on connection close forEachActiveStream(stream -> { + //ignore remote side close + if (!stream.state().remoteSideOpen()) { + return true; + } DefaultHttp2ResetFrame resetFrame = new DefaultHttp2ResetFrame(Http2Error.NO_ERROR).stream(stream); ctx.fireChannelRead(resetFrame); return true; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory new file mode 100644 index 0000000000..1ea7a85f72 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory @@ -0,0 +1 @@ +grpc=org.apache.dubbo.rpc.protocol.tri.h12.grpc.GrpcHttp2ServerTransportListenerFactory diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec new file mode 100644 index 0000000000..388cbd7e3e --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec @@ -0,0 +1,2 @@ +grpc=org.apache.dubbo.rpc.protocol.tri.h12.grpc.GrpcCompositeCodec +protobuf=org.apache.dubbo.rpc.protocol.tri.h12.grpc.ProtobufHttpMessageCodec diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory new file mode 100644 index 0000000000..39350a2c21 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory @@ -0,0 +1 @@ +grpc=org.apache.dubbo.rpc.protocol.tri.h12.grpc.GrpcCompositeCodecFactory diff --git a/dubbo-test/dubbo-dependencies-all/pom.xml b/dubbo-test/dubbo-dependencies-all/pom.xml index 2a5f1a3e1d..84ce1ca939 100644 --- a/dubbo-test/dubbo-dependencies-all/pom.xml +++ b/dubbo-test/dubbo-dependencies-all/pom.xml @@ -411,6 +411,11 @@ dubbo-remoting-http ${project.version} + + org.apache.dubbo + dubbo-remoting-http12 + ${project.version} + org.apache.dubbo dubbo-remoting-netty From cfd0be3a3a542269ad080ede13deae6ac6745f55 Mon Sep 17 00:00:00 2001 From: icodening Date: Fri, 1 Sep 2023 17:05:45 +0800 Subject: [PATCH 07/14] fix h1 and grpc status code (#12994) --- .../remoting/http12/AbstractServerHttpChannelObserver.java | 3 +++ .../protocol/tri/h12/AbstractServerTransportListener.java | 2 +- .../tri/h12/grpc/GrpcHttp2ServerTransportListener.java | 7 +++++++ .../h12/http1/DefaultHttp11ServerTransportListener.java | 2 ++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java index 3e0b2a9b75..adc23ec718 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.remoting.http12; +import org.apache.dubbo.remoting.http12.exception.EncodeException; import org.apache.dubbo.remoting.http12.exception.HttpStatusException; import org.apache.dubbo.remoting.http12.message.HttpMessageCodec; @@ -119,6 +120,8 @@ public abstract class AbstractServerHttpChannelObserver implements CustomizableH HttpOutputMessage httpOutputMessage = encodeHttpOutputMessage(errorResponse); this.httpMessageCodec.encode(httpOutputMessage.getBody(), errorResponse); getHttpChannel().writeMessage(httpOutputMessage); + } catch (Throwable ex) { + throwable = new EncodeException(ex); } finally { doOnCompleted(throwable); } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java index a294d61e2a..1e442d1e5c 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java @@ -161,7 +161,7 @@ public abstract class AbstractServerTransportListener
invoker, ServiceDescriptor serviceDescriptor, MethodDescriptor methodDescriptor) { RpcInvocation rpcInvocation = super.buildRpcInvocation(invoker, serviceDescriptor, methodDescriptor); diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListener.java index e8c880753e..c7d34b1a87 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListener.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListener.java @@ -81,6 +81,8 @@ public class DefaultHttp11ServerTransportListener extends AbstractServerTranspor MethodDescriptor methodDescriptor = findMethodDescriptor(getServiceDescriptor(), originalMethodName, hasStub); MethodMetadata methodMetadata = MethodMetadata.fromMethodDescriptor(methodDescriptor); RpcInvocation rpcInvocation = buildRpcInvocation(getInvoker(), getServiceDescriptor(), methodDescriptor); + setMethodDescriptor(methodDescriptor); + setMethodMetadata(methodMetadata); setRpcInvocation(rpcInvocation); HttpMessageCodec httpMessageCodec = getHttpMessageCodec(); ListeningDecoder listeningDecoder = newListeningDecoder(httpMessageCodec, methodMetadata.getActualRequestTypes()); From fe2af7e35491564ecbe67127740d879693fe15c9 Mon Sep 17 00:00:00 2001 From: icodening Date: Fri, 1 Sep 2023 17:16:41 +0800 Subject: [PATCH 08/14] fix h2 curl error --- .../http12/message/NoOpStreamingDecoder.java | 46 +++++++++++++++++++ .../GenericHttp2ServerTransportListener.java | 6 +-- 2 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/NoOpStreamingDecoder.java diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/NoOpStreamingDecoder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/NoOpStreamingDecoder.java new file mode 100644 index 0000000000..60e2909b83 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/NoOpStreamingDecoder.java @@ -0,0 +1,46 @@ +/* + * 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.remoting.http12.message; + +import org.apache.dubbo.remoting.http12.exception.DecodeException; + +import java.io.InputStream; + +public class NoOpStreamingDecoder implements StreamingDecoder { + + private FragmentListener listener; + + @Override + public void request(int numMessages) { + // do nothing + } + + @Override + public void decode(InputStream inputStream) throws DecodeException { + listener.onFragmentMessage(inputStream); + } + + @Override + public void close() { + this.listener.onClose(); + } + + @Override + public void setFragmentListener(FragmentListener listener) { + this.listener = listener; + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListener.java index 8c325fab2a..bb09853da2 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListener.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http2/GenericHttp2ServerTransportListener.java @@ -28,9 +28,9 @@ import org.apache.dubbo.remoting.http12.h2.Http2ServerChannelObserver; import org.apache.dubbo.remoting.http12.h2.Http2TransportListener; import org.apache.dubbo.remoting.http12.message.DefaultListeningDecoder; import org.apache.dubbo.remoting.http12.message.JsonCodec; -import org.apache.dubbo.remoting.http12.message.LengthFieldStreamingDecoder; import org.apache.dubbo.remoting.http12.message.ListeningDecoder; import org.apache.dubbo.remoting.http12.message.MethodMetadata; +import org.apache.dubbo.remoting.http12.message.NoOpStreamingDecoder; import org.apache.dubbo.remoting.http12.message.StreamingDecoder; import org.apache.dubbo.rpc.CancellationContext; import org.apache.dubbo.rpc.Invoker; @@ -116,8 +116,8 @@ public class GenericHttp2ServerTransportListener extends AbstractServerTransport } protected StreamingDecoder newStreamingDecoder() { - //default lengthFieldLength = 4 - return new LengthFieldStreamingDecoder(); + //default no op + return new NoOpStreamingDecoder(); } protected void doOnMetadata(Http2Header metadata) { From d596eeb1514c14cc2e0d0031a19e49b15132eac9 Mon Sep 17 00:00:00 2001 From: icodening Date: Sat, 2 Sep 2023 10:48:41 +0800 Subject: [PATCH 09/14] Add protobuf json format support for triple (#12996) --- dubbo-remoting/dubbo-remoting-http12/pom.xml | 4 ++ .../remoting/http12/message/JsonCodec.java | 20 ++++++++ .../http12/message/NoOpStreamingDecoder.java | 46 +++++++++++++++++++ .../h12/AbstractServerTransportListener.java | 4 ++ .../GenericHttp2ServerTransportListener.java | 6 +-- 5 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/NoOpStreamingDecoder.java diff --git a/dubbo-remoting/dubbo-remoting-http12/pom.xml b/dubbo-remoting/dubbo-remoting-http12/pom.xml index 514786699c..ad702991e9 100644 --- a/dubbo-remoting/dubbo-remoting-http12/pom.xml +++ b/dubbo-remoting/dubbo-remoting-http12/pom.xml @@ -46,6 +46,10 @@ dubbo-remoting-api ${project.parent.version} + + com.google.protobuf + protobuf-java-util + io.netty diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java index fb6a6f6faa..819de6f420 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java @@ -17,8 +17,11 @@ package org.apache.dubbo.remoting.http12.message; import com.alibaba.fastjson2.JSONObject; +import com.google.protobuf.Message; +import com.google.protobuf.util.JsonFormat; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.common.utils.JsonUtils; +import org.apache.dubbo.common.utils.MethodUtils; import org.apache.dubbo.remoting.http12.exception.DecodeException; import org.apache.dubbo.remoting.http12.exception.EncodeException; @@ -45,6 +48,11 @@ public class JsonCodec implements HttpMessageCodec { public void encode(OutputStream outputStream, Object unSerializedBody) throws EncodeException { try { try { + if (unSerializedBody instanceof Message) { + String jsonString = JsonFormat.printer().print((Message) unSerializedBody); + outputStream.write(jsonString.getBytes(StandardCharsets.UTF_8)); + return; + } String jsonString = JsonUtils.toJson(unSerializedBody); outputStream.write(jsonString.getBytes(StandardCharsets.UTF_8)); } finally { @@ -79,6 +87,11 @@ public class JsonCodec implements HttpMessageCodec { while ((len = body.read(data)) != -1) { builder.append(new String(data, 0, len)); } + if (isProtobuf(targetType)) { + Message.Builder newBuilder = (Message.Builder) MethodUtils.findMethod(targetType, "newBuilder").invoke(null); + JsonFormat.parser().ignoringUnknownFields().merge(builder.toString(), newBuilder); + return newBuilder.build(); + } return JsonUtils.toJavaObject(builder.toString(), targetType); } finally { body.close(); @@ -124,4 +137,11 @@ public class JsonCodec implements HttpMessageCodec { } } + private boolean isProtobuf(Class targetType) { + if (targetType == null) { + return false; + } + return Message.class.isAssignableFrom(targetType); + } + } diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/NoOpStreamingDecoder.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/NoOpStreamingDecoder.java new file mode 100644 index 0000000000..60e2909b83 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/NoOpStreamingDecoder.java @@ -0,0 +1,46 @@ +/* + * 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.remoting.http12.message; + +import org.apache.dubbo.remoting.http12.exception.DecodeException; + +import java.io.InputStream; + +public class NoOpStreamingDecoder implements StreamingDecoder { + + private FragmentListener listener; + + @Override + public void request(int numMessages) { + // do nothing + } + + @Override + public void decode(InputStream inputStream) throws DecodeException { + listener.onFragmentMessage(inputStream); + } + + @Override + public void close() { + this.listener.onClose(); + } + + @Override + public void setFragmentListener(FragmentListener listener) { + this.listener = listener; + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java index 1e442d1e5c..a80785ab13 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java @@ -118,10 +118,12 @@ public abstract class AbstractServerTransportListener
Date: Mon, 4 Sep 2023 10:53:51 +0800 Subject: [PATCH 10/14] fix pb class not found (#12997) --- .../remoting/http12/message/JsonCodec.java | 21 ---- .../http12/message/JsonCodecFactory.java | 2 + .../remoting/http12/message/JsonPbCodec.java | 101 ++++++++++++++++++ .../http12/message/JsonPbCodecFactory.java | 44 ++++++++ ...ing.http12.message.HttpMessageCodecFactory | 1 + 5 files changed, 148 insertions(+), 21 deletions(-) create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodec.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodecFactory.java diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java index 819de6f420..5ee8dfb13e 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java @@ -17,11 +17,8 @@ package org.apache.dubbo.remoting.http12.message; import com.alibaba.fastjson2.JSONObject; -import com.google.protobuf.Message; -import com.google.protobuf.util.JsonFormat; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.common.utils.JsonUtils; -import org.apache.dubbo.common.utils.MethodUtils; import org.apache.dubbo.remoting.http12.exception.DecodeException; import org.apache.dubbo.remoting.http12.exception.EncodeException; @@ -48,11 +45,6 @@ public class JsonCodec implements HttpMessageCodec { public void encode(OutputStream outputStream, Object unSerializedBody) throws EncodeException { try { try { - if (unSerializedBody instanceof Message) { - String jsonString = JsonFormat.printer().print((Message) unSerializedBody); - outputStream.write(jsonString.getBytes(StandardCharsets.UTF_8)); - return; - } String jsonString = JsonUtils.toJson(unSerializedBody); outputStream.write(jsonString.getBytes(StandardCharsets.UTF_8)); } finally { @@ -87,11 +79,6 @@ public class JsonCodec implements HttpMessageCodec { while ((len = body.read(data)) != -1) { builder.append(new String(data, 0, len)); } - if (isProtobuf(targetType)) { - Message.Builder newBuilder = (Message.Builder) MethodUtils.findMethod(targetType, "newBuilder").invoke(null); - JsonFormat.parser().ignoringUnknownFields().merge(builder.toString(), newBuilder); - return newBuilder.build(); - } return JsonUtils.toJavaObject(builder.toString(), targetType); } finally { body.close(); @@ -136,12 +123,4 @@ public class JsonCodec implements HttpMessageCodec { throw new DecodeException(e); } } - - private boolean isProtobuf(Class targetType) { - if (targetType == null) { - return false; - } - return Message.class.isAssignableFrom(targetType); - } - } diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodecFactory.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodecFactory.java index 8f7d2f356c..64a7cd2f55 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodecFactory.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodecFactory.java @@ -23,6 +23,8 @@ import org.apache.dubbo.rpc.model.FrameworkModel; @Activate public class JsonCodecFactory implements HttpMessageCodecFactory { + public static final String NAME = "json"; + @Override public HttpMessageCodec createCodec(URL url, FrameworkModel frameworkModel) { return new JsonCodec(); diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodec.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodec.java new file mode 100644 index 0000000000..4ade704e97 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodec.java @@ -0,0 +1,101 @@ +/* + * 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.remoting.http12.message; + +import com.google.protobuf.Message; +import com.google.protobuf.util.JsonFormat; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.utils.ClassUtils; +import org.apache.dubbo.common.utils.MethodUtils; +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.exception.EncodeException; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +@Activate +public class JsonPbCodec implements HttpMessageCodec { + + private HttpMessageCodec jsonCodec; + + public void setJsonCodec(HttpMessageCodec jsonCodec) { + this.jsonCodec = jsonCodec; + } + + @Override + public MediaType contentType() { + return jsonCodec.contentType(); + } + + @Override + public boolean support(String contentType) { + return HttpMessageCodec.super.support(contentType) && ClassUtils.isPresent("com.google.protobuf.Message", getClass().getClassLoader()); + } + + @Override + public void encode(OutputStream outputStream, Object unSerializedBody) throws EncodeException { + try { + if (unSerializedBody instanceof Message) { + String jsonString = JsonFormat.printer().print((Message) unSerializedBody); + outputStream.write(jsonString.getBytes(StandardCharsets.UTF_8)); + return; + } + } catch (IOException e) { + throw new EncodeException(e); + } + jsonCodec.encode(outputStream, unSerializedBody); + } + + @Override + public void encode(OutputStream outputStream, Object[] data) throws EncodeException { + jsonCodec.encode(outputStream, data); + } + + @Override + public Object decode(InputStream body, Class targetType) throws DecodeException { + try { + if (isProtobuf(targetType)) { + int len; + byte[] data = new byte[4096]; + StringBuilder builder = new StringBuilder(4096); + while ((len = body.read(data)) != -1) { + builder.append(new String(data, 0, len)); + } + Message.Builder newBuilder = (Message.Builder) MethodUtils.findMethod(targetType, "newBuilder").invoke(null); + JsonFormat.parser().ignoringUnknownFields().merge(builder.toString(), newBuilder); + return newBuilder.build(); + } + } catch (Throwable e) { + throw new DecodeException(e); + } + return jsonCodec.decode(body, targetType); + } + + @Override + public Object[] decode(InputStream dataInputStream, Class[] targetTypes) throws DecodeException { + return jsonCodec.decode(dataInputStream, targetTypes); + } + + private boolean isProtobuf(Class targetType) { + if (targetType == null) { + return false; + } + return Message.class.isAssignableFrom(targetType); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodecFactory.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodecFactory.java new file mode 100644 index 0000000000..3b7cf19d0a --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodecFactory.java @@ -0,0 +1,44 @@ +/* + * 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.remoting.http12.message; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.utils.ClassUtils; +import org.apache.dubbo.rpc.model.FrameworkModel; + +@Activate(order = -100) +public class JsonPbCodecFactory implements HttpMessageCodecFactory { + + @Override + public HttpMessageCodec createCodec(URL url, FrameworkModel frameworkModel) { + HttpMessageCodec codec = frameworkModel.getExtensionLoader(HttpMessageCodecFactory.class).getExtension(JsonCodecFactory.NAME).createCodec(url, frameworkModel); + JsonPbCodec jsonPbCodec = new JsonPbCodec(); + jsonPbCodec.setJsonCodec(codec); + return jsonPbCodec; + } + + @Override + public MediaType contentType() { + return MediaType.APPLICATION_JSON_VALUE; + } + + @Override + public boolean support(String contentType) { + return HttpMessageCodecFactory.super.support(contentType) && ClassUtils.isPresent("com.google.protobuf.Message", getClass().getClassLoader()); + } +} diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory b/dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory index f72f51f4b6..0fcf5fb19a 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory @@ -1 +1,2 @@ json=org.apache.dubbo.remoting.http12.message.JsonCodecFactory +jsonpb=org.apache.dubbo.remoting.http12.message.JsonPbCodecFactory From 99ba6e30379f89ad6c294767fbeef8afb9b9e02c Mon Sep 17 00:00:00 2001 From: icodening Date: Wed, 6 Sep 2023 21:28:14 +0800 Subject: [PATCH 11/14] Fix hard dependency on protobuf on pojo mode (#13012) --- .../remoting/http12/message/JsonCodec.java | 3 -- .../remoting/http12/message/JsonPbCodec.java | 19 ++++++- .../tri/h12/grpc/GrpcCompositeCodec.java | 54 ++++++++++++++----- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java index 5ee8dfb13e..852e1d0ceb 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java @@ -93,9 +93,6 @@ public class JsonCodec implements HttpMessageCodec { List result = new ArrayList<>(); try { try { - if (targetTypes.length == 1) { - return new Object[]{this.decode(dataInputStream, targetTypes[0])}; - } int len; byte[] data = new byte[4096]; StringBuilder builder = new StringBuilder(4096); diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodec.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodec.java index 4ade704e97..6d7a760b7e 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodec.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodec.java @@ -89,13 +89,30 @@ public class JsonPbCodec implements HttpMessageCodec { @Override public Object[] decode(InputStream dataInputStream, Class[] targetTypes) throws DecodeException { + try { + if (hasProtobuf(targetTypes)) { + //protobuf only support one parameter + return new Object[]{decode(dataInputStream, targetTypes[0])}; + } + } catch (Throwable e) { + throw new DecodeException(e); + } return jsonCodec.decode(dataInputStream, targetTypes); } - private boolean isProtobuf(Class targetType) { + private static boolean isProtobuf(Class targetType) { if (targetType == null) { return false; } return Message.class.isAssignableFrom(targetType); } + + private static boolean hasProtobuf(Class[] classes){ + for (Class clazz : classes) { + if (isProtobuf(clazz)) { + return true; + } + } + return false; + } } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java index 5ff1b1da21..48171cf234 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java @@ -27,6 +27,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import static org.apache.dubbo.common.constants.CommonConstants.PROTOBUF_MESSAGE_CLASS_NAME; + /** * compatible low version. * version < 3.3 @@ -64,11 +66,8 @@ public class GrpcCompositeCodec implements HttpMessageCodec { try { int compressed = 0; outputStream.write(compressed); - if (data instanceof Message) { - int serializedSize = ((Message) data).getSerializedSize(); - //write length - writeLength(outputStream, serializedSize); - protobufHttpMessageCodec.encode(outputStream, data); + if (isProtobuf(data)) { + ProtobufWriter.write(protobufHttpMessageCodec, outputStream, data); return; } //wrapper @@ -80,7 +79,7 @@ public class GrpcCompositeCodec implements HttpMessageCodec { @Override public Object decode(InputStream inputStream, Class targetType) throws DecodeException { - if (isProtobuf(targetType)) { + if (isProtoClass(targetType)) { return protobufHttpMessageCodec.decode(inputStream, targetType); } return wrapperHttpMessageCodec.decode(inputStream, targetType); @@ -94,13 +93,6 @@ public class GrpcCompositeCodec implements HttpMessageCodec { return HttpMessageCodec.super.decode(inputStream, targetTypes); } - private boolean isProtobuf(Class targetType) { - if (targetType == null) { - return false; - } - return Message.class.isAssignableFrom(targetType); - } - private static void writeLength(OutputStream outputStream, int length) { try { outputStream.write(((length >> 24) & 0xFF)); @@ -121,4 +113,40 @@ public class GrpcCompositeCodec implements HttpMessageCodec { public boolean support(String contentType) { return contentType.startsWith(MEDIA_TYPE.getName()); } + + private static boolean isProtobuf(Object data) { + if (data == null) { + return false; + } + return isProtoClass(data.getClass()); + } + + private static boolean isProtoClass(Class clazz) { + while (clazz != Object.class && clazz != null) { + Class[] interfaces = clazz.getInterfaces(); + if (interfaces.length > 0) { + for (Class clazzInterface : interfaces) { + if (PROTOBUF_MESSAGE_CLASS_NAME.equalsIgnoreCase(clazzInterface.getName())) { + return true; + } + } + } + clazz = clazz.getSuperclass(); + } + return false; + } + + /** + * lazy init protobuf class + */ + private static class ProtobufWriter { + + private static void write(HttpMessageCodec codec, OutputStream outputStream, Object data) { + int serializedSize = ((Message) data).getSerializedSize(); + //write length + writeLength(outputStream, serializedSize); + codec.encode(outputStream, data); + } + + } } From cff9bfd1d2901501d9d8ded74fac430edaf0a900 Mon Sep 17 00:00:00 2001 From: Ken Liu Date: Sat, 23 Sep 2023 16:54:00 +0800 Subject: [PATCH 12/14] fix loading process cannot load environment variables. (#13091) --- .../common/config/ConfigurationUtils.java | 4 +-- .../deploy/DefaultApplicationDeployer.java | 25 ++++++++++++------- .../integration/RegistryProtocol.java | 2 +- .../rest/NoAnnotationRestProtocolTest.java | 9 ++++--- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java index 043cdd9e78..ab91c881bb 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java @@ -277,7 +277,7 @@ public final class ConfigurationUtils { for (Map.Entry entry : copy.entrySet()) { String key = entry.getKey(); V val = entry.getValue(); - if (StringUtils.startsWithIgnoreCase(key, prefix) + if ((StringUtils.startsWithIgnoreCase(key, prefix) || StringUtils.startsWithIgnoreCase(key, StringUtils.toOSStyleKey(prefix))) && key.length() > prefix.length() && !ConfigurationUtils.isEmptyValue(val)) { @@ -317,7 +317,7 @@ public final class ConfigurationUtils { } for (Map.Entry entry : copy.entrySet()) { String key = entry.getKey(); - if (StringUtils.startsWithIgnoreCase(key, prefix) + if ((StringUtils.startsWithIgnoreCase(key, prefix) || StringUtils.startsWithIgnoreCase(key, StringUtils.toOSStyleKey(prefix))) && key.length() > prefix.length() && !ConfigurationUtils.isEmptyValue(entry.getValue())) { return true; diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java index 3e194f6557..dad986d200 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultApplicationDeployer.java @@ -187,7 +187,7 @@ public class DefaultApplicationDeployer extends AbstractDeployer applicationOptional = getApplication(); + if (applicationOptional.isPresent()) { + appGroup = applicationOptional.get().getName(); + if (isNotEmpty(appGroup)) { + appConfigFile = isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(); + appConfigContent = dynamicConfiguration.getProperties(appConfigFile, appGroup); + if (StringUtils.isNotEmpty(appConfigContent)) { + logger.info(String.format("Got application specific remote configuration from config center with key %s and group %s: \n %s", appConfigFile, appGroup, appConfigContent)); + } } } try { @@ -1322,9 +1326,12 @@ public class DefaultApplicationDeployer extends AbstractDeployer getApplication() { + return configManager.getApplication(); + } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java index f8d3f72e77..a15f1ad0cf 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java @@ -917,7 +917,7 @@ public class RegistryProtocol implements Protocol, ScopeModelAware { public ProviderConfigurationListener(ModuleModel moduleModel) { super(moduleModel); this.moduleModel = moduleModel; - if (moduleModel.modelEnvironment().getConfiguration().convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true)) { + if (moduleModel.modelEnvironment().getConfiguration().getBoolean(ENABLE_CONFIGURATION_LISTEN, true)) { this.initWith(moduleModel.getApplicationModel().getApplicationName() + CONFIGURATORS_SUFFIX); } } diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/NoAnnotationRestProtocolTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/NoAnnotationRestProtocolTest.java index 3d8ad1b2fe..b7a7b439bf 100644 --- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/NoAnnotationRestProtocolTest.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/NoAnnotationRestProtocolTest.java @@ -21,7 +21,6 @@ import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.JsonUtils; import org.apache.dubbo.common.utils.NetUtils; - import org.apache.dubbo.rpc.Exporter; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Protocol; @@ -31,13 +30,11 @@ import org.apache.dubbo.rpc.model.FrameworkModel; import org.apache.dubbo.rpc.model.ModuleServiceRepository; import org.apache.dubbo.rpc.model.ProviderModel; import org.apache.dubbo.rpc.model.ServiceDescriptor; - import org.apache.dubbo.rpc.protocol.rest.noannotation.NoAnnotationDemoService; import org.apache.dubbo.rpc.protocol.rest.noannotation.NoAnnotationDemoServiceImpl; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; - import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -53,6 +50,12 @@ class NoAnnotationRestProtocolTest { public void tearDown() { protocol.destroy(); FrameworkModel.destroyAll(); + new JsonUtils() { + public void clearJson() { + setJson(null); + } + }.clearJson(); + System.clearProperty(CommonConstants.PREFER_JSON_FRAMEWORK_NAME); } @Test From 7246fad6b5e0a70b54098696da0972238bc1ee5b Mon Sep 17 00:00:00 2001 From: Ken Liu Date: Tue, 26 Sep 2023 16:00:52 +0800 Subject: [PATCH 13/14] fix javadoc compile issue (#13128) --- pom.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 12acffbcd8..d16af112f1 100644 --- a/pom.xml +++ b/pom.xml @@ -464,7 +464,9 @@ ${log4j2_version} - all,-missing + + + none @@ -473,7 +475,7 @@ UTF-8 UTF-8 UTF-8 - ${maven_source_version} + ${java_source_version} http://docs.oracle.com/javase/8/docs/api From 0b2b9f735a35869936c205eca866b4f3c5a0ac3a Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Tue, 26 Sep 2023 16:38:32 +0800 Subject: [PATCH 14/14] Fix conflicts --- .../remoting/transport/netty4/PortUnificationServerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java index 12f3fc8905..21b0c8efa9 100644 --- a/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java +++ b/dubbo-remoting/dubbo-remoting-netty4/src/test/java/org/apache/dubbo/remoting/transport/netty4/PortUnificationServerTest.java @@ -30,6 +30,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_MANAGEMENT_MODE_DEFAULT; +import static org.apache.dubbo.common.constants.CommonConstants.EXT_PROTOCOL; class PortUnificationServerTest {