Skip to content

Commit c99c079

Browse files
authored
Port GraalVM reachability to 3.x (#3884)
* Extract class PluginIndex * Prepare PluginProcessor for introduction of GraalVmProcessor This refactors and updates PluginProcessor to function more similarly to GraalVmProcessor. This re-uses the recently added PluginIndex class for tracking processed plugins before dumping this data in the final annotation processing round. * Port GraalVM reachability to 3.x This ports the GraalVmProcessor introduced in a14f0ad (released in 2.25.0) to the plugin model of 3.x.
1 parent 98cacc2 commit c99c079

File tree

19 files changed

+1562
-273
lines changed

19 files changed

+1562
-273
lines changed

log4j-parent/pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,9 @@
869869
<arg>-Alog4j.docgen.version=${project.version}</arg>
870870
<arg>-Alog4j.docgen.description=${project.description}</arg>
871871
<arg>-Alog4j.docgen.typeFilter.excludePattern=${log4j.docgen.typeFilter.excludePattern}</arg>
872+
<!-- Provide arguments for the GraalVM processor -->
873+
<arg>-Alog4j.graalvm.groupId=${project.groupId}</arg>
874+
<arg>-Alog4j.graalvm.artifactId=${project.artifactId}</arg>
872875
</compilerArgs>
873876
</configuration>
874877

log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/GraalVmProcessor.java

Lines changed: 355 additions & 0 deletions
Large diffs are not rendered by default.

log4j-plugin-processor/src/main/java/org/apache/logging/log4j/plugin/processor/PluginProcessor.java

Lines changed: 120 additions & 143 deletions
Large diffs are not rendered by default.
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.logging.log4j.plugin.processor.internal;
18+
19+
import java.util.Collection;
20+
import java.util.HashMap;
21+
import java.util.List;
22+
import java.util.Map;
23+
import javax.lang.model.element.AnnotationMirror;
24+
import javax.lang.model.element.AnnotationValue;
25+
import javax.lang.model.element.Element;
26+
import javax.lang.model.element.TypeElement;
27+
import javax.lang.model.type.DeclaredType;
28+
import javax.lang.model.util.Elements;
29+
import org.apache.logging.log4j.plugin.processor.GraalVmProcessor;
30+
31+
public final class Annotations {
32+
33+
private static final Collection<String> FACTORY_TYPE_NAMES = List.of(
34+
"org.apache.logging.log4j.plugins.Factory",
35+
"org.apache.logging.log4j.plugins.PluginFactory",
36+
"org.apache.logging.log4j.plugins.SingletonFactory",
37+
"org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory",
38+
"org.apache.logging.log4j.core.config.plugins.PluginFactory");
39+
40+
private static final Collection<String> INJECT_NAMES = List.of("org.apache.logging.log4j.plugins.Inject");
41+
42+
private static final Collection<String> QUALIFIER_TYPE_NAMES = List.of(
43+
"org.apache.logging.log4j.plugins.Named",
44+
"org.apache.logging.log4j.plugins.PluginAttribute",
45+
"org.apache.logging.log4j.plugins.PluginBuilderAttribute",
46+
"org.apache.logging.log4j.plugins.PluginElement",
47+
"org.apache.logging.log4j.plugins.PluginNode",
48+
"org.apache.logging.log4j.plugins.PluginValue",
49+
"org.apache.logging.log4j.core.config.plugins.PluginAttribute",
50+
"org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute",
51+
"org.apache.logging.log4j.core.config.plugins.PluginConfiguration",
52+
"org.apache.logging.log4j.core.config.plugins.PluginElement",
53+
"org.apache.logging.log4j.core.config.plugins.PluginLoggerContext",
54+
"org.apache.logging.log4j.core.config.plugins.PluginNode",
55+
"org.apache.logging.log4j.core.config.plugins.PluginValue");
56+
57+
/**
58+
* These must be public types with either:
59+
* <ul>
60+
* <li>A factory method.</li>
61+
* <li>A static method called {@code newInstance}.</li>
62+
* <li>A public no-argument constructor.</li>
63+
* </ul>
64+
* <p>
65+
* <strong>Note:</strong> The annotations listed here must also be declared in
66+
* {@link GraalVmProcessor}.
67+
* </p>
68+
*/
69+
private static final Collection<String> PLUGIN_ANNOTATION_NAMES =
70+
List.of("org.apache.logging.log4j.plugins.Plugin", "org.apache.logging.log4j.core.config.plugins.Plugin");
71+
72+
/**
73+
* Reflection is also used to create meta annotation strategies.
74+
* .
75+
* <p>
76+
* <strong>Note:</strong> The annotations listed here must also be declared in
77+
* {@link GraalVmProcessor}.
78+
* </p>
79+
*/
80+
private static final Collection<String> META_ANNOTATION_STRATEGY_NAMES = List.of(
81+
"org.apache.logging.log4j.plugins.condition.Conditional",
82+
"org.apache.logging.log4j.plugins.validation.Constraint");
83+
84+
public enum Type {
85+
INJECT,
86+
/**
87+
* Annotation used to mark a configuration attribute, element or other injected parameters.
88+
*/
89+
QUALIFIER,
90+
/**
91+
* Annotation used to mark a Log4j Plugin factory method.
92+
*/
93+
FACTORY,
94+
/**
95+
* Annotation used to mark a Log4j Plugin class.
96+
*/
97+
PLUGIN,
98+
/**
99+
* Annotation containing the name of a
100+
* {@link org.apache.logging.log4j.plugins.validation.ConstraintValidator}
101+
* or
102+
* {@link org.apache.logging.log4j.plugins.condition.Condition}.
103+
*/
104+
META_ANNOTATION_STRATEGY,
105+
/**
106+
* Unknown
107+
*/
108+
UNKNOWN
109+
}
110+
111+
private final Map<TypeElement, Type> typeElementToTypeMap = new HashMap<>();
112+
113+
public Annotations(final Elements elements) {
114+
FACTORY_TYPE_NAMES.forEach(className -> addTypeElementIfExists(elements, className, Type.FACTORY));
115+
INJECT_NAMES.forEach(className -> addTypeElementIfExists(elements, className, Type.INJECT));
116+
QUALIFIER_TYPE_NAMES.forEach(className -> addTypeElementIfExists(elements, className, Type.QUALIFIER));
117+
PLUGIN_ANNOTATION_NAMES.forEach(className -> addTypeElementIfExists(elements, className, Type.PLUGIN));
118+
META_ANNOTATION_STRATEGY_NAMES.forEach(
119+
className -> addTypeElementIfExists(elements, className, Type.META_ANNOTATION_STRATEGY));
120+
}
121+
122+
private void addTypeElementIfExists(Elements elements, CharSequence className, Type type) {
123+
final TypeElement element = elements.getTypeElement(className);
124+
if (element != null) {
125+
typeElementToTypeMap.put(element, type);
126+
}
127+
}
128+
129+
public Annotations.Type classifyAnnotation(TypeElement element) {
130+
return typeElementToTypeMap.getOrDefault(element, Type.UNKNOWN);
131+
}
132+
133+
public Element getAnnotationClassValue(Element element, TypeElement annotation) {
134+
// This prevents getting an "Attempt to access Class object for TypeMirror" exception
135+
AnnotationMirror annotationMirror = element.getAnnotationMirrors().stream()
136+
.filter(am -> am.getAnnotationType().asElement().equals(annotation))
137+
.findFirst()
138+
.orElseThrow(
139+
() -> new IllegalStateException("No `@" + annotation + "` annotation found on " + element));
140+
AnnotationValue annotationValue = annotationMirror.getElementValues().entrySet().stream()
141+
.filter(e -> "value".equals(e.getKey().getSimpleName().toString()))
142+
.map(Map.Entry::getValue)
143+
.findFirst()
144+
.orElseThrow(() ->
145+
new IllegalStateException("No `value` found `@" + annotation + "` annotation on " + element));
146+
DeclaredType value = (DeclaredType) annotationValue.getValue();
147+
return value.asElement();
148+
}
149+
}

0 commit comments

Comments
 (0)