1
1
/*
2
- * Copyright 2002-2023 the original author or authors.
2
+ * Copyright 2002-2024 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.
16
16
17
17
package org .springframework .aot .nativex ;
18
18
19
+ import java .util .ArrayList ;
19
20
import java .util .Collection ;
20
21
import java .util .Comparator ;
21
22
import java .util .LinkedHashMap ;
22
23
import java .util .List ;
23
24
import java .util .Map ;
24
25
import java .util .Set ;
26
+ import java .util .stream .Collectors ;
25
27
import java .util .stream .Stream ;
26
28
29
+ import org .springframework .aot .hint .ConditionalHint ;
27
30
import org .springframework .aot .hint .ExecutableHint ;
28
31
import org .springframework .aot .hint .ExecutableMode ;
29
32
import org .springframework .aot .hint .FieldHint ;
33
+ import org .springframework .aot .hint .JdkProxyHint ;
30
34
import org .springframework .aot .hint .MemberCategory ;
31
35
import org .springframework .aot .hint .ReflectionHints ;
36
+ import org .springframework .aot .hint .RuntimeHints ;
32
37
import org .springframework .aot .hint .TypeHint ;
38
+ import org .springframework .aot .hint .TypeReference ;
33
39
import org .springframework .lang .Nullable ;
34
40
35
41
/**
36
- * Write {@link ReflectionHints} to the JSON output expected by the GraalVM
37
- * {@code native-image} compiler, typically named {@code reflect-config.json}
38
- * or {@code jni-config.json}.
42
+ * Collect {@link ReflectionHints} as map attributes ready for JSON serialization for the GraalVM
43
+ * {@code native-image} compiler.
39
44
*
40
45
* @author Sebastien Deleuze
41
46
* @author Stephane Nicoll
42
47
* @author Janne Valkealahti
43
- * @since 6.0
44
- * @see <a href="https://www.graalvm.org/22.0/reference-manual/native-image/Reflection/">Reflection Use in Native Images</a>
45
- * @see <a href="https://www.graalvm.org/22.0/reference-manual/native-image/JNI/">Java Native Interface (JNI) in Native Image</a>
46
- * @see <a href="https://www.graalvm.org/22.0/reference-manual/native-image/BuildConfiguration/">Native Image Build Configuration</a>
48
+ * @see <a href="https://www.graalvm.org/jdk23/reference-manual/native-image/metadata/#reflection">Reflection Use in Native Images</a>
49
+ * @see <a href="https://www.graalvm.org/jdk23/reference-manual/native-image/dynamic-features/JNI/">Java Native Interface (JNI) in Native Image</a>
50
+ * @see <a href="https://www.graalvm.org/jdk23/reference-manual/native-image/overview/BuildConfiguration/">Native Image Build Configuration</a>
47
51
*/
48
- class ReflectionHintsWriter {
52
+ class ReflectionHintsAttributes {
49
53
50
- public static final ReflectionHintsWriter INSTANCE = new ReflectionHintsWriter ();
54
+ private static final Comparator <JdkProxyHint > JDK_PROXY_HINT_COMPARATOR =
55
+ (left , right ) -> {
56
+ String leftSignature = left .getProxiedInterfaces ().stream ()
57
+ .map (TypeReference ::getCanonicalName ).collect (Collectors .joining ("," ));
58
+ String rightSignature = right .getProxiedInterfaces ().stream ()
59
+ .map (TypeReference ::getCanonicalName ).collect (Collectors .joining ("," ));
60
+ return leftSignature .compareTo (rightSignature );
61
+ };
51
62
52
- public void write (BasicJsonWriter writer , ReflectionHints hints ) {
53
- writer .writeArray (hints .typeHints ()
63
+ public List <Map <String , Object >> reflection (RuntimeHints hints ) {
64
+ List <Map <String , Object >> reflectionHints = new ArrayList <>();
65
+ reflectionHints .addAll (hints .reflection ().typeHints ()
54
66
.sorted (Comparator .comparing (TypeHint ::getType ))
55
67
.map (this ::toAttributes ).toList ());
68
+ reflectionHints .addAll (hints .proxies ().jdkProxyHints ()
69
+ .sorted (JDK_PROXY_HINT_COMPARATOR )
70
+ .map (this ::toAttributes ).toList ());
71
+ return reflectionHints ;
72
+ }
73
+
74
+ public List <Map <String , Object >> jni (RuntimeHints hints ) {
75
+ List <Map <String , Object >> jniHints = new ArrayList <>();
76
+ jniHints .addAll (hints .jni ().typeHints ()
77
+ .sorted (Comparator .comparing (TypeHint ::getType ))
78
+ .map (this ::toAttributes ).toList ());
79
+ return jniHints ;
56
80
}
57
81
58
82
private Map <String , Object > toAttributes (TypeHint hint ) {
59
83
Map <String , Object > attributes = new LinkedHashMap <>();
60
- attributes .put ("name " , hint .getType ());
84
+ attributes .put ("type " , hint .getType ());
61
85
handleCondition (attributes , hint );
62
86
handleCategories (attributes , hint .getMemberCategories ());
63
87
handleFields (attributes , hint .fields ());
@@ -66,33 +90,23 @@ private Map<String, Object> toAttributes(TypeHint hint) {
66
90
return attributes ;
67
91
}
68
92
69
- private void handleCondition (Map <String , Object > attributes , TypeHint hint ) {
93
+ private void handleCondition (Map <String , Object > attributes , ConditionalHint hint ) {
70
94
if (hint .getReachableType () != null ) {
71
- Map <String , Object > conditionAttributes = new LinkedHashMap <>();
72
- conditionAttributes .put ("typeReachable" , hint .getReachableType ());
73
- attributes .put ("condition" , conditionAttributes );
95
+ attributes .put ("condition" , Map .of ("typeReached" , hint .getReachableType ()));
74
96
}
75
97
}
76
98
77
99
private void handleFields (Map <String , Object > attributes , Stream <FieldHint > fields ) {
78
100
addIfNotEmpty (attributes , "fields" , fields
79
101
.sorted (Comparator .comparing (FieldHint ::getName , String ::compareToIgnoreCase ))
80
- .map (this ::toAttributes ).toList ());
81
- }
82
-
83
- private Map <String , Object > toAttributes (FieldHint hint ) {
84
- Map <String , Object > attributes = new LinkedHashMap <>();
85
- attributes .put ("name" , hint .getName ());
86
- return attributes ;
102
+ .map (fieldHint -> Map .of ("name" , fieldHint .getName ()))
103
+ .toList ());
87
104
}
88
105
89
106
private void handleExecutables (Map <String , Object > attributes , List <ExecutableHint > hints ) {
90
107
addIfNotEmpty (attributes , "methods" , hints .stream ()
91
108
.filter (h -> h .getMode ().equals (ExecutableMode .INVOKE ))
92
109
.map (this ::toAttributes ).toList ());
93
- addIfNotEmpty (attributes , "queriedMethods" , hints .stream ()
94
- .filter (h -> h .getMode ().equals (ExecutableMode .INTROSPECT ))
95
- .map (this ::toAttributes ).toList ());
96
110
}
97
111
98
112
private Map <String , Object > toAttributes (ExecutableHint hint ) {
@@ -102,28 +116,19 @@ private Map<String, Object> toAttributes(ExecutableHint hint) {
102
116
return attributes ;
103
117
}
104
118
119
+ @ SuppressWarnings ("removal" )
105
120
private void handleCategories (Map <String , Object > attributes , Set <MemberCategory > categories ) {
106
121
categories .stream ().sorted ().forEach (category -> {
107
122
switch (category ) {
108
- case PUBLIC_FIELDS -> attributes .put ("allPublicFields" , true );
109
- case DECLARED_FIELDS -> attributes .put ("allDeclaredFields" , true );
110
- case INTROSPECT_PUBLIC_CONSTRUCTORS ->
111
- attributes .put ("queryAllPublicConstructors" , true );
112
- case INTROSPECT_DECLARED_CONSTRUCTORS ->
113
- attributes .put ("queryAllDeclaredConstructors" , true );
123
+ case INVOKE_PUBLIC_FIELDS , PUBLIC_FIELDS -> attributes .put ("allPublicFields" , true );
124
+ case INVOKE_DECLARED_FIELDS , DECLARED_FIELDS -> attributes .put ("allDeclaredFields" , true );
114
125
case INVOKE_PUBLIC_CONSTRUCTORS ->
115
126
attributes .put ("allPublicConstructors" , true );
116
127
case INVOKE_DECLARED_CONSTRUCTORS ->
117
128
attributes .put ("allDeclaredConstructors" , true );
118
- case INTROSPECT_PUBLIC_METHODS ->
119
- attributes .put ("queryAllPublicMethods" , true );
120
- case INTROSPECT_DECLARED_METHODS ->
121
- attributes .put ("queryAllDeclaredMethods" , true );
122
129
case INVOKE_PUBLIC_METHODS -> attributes .put ("allPublicMethods" , true );
123
130
case INVOKE_DECLARED_METHODS ->
124
131
attributes .put ("allDeclaredMethods" , true );
125
- case PUBLIC_CLASSES -> attributes .put ("allPublicClasses" , true );
126
- case DECLARED_CLASSES -> attributes .put ("allDeclaredClasses" , true );
127
132
}
128
133
}
129
134
);
@@ -135,4 +140,11 @@ private void addIfNotEmpty(Map<String, Object> attributes, String name, @Nullabl
135
140
}
136
141
}
137
142
143
+ private Map <String , Object > toAttributes (JdkProxyHint hint ) {
144
+ Map <String , Object > attributes = new LinkedHashMap <>();
145
+ handleCondition (attributes , hint );
146
+ attributes .put ("type" , Map .of ("proxy" , hint .getProxiedInterfaces ()));
147
+ return attributes ;
148
+ }
149
+
138
150
}
0 commit comments