Merge branch '3.3.0-beta.1-release' into apache-3.3
# Conflicts: # .github/workflows/release-test.yml # dubbo-annotation-processor/pom.xml # dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java # dubbo-config/dubbo-config-api/pom.xml # dubbo-config/pom.xml # dubbo-metadata/dubbo-metadata-processor/pom.xml # dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java # pom.xml
This commit is contained in:
commit
d00757e65b
|
|
@ -84,6 +84,7 @@ dubbo-registry-zookeeper
|
|||
dubbo-remoting
|
||||
dubbo-remoting-api
|
||||
dubbo-remoting-http
|
||||
dubbo-remoting-http12
|
||||
dubbo-remoting-netty
|
||||
dubbo-remoting-netty4
|
||||
dubbo-remoting-zookeeper-api
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ jobs:
|
|||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 8
|
||||
java-version: 17
|
||||
- uses: actions/cache@v3
|
||||
name: "Cache local Maven repository"
|
||||
with:
|
||||
|
|
@ -132,7 +132,7 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
jdk: [ 8, 11, 17, 21 ]
|
||||
jdk: [ 17, 21 ]
|
||||
env:
|
||||
DISABLE_FILE_SYSTEM_TEST: true
|
||||
steps:
|
||||
|
|
@ -175,7 +175,7 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
os: [ ubuntu-latest, windows-latest ]
|
||||
jdk: [ 8, 11, 17, 21 ]
|
||||
jdk: [ 17, 21 ]
|
||||
env:
|
||||
DISABLE_FILE_SYSTEM_TEST: true
|
||||
DUBBO_DEFAULT_SERIALIZATION: fastjson2
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ header:
|
|||
- 'dubbo-plugin/dubbo-native/src/main/java/org/apache/dubbo/aot/api/MemberCategory.java'
|
||||
- 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboMergingDigest.java'
|
||||
- 'dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/aggregate/DubboAbstractTDigest.java'
|
||||
- 'dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/**'
|
||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/FormattingTuple.java'
|
||||
- 'dubbo-common/src/main/java/org/apache/dubbo/common/logger/helpers/MessageFormatter.java'
|
||||
- 'dubbo-maven-plugin/src/main/java/org/apache/dubbo/maven/plugin/protoc/DubboProtocCompilerMojo.java'
|
||||
|
|
|
|||
2
NOTICE
2
NOTICE
|
|
@ -4,7 +4,7 @@ Copyright 2018-2023 The Apache Software Foundation
|
|||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
|
||||
This product contains code from the Netty Project:
|
||||
This product contains code form the Netty Project:
|
||||
|
||||
The Netty Project
|
||||
=================
|
||||
|
|
|
|||
|
|
@ -1,164 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-annotation-processor</artifactId>
|
||||
<version>1.0.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<!-- System dependencies may cause problems in checkstyle. -->
|
||||
<checkstyle.skip>true</checkstyle.skip>
|
||||
<checkstyle_unix.skip>true</checkstyle_unix.skip>
|
||||
<rat.skip>true</rat.skip>
|
||||
<jacoco.skip>true</jacoco.skip>
|
||||
<maven.deploy.skip>true</maven.deploy.skip>
|
||||
|
||||
<junit_jupiter_version>5.9.0</junit_jupiter_version>
|
||||
<javassist_version>3.29.2-GA</javassist_version>
|
||||
</properties>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!-- JUnit Jupiter Engine to depend on the JUnit5 engine and JUnit 5 API -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit_jupiter_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit_jupiter_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>${junit_jupiter_version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
<version>${javassist_version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<configuration>
|
||||
<proc>none</proc>
|
||||
<fork>true</fork>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default-profile-in-jdk-8</id>
|
||||
<activation>
|
||||
<file>
|
||||
<exists>${java.home}/../lib/tools.jar</exists>
|
||||
</file>
|
||||
<jdk>(, 9)</jdk>
|
||||
</activation>
|
||||
<properties>
|
||||
<toolsjar>${java.home}/../lib/tools.jar</toolsjar>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javac</groupId>
|
||||
<artifactId>javac</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${toolsjar}</systemPath>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>legacy-apple-jdk-profile</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
<file>
|
||||
<exists>${java.home}/../Classes/classes.jar</exists>
|
||||
</file>
|
||||
<jdk>(, 9)</jdk>
|
||||
</activation>
|
||||
|
||||
<properties>
|
||||
<toolsjar>${java.home}/../Classes/classes.jar</toolsjar>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javac</groupId>
|
||||
<artifactId>javac</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${toolsjar}</systemPath>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>add-export-greater-than-9</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
<jdk>[9, )</jdk>
|
||||
</activation>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
<proc>none</proc>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dubbo.annotation;
|
||||
|
||||
import com.sun.source.util.Trees;
|
||||
import com.sun.tools.javac.api.JavacTrees;
|
||||
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
|
||||
import com.sun.tools.javac.tree.TreeMaker;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.Names;
|
||||
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The Context Object of Annotation Processor, which stores objects related to javac.
|
||||
*/
|
||||
public class AnnotationProcessorContext {
|
||||
private JavacProcessingEnvironment javacProcessingEnvironment;
|
||||
private JavacTrees javacTrees;
|
||||
private TreeMaker treeMaker;
|
||||
private Names names;
|
||||
private Context javacContext;
|
||||
private Trees trees;
|
||||
|
||||
private AnnotationProcessorContext() { }
|
||||
|
||||
private static <T> T jbUnwrap(Class<? extends T> iface, T wrapper) {
|
||||
T unwrapped = null;
|
||||
try {
|
||||
final Class<?> apiWrappers = wrapper.getClass().getClassLoader().loadClass("org.jetbrains.jps.javac.APIWrappers");
|
||||
final Method unwrapMethod = apiWrappers.getDeclaredMethod("unwrap", Class.class, Object.class);
|
||||
unwrapped = iface.cast(unwrapMethod.invoke(null, iface, wrapper));
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
return unwrapped != null ? unwrapped : wrapper;
|
||||
}
|
||||
|
||||
public static AnnotationProcessorContext fromProcessingEnvironment(ProcessingEnvironment processingEnv) {
|
||||
AnnotationProcessorContext apContext = new AnnotationProcessorContext();
|
||||
|
||||
Object procEnvToUnwrap = processingEnv.getClass() == JavacProcessingEnvironment.class ?
|
||||
processingEnv : jbUnwrap(JavacProcessingEnvironment.class, processingEnv);
|
||||
|
||||
JavacProcessingEnvironment jcProcessingEnvironment = (JavacProcessingEnvironment) procEnvToUnwrap;
|
||||
|
||||
Context context = jcProcessingEnvironment.getContext();
|
||||
|
||||
apContext.javacProcessingEnvironment = jcProcessingEnvironment;
|
||||
|
||||
apContext.javacContext = context;
|
||||
apContext.javacTrees = JavacTrees.instance(jcProcessingEnvironment);
|
||||
apContext.treeMaker = TreeMaker.instance(context);
|
||||
apContext.names = Names.instance(context);
|
||||
|
||||
apContext.trees = Trees.instance(jcProcessingEnvironment);
|
||||
|
||||
return apContext;
|
||||
}
|
||||
|
||||
// Auto-generated methods.
|
||||
|
||||
public JavacTrees getJavacTrees() {
|
||||
return javacTrees;
|
||||
}
|
||||
|
||||
public TreeMaker getTreeMaker() {
|
||||
return treeMaker;
|
||||
}
|
||||
|
||||
public Names getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
public Context getJavacContext() {
|
||||
return javacContext;
|
||||
}
|
||||
|
||||
public Trees getTrees() {
|
||||
return trees;
|
||||
}
|
||||
|
||||
public JavacProcessingEnvironment getJavacProcessingEnvironment() {
|
||||
return javacProcessingEnvironment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
AnnotationProcessorContext context = (AnnotationProcessorContext) o;
|
||||
|
||||
if (!Objects.equals(javacTrees, context.javacTrees)) return false;
|
||||
if (!Objects.equals(treeMaker, context.treeMaker)) return false;
|
||||
if (!Objects.equals(names, context.names)) return false;
|
||||
if (!Objects.equals(javacContext, context.javacContext))
|
||||
return false;
|
||||
return Objects.equals(trees, context.trees);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = javacTrees != null ? javacTrees.hashCode() : 0;
|
||||
result = 31 * result + (treeMaker != null ? treeMaker.hashCode() : 0);
|
||||
result = 31 * result + (names != null ? names.hashCode() : 0);
|
||||
result = 31 * result + (javacContext != null ? javacContext.hashCode() : 0);
|
||||
result = 31 * result + (trees != null ? trees.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AnnotationProcessorContext{" +
|
||||
"javacTrees=" + javacTrees +
|
||||
", treeMaker=" + treeMaker +
|
||||
", names=" + names +
|
||||
", javacContext=" + javacContext +
|
||||
", trees=" + trees +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dubbo.annotation;
|
||||
|
||||
import org.apache.dubbo.annotation.permit.Permit;
|
||||
import org.apache.dubbo.annotation.util.FileUtils;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.processing.JavacRoundEnvironment;
|
||||
|
||||
import javax.annotation.processing.AbstractProcessor;
|
||||
import javax.annotation.processing.ProcessingEnvironment;
|
||||
import javax.annotation.processing.RoundEnvironment;
|
||||
import javax.annotation.processing.SupportedAnnotationTypes;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.tools.Diagnostic;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Dispatching annotation processor, which uses a file to locate handlers and invoke them.
|
||||
*/
|
||||
@SupportedAnnotationTypes("*")
|
||||
public class DispatchingAnnotationProcessor extends AbstractProcessor {
|
||||
|
||||
private static Set<AnnotationProcessingHandler> handlers;
|
||||
|
||||
private static Set<AnnotationProcessingHandler> loadHandlers() {
|
||||
List<String> classNames = FileUtils.loadConfigurationFileInResources("handlers.cfg");
|
||||
Set<AnnotationProcessingHandler> tempHandlers = new HashSet<>();
|
||||
|
||||
for (String clsName : classNames) {
|
||||
try {
|
||||
Class<? extends AnnotationProcessingHandler> cls = (Class<? extends AnnotationProcessingHandler>) Class.forName(clsName);
|
||||
AnnotationProcessingHandler r = cls.getConstructor().newInstance();
|
||||
|
||||
tempHandlers.add(r);
|
||||
|
||||
} catch (InstantiationException | NoSuchMethodException | InvocationTargetException |
|
||||
IllegalAccessException | ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableSet(tempHandlers);
|
||||
}
|
||||
|
||||
private AnnotationProcessorContext apContext;
|
||||
|
||||
@Override
|
||||
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||
Permit.addOpens();
|
||||
super.init(processingEnv);
|
||||
|
||||
if (processingEnv.getClass().getName().startsWith("org.eclipse.jdt.")) {
|
||||
// Don't run on ECJ, since this processor is javac based.
|
||||
processingEnv
|
||||
.getMessager()
|
||||
.printMessage(Diagnostic.Kind.WARNING, "The Annotation processor doesn't support ECJ.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (handlers == null) {
|
||||
handlers = loadHandlers();
|
||||
}
|
||||
|
||||
apContext = AnnotationProcessorContext.fromProcessingEnvironment(processingEnv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
|
||||
if (processingEnv.getClass().getName().startsWith("org.eclipse.jdt.")) {
|
||||
// Don't run on ECJ, since this processor is javac based.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (AnnotationProcessingHandler i : handlers) {
|
||||
Set<Element> elements = new HashSet<>(16);
|
||||
|
||||
for (Class<? extends Annotation> annotationClass : i.getAnnotationsToHandle()) {
|
||||
elements.addAll(getElementsAnnotatedWith(annotationClass, roundEnv));
|
||||
}
|
||||
|
||||
i.process(elements, apContext);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A hack to make comment only .java file pass the compilation by skipping package symbol scan.
|
||||
*
|
||||
* @param annotationClass the annotation class to find
|
||||
* @param roundEnvironment the javac's round environment
|
||||
* @return the elements annotated with specified annotation
|
||||
*/
|
||||
private Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> annotationClass, RoundEnvironment roundEnvironment) {
|
||||
|
||||
TypeElement a = processingEnv.getElementUtils().getTypeElement(annotationClass.getCanonicalName());
|
||||
|
||||
// Detect the Javac's version.
|
||||
if (Integer.parseInt(SourceVersion.latest().name().split("_")[1]) > 8) {
|
||||
return roundEnvironment.getElementsAnnotatedWith(a);
|
||||
}
|
||||
|
||||
Set<Element> result = Collections.emptySet();
|
||||
|
||||
try {
|
||||
Class annotationSetScannerClass = Class.forName("com.sun.tools.javac.processing.JavacRoundEnvironment$AnnotationSetScanner");
|
||||
Constructor scannerConstructor = Permit.getConstructor(annotationSetScannerClass, JavacRoundEnvironment.class, Set.class);
|
||||
Object scanner = scannerConstructor.newInstance(roundEnvironment, result);
|
||||
|
||||
Set<? extends Element> rootElements1 = roundEnvironment
|
||||
.getRootElements()
|
||||
.stream()
|
||||
.filter(x -> x.getClass() != Symbol.PackageSymbol.class)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
for (Element element : rootElements1) {
|
||||
Method scanningMethod = Permit.getMethod(annotationSetScannerClass, "scan", Element.class, TypeElement.class);
|
||||
result = (Set<Element>) scanningMethod.invoke(scanner, element, a);
|
||||
}
|
||||
|
||||
} catch (InstantiationException | NoSuchMethodException | ClassNotFoundException | InvocationTargetException |
|
||||
IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceVersion getSupportedSourceVersion() {
|
||||
return SourceVersion.latestSupported();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.dubbo.annotation.handler;
|
||||
|
||||
import org.apache.dubbo.annotation.AnnotationProcessingHandler;
|
||||
import org.apache.dubbo.annotation.AnnotationProcessorContext;
|
||||
import org.apache.dubbo.annotation.util.ASTUtils;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.TreeTranslator;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Handles @Deprecated annotation and adds logger warn call to the methods that are annotated with it.
|
||||
*/
|
||||
public class DeprecatedHandler implements AnnotationProcessingHandler {
|
||||
|
||||
@Override
|
||||
public Set<Class<? extends Annotation>> getAnnotationsToHandle() {
|
||||
return new HashSet<>(
|
||||
Collections.singletonList(Deprecated.class)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Set<Element> elements, AnnotationProcessorContext apContext) {
|
||||
for (Element element : elements) {
|
||||
// Only interested in methods.
|
||||
if (!(element instanceof Symbol.MethodSymbol)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Symbol.ClassSymbol classSymbol = (Symbol.ClassSymbol) element.getEnclosingElement();
|
||||
|
||||
ASTUtils.addImportStatement(apContext, classSymbol, "org.apache.dubbo.common", "DeprecatedMethodInvocationCounter");
|
||||
|
||||
JCTree methodTree = apContext.getJavacTrees().getTree(element);
|
||||
|
||||
methodTree.accept(new TreeTranslator() {
|
||||
@Override
|
||||
public void visitMethodDef(JCTree.JCMethodDecl jcMethodDecl) {
|
||||
|
||||
JCTree.JCBlock block = jcMethodDecl.body;
|
||||
|
||||
if (block == null) {
|
||||
// No method body. (i.e. interface method declaration.)
|
||||
return;
|
||||
}
|
||||
|
||||
ASTUtils.insertStatementToHeadOfMethod(block, jcMethodDecl, generateCounterStatement(apContext, classSymbol, jcMethodDecl));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an expression statement like this:
|
||||
* <code>DeprecatedMethodInvocationCounter.onDeprecatedMethodCalled("....");
|
||||
*
|
||||
* @param originalMethodDecl the method declaration that will add logger statement
|
||||
* @param apContext annotation processor context
|
||||
* @param classSymbol the enclosing class that will be the logger's name
|
||||
* @return generated expression statement
|
||||
*/
|
||||
private JCTree.JCExpressionStatement generateCounterStatement(AnnotationProcessorContext apContext,
|
||||
Symbol.ClassSymbol classSymbol,
|
||||
JCTree.JCMethodDecl originalMethodDecl) {
|
||||
|
||||
JCTree.JCExpression fullStatement = apContext.getTreeMaker().Apply(
|
||||
com.sun.tools.javac.util.List.nil(),
|
||||
|
||||
apContext.getTreeMaker().Select(
|
||||
apContext.getTreeMaker().Ident(apContext.getNames().fromString("DeprecatedMethodInvocationCounter")),
|
||||
apContext.getNames().fromString("onDeprecatedMethodCalled")
|
||||
),
|
||||
|
||||
com.sun.tools.javac.util.List.of(
|
||||
apContext.getTreeMaker().Literal(getMethodDefinition(classSymbol, originalMethodDecl))
|
||||
)
|
||||
);
|
||||
|
||||
return apContext.getTreeMaker().Exec(fullStatement);
|
||||
}
|
||||
|
||||
private String getMethodDefinition(Symbol.ClassSymbol classSymbol, JCTree.JCMethodDecl originalMethodDecl) {
|
||||
return classSymbol.getQualifiedName() + "."
|
||||
+ originalMethodDecl.name.toString() + "(" + originalMethodDecl.params.toString() + ")";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,429 +0,0 @@
|
|||
/*
|
||||
* Authored by Project Lombok and licensed by MIT License, which is attached below:
|
||||
*
|
||||
* Copyright (C) 2018-2021 The Project Lombok Authors.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.apache.dubbo.annotation.permit;
|
||||
|
||||
import org.apache.dubbo.annotation.permit.dummy.Parent;
|
||||
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
// sunapi suppresses javac's warning about using Unsafe; 'all' suppresses eclipse's warning about the unspecified 'sunapi' key. Leave them both.
|
||||
// Yes, javac's definition of the word 'all' is quite contrary to what the dictionary says it means. 'all' does NOT include 'sunapi' according to javac.
|
||||
@SuppressWarnings({"sunapi", "all"})
|
||||
public class Permit {
|
||||
private Permit() {
|
||||
}
|
||||
|
||||
|
||||
private static final long ACCESSIBLE_OVERRIDE_FIELD_OFFSET;
|
||||
private static final IllegalAccessException INIT_ERROR;
|
||||
private static final sun.misc.Unsafe UNSAFE = (sun.misc.Unsafe) reflectiveStaticFieldAccess(sun.misc.Unsafe.class, "theUnsafe");
|
||||
|
||||
static {
|
||||
Field f;
|
||||
long g;
|
||||
Throwable ex;
|
||||
|
||||
try {
|
||||
g = getOverrideFieldOffset();
|
||||
ex = null;
|
||||
} catch (Throwable t) {
|
||||
f = null;
|
||||
g = -1L;
|
||||
ex = t;
|
||||
}
|
||||
|
||||
ACCESSIBLE_OVERRIDE_FIELD_OFFSET = g;
|
||||
if (ex == null) INIT_ERROR = null;
|
||||
else if (ex instanceof IllegalAccessException) INIT_ERROR = (IllegalAccessException) ex;
|
||||
else {
|
||||
INIT_ERROR = new IllegalAccessException("Cannot initialize Unsafe-based permit");
|
||||
INIT_ERROR.initCause(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends AccessibleObject> T setAccessible(T accessor) {
|
||||
if (INIT_ERROR == null) {
|
||||
UNSAFE.putBoolean(accessor, ACCESSIBLE_OVERRIDE_FIELD_OFFSET, true);
|
||||
} else {
|
||||
accessor.setAccessible(true);
|
||||
}
|
||||
|
||||
return accessor;
|
||||
}
|
||||
|
||||
private static long getOverrideFieldOffset() throws Throwable {
|
||||
Field f = null;
|
||||
Throwable saved = null;
|
||||
try {
|
||||
f = AccessibleObject.class.getDeclaredField("override");
|
||||
} catch (Throwable t) {
|
||||
saved = t;
|
||||
}
|
||||
|
||||
if (f != null) {
|
||||
return UNSAFE.objectFieldOffset(f);
|
||||
}
|
||||
// The below seems very risky, but for all AccessibleObjects in java today it does work, and starting with JDK12, making the field accessible is no longer possible.
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(Fake.class.getDeclaredField("override"));
|
||||
} catch (Throwable t) {
|
||||
throw saved;
|
||||
}
|
||||
}
|
||||
|
||||
static class Fake {
|
||||
boolean override;
|
||||
Object accessCheckCache;
|
||||
}
|
||||
|
||||
public static Method getMethod(Class<?> c, String mName, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
Method m = null;
|
||||
Class<?> oc = c;
|
||||
while (c != null) {
|
||||
try {
|
||||
m = c.getDeclaredMethod(mName, parameterTypes);
|
||||
break;
|
||||
} catch (NoSuchMethodException e) {
|
||||
}
|
||||
c = c.getSuperclass();
|
||||
}
|
||||
|
||||
if (m == null) throw new NoSuchMethodException(oc.getName() + " :: " + mName + "(args)");
|
||||
return setAccessible(m);
|
||||
}
|
||||
|
||||
public static Method permissiveGetMethod(Class<?> c, String mName, Class<?>... parameterTypes) {
|
||||
try {
|
||||
return getMethod(c, mName, parameterTypes);
|
||||
} catch (Exception ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Field getField(Class<?> c, String fName) throws NoSuchFieldException {
|
||||
Field f = null;
|
||||
Class<?> oc = c;
|
||||
while (c != null) {
|
||||
try {
|
||||
f = c.getDeclaredField(fName);
|
||||
break;
|
||||
} catch (NoSuchFieldException e) {
|
||||
}
|
||||
c = c.getSuperclass();
|
||||
}
|
||||
|
||||
if (f == null) throw new NoSuchFieldException(oc.getName() + " :: " + fName);
|
||||
|
||||
return setAccessible(f);
|
||||
}
|
||||
|
||||
public static Field permissiveGetField(Class<?> c, String fName) {
|
||||
try {
|
||||
return getField(c, fName);
|
||||
} catch (Exception ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T permissiveReadField(Class<T> type, Field f, Object instance) {
|
||||
try {
|
||||
return type.cast(f.get(instance));
|
||||
} catch (Exception ignore) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> Constructor<T> getConstructor(Class<T> c, Class<?>... parameterTypes) throws NoSuchMethodException {
|
||||
return setAccessible(c.getDeclaredConstructor(parameterTypes));
|
||||
}
|
||||
|
||||
private static Object reflectiveStaticFieldAccess(Class<?> c, String fName) {
|
||||
try {
|
||||
Field f = c.getDeclaredField(fName);
|
||||
f.setAccessible(true);
|
||||
return f.get(null);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isDebugReflection() {
|
||||
return !"false".equals(System.getProperty("lombok.debug.reflection", "false"));
|
||||
}
|
||||
|
||||
public static void handleReflectionDebug(Throwable t, Throwable initError) {
|
||||
if (!isDebugReflection()) return;
|
||||
|
||||
System.err.println("** LOMBOK REFLECTION exception: " + t.getClass() + ": " + (t.getMessage() == null ? "(no message)" : t.getMessage()));
|
||||
t.printStackTrace(System.err);
|
||||
if (initError != null) {
|
||||
System.err.println("*** ADDITIONALLY, exception occurred setting up reflection: ");
|
||||
initError.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object invoke(Method m, Object receiver, Object... args) throws IllegalAccessException, InvocationTargetException {
|
||||
return invoke(null, m, receiver, args);
|
||||
}
|
||||
|
||||
public static Object invoke(Throwable initError, Method m, Object receiver, Object... args) throws IllegalAccessException, InvocationTargetException {
|
||||
try {
|
||||
return m.invoke(receiver, args);
|
||||
} catch (IllegalAccessException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object invokeSneaky(Method m, Object receiver, Object... args) {
|
||||
return invokeSneaky(null, m, receiver, args);
|
||||
}
|
||||
|
||||
public static Object invokeSneaky(Throwable initError, Method m, Object receiver, Object... args) {
|
||||
try {
|
||||
return m.invoke(receiver, args);
|
||||
} catch (NoClassDefFoundError e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
//ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
|
||||
//do anything useful here.
|
||||
return null;
|
||||
} catch (NullPointerException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
//ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
|
||||
//do anything useful here.
|
||||
return null;
|
||||
} catch (IllegalAccessException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw sneakyThrow(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw sneakyThrow(e.getCause());
|
||||
} catch (RuntimeException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T newInstance(Constructor<T> c, Object... args) throws IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
return newInstance(null, c, args);
|
||||
}
|
||||
|
||||
public static <T> T newInstance(Throwable initError, Constructor<T> c, Object... args) throws IllegalAccessException, InvocationTargetException, InstantiationException {
|
||||
try {
|
||||
return c.newInstance(args);
|
||||
} catch (IllegalAccessException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
} catch (InstantiationException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T newInstanceSneaky(Constructor<T> c, Object... args) {
|
||||
return newInstanceSneaky(null, c, args);
|
||||
}
|
||||
|
||||
public static <T> T newInstanceSneaky(Throwable initError, Constructor<T> c, Object... args) {
|
||||
try {
|
||||
return c.newInstance(args);
|
||||
} catch (NoClassDefFoundError e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
//ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
|
||||
//do anything useful here.
|
||||
return null;
|
||||
} catch (NullPointerException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
//ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
|
||||
//do anything useful here.
|
||||
return null;
|
||||
} catch (IllegalAccessException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw sneakyThrow(e);
|
||||
} catch (InstantiationException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw sneakyThrow(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw sneakyThrow(e.getCause());
|
||||
} catch (RuntimeException e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
handleReflectionDebug(e, initError);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object get(Field f, Object receiver) throws IllegalAccessException {
|
||||
try {
|
||||
return f.get(receiver);
|
||||
} catch (IllegalAccessException e) {
|
||||
handleReflectionDebug(e, null);
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
handleReflectionDebug(e, null);
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
handleReflectionDebug(e, null);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static void set(Field f, Object receiver, Object newValue) throws IllegalAccessException {
|
||||
try {
|
||||
f.set(receiver, newValue);
|
||||
} catch (IllegalAccessException e) {
|
||||
handleReflectionDebug(e, null);
|
||||
throw e;
|
||||
} catch (RuntimeException e) {
|
||||
handleReflectionDebug(e, null);
|
||||
throw e;
|
||||
} catch (Error e) {
|
||||
handleReflectionDebug(e, null);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static void reportReflectionProblem(Throwable initError, String msg) {
|
||||
if (!isDebugReflection()) return;
|
||||
System.err.println("** LOMBOK REFLECTION issue: " + msg);
|
||||
if (initError != null) {
|
||||
System.err.println("*** ADDITIONALLY, exception occurred setting up reflection: ");
|
||||
initError.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
|
||||
public static RuntimeException sneakyThrow(Throwable t) {
|
||||
if (t == null) throw new NullPointerException("t");
|
||||
return Permit.<RuntimeException>sneakyThrow0(t);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T extends Throwable> 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) {}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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.
|
||||
* <p>
|
||||
* NB: It's usually 12, on the vast majority of OS, VM, and architecture combos.
|
||||
*/
|
||||
package org.apache.dubbo.annotation.permit.dummy;
|
||||
|
|
@ -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
|
||||
* <p>
|
||||
* 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;
|
||||
|
|
@ -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<JCTree.JCImport> 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<JCTree> defs = compilationUnit.defs;
|
||||
|
||||
ListBuffer<JCTree> 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("<init>");
|
||||
ListBuffer<JCTree.JCStatement> 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Path> getAllClassFilePaths(String rootPath) {
|
||||
List<Path> targetFolders;
|
||||
|
||||
try (Stream<Path> 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<String> loadConfigurationFileInResources(String path) {
|
||||
|
||||
ReadableByteChannel resourceReadableByteChannel = Channels.newChannel(
|
||||
Objects.requireNonNull(FileUtils.class.getClassLoader().getResourceAsStream(path)));
|
||||
|
||||
List<String> 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Get absolute path of resource.
|
||||
*
|
||||
* <p>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<Path> getAllFilesInDirectory(Path targetFolder) {
|
||||
|
||||
try (Stream<Path> classFilesStream = Files.walk(targetFolder)) {
|
||||
|
||||
return classFilesStream
|
||||
.filter(x -> x.toFile().isFile())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
} catch (IOException e) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
org.apache.dubbo.annotation.DispatchingAnnotationProcessor
|
||||
|
|
@ -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
|
||||
|
|
@ -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<String, Boolean> 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<String, Boolean> 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<String> stringItems = JavassistUtils.getConstPoolStringItems(classFile.getConstPool());
|
||||
|
||||
Assertions.assertEquals(i.getValue(), stringItems.contains("org/apache/dubbo/common/DeprecatedMethodInvocationCounter"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Class, Field> 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<Object> getConstPoolItems(ConstPool cp) {
|
||||
List<Object> 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<ConstPool> 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<String> getConstPoolStringItems(ConstPool cp) {
|
||||
List<Object> objects = getConstPoolItems(cp);
|
||||
List<String> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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.
|
||||
* <p>
|
||||
* 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<String, LongAdder> 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<String, Integer> getInvocationRecord() {
|
||||
// Perform a deep-copy to avoid concurrent issues.
|
||||
HashMap<String, Integer> copyOfCounters = new HashMap<>();
|
||||
|
||||
for (Map.Entry<String, LongAdder> entry : COUNTERS.entrySet()) {
|
||||
copyOfCounters.put(entry.getKey(), entry.getValue().intValue());
|
||||
}
|
||||
|
||||
return Collections.unmodifiableMap(copyOfCounters);
|
||||
}
|
||||
}
|
||||
|
|
@ -277,7 +277,7 @@ public final class ConfigurationUtils {
|
|||
for (Map.Entry<String, V> 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<String, V> 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;
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@ public interface ApplicationDeployer extends Deployer<ApplicationModel> {
|
|||
/**
|
||||
* Register application instance and start internal services
|
||||
*/
|
||||
void prepareApplicationInstance();
|
||||
void prepareApplicationInstance(ModuleModel moduleModel);
|
||||
|
||||
void exportMetadataService();
|
||||
|
||||
/**
|
||||
* Register application instance and start internal services
|
||||
|
|
|
|||
|
|
@ -50,4 +50,8 @@ public interface ModuleDeployer extends Deployer<ModuleModel> {
|
|||
* Whether start in background, do not await finish
|
||||
*/
|
||||
boolean isBackground();
|
||||
|
||||
boolean hasRegistryInteraction();
|
||||
|
||||
ApplicationDeployer getApplicationDeployer();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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<String, Integer> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<T> extends ServiceConfigBase<T> {
|
|||
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<T> extends ServiceConfigBase<T> {
|
|||
// 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<String> 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<T> extends ServiceConfigBase<T> {
|
|||
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()) {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY;
|
|||
public class InternalServiceConfigBuilder<T> {
|
||||
|
||||
private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass());
|
||||
private static final Set<String> UNACCEPTABLE_PROTOCOL = Stream.of("rest", "grpc").collect(Collectors.toSet());
|
||||
private static final Set<String> ACCEPTABLE_PROTOCOL = Stream.of("dubbo", "tri", "injvm").collect(Collectors.toSet());
|
||||
|
||||
private final ApplicationModel applicationModel;
|
||||
private String protocol;
|
||||
|
|
@ -112,19 +112,20 @@ public class InternalServiceConfigBuilder<T> {
|
|||
*/
|
||||
private String getRelatedOrDefaultProtocol() {
|
||||
String protocol = "";
|
||||
// <dubbo:consumer/>
|
||||
List<ModuleModel> 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("");
|
||||
// <dubbo:protocol/>
|
||||
if (StringUtils.isEmpty(protocol)) {
|
||||
Collection<ProtocolConfig> 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("");
|
||||
}
|
||||
}
|
||||
// <dubbo:provider/>
|
||||
List<ModuleModel> moduleModels = applicationModel.getPubModuleModels();
|
||||
if (StringUtils.isEmpty(protocol)) {
|
||||
Stream<ProviderConfig> providerConfigStream = moduleModels.stream()
|
||||
.map(ModuleModel::getConfigManager)
|
||||
|
|
@ -145,22 +146,10 @@ public class InternalServiceConfigBuilder<T> {
|
|||
}
|
||||
})
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.filter(p -> !UNACCEPTABLE_PROTOCOL.contains(p))
|
||||
.filter(p -> ACCEPTABLE_PROTOCOL.contains(p))
|
||||
.findFirst()
|
||||
.orElse("");
|
||||
}
|
||||
// <dubbo:protocol/>
|
||||
if (StringUtils.isEmpty(protocol)) {
|
||||
Collection<ProtocolConfig> 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("");
|
||||
}
|
||||
}
|
||||
// <dubbo:application/>
|
||||
if (StringUtils.isEmpty(protocol)) {
|
||||
protocol = getApplicationConfig().getProtocol();
|
||||
|
|
@ -171,7 +160,18 @@ public class InternalServiceConfigBuilder<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
return StringUtils.isNotEmpty(protocol) && !UNACCEPTABLE_PROTOCOL.contains(protocol) ? protocol : DUBBO_PROTOCOL;
|
||||
// <dubbo:consumer/>
|
||||
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<T> protocol(String protocol) {
|
||||
|
|
@ -254,7 +254,11 @@ public class InternalServiceConfigBuilder<T> {
|
|||
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();
|
||||
|
||||
|
|
|
|||
|
|
@ -183,13 +183,13 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
}
|
||||
|
||||
/**
|
||||
* Close registration of instance for pure Consumer process by setting registerConsumer to 'false'
|
||||
* by default is true.
|
||||
* Enable registration of instance for pure Consumer process by setting registerConsumer to 'true'
|
||||
* by default is false.
|
||||
*/
|
||||
private boolean isRegisterConsumerInstance() {
|
||||
Boolean registerConsumer = getApplication().getRegisterConsumer();
|
||||
Boolean registerConsumer = getApplicationOrElseThrow().getRegisterConsumer();
|
||||
if (registerConsumer == null) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
return Boolean.TRUE.equals(registerConsumer);
|
||||
}
|
||||
|
|
@ -310,7 +310,7 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
|
||||
useRegistryAsMetadataCenterIfNecessary();
|
||||
|
||||
ApplicationConfig applicationConfig = getApplication();
|
||||
ApplicationConfig applicationConfig = getApplicationOrElseThrow();
|
||||
|
||||
String metadataType = applicationConfig.getMetadataType();
|
||||
// FIXME, multiple metadata config support.
|
||||
|
|
@ -747,7 +747,7 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
}
|
||||
|
||||
@Override
|
||||
public void prepareApplicationInstance() {
|
||||
public void prepareApplicationInstance(ModuleModel moduleModel) {
|
||||
if (hasPreparedApplicationInstance.get()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -755,8 +755,7 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
// export MetricsService
|
||||
exportMetricsService();
|
||||
|
||||
if (isRegisterConsumerInstance()) {
|
||||
exportMetadataService();
|
||||
if (isRegisterConsumerInstance() || moduleModel.getDeployer().hasRegistryInteraction()) {
|
||||
if (hasPreparedApplicationInstance.compareAndSet(false, true)) {
|
||||
// register the local ServiceInstance if required
|
||||
registerServiceInstance();
|
||||
|
|
@ -764,6 +763,11 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void exportMetadataService() {
|
||||
doExportMetadataService();
|
||||
}
|
||||
|
||||
public void prepareInternalModule() {
|
||||
if (hasPreparedInternalModule) {
|
||||
return;
|
||||
|
|
@ -855,14 +859,18 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
if (StringUtils.isNotEmpty(configContent)) {
|
||||
logger.info(String.format("Got global remote configuration from config center with key-%s and group-%s: \n %s", configCenter.getConfigFile(), configCenter.getGroup(), configContent));
|
||||
}
|
||||
String appGroup = getApplication().getName();
|
||||
String appGroup = "";
|
||||
String appConfigContent = null;
|
||||
String appConfigFile = null;
|
||||
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));
|
||||
Optional<ApplicationConfig> 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<ApplicationMode
|
|||
public void checkState(ModuleModel moduleModel, DeployState moduleState) {
|
||||
synchronized (stateLock) {
|
||||
if (!moduleModel.isInternal() && moduleState == DeployState.STARTED) {
|
||||
prepareApplicationInstance();
|
||||
prepareApplicationInstance(moduleModel);
|
||||
}
|
||||
DeployState newState = calculateState();
|
||||
switch (newState) {
|
||||
|
|
@ -1184,8 +1192,8 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
}
|
||||
}
|
||||
|
||||
private void exportMetadataService() {
|
||||
if (!isStarting()) {
|
||||
private void doExportMetadataService() {
|
||||
if (!isStarting() && !isStarted()) {
|
||||
return;
|
||||
}
|
||||
for (DeployListener<ApplicationModel> listener : listeners) {
|
||||
|
|
@ -1319,9 +1327,12 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
}
|
||||
}
|
||||
|
||||
private ApplicationConfig getApplication() {
|
||||
private ApplicationConfig getApplicationOrElseThrow() {
|
||||
return configManager.getApplicationOrElseThrow();
|
||||
}
|
||||
|
||||
private Optional<ApplicationConfig> getApplication() {
|
||||
return configManager.getApplication();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,6 +87,9 @@ public class DefaultModuleDeployer extends AbstractDeployer<ModuleModel> 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<ModuleModel> impleme
|
|||
exportedServices.add(sc);
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceConfig.hasRegistrySpecified()) {
|
||||
registryInteracted = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void registerServiceInternal(ServiceConfigBase sc) {
|
||||
|
|
@ -578,4 +585,13 @@ public class DefaultModuleDeployer extends AbstractDeployer<ModuleModel> impleme
|
|||
this.initialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRegistryInteraction() {
|
||||
return registryInteracted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationDeployer getApplicationDeployer() {
|
||||
return applicationDeployer;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<Exporter<?>> injvmExporters = exporterListener.getExportedExporters()
|
||||
.stream()
|
||||
.filter(
|
||||
exporter -> PROTOCOL_NAME.equalsIgnoreCase(exporter.getInvoker().getUrl().getProtocol())
|
||||
).collect(Collectors.toList());
|
||||
List<Exporter<?>> 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...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Exporter<?>> injvmExporters = exporterListener.getExportedExporters()
|
||||
.stream()
|
||||
.filter(
|
||||
exporter -> PROTOCOL_NAME.equalsIgnoreCase(exporter.getInvoker().getUrl().getProtocol())
|
||||
).collect(Collectors.toList());
|
||||
List<Exporter<?>> 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...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class MetadataServiceURLParamsMetadataCustomizerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
void test() throws InterruptedException {
|
||||
DubboBootstrap providerBootstrap = DubboBootstrap.newInstance();
|
||||
ServiceConfig<DemoService> 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,17 @@
|
|||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>spring6</id>
|
||||
<activation>
|
||||
<jdk>[17,)</jdk>
|
||||
</activation>
|
||||
<modules>
|
||||
<module>dubbo-config-api</module>
|
||||
<module>dubbo-config-spring</module>
|
||||
<module>dubbo-config-spring6</module>
|
||||
</modules>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
<modules>
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@
|
|||
<portlet_version>2.0</portlet_version>
|
||||
<maven_flatten_version>1.5.0</maven_flatten_version>
|
||||
<commons_compress_version>1.23.0</commons_compress_version>
|
||||
<revision>3.3.0-beta.1-SNAPSHOT</revision>
|
||||
<revision>3.3.0-beta.1</revision>
|
||||
<open_feign_version>3.1.5</open_feign_version>
|
||||
</properties>
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<revision>3.3.0-beta.1-SNAPSHOT</revision>
|
||||
<revision>3.3.0-beta.1</revision>
|
||||
<maven_flatten_version>1.5.0</maven_flatten_version>
|
||||
<slf4j_version>1.7.36</slf4j_version>
|
||||
<curator5_version>5.1.0</curator5_version>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
<packaging>pom</packaging>
|
||||
|
||||
<properties>
|
||||
<revision>3.3.0-beta.1-SNAPSHOT</revision>
|
||||
<revision>3.3.0-beta.1</revision>
|
||||
<maven_flatten_version>1.5.0</maven_flatten_version>
|
||||
<slf4j_version>1.7.36</slf4j_version>
|
||||
<curator_version>4.3.0</curator_version>
|
||||
|
|
|
|||
|
|
@ -496,6 +496,13 @@
|
|||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-remoting-http12</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-remoting-netty</artifactId>
|
||||
|
|
@ -714,6 +721,7 @@
|
|||
<include>org.apache.dubbo:dubbo-registry-zookeeper</include>
|
||||
<include>org.apache.dubbo:dubbo-remoting-api</include>
|
||||
<include>org.apache.dubbo:dubbo-remoting-http</include>
|
||||
<include>org.apache.dubbo:dubbo-remoting-http12</include>
|
||||
<include>org.apache.dubbo:dubbo-remoting-netty4</include>
|
||||
<include>org.apache.dubbo:dubbo-remoting-netty</include>
|
||||
<include>org.apache.dubbo:dubbo-remoting-zookeeper-api</include>
|
||||
|
|
@ -1233,6 +1241,30 @@
|
|||
META-INF/dubbo/internal/org.apache.dubbo.remoting.http.HttpBinder
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodec
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.message.HttpMessageCodecFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.h2.Http2ServerTransportListenerFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
META-INF/dubbo/internal/org.apache.dubbo.remoting.http12.h1.Http1ServerTransportListenerFactory
|
||||
</resource>
|
||||
</transformer>
|
||||
<transformer
|
||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||
<resource>
|
||||
|
|
|
|||
|
|
@ -517,6 +517,11 @@
|
|||
<artifactId>dubbo-remoting-http</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-remoting-http12</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-remoting-netty</artifactId>
|
||||
|
|
|
|||
|
|
@ -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<ServiceInfo> subServices = subscribedServices.get(serviceKeyWithoutProtocol);
|
||||
if (CollectionUtils.isNotEmpty(subServices)) {
|
||||
return subServices.iterator().next();
|
||||
List<ServiceInfo> 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,15 +121,4 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<proc>none</proc>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -34,6 +34,6 @@
|
|||
<artifactId>dubbo-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -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<R> response = func.apply(Mono.just(request));
|
||||
ServerTripleReactorSubscriber<R> subscriber = response.subscribeWith(new ServerTripleReactorSubscriber<>());
|
||||
subscriber.subscribe((ServerCallToObserverAdapter<R>) responseObserver);
|
||||
subscriber.subscribe((CallStreamObserver<R>) responseObserver);
|
||||
} catch (Throwable throwable) {
|
||||
responseObserver.onError(throwable);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry {
|
|||
return factory.getServiceDiscovery(registryURL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldRegister(URL providerURL) {
|
||||
|
||||
String side = providerURL.getSide();
|
||||
|
|
|
|||
|
|
@ -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<T> extends DynamicDirectory<T> {
|
|||
.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());
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ServiceDiscovery> 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<ServiceDiscovery> 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;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<T> extends DynamicDirectory<T> {
|
|||
}
|
||||
|
||||
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<T> extends DynamicDirectory<T> {
|
|||
return newUrlInvokerMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the protocol to consume by matching the consumer acceptable protocols and the available provider protocols.
|
||||
* <p>
|
||||
* 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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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<WireProtocol> 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<WireProtocol> loader = url.getOrDefaultFrameworkModel().getExtensionLoader(WireProtocol.class);
|
||||
List<WireProtocol> 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<WireProtocol> getProtocols() {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-remoting</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>dubbo-remoting-http12</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>The http1/2 remoting module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-rpc-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-remoting-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java-util</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-codec-http2</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -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<Object> {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<InputStream> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<T> extends HttpChannelObserver<T> {
|
||||
|
||||
void setHeadersCustomizer(HeadersCustomizer headersCustomizer);
|
||||
|
||||
void setTrailersCustomizer(TrailersCustomizer trailersCustomizer);
|
||||
|
||||
void setErrorResponseCustomizer(ErrorResponseCustomizer errorResponseCustomizer);
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<ErrorResponse, Throwable> {
|
||||
|
||||
ErrorResponseCustomizer NO_OP = (errorResponse, throwable) -> {
|
||||
};
|
||||
}
|
||||
|
|
@ -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<T> extends StreamObserver<T> {
|
||||
|
||||
/**
|
||||
* 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
|
||||
* <p>This method is safe to call from multiple threads without external synchronization.
|
||||
*
|
||||
* @param count more messages
|
||||
*/
|
||||
Set<Class<? extends Annotation>> 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<Element> elements,
|
||||
AnnotationProcessorContext annotationProcessorContext);
|
||||
void disableAutoFlowControl();
|
||||
|
||||
}
|
||||
|
|
@ -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<HttpHeaders> {
|
||||
|
||||
HeadersCustomizer NO_OP = headers -> {
|
||||
};
|
||||
}
|
||||
|
|
@ -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<Void> writeHeader(HttpMetadata httpMetadata);
|
||||
|
||||
CompletableFuture<Void> writeMessage(HttpOutputMessage httpOutputMessage);
|
||||
|
||||
HttpOutputMessage newOutputMessage();
|
||||
|
||||
SocketAddress remoteAddress();
|
||||
|
||||
void flush();
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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<T> extends StreamObserver<T> {
|
||||
|
||||
HttpChannel getHttpChannel();
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String, List<String>>, Serializable, Cloneable {
|
||||
|
||||
private final LinkedHashMap<String, List<String>> targetMap;
|
||||
|
||||
private final HashMap<String, String> caseInsensitiveKeys;
|
||||
|
||||
private final Locale locale;
|
||||
|
||||
private transient volatile Set<String> keySet;
|
||||
|
||||
private transient volatile Collection<List<String>> values;
|
||||
|
||||
private transient volatile Set<Entry<String, List<String>>> 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<String> 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<String> values = get(name);
|
||||
if (values == null || values.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return values.get(0);
|
||||
}
|
||||
|
||||
public void set(String name, String value) {
|
||||
List<String> values = new ArrayList<>();
|
||||
values.add(value);
|
||||
put(name, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public List<String> getOrDefault(Object key, List<String> 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<String> put(String key, List<String> value) {
|
||||
String oldKey = this.caseInsensitiveKeys.put(convertKey(key), key);
|
||||
List<String> oldKeyValue = null;
|
||||
if (oldKey != null && !oldKey.equals(key)) {
|
||||
oldKeyValue = this.targetMap.remove(oldKey);
|
||||
}
|
||||
List<String> oldValue = this.targetMap.put(key, value);
|
||||
return (oldKeyValue != null ? oldKeyValue : oldValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends String, ? extends List<String>> map) {
|
||||
if (map.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
map.forEach(this::put);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public List<String> putIfAbsent(String key, List<String> value) {
|
||||
String oldKey = this.caseInsensitiveKeys.putIfAbsent(convertKey(key), key);
|
||||
if (oldKey != null) {
|
||||
List<String> oldKeyValue = this.targetMap.get(oldKey);
|
||||
if (oldKeyValue != null) {
|
||||
return oldKeyValue;
|
||||
} else {
|
||||
key = oldKey;
|
||||
}
|
||||
}
|
||||
return this.targetMap.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public List<String> computeIfAbsent(String key, Function<? super String, ? extends List<String>> mappingFunction) {
|
||||
String oldKey = this.caseInsensitiveKeys.putIfAbsent(convertKey(key), key);
|
||||
if (oldKey != null) {
|
||||
List<String> oldKeyValue = this.targetMap.get(oldKey);
|
||||
if (oldKeyValue != null) {
|
||||
return oldKeyValue;
|
||||
} else {
|
||||
key = oldKey;
|
||||
}
|
||||
}
|
||||
return this.targetMap.computeIfAbsent(key, mappingFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public List<String> 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<String> keySet() {
|
||||
Set<String> keySet = this.keySet;
|
||||
if (keySet == null) {
|
||||
keySet = new KeySet(this.targetMap.keySet());
|
||||
this.keySet = keySet;
|
||||
}
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<List<String>> values() {
|
||||
Collection<List<String>> values = this.values;
|
||||
if (values == null) {
|
||||
values = new Values(this.targetMap.values());
|
||||
this.values = values;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Entry<String, List<String>>> entrySet() {
|
||||
Set<Entry<String, List<String>>> entrySet = this.entrySet;
|
||||
if (entrySet == null) {
|
||||
entrySet = new EntrySet(this.targetMap.entrySet());
|
||||
this.entrySet = entrySet;
|
||||
}
|
||||
return entrySet;
|
||||
}
|
||||
|
||||
public Map<String, String> toSingleValueMap() {
|
||||
Map<String, String> 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<String, List<String>> eldest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private String removeCaseInsensitiveKey(String key) {
|
||||
return this.caseInsensitiveKeys.remove(convertKey(key));
|
||||
}
|
||||
|
||||
|
||||
private class KeySet extends AbstractSet<String> {
|
||||
|
||||
private final Set<String> delegate;
|
||||
|
||||
KeySet(Set<String> 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<String> 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<String> spliterator() {
|
||||
return this.delegate.spliterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super String> action) {
|
||||
this.delegate.forEach(action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class Values extends AbstractCollection<List<String>> {
|
||||
|
||||
private final Collection<List<String>> delegate;
|
||||
|
||||
Values(Collection<List<String>> 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<List<String>> iterator() {
|
||||
return new ValuesIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
HttpHeaders.this.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<List<String>> spliterator() {
|
||||
return this.delegate.spliterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super List<String>> action) {
|
||||
this.delegate.forEach(action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class EntrySet extends AbstractSet<Entry<String, List<String>>> {
|
||||
|
||||
private final Set<Entry<String, List<String>>> delegate;
|
||||
|
||||
public EntrySet(Set<Entry<String, List<String>>> 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<Entry<String, List<String>>> iterator() {
|
||||
return new EntrySetIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean remove(Object o) {
|
||||
if (this.delegate.remove(o)) {
|
||||
removeCaseInsensitiveKey(((Map.Entry<String, List<String>>) o).getKey());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.delegate.clear();
|
||||
caseInsensitiveKeys.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<Entry<String, List<String>>> spliterator() {
|
||||
return this.delegate.spliterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEach(Consumer<? super Entry<String, List<String>>> action) {
|
||||
this.delegate.forEach(action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private abstract class EntryIterator<T> implements Iterator<T> {
|
||||
|
||||
private final Iterator<Entry<String, List<String>>> delegate;
|
||||
|
||||
|
||||
private Entry<String, List<String>> last;
|
||||
|
||||
public EntryIterator() {
|
||||
this.delegate = targetMap.entrySet().iterator();
|
||||
}
|
||||
|
||||
protected Entry<String, List<String>> nextEntry() {
|
||||
Entry<String, List<String>> 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<String> {
|
||||
|
||||
@Override
|
||||
public String next() {
|
||||
return nextEntry().getKey();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class ValuesIterator extends EntryIterator<List<String>> {
|
||||
|
||||
@Override
|
||||
public List<String> next() {
|
||||
return nextEntry().getValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class EntrySetIterator extends EntryIterator<Entry<String, List<String>>> {
|
||||
|
||||
@Override
|
||||
public Entry<String, List<String>> next() {
|
||||
return nextEntry();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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! ");
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<HEADER extends HttpMetadata, MESSAGE extends HttpInputMessage> {
|
||||
|
||||
void onMetadata(HEADER metadata);
|
||||
|
||||
void onData(MESSAGE message);
|
||||
|
||||
}
|
||||
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
|
@ -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<HttpHeaders, Throwable>, HeadersCustomizer {
|
||||
|
||||
TrailersCustomizer NO_OP = (headers, throwable) -> {
|
||||
};
|
||||
|
||||
@Override
|
||||
default void accept(HttpHeaders headers) {
|
||||
this.accept(headers, null);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Void> implements QueueCommand, HttpChannelHolder {
|
||||
|
||||
private HttpChannelHolder httpChannelHolder;
|
||||
|
||||
public void setHttpChannel(HttpChannelHolder httpChannelHolder) {
|
||||
this.httpChannelHolder = httpChannelHolder;
|
||||
}
|
||||
|
||||
public HttpChannel getHttpChannel() {
|
||||
return httpChannelHolder.getHttpChannel();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<HttpChannelQueueCommand> {
|
||||
|
||||
private final Executor executor;
|
||||
|
||||
public HttpWriteQueue(Executor executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Object> {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue