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:
Albumen Kevin 2023-11-03 21:30:19 +08:00
commit d00757e65b
190 changed files with 7409 additions and 2245 deletions

View File

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

View File

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

View File

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

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

View File

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

View File

@ -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 +
'}';
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1 +0,0 @@
org.apache.dubbo.annotation.DispatchingAnnotationProcessor

View File

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

View File

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

View File

@ -1,71 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -50,4 +50,8 @@ public interface ModuleDeployer extends Deployer<ModuleModel> {
* Whether start in background, do not await finish
*/
boolean isBackground();
boolean hasRegistryInteraction();
ApplicationDeployer getApplicationDeployer();
}

View File

@ -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() {

View File

@ -1,59 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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);
}
}
}

View File

@ -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()) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,6 +34,6 @@
<artifactId>dubbo-common</artifactId>
<version>${project.parent.version}</version>
</dependency>
</dependencies>
</dependencies>
</project>

View File

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

View File

@ -127,6 +127,7 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry {
return factory.getServiceDiscovery(registryURL);
}
@Override
protected boolean shouldRegister(URL providerURL) {
String side = providerURL.getSide();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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");
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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