1
1
/*
2
- * Copyright 2012-2020 the original author or authors.
2
+ * Copyright 2012-2022 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
51
51
*
52
52
* @author Madhura Bhave
53
53
* @author Phillip Webb
54
+ * @author Moritz Halbritter
54
55
* @since 1.5.0
55
56
*/
56
57
@ SupportedAnnotationTypes ({ "org.springframework.boot.autoconfigure.condition.ConditionalOnClass" ,
59
60
"org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication" ,
60
61
"org.springframework.boot.autoconfigure.AutoConfigureBefore" ,
61
62
"org.springframework.boot.autoconfigure.AutoConfigureAfter" ,
62
- "org.springframework.boot.autoconfigure.AutoConfigureOrder" })
63
+ "org.springframework.boot.autoconfigure.AutoConfigureOrder" ,
64
+ "org.springframework.boot.autoconfigure.AutoConfiguration" })
63
65
public class AutoConfigureAnnotationProcessor extends AbstractProcessor {
64
66
65
67
protected static final String PROPERTIES_PATH = "META-INF/spring-autoconfigure-metadata.properties" ;
66
68
67
- private final Map <String , String > annotations ;
68
-
69
- private final Map <String , ValueExtractor > valueExtractors ;
70
-
71
69
private final Map <String , String > properties = new TreeMap <>();
72
70
73
- public AutoConfigureAnnotationProcessor () {
74
- Map <String , String > annotations = new LinkedHashMap <>();
75
- addAnnotations (annotations );
76
- this .annotations = Collections .unmodifiableMap (annotations );
77
- Map <String , ValueExtractor > valueExtractors = new LinkedHashMap <>();
78
- addValueExtractors (valueExtractors );
79
- this .valueExtractors = Collections .unmodifiableMap (valueExtractors );
80
- }
71
+ private final List <PropertyGenerator > propertyGenerators ;
81
72
82
- protected void addAnnotations (Map <String , String > annotations ) {
83
- annotations .put ("ConditionalOnClass" , "org.springframework.boot.autoconfigure.condition.ConditionalOnClass" );
84
- annotations .put ("ConditionalOnBean" , "org.springframework.boot.autoconfigure.condition.ConditionalOnBean" );
85
- annotations .put ("ConditionalOnSingleCandidate" ,
86
- "org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate" );
87
- annotations .put ("ConditionalOnWebApplication" ,
88
- "org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication" );
89
- annotations .put ("AutoConfigureBefore" , "org.springframework.boot.autoconfigure.AutoConfigureBefore" );
90
- annotations .put ("AutoConfigureAfter" , "org.springframework.boot.autoconfigure.AutoConfigureAfter" );
91
- annotations .put ("AutoConfigureOrder" , "org.springframework.boot.autoconfigure.AutoConfigureOrder" );
73
+ public AutoConfigureAnnotationProcessor () {
74
+ this .propertyGenerators = Collections .unmodifiableList (getPropertyGenerators ());
92
75
}
93
76
94
- private void addValueExtractors (Map <String , ValueExtractor > attributes ) {
95
- attributes .put ("ConditionalOnClass" , new OnClassConditionValueExtractor ());
96
- attributes .put ("ConditionalOnBean" , new OnBeanConditionValueExtractor ());
97
- attributes .put ("ConditionalOnSingleCandidate" , new OnBeanConditionValueExtractor ());
98
- attributes .put ("ConditionalOnWebApplication" , ValueExtractor .allFrom ("type" ));
99
- attributes .put ("AutoConfigureBefore" , ValueExtractor .allFrom ("value" , "name" ));
100
- attributes .put ("AutoConfigureAfter" , ValueExtractor .allFrom ("value" , "name" ));
101
- attributes .put ("AutoConfigureOrder" , ValueExtractor .allFrom ("value" ));
77
+ protected List <PropertyGenerator > getPropertyGenerators () {
78
+ List <PropertyGenerator > generators = new ArrayList <>();
79
+ generators .add (PropertyGenerator .of ("ConditionalOnClass" ,
80
+ "org.springframework.boot.autoconfigure.condition.ConditionalOnClass" ,
81
+ new OnClassConditionValueExtractor ()));
82
+ generators .add (PropertyGenerator .of ("ConditionalOnBean" ,
83
+ "org.springframework.boot.autoconfigure.condition.ConditionalOnBean" ,
84
+ new OnBeanConditionValueExtractor ()));
85
+ generators .add (PropertyGenerator .of ("ConditionalOnSingleCandidate" ,
86
+ "org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate" ,
87
+ new OnBeanConditionValueExtractor ()));
88
+ generators .add (PropertyGenerator .of ("ConditionalOnWebApplication" ,
89
+ "org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication" ,
90
+ ValueExtractor .allFrom ("type" )));
91
+ generators .add (PropertyGenerator .of ("AutoConfigureBefore" ,
92
+ "org.springframework.boot.autoconfigure.AutoConfigureBefore" , ValueExtractor .allFrom ("value" , "name" ),
93
+ "org.springframework.boot.autoconfigure.AutoConfiguration" ,
94
+ ValueExtractor .allFrom ("before" , "beforeName" )));
95
+ generators .add (PropertyGenerator .of ("AutoConfigureAfter" ,
96
+ "org.springframework.boot.autoconfigure.AutoConfigureAfter" , ValueExtractor .allFrom ("value" , "name" ),
97
+ "org.springframework.boot.autoconfigure.AutoConfiguration" ,
98
+ ValueExtractor .allFrom ("after" , "afterName" )));
99
+ generators .add (PropertyGenerator .of ("AutoConfigureOrder" ,
100
+ "org.springframework.boot.autoconfigure.AutoConfigureOrder" , ValueExtractor .allFrom ("value" )));
101
+ return generators ;
102
102
}
103
103
104
104
@ Override
@@ -108,8 +108,8 @@ public SourceVersion getSupportedSourceVersion() {
108
108
109
109
@ Override
110
110
public boolean process (Set <? extends TypeElement > annotations , RoundEnvironment roundEnv ) {
111
- for (Map . Entry < String , String > entry : this .annotations . entrySet () ) {
112
- process (roundEnv , entry . getKey (), entry . getValue () );
111
+ for (PropertyGenerator generator : this .propertyGenerators ) {
112
+ process (roundEnv , generator );
113
113
}
114
114
if (roundEnv .processingOver ()) {
115
115
try {
@@ -122,22 +122,24 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
122
122
return false ;
123
123
}
124
124
125
- private void process (RoundEnvironment roundEnv , String propertyKey , String annotationName ) {
126
- TypeElement annotationType = this .processingEnv .getElementUtils ().getTypeElement (annotationName );
127
- if (annotationType != null ) {
128
- for (Element element : roundEnv .getElementsAnnotatedWith (annotationType )) {
129
- processElement (element , propertyKey , annotationName );
125
+ private void process (RoundEnvironment roundEnv , PropertyGenerator generator ) {
126
+ for (String annotationName : generator .getSupportedAnnotations ()) {
127
+ TypeElement annotationType = this .processingEnv .getElementUtils ().getTypeElement (annotationName );
128
+ if (annotationType != null ) {
129
+ for (Element element : roundEnv .getElementsAnnotatedWith (annotationType )) {
130
+ processElement (element , generator , annotationName );
131
+ }
130
132
}
131
133
}
132
134
}
133
135
134
- private void processElement (Element element , String propertyKey , String annotationName ) {
136
+ private void processElement (Element element , PropertyGenerator generator , String annotationName ) {
135
137
try {
136
138
String qualifiedName = Elements .getQualifiedName (element );
137
139
AnnotationMirror annotation = getAnnotation (element , annotationName );
138
140
if (qualifiedName != null && annotation != null ) {
139
- List <Object > values = getValues (propertyKey , annotation );
140
- this .properties . put ( qualifiedName + "." + propertyKey , toCommaDelimitedString ( values ) );
141
+ List <Object > values = getValues (generator , annotationName , annotation );
142
+ generator . applyToProperties ( this .properties , qualifiedName , values );
141
143
this .properties .put (qualifiedName , "" );
142
144
}
143
145
}
@@ -157,17 +159,8 @@ private AnnotationMirror getAnnotation(Element element, String type) {
157
159
return null ;
158
160
}
159
161
160
- private String toCommaDelimitedString (List <Object > list ) {
161
- StringBuilder result = new StringBuilder ();
162
- for (Object item : list ) {
163
- result .append ((result .length () != 0 ) ? "," : "" );
164
- result .append (item );
165
- }
166
- return result .toString ();
167
- }
168
-
169
- private List <Object > getValues (String propertyKey , AnnotationMirror annotation ) {
170
- ValueExtractor extractor = this .valueExtractors .get (propertyKey );
162
+ private List <Object > getValues (PropertyGenerator generator , String annotationName , AnnotationMirror annotation ) {
163
+ ValueExtractor extractor = generator .getValueExtractor (annotationName );
171
164
if (extractor == null ) {
172
165
return Collections .emptyList ();
173
166
}
@@ -190,7 +183,7 @@ private void writeProperties() throws IOException {
190
183
}
191
184
192
185
@ FunctionalInterface
193
- private interface ValueExtractor {
186
+ interface ValueExtractor {
194
187
195
188
List <Object > getValues (AnnotationMirror annotation );
196
189
@@ -245,7 +238,7 @@ public List<Object> getValues(AnnotationMirror annotation) {
245
238
246
239
}
247
240
248
- private static class OnBeanConditionValueExtractor extends AbstractValueExtractor {
241
+ static class OnBeanConditionValueExtractor extends AbstractValueExtractor {
249
242
250
243
@ Override
251
244
public List <Object > getValues (AnnotationMirror annotation ) {
@@ -263,7 +256,7 @@ public List<Object> getValues(AnnotationMirror annotation) {
263
256
264
257
}
265
258
266
- private static class OnClassConditionValueExtractor extends NamedValuesExtractor {
259
+ static class OnClassConditionValueExtractor extends NamedValuesExtractor {
267
260
268
261
OnClassConditionValueExtractor () {
269
262
super ("value" , "name" );
@@ -287,4 +280,66 @@ private boolean isSpringClass(String type) {
287
280
288
281
}
289
282
283
+ static final class PropertyGenerator {
284
+
285
+ private final String keyName ;
286
+
287
+ /**
288
+ * Maps from annotation class name -> {@link ValueExtractor}.
289
+ */
290
+ private final Map <String , ValueExtractor > valueExtractors ;
291
+
292
+ private PropertyGenerator (String keyName , Map <String , ValueExtractor > valueExtractors ) {
293
+ this .keyName = keyName ;
294
+ this .valueExtractors = valueExtractors ;
295
+ }
296
+
297
+ Set <String > getSupportedAnnotations () {
298
+ return Collections .unmodifiableSet (this .valueExtractors .keySet ());
299
+ }
300
+
301
+ ValueExtractor getValueExtractor (String annotation ) {
302
+ return this .valueExtractors .get (annotation );
303
+ }
304
+
305
+ void applyToProperties (Map <String , String > properties , String className , List <Object > annotationValues ) {
306
+ mergeProperties (properties , className + "." + this .keyName , toCommaDelimitedString (annotationValues ));
307
+ }
308
+
309
+ private void mergeProperties (Map <String , String > properties , String key , String value ) {
310
+ String existingKey = properties .get (key );
311
+ if (existingKey == null || existingKey .isEmpty ()) {
312
+ properties .put (key , value );
313
+ }
314
+ else if (!value .isEmpty ()) {
315
+ properties .put (key , existingKey + "," + value );
316
+ }
317
+ }
318
+
319
+ private String toCommaDelimitedString (List <Object > list ) {
320
+ if (list .isEmpty ()) {
321
+ return "" ;
322
+ }
323
+ StringBuilder result = new StringBuilder ();
324
+ for (Object item : list ) {
325
+ result .append ((result .length () != 0 ) ? "," : "" );
326
+ result .append (item );
327
+ }
328
+ return result .toString ();
329
+ }
330
+
331
+ static PropertyGenerator of (String keyName , String annotation , ValueExtractor valueExtractor ) {
332
+ return new PropertyGenerator (keyName , Collections .singletonMap (annotation , valueExtractor ));
333
+ }
334
+
335
+ static PropertyGenerator of (String keyName , String annotation1 , ValueExtractor valueExtractor1 ,
336
+ String annotation2 , ValueExtractor valueExtractor2 ) {
337
+ Map <String , ValueExtractor > valueExtractors = new LinkedHashMap <>();
338
+ valueExtractors .put (annotation1 , valueExtractor1 );
339
+ valueExtractors .put (annotation2 , valueExtractor2 );
340
+ return new PropertyGenerator (keyName , valueExtractors );
341
+ }
342
+
343
+ }
344
+
290
345
}
0 commit comments