This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.3
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.3 by this push:
new 0b6f2e4a8d Add Dubbo Annotation Processor (Add deprecated method warn
when called by user, #10850) (#11513)
0b6f2e4a8d is described below
commit 0b6f2e4a8d045e137ce2b440e7fdd79941c57ec5
Author: Andy Cheung <[email protected]>
AuthorDate: Fri Mar 24 09:48:08 2023 +0800
Add Dubbo Annotation Processor (Add deprecated method warn when called by
user, #10850) (#11513)
---
.licenserc.yaml | 1 +
NOTICE | 2 +-
dubbo-annotation-processor/pom.xml | 165 ++++++++
.../annotation/AnnotationProcessingHandler.java | 44 +++
.../annotation/AnnotationProcessorContext.java | 139 +++++++
.../annotation/DispatchingAnnotationProcessor.java | 162 ++++++++
.../annotation/handler/DeprecatedHandler.java | 110 ++++++
.../org/apache/dubbo/annotation/permit/Permit.java | 429 +++++++++++++++++++++
.../dubbo/annotation/permit/dummy/Child.java | 33 ++
.../dubbo/annotation/permit/dummy/GrandChild.java | 43 +++
.../dubbo/annotation/permit/dummy/Parent.java | 36 ++
.../annotation/permit/dummy/package-info.java | 32 ++
.../dubbo/annotation/permit/package-info.java | 32 ++
.../org/apache/dubbo/annotation/util/ASTUtils.java | 111 ++++++
.../apache/dubbo/annotation/util/FileUtils.java | 155 ++++++++
.../services/javax.annotation.processing.Processor | 1 +
.../src/main/resources/handlers.cfg | 17 +
.../dubbo/annotation/RealInvocationTest.java | 64 +++
.../apache/dubbo/annotation/TestingCommons.java | 71 ++++
.../common/DeprecatedMethodInvocationCounter.java | 36 ++
.../apache/dubbo/eci/extractor/JavassistUtils.java | 151 ++++++++
.../org/apache/dubbo/eci/util/ReflectUtils.java | 51 +++
.../org/testing/dm/TestConstructorMethod.java | 28 ++
.../dm/TestConstructorMethodParentClass.java | 27 ++
.../testing/dm/TestConstructorMethodSubClass.java | 30 ++
.../org/testing/dm/TestDeprecatedMethod.java | 26 ++
.../testing/dm/TestInterfaceDeprecatedMethod.java | 24 ++
dubbo-build-tools/pom.xml | 8 +-
.../common/DeprecatedMethodInvocationCounter.java | 83 ++++
...DeprecatedMethodInvocationCounterConstants.java | 35 ++
.../common/constants/LoggerCodeConstants.java | 4 +
.../DeprecatedMethodInvocationCounterTest.java | 59 +++
dubbo-config/dubbo-config-api/pom.xml | 1 -
dubbo-metadata/dubbo-metadata-processor/pom.xml | 13 +
.../java/org/apache/dubbo/dependency/FileTest.java | 2 +
pom.xml | 10 +-
36 files changed, 2228 insertions(+), 7 deletions(-)
diff --git a/.licenserc.yaml b/.licenserc.yaml
index 5b8980c95e..de74c43f6c 100644
--- a/.licenserc.yaml
+++ b/.licenserc.yaml
@@ -98,6 +98,7 @@ header:
-
'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/BasicJsonWriter.java'
-
'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/ExecutableMode.java'
-
'dubbo-native/src/main/java/org/apache/dubbo/aot/generate/MemberCategory.java'
+ -
'dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/**'
comment: on-failure
diff --git a/NOTICE b/NOTICE
index a060218b41..d409c01b52 100644
--- a/NOTICE
+++ b/NOTICE
@@ -4,7 +4,7 @@ Copyright 2018-2023 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
-This product contains code form the Netty Project:
+This product contains code from the Netty Project:
The Netty Project
=================
diff --git a/dubbo-annotation-processor/pom.xml
b/dubbo-annotation-processor/pom.xml
new file mode 100644
index 0000000000..8a89f1bf74
--- /dev/null
+++ b/dubbo-annotation-processor/pom.xml
@@ -0,0 +1,165 @@
+<?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>8</maven.compiler.source>
+ <maven.compiler.target>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>
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessingHandler.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessingHandler.java
new file mode 100644
index 0000000000..4830e32704
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessingHandler.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.annotation;
+
+import javax.lang.model.element.Element;
+import java.lang.annotation.Annotation;
+import java.util.Set;
+
+/**
+ * Represents an annotation processing handler, which is invoked by
DispatchingAnnotationProcessor.
+ */
+public interface AnnotationProcessingHandler {
+
+ /**
+ * Set the annotations that this handler will handle.
+ *
+ * @return annotations to handle
+ */
+ Set<Class<? extends Annotation>> getAnnotationsToHandle();
+
+ /**
+ * Formal processing method.
+ *
+ * @param elements the elements that annotated by the annotations of
getAnnotationsToHandle()
+ * @param annotationProcessorContext the annotation processor context
object (Javac object encapsulation)
+ */
+ void process(Set<Element> elements,
+ AnnotationProcessorContext annotationProcessorContext);
+}
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessorContext.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessorContext.java
new file mode 100644
index 0000000000..958385aba6
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/AnnotationProcessorContext.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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 +
+ '}';
+ }
+}
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/DispatchingAnnotationProcessor.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/DispatchingAnnotationProcessor.java
new file mode 100644
index 0000000000..8c11d72eff
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/DispatchingAnnotationProcessor.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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();
+ }
+}
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/handler/DeprecatedHandler.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/handler/DeprecatedHandler.java
new file mode 100644
index 0000000000..c87cb8f6c9
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/handler/DeprecatedHandler.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.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() + ")";
+ }
+}
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/Permit.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/Permit.java
new file mode 100644
index 0000000000..3d5c941764
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/Permit.java
@@ -0,0 +1,429 @@
+/*
+ * 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) {}
+ }
+}
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Child.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Child.java
new file mode 100644
index 0000000000..46c647bedc
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Child.java
@@ -0,0 +1,33 @@
+/*
+ * Authored by Project Lombok and licensed by MIT License, which is attached
below:
+ *
+ * Copyright (C) 2018-2021 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.dubbo.annotation.permit.dummy;
+
+@SuppressWarnings("all")
+public abstract class Child extends Parent {
+ private transient volatile boolean foo;
+ private transient volatile Object[] bar;
+ private transient volatile Object baz;
+
+}
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/GrandChild.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/GrandChild.java
new file mode 100644
index 0000000000..c2bf737629
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/GrandChild.java
@@ -0,0 +1,43 @@
+/*
+ * Authored by Project Lombok and licensed by MIT License, which is attached
below:
+ *
+ * Copyright (C) 2018-2021 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.dubbo.annotation.permit.dummy;
+
+@SuppressWarnings("all")
+public final class GrandChild extends Child {
+ private Class<?> a;
+ private int b;
+ private String c;
+ private Class<?> d;
+ private Class<?>[] e;
+ private Class<?>[] f;
+ private int g;
+ private transient String h;
+ private transient Object i;
+ private byte[] j;
+ private byte[] k;
+ private byte[] l;
+ private volatile Object m;
+ private Object n;
+}
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Parent.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Parent.java
new file mode 100644
index 0000000000..53cb8c8ce5
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/Parent.java
@@ -0,0 +1,36 @@
+/*
+ * Authored by Project Lombok and licensed by MIT License, which is attached
below:
+ *
+ * Copyright (C) 2018-2021 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+package org.apache.dubbo.annotation.permit.dummy;
+
+import java.io.OutputStream;
+
+@SuppressWarnings("all")
+public class Parent {
+ boolean first;
+ static final Object staticObj = OutputStream.class;
+ volatile Object second;
+ private static volatile boolean staticSecond;
+ private static volatile boolean staticThird;
+}
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/package-info.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/package-info.java
new file mode 100644
index 0000000000..dcbf5a58a0
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/dummy/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/package-info.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/package-info.java
new file mode 100644
index 0000000000..95b72451c6
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/permit/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/ASTUtils.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/ASTUtils.java
new file mode 100644
index 0000000000..bfd463785f
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/ASTUtils.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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();
+ }
+}
diff --git
a/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/FileUtils.java
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/FileUtils.java
new file mode 100644
index 0000000000..66a897913a
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/java/org/apache/dubbo/annotation/util/FileUtils.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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();
+ }
+ }
+}
diff --git
a/dubbo-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
b/dubbo-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000000..fe51e15be0
--- /dev/null
+++
b/dubbo-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+org.apache.dubbo.annotation.DispatchingAnnotationProcessor
diff --git a/dubbo-annotation-processor/src/main/resources/handlers.cfg
b/dubbo-annotation-processor/src/main/resources/handlers.cfg
new file mode 100644
index 0000000000..bcdca71445
--- /dev/null
+++ b/dubbo-annotation-processor/src/main/resources/handlers.cfg
@@ -0,0 +1,17 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+org.apache.dubbo.annotation.handler.DeprecatedHandler
diff --git
a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/RealInvocationTest.java
b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/RealInvocationTest.java
new file mode 100644
index 0000000000..9544990ffe
--- /dev/null
+++
b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/RealInvocationTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.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"));
+ }
+ }
+}
diff --git
a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/TestingCommons.java
b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/TestingCommons.java
new file mode 100644
index 0000000000..cca11f56e6
--- /dev/null
+++
b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/annotation/TestingCommons.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.annotation;
+
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Locale;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Common code of annotation processor testing.
+ */
+public final class TestingCommons {
+ private TestingCommons() {
+ throw new UnsupportedOperationException("No instance of TestingCommons
for you! ");
+ }
+
+ private static class ObjectHolders {
+ static final JavaCompiler javaCompiler =
ToolProvider.getSystemJavaCompiler();
+
+ static final StandardJavaFileManager javaFileManager =
javaCompiler.getStandardFileManager(
+ null,
+ Locale.ROOT,
+ StandardCharsets.UTF_8
+ );
+ }
+
+ public static boolean compileTheSource(String filePath) {
+
+
+ JavaCompiler.CompilationTask compilationTask =
ObjectHolders.javaCompiler.getTask(
+ null,
+ ObjectHolders.javaFileManager,
+ null,
+ asList("-parameters", "-Xlint:unchecked", "-nowarn",
"-Xlint:deprecation"),
+ null,
+ getSourceFileJavaFileObject(filePath)
+ );
+
+ compilationTask.setProcessors(
+ Collections.singletonList(new DispatchingAnnotationProcessor())
+ );
+
+ return compilationTask.call();
+ }
+
+ private static Iterable<? extends JavaFileObject>
getSourceFileJavaFileObject(String filePath) {
+
+ return ObjectHolders.javaFileManager.getJavaFileObjects(filePath);
+ }
+}
diff --git
a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java
b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java
new file mode 100644
index 0000000000..cc34299c81
--- /dev/null
+++
b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.common;
+
+/**
+ * Reduced mock of Deprecated method invocation counter.
+ */
+public final class DeprecatedMethodInvocationCounter {
+ private DeprecatedMethodInvocationCounter() {
+ throw new UnsupportedOperationException("No instance of
DeprecatedMethodInvocationCounter for you! ");
+ }
+
+ /**
+ * Invoked by (modified) deprecated method.
+ *
+ * @param methodDefinition filled by annotation processor. (like
'org.apache.dubbo.common.URL.getServiceName()')
+ */
+ public static void onDeprecatedMethodCalled(String methodDefinition) {
+ // Intended to be empty.
+ }
+}
diff --git
a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/extractor/JavassistUtils.java
b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/extractor/JavassistUtils.java
new file mode 100644
index 0000000000..3a2475591a
--- /dev/null
+++
b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/extractor/JavassistUtils.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.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;
+ }
+}
diff --git
a/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/util/ReflectUtils.java
b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/util/ReflectUtils.java
new file mode 100644
index 0000000000..681bdc0441
--- /dev/null
+++
b/dubbo-annotation-processor/src/test/java/org/apache/dubbo/eci/util/ReflectUtils.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.eci.util;
+
+import java.lang.reflect.Field;
+
+/**
+ * Tools of reflective operations.
+ */
+public final class ReflectUtils {
+ private ReflectUtils() {
+ throw new UnsupportedOperationException("No instance of ReflectUtils
for you! ");
+ }
+
+ /**
+ * Searches (a private) field in super classes recursively.
+ *
+ * @param cls the actual type
+ * @param name the field name
+ * @return the corresponding Field object, or null if the field does not
exist.
+ */
+ public static Field getDeclaredFieldRecursively(Class cls, String name) {
+ try {
+ Field indexField = cls.getDeclaredField(name);
+ indexField.setAccessible(true);
+
+ return indexField;
+ } catch (NoSuchFieldException e) {
+ if (cls == Object.class) {
+ return null;
+ }
+
+ return getDeclaredFieldRecursively(cls.getSuperclass(), name);
+ }
+ }
+}
diff --git
a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethod.java
b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethod.java
new file mode 100644
index 0000000000..c705ca8d13
--- /dev/null
+++
b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethod.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.testing.dm;
+
+public class TestConstructorMethod {
+ @Deprecated
+ TestConstructorMethod() {
+ this("1");
+ }
+
+ TestConstructorMethod(String s) {
+ }
+}
diff --git
a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodParentClass.java
b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodParentClass.java
new file mode 100644
index 0000000000..8e14e67c51
--- /dev/null
+++
b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodParentClass.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.testing.dm;
+
+public class TestConstructorMethodParentClass {
+
+ public TestConstructorMethodParentClass() {
+ }
+
+ public TestConstructorMethodParentClass(String s) {
+ }
+}
diff --git
a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodSubClass.java
b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodSubClass.java
new file mode 100644
index 0000000000..3b71626c9b
--- /dev/null
+++
b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestConstructorMethodSubClass.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.testing.dm;
+
+public class TestConstructorMethodSubClass extends
TestConstructorMethodParentClass {
+
+ @Deprecated
+ public TestConstructorMethodSubClass(int i) {
+ super();
+ }
+
+ public TestConstructorMethodSubClass(String s) {
+ super(s);
+ }
+}
diff --git
a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestDeprecatedMethod.java
b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestDeprecatedMethod.java
new file mode 100644
index 0000000000..6360c3e137
--- /dev/null
+++
b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestDeprecatedMethod.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.testing.dm;
+
+public class TestDeprecatedMethod {
+
+ @Deprecated
+ public void m1() {
+ System.out.println("M1! ");
+ }
+}
diff --git
a/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestInterfaceDeprecatedMethod.java
b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestInterfaceDeprecatedMethod.java
new file mode 100644
index 0000000000..a2ce7af598
--- /dev/null
+++
b/dubbo-annotation-processor/src/test/resources/org/testing/dm/TestInterfaceDeprecatedMethod.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.testing.dm;
+
+public interface TestInterfaceDeprecatedMethod {
+
+ @Deprecated
+ public void m1();
+}
diff --git a/dubbo-build-tools/pom.xml b/dubbo-build-tools/pom.xml
index 28bae806b1..5c3b83e2dd 100644
--- a/dubbo-build-tools/pom.xml
+++ b/dubbo-build-tools/pom.xml
@@ -13,8 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+<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>
@@ -24,7 +24,7 @@
<packaging>jar</packaging>
<properties>
- <maven.deploy.skip>true</maven.deploy.skip>
+ <maven.deploy.skip>true</maven.deploy.skip>
</properties>
-</project>
\ No newline at end of file
+</project>
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java
b/dubbo-common/src/main/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java
new file mode 100644
index 0000000000..b4245c5bfa
--- /dev/null
+++
b/dubbo-common/src/main/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounter.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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);
+ }
+}
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/DeprecatedMethodInvocationCounterConstants.java
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/DeprecatedMethodInvocationCounterConstants.java
new file mode 100644
index 0000000000..f747568491
--- /dev/null
+++
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/DeprecatedMethodInvocationCounterConstants.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.common.constants;
+
+/**
+ * Constants of Deprecated Method Invocation Counter.
+ */
+public final class DeprecatedMethodInvocationCounterConstants {
+ private DeprecatedMethodInvocationCounterConstants() {
+ throw new UnsupportedOperationException("No instance of
DeprecatedMethodInvocationCounterConstants for you! ");
+ }
+
+ public static final String ERROR_CODE =
LoggerCodeConstants.COMMON_DEPRECATED_METHOD_INVOKED;
+
+ public static final String POSSIBLE_CAUSE = "invocation of deprecated
method";
+
+ public static final String EXTENDED_MESSAGE = "";
+
+ public static final String LOGGER_MESSAGE_PREFIX = "Deprecated method
invoked. The method is ";
+}
diff --git
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java
index 0682c5233d..c39fa1c698 100644
---
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java
+++
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoggerCodeConstants.java
@@ -92,6 +92,10 @@ public interface LoggerCodeConstants {
String VULNERABILITY_WARNING = "0-28";
+ /**
+ * Used in annotation processor to indicate a deprecated method is invoked.
+ */
+ String COMMON_DEPRECATED_METHOD_INVOKED = "0-99";
// Registry module
diff --git
a/dubbo-common/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounterTest.java
b/dubbo-common/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounterTest.java
new file mode 100644
index 0000000000..b1ad0943a7
--- /dev/null
+++
b/dubbo-common/src/test/java/org/apache/dubbo/common/DeprecatedMethodInvocationCounterTest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF 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:[email protected]: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);
+ }
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/pom.xml
b/dubbo-config/dubbo-config-api/pom.xml
index 42ee10a4e0..4687ce2285 100644
--- a/dubbo-config/dubbo-config-api/pom.xml
+++ b/dubbo-config/dubbo-config-api/pom.xml
@@ -226,6 +226,5 @@
<version>1.17.6</version>
<scope>test</scope>
</dependency>
-
</dependencies>
</project>
diff --git a/dubbo-metadata/dubbo-metadata-processor/pom.xml
b/dubbo-metadata/dubbo-metadata-processor/pom.xml
index 0cb2c9139d..009ce910e4 100644
--- a/dubbo-metadata/dubbo-metadata-processor/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-processor/pom.xml
@@ -161,4 +161,17 @@
<scope>test</scope>
</dependency>
</dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <fork>true</fork>
+ <proc>none</proc>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git
a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java
b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java
index 4f912e3001..7f4b3250b4 100644
---
a/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java
+++
b/dubbo-test/dubbo-test-modules/src/test/java/org/apache/dubbo/dependency/FileTest.java
@@ -48,6 +48,7 @@ class FileTest {
ignoredModules.add(Pattern.compile("dubbo-parent"));
ignoredModules.add(Pattern.compile("dubbo-core-spi"));
ignoredModules.add(Pattern.compile("dubbo-demo.*"));
+ ignoredModules.add(Pattern.compile("dubbo-annotation-processor"));
ignoredModulesInDubboAll.add(Pattern.compile("dubbo"));
ignoredModulesInDubboAll.add(Pattern.compile("dubbo-bom"));
@@ -57,6 +58,7 @@ class FileTest {
ignoredModulesInDubboAll.add(Pattern.compile("dubbo-metadata-processor"));
ignoredModulesInDubboAll.add(Pattern.compile("dubbo-native.*"));
ignoredModulesInDubboAll.add(Pattern.compile("dubbo-spring-boot.*"));
+
ignoredModulesInDubboAll.add(Pattern.compile("dubbo-annotation-processor.*"));
ignoredModulesInDubboAll.add(Pattern.compile("dubbo-maven-plugin"));
}
diff --git a/pom.xml b/pom.xml
index 0af455fd55..a792bd4a95 100644
--- a/pom.xml
+++ b/pom.xml
@@ -125,6 +125,7 @@
<maven_flatten_version>1.3.0</maven_flatten_version>
<maven_enforce_version>3.2.1</maven_enforce_version>
<maven_antrun_version>3.1.0</maven_antrun_version>
+
<dubbo_annotation_processor_version>1.0.0</dubbo_annotation_processor_version>
<arguments />
<checkstyle.skip>true</checkstyle.skip>
<checkstyle_unix.skip>true</checkstyle_unix.skip>
@@ -134,6 +135,7 @@
</properties>
<modules>
+ <module>dubbo-annotation-processor</module>
<module>dubbo-common</module>
<module>dubbo-container</module>
<module>dubbo-compiler</module>
@@ -177,6 +179,13 @@
</dependencyManagement>
<dependencies>
+
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-annotation-processor</artifactId>
+ <version>${dubbo_annotation_processor_version}</version>
+ </dependency>
+
<!--JUnit Jupiter Engine to depend on the JUnit5 engine and JUnit 5
API -->
<dependency>
<groupId>org.junit.jupiter</groupId>
@@ -710,7 +719,6 @@
<version>${maven_compiler_version}</version>
<configuration>
<compilerArgs>
- <compilerArg>-proc:none</compilerArg>
<compilerArg>-parameters</compilerArg>
</compilerArgs>
<fork>true</fork>