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 extends JavaFileObject> getSourceFileJavaFileObject(String filePath) {
-
- return ObjectHolders.javaFileManager.getJavaFileObjects(filePath);
- }
-}
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-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/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-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 b75b5a53d0..2c6baee9ab 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
@@ -645,9 +645,16 @@ public interface CommonConstants {
String SERVICE_DEPLOYER_ATTRIBUTE_KEY = "serviceDeployer";
+
+
String DUBBO_MANUAL_REGISTER_KEY = "dubbo.application.manual-register";
String POD_NAMESPACE = "POD_NAMESPACE";
String CLUSTER_DOMAIN = "CLUSTER_DOMAIN";
+
+ String EXT_PROTOCOL = "ext.protocol";
+
+ String IS_EXTRA = "isExtra";
+
}
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/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 f1243755cb..8f4b628637 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;
@@ -83,6 +84,8 @@ public class ApplicationConfig extends AbstractConfig {
private static final long serialVersionUID = 5508512956753757169L;
+ private static final String DEFAULT_NAME_PREFIX = "DUBBO_APP_";
+
/**
* Application name
*/
@@ -762,6 +765,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-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/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 41ba085d7c..f7290aa9fc 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
@@ -81,6 +81,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;
@@ -376,7 +378,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) {
@@ -761,14 +773,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();
}
@@ -786,6 +797,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 af37236120..c6a1557137 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 b4cee19e11..4d81c1497b 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 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 {
@@ -1082,7 +1090,7 @@ public class DefaultApplicationDeployer extends AbstractDeployer listener : listeners) {
@@ -1319,9 +1327,12 @@ public class DefaultApplicationDeployer extends AbstractDeployer getApplication() {
+ return configManager.getApplication();
+ }
}
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 bc52ea8f7b..3d8a84047d 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;
@@ -465,7 +464,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 3e0c748b6b..0c57ca80f3 100644
--- a/dubbo-config/pom.xml
+++ b/dubbo-config/pom.xml
@@ -50,6 +50,17 @@
+
+ spring6
+
+ [17,)
+
+
+ dubbo-config-api
+ dubbo-config-spring
+ dubbo-config-spring6
+
+
release
diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml
index 4a0c769f52..c36191150a 100644
--- a/dubbo-dependencies-bom/pom.xml
+++ b/dubbo-dependencies-bom/pom.xml
@@ -203,7 +203,7 @@
2.0
1.5.0
1.23.0
- 3.3.0-beta.1-SNAPSHOT
+ 3.3.0-beta.1
3.1.5
diff --git a/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml b/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml
index 07f39b2da2..2bdfd886ad 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
1.7.36
5.1.0
diff --git a/dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml b/dubbo-dependencies/dubbo-dependencies-zookeeper/pom.xml
index cb9cd5a2a0..ebacbdb94d 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
1.7.36
4.3.0
diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml
index cb507d5eab..744e115887 100644
--- a/dubbo-distribution/dubbo-all/pom.xml
+++ b/dubbo-distribution/dubbo-all/pom.xml
@@ -496,6 +496,13 @@
compile
true
+
+ org.apache.dubbo
+ dubbo-remoting-http12
+ ${project.version}
+ compile
+ true
+
org.apache.dubbo
dubbo-remoting-netty
@@ -714,6 +721,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
@@ -1233,6 +1241,30 @@
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.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 6e6449b420..f0e941af74 100644
--- a/dubbo-distribution/dubbo-bom/pom.xml
+++ b/dubbo-distribution/dubbo-bom/pom.xml
@@ -517,6 +517,11 @@
dubbo-remoting-http
${project.version}
+
+ org.apache.dubbo
+ dubbo-remoting-http12
+ ${project.version}
+
org.apache.dubbo
dubbo-remoting-netty
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-metadata/dubbo-metadata-processor/pom.xml b/dubbo-metadata/dubbo-metadata-processor/pom.xml
index 9a5aeab0dd..87ec734449 100644
--- a/dubbo-metadata/dubbo-metadata-processor/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-processor/pom.xml
@@ -121,15 +121,4 @@
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
- none
-
-
-
-
diff --git a/dubbo-plugin/dubbo-native/pom.xml b/dubbo-plugin/dubbo-native/pom.xml
index e8b74f45ca..10cf45a60b 100644
--- a/dubbo-plugin/dubbo-native/pom.xml
+++ b/dubbo-plugin/dubbo-native/pom.xml
@@ -34,6 +34,6 @@
dubbo-common
${project.parent.version}
-
+
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-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 ec125e37be..a61cb85bed 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 456b581fde..fe0d1be634 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/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-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-http12/pom.xml b/dubbo-remoting/dubbo-remoting-http12/pom.xml
new file mode 100644
index 0000000000..ad702991e9
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-http12/pom.xml
@@ -0,0 +1,65 @@
+
+
+ 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}
+
+
+ com.google.protobuf
+ protobuf-java-util
+
+
+
+ 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/AbstractServerHttpChannelObserver.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java
new file mode 100644
index 0000000000..adc23ec718
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/AbstractServerHttpChannelObserver.java
@@ -0,0 +1,158 @@
+/*
+ * 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.EncodeException;
+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;
+ }
+
+ protected HttpMessageCodec getHttpMessageCodec() {
+ return 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);
+ } catch (Throwable ex) {
+ throwable = new EncodeException(ex);
+ } 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/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-annotation-processor/src/test/resources/org/testing/dm/TestInterfaceDeprecatedMethod.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorCodeHolder.java
similarity index 87%
rename from dubbo-annotation-processor/src/test/resources/org/testing/dm/TestInterfaceDeprecatedMethod.java
rename to dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorCodeHolder.java
index a2ce7af598..fa7361aa9c 100644
--- a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestInterfaceDeprecatedMethod.java
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/ErrorCodeHolder.java
@@ -14,11 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.dubbo.remoting.http12;
-package org.testing.dm;
+public interface ErrorCodeHolder {
-public interface TestInterfaceDeprecatedMethod {
+ long getErrorCode();
- @Deprecated
- public void m1();
}
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-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessingHandler.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/FlowControlStreamObserver.java
similarity index 51%
rename from dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessingHandler.java
rename to dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/FlowControlStreamObserver.java
index 4830e32704..92bfd38e1e 100644
--- a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessingHandler.java
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/FlowControlStreamObserver.java
@@ -14,31 +14,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.dubbo.remoting.http12;
-package org.apache.dubbo.annotation;
+import org.apache.dubbo.common.stream.StreamObserver;
-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 {
+public interface FlowControlStreamObserver extends StreamObserver {
/**
- * Set the annotations that this handler will handle.
+ * Requests the peer to produce {@code count} more messages to be delivered to the 'inbound'
+ * {@link StreamObserver}.
*
- * @return annotations to handle
+ * This method is safe to call from multiple threads without external synchronization.
+ *
+ * @param count more messages
*/
- Set> getAnnotationsToHandle();
+ void request(int count);
+
+ boolean isAutoRequestN();
/**
- * Formal processing method.
- *
- * @param elements the elements that annotated by the annotations of getAnnotationsToHandle()
- * @param annotationProcessorContext the annotation processor context object (Javac object encapsulation)
+ * 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 process(Set elements,
- AnnotationProcessorContext annotationProcessorContext);
+ 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 extends String, ? extends List> 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 super String, ? extends List> 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 super String> 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 super List> 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 super Entry>> 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-annotation-processor/src/test/resources/org/testing/dm/TestDeprecatedMethod.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpInputMessage.java
similarity index 85%
rename from dubbo-annotation-processor/src/test/resources/org/testing/dm/TestDeprecatedMethod.java
rename to dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpInputMessage.java
index 6360c3e137..b80833764a 100644
--- a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestDeprecatedMethod.java
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpInputMessage.java
@@ -14,13 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.dubbo.remoting.http12;
-package org.testing.dm;
+import java.io.InputStream;
-public class TestDeprecatedMethod {
+public interface HttpInputMessage {
+
+ InputStream getBody();
- @Deprecated
- public void m1() {
- System.out.println("M1! ");
- }
}
diff --git a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethod.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpMetadata.java
similarity index 82%
rename from dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethod.java
rename to dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpMetadata.java
index c705ca8d13..c1fce4a759 100644
--- a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethod.java
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpMetadata.java
@@ -14,15 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.dubbo.remoting.http12;
-package org.testing.dm;
+public interface HttpMetadata {
-public class TestConstructorMethod {
- @Deprecated
- TestConstructorMethod() {
- this("1");
- }
+ HttpHeaders headers();
- TestConstructorMethod(String s) {
- }
}
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-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodParentClass.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/RequestMetadata.java
similarity index 81%
rename from dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodParentClass.java
rename to dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/RequestMetadata.java
index 8e14e67c51..7d3c773764 100644
--- a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodParentClass.java
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/RequestMetadata.java
@@ -14,14 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.dubbo.remoting.http12;
-package org.testing.dm;
+public interface RequestMetadata extends HttpMetadata {
-public class TestConstructorMethodParentClass {
+ String method();
- public TestConstructorMethodParentClass() {
- }
+ String path();
- public TestConstructorMethodParentClass(String s) {
- }
}
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/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..9e41598f42
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h1/Http1ServerTransportListener.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.h1;
+
+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 {
+
+}
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/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-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodSubClass.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Headers.java
similarity index 74%
rename from dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodSubClass.java
rename to dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Headers.java
index 3b71626c9b..4a2c885e18 100644
--- a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodSubClass.java
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2Headers.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.h2;
-package org.testing.dm;
+public enum Http2Headers {
-public class TestConstructorMethodSubClass extends TestConstructorMethodParentClass {
+ PATH(":path"),
- @Deprecated
- public TestConstructorMethodSubClass(int i) {
- super();
+ METHOD(":method"),
+
+ STATUS(":status");
+
+ private final String name;
+
+ Http2Headers(String name) {
+ this.name = name;
}
- public TestConstructorMethodSubClass(String s) {
- super(s);
+ 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..19faa32e4d
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/h2/Http2TransportListener.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.h2;
+
+public interface Http2TransportListener extends CancelableTransportListener {
+
+}
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..65c3ad65e9
--- /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 == 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 == null || targetTypes.length == 0 ? null : targetTypes[0])};
+ }
+
+ MediaType contentType();
+
+ default boolean support(String contentType) {
+ MediaType mediaType = this.contentType();
+ return mediaType.getName().startsWith(contentType);
+ }
+
+}
diff --git a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodecFactory.java
similarity index 57%
rename from dubbo-annotation-processor/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java
rename to dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodecFactory.java
index cc34299c81..80978b6a98 100644
--- a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/HttpMessageCodecFactory.java
@@ -14,23 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.dubbo.remoting.http12.message;
-package org.apache.dubbo.common;
+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;
/**
- * Reduced mock of Deprecated method invocation counter.
+ * for http body codec
*/
-public final class DeprecatedMethodInvocationCounter {
- private DeprecatedMethodInvocationCounter() {
- throw new UnsupportedOperationException("No instance of DeprecatedMethodInvocationCounter for you! ");
+@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);
}
- /**
- * 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-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..852e1d0ceb
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodec.java
@@ -0,0 +1,123 @@
+/*
+ * 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 {
+ 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/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..64a7cd2f55
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonCodecFactory.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.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 {
+
+ public static final String NAME = "json";
+
+ @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/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..6d7a760b7e
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/JsonPbCodec.java
@@ -0,0 +1,118 @@
+/*
+ * 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 {
+ 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 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-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/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..67da0dea90
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java
@@ -0,0 +1,192 @@
+/*
+ * 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.ByteArrayOutputStream;
+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 FragmentListener listener;
+
+ private final int lengthFieldOffset;
+
+ private final int lengthFieldLength;
+
+ private int requiredLength;
+
+ private InputStream dataHeader = new ByteArrayInputStream(new byte[0]);
+
+ public LengthFieldStreamingDecoder() {
+ this(4);
+ }
+
+ public LengthFieldStreamingDecoder(int lengthFieldLength) {
+ this(0, lengthFieldLength);
+ }
+
+ public LengthFieldStreamingDecoder(int lengthFieldOffset, int lengthFieldLength) {
+ this.lengthFieldOffset = lengthFieldOffset;
+ this.lengthFieldLength = lengthFieldLength;
+ this.requiredLength = lengthFieldOffset + lengthFieldLength;
+ }
+
+ @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 setFragmentListener(FragmentListener 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 {
+ 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];
+ ignore = accumulate.read(lengthBytes);
+ bos.write(lengthBytes);
+ requiredLength = bytesToInt(lengthBytes);
+ this.dataHeader = new ByteArrayInputStream(bos.toByteArray());
+
+ // 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;
+ }
+ int ignore = inputStream.read(new byte[lengthFieldOffset]);
+ }
+
+ private void processBody() throws IOException {
+ byte[] rawMessage = readRawMessage(accumulate, requiredLength);
+ InputStream inputStream = new ByteArrayInputStream(rawMessage);
+ 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);
+ 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/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-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..f1b1b2e046
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/StreamingDecoder.java
@@ -0,0 +1,70 @@
+/*
+ * 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 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/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..9385a30564
--- /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.HttpMessageCodecFactory;
+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);
+ }
+ HttpMessageCodecFactory codecFactory = findSuitableCodec(contentType, frameworkModel.getExtensionLoader(HttpMessageCodecFactory.class).getActivateExtensions());
+ if (codecFactory == null) {
+ throw new UnsupportedMediaTypeException(contentType);
+ }
+ this.errorResponseObserver = new Http1ServerChannelObserver(new NettyHttp1Channel(ctx.channel()));
+ this.errorResponseObserver.setHttpMessageCodec(codecFactory.createCodec(url, frameworkModel));
+ return http1TransportListener;
+ }
+
+ 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/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/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..0fcf5fb19a
--- /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,2 @@
+json=org.apache.dubbo.remoting.http12.message.JsonCodecFactory
+jsonpb=org.apache.dubbo.remoting.http12.message.JsonPbCodecFactory
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 c5b1234e0e..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
@@ -16,6 +16,7 @@
*/
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.utils.NetUtils;
@@ -29,13 +30,14 @@ 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 {
@Test
void testBind() throws Throwable {
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);
@@ -51,6 +53,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-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
diff --git a/dubbo-rpc/dubbo-rpc-triple/pom.xml b/dubbo-rpc/dubbo-rpc-triple/pom.xml
index c13ec7b15c..775be67310 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 66f34d48c3..766ff91397 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,6 +17,7 @@
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;
@@ -133,7 +134,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 70d018d78a..d41f41ec62 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
@@ -17,39 +17,44 @@
package org.apache.dubbo.rpc.protocol.tri;
-import org.apache.dubbo.common.URL;
-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.utils.UrlUtils;
-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.transport.TripleCommandOutBoundHandler;
-import org.apache.dubbo.rpc.protocol.tri.transport.TripleGoAwayHandler;
-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 io.netty.channel.ChannelDuplexHandler;
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;
import io.netty.handler.codec.http2.Http2StreamChannel;
import io.netty.handler.flush.FlushConsolidationHandler;
import io.netty.handler.logging.LogLevel;
+import org.apache.dubbo.common.URL;
+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.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.remoting.utils.UrlUtils;
+import org.apache.dubbo.rpc.HeaderFilter;
+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.TripleGoAwayHandler;
+import org.apache.dubbo.rpc.protocol.tri.transport.TripleServerConnectionHandler;
+import org.apache.dubbo.rpc.protocol.tri.transport.TripleTailHandler;
import java.util.ArrayList;
import java.util.Collections;
@@ -83,7 +88,7 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo
private FrameworkModel frameworkModel;
public TripleHttp2Protocol() {
- super(new Http2ProtocolDetector());
+ super(new TripleProtocolDetector());
}
@Override
@@ -97,8 +102,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) {
@@ -120,55 +178,22 @@ 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 TripleGoAwayHandler()));
+ handlers.add(new ChannelHandlerPretender(new TriplePingPongHandler(UrlUtils.getCloseTimeout(url))));
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());
- List handlers = new ArrayList<>();
- handlers.add(new ChannelHandlerPretender(codec));
- handlers.add(new ChannelHandlerPretender(new Http2MultiplexHandler(new ChannelDuplexHandler())));
- handlers.add(new ChannelHandlerPretender(new TripleGoAwayHandler()));
- handlers.add(new ChannelHandlerPretender(new TriplePingPongHandler(UrlUtils.getCloseTimeout(url))));
- 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-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerCallListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerCallListener.java
new file mode 100644
index 0000000000..2ae592501c
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerCallListener.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.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 {
+
+ 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() {
+ 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()) {
+ onResponseException(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 onResponseException(Throwable t) {
+ responseObserver.onError(t);
+ }
+
+ public abstract void onReturn(Object value);
+
+}
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..a80785ab13
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/AbstractServerTransportListener.java
@@ -0,0 +1,483 @@
+/*
+ * 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) {
+ LOGGER.error("initialize executor fail.", throwable);
+ onError(throwable);
+ return;
+ }
+ if (this.executor == null) {
+ LOGGER.error("executor must be not null.");
+ onError(new NullPointerException("initializeExecutor return null"));
+ return;
+ }
+ executor.execute(() -> {
+ try {
+ doOnMetadata(metadata);
+ } catch (Throwable throwable) {
+ LOGGER.error("server internal error", 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;
+ setServiceDescriptor(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) {
+ LOGGER.error("server internal error", 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-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/BiStreamServerCallListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/BiStreamServerCallListener.java
new file mode 100644
index 0000000000..0ffd8d7ca7
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/BiStreamServerCallListener.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.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;
+
+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-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-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerCallListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerCallListener.java
new file mode 100644
index 0000000000..55616bdd82
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/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.rpc.protocol.tri.h12;
+
+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-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-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerStreamServerCallListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/ServerStreamServerCallListener.java
new file mode 100644
index 0000000000..5a0e60969a
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/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.rpc.protocol.tri.h12;
+
+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-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-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/UnaryServerCallListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/UnaryServerCallListener.java
new file mode 100644
index 0000000000..f933020ddd
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/UnaryServerCallListener.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.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);
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void onMessage(Object message) {
+ if (message instanceof Object[]) {
+ invocation.setArguments((Object[]) message);
+ } else {
+ invocation.setArguments(new Object[]{message});
+ }
+ }
+
+ @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
+ }
+
+ @Override
+ public void onComplete() {
+ invoke();
+ }
+}
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..48171cf234
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java
@@ -0,0 +1,152 @@
+/*
+ * 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;
+
+import static org.apache.dubbo.common.constants.CommonConstants.PROTOBUF_MESSAGE_CLASS_NAME;
+
+/**
+ * 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 (isProtobuf(data)) {
+ ProtobufWriter.write(protobufHttpMessageCodec, 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 (isProtoClass(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 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());
+ }
+
+ 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);
+ }
+
+ }
+}
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..43ae3ec817
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcHttp2ServerTransportListener.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.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.TriRpcStatus;
+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_STATUS.getName(), httpStatusToGrpcStatus(throwable));
+ httpHeaders.set(GrpcHeaderNames.GRPC_MESSAGE.getName(), throwable.getMessage());
+ }
+ }
+
+ private static String httpStatusToGrpcStatus(Throwable throwable) {
+ //http status code map to grpc status code
+ return String.valueOf(TriRpcStatus.INTERNAL.code.code);
+ }
+
+ @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-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/StreamingHttpMessageListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/StreamingHttpMessageListener.java
new file mode 100644
index 0000000000..bbcac87d43
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/StreamingHttpMessageListener.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.rpc.protocol.tri.h12.grpc;
+
+import org.apache.dubbo.remoting.http12.message.StreamingDecoder;
+import org.apache.dubbo.rpc.protocol.tri.h12.HttpMessageListener;
+
+import java.io.InputStream;
+
+public class StreamingHttpMessageListener implements HttpMessageListener {
+
+ private StreamingDecoder streamingDecoder;
+
+ public StreamingHttpMessageListener() {
+ }
+
+ public StreamingHttpMessageListener(StreamingDecoder streamingDecoder) {
+ this.streamingDecoder = streamingDecoder;
+ }
+
+ @Override
+ 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..c7d34b1a87
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListener.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.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);
+ setMethodDescriptor(methodDescriptor);
+ setMethodMetadata(methodMetadata);
+ 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-common/src/main/java/org/apache/dubbo/common/constants/DeprecatedMethodInvocationCounterConstants.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListenerFactory.java
similarity index 50%
rename from dubbo-common/src/main/java/org/apache/dubbo/common/constants/DeprecatedMethodInvocationCounterConstants.java
rename to dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListenerFactory.java
index f747568491..cddeb4182e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/DeprecatedMethodInvocationCounterConstants.java
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/http1/DefaultHttp11ServerTransportListenerFactory.java
@@ -14,22 +14,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.dubbo.rpc.protocol.tri.h12.http1;
-package org.apache.dubbo.common.constants;
+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;
-/**
- * Constants of Deprecated Method Invocation Counter.
- */
-public final class DeprecatedMethodInvocationCounterConstants {
- private DeprecatedMethodInvocationCounterConstants() {
- throw new UnsupportedOperationException("No instance of DeprecatedMethodInvocationCounterConstants for you! ");
+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);
}
-
- 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-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..bb09853da2
--- /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.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;
+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 no op
+ return new NoOpStreamingDecoder();
+ }
+
+ 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 2850fef28d..ab5635e36e 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}
-
+
+
+
+
+
@@ -415,6 +415,11 @@
dubbo-remoting-http
${project.version}
+
+ org.apache.dubbo
+ dubbo-remoting-http12
+ ${project.version}
+
org.apache.dubbo
dubbo-remoting-netty
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 6059919675..b971b22908 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,7 @@ class FileTest {
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"));
ignoredModules.add(Pattern.compile("dubbo-plugin-loom.*"));
ignoredArtifacts.add(Pattern.compile("dubbo-demo.*"));
@@ -67,7 +68,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 e406541a66..474423f7ca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -120,18 +120,16 @@
1.5.0
3.3.0
3.1.0
- 1.0.0
1.7.1
0.6.1
3.22.3
1.54.0
- 3.3.0-beta.1-SNAPSHOT
+ 3.3.0-beta.1
- dubbo-annotation-processor
dubbo-common
dubbo-container
dubbo-remoting
@@ -170,13 +168,6 @@
-
- org.apache.dubbo
- dubbo-annotation-processor
- ${dubbo_annotation_processor_version}
- true
-
-
org.junit.jupiter
@@ -441,7 +432,9 @@
${log4j2_version}
- all,-missing
+
+
+ none
@@ -450,7 +443,7 @@
UTF-8
UTF-8
UTF-8
- ${maven_source_version}
+ ${java_source_version}
https://docs.oracle.com/javase/8/docs/api
@@ -696,6 +689,7 @@
${maven_compiler_version}
+ -proc:none
-parameters
true