5
5
package org .hibernate .models .internal ;
6
6
7
7
import java .lang .annotation .Annotation ;
8
- import java .lang .reflect .Constructor ;
9
- import java .lang .reflect .InvocationTargetException ;
8
+ import java .lang .invoke .MethodHandle ;
9
+ import java .lang .invoke .MethodHandles ;
10
+ import java .lang .invoke .MethodType ;
10
11
import java .util .Collections ;
11
12
import java .util .List ;
12
13
import java .util .Map ;
22
23
* does not collect annotations from the annotation class as we never care about
23
24
* meta-annotations in these cases.
24
25
*
26
+ * @implNote There are a few cases in Hibernate ORM e.g. where we do care about meta-annotations,
27
+ * but those are handled specially there.
28
+ *
25
29
* @author Steve Ebersole
26
30
*/
27
31
public class OrmAnnotationDescriptor <A extends Annotation , C extends A >
@@ -30,8 +34,8 @@ public class OrmAnnotationDescriptor<A extends Annotation, C extends A>
30
34
private final Class <C > concreteClass ;
31
35
private final List <AttributeDescriptor <?>> attributeDescriptors ;
32
36
33
- private DynamicCreator <A ,C > dynamicCreator ;
34
- private JdkCreator <A ,C > jdkCreator ;
37
+ private final DynamicCreator <A ,C > dynamicCreator ;
38
+ private final JdkCreator <A ,C > jdkCreator ;
35
39
private DeTypedCreator <A ,C > deTypedCreator ;
36
40
37
41
public OrmAnnotationDescriptor (
@@ -53,6 +57,9 @@ public OrmAnnotationDescriptor(
53
57
54
58
this .concreteClass = concreteClass ;
55
59
this .attributeDescriptors = AnnotationDescriptorBuilding .extractAttributeDescriptors ( annotationType );
60
+
61
+ this .dynamicCreator = new DynamicCreator <>( annotationType , concreteClass );
62
+ this .jdkCreator = new JdkCreator <>( annotationType , concreteClass );
56
63
}
57
64
58
65
@ Override
@@ -69,17 +76,11 @@ public Class<C> getMutableAnnotationType() {
69
76
70
77
@ Override
71
78
public C createUsage (SourceModelBuildingContext context ) {
72
- if ( dynamicCreator == null ) {
73
- dynamicCreator = new DynamicCreator <>( getAnnotationType (), concreteClass );
74
- }
75
79
return dynamicCreator .createUsage ( context );
76
80
}
77
81
78
82
@ Override
79
83
public C createUsage (A jdkAnnotation , SourceModelBuildingContext context ) {
80
- if ( jdkCreator == null ) {
81
- jdkCreator = new JdkCreator <>( getAnnotationType (), concreteClass );
82
- }
83
84
return jdkCreator .createUsage ( jdkAnnotation , context );
84
85
}
85
86
@@ -102,93 +103,105 @@ public String toString() {
102
103
}
103
104
104
105
public static class DynamicCreator <A extends Annotation , C extends A > {
105
- private final Constructor <C > constructor ;
106
+ private final MethodHandle constructor ;
107
+ private final Class <C > concreteClass ;
106
108
107
109
public DynamicCreator (Class <A > annotationType , Class <C > concreteClass ) {
108
- this ( resolveConstructor ( concreteClass ) );
110
+ this ( resolveConstructor ( concreteClass ), concreteClass );
109
111
}
110
112
111
- private static <A extends Annotation , C extends A > Constructor < C > resolveConstructor (Class <C > concreteClass ) {
113
+ private static <A extends Annotation , C extends A > MethodHandle resolveConstructor (Class <C > concreteClass ) {
112
114
try {
113
- return concreteClass .getDeclaredConstructor ( SourceModelBuildingContext .class );
115
+ final MethodType methodType = MethodType .methodType ( void .class , SourceModelBuildingContext .class );
116
+ return MethodHandles .publicLookup ().findConstructor ( concreteClass , methodType );
114
117
}
115
- catch (NoSuchMethodException e ) {
116
- throw new RuntimeException ( e );
118
+ catch (Exception e ) {
119
+ throw new MethodResolutionException ( "Unable to locate default-variant constructor for `" + concreteClass . getName () + "`" , e );
117
120
}
118
121
}
119
122
120
- public DynamicCreator (Constructor <C > constructor ) {
123
+ public DynamicCreator (MethodHandle constructor , Class <C > concreteClass ) {
121
124
this .constructor = constructor ;
125
+ this .concreteClass = concreteClass ;
122
126
}
123
127
124
128
public C createUsage (SourceModelBuildingContext context ) {
125
129
try {
126
- return constructor .newInstance ( context );
130
+ //noinspection unchecked
131
+ return (C ) constructor .invoke ( context );
127
132
}
128
- catch (InvocationTargetException | InstantiationException | IllegalAccessException e ) {
129
- throw new RuntimeException ( e );
133
+ catch (Throwable e ) {
134
+ throw new MethodInvocationException ( "Unable to invoke default-variant constructor for `" + concreteClass . getName () + "`" , e );
130
135
}
131
136
}
132
137
}
133
138
134
139
public static class JdkCreator <A extends Annotation , C extends A > {
135
- private final Constructor <C > constructor ;
140
+ private final MethodHandle constructor ;
141
+ private final Class <C > concreteClass ;
136
142
137
143
public JdkCreator (Class <A > annotationType , Class <C > concreteClass ) {
138
- this ( resolveConstructor ( annotationType , concreteClass ) );
144
+ this ( resolveConstructor ( annotationType , concreteClass ), concreteClass );
139
145
}
140
146
141
- private static <A extends Annotation , C extends A > Constructor < C > resolveConstructor (
147
+ private static <A extends Annotation , C extends A > MethodHandle resolveConstructor (
142
148
Class <A > annotationType ,
143
149
Class <C > concreteClass ) {
144
150
try {
145
- return concreteClass .getDeclaredConstructor ( annotationType , SourceModelBuildingContext .class );
151
+ final MethodType methodType = MethodType .methodType ( void .class , annotationType , SourceModelBuildingContext .class );
152
+ return MethodHandles .publicLookup ().findConstructor ( concreteClass , methodType );
146
153
}
147
- catch (NoSuchMethodException e ) {
148
- throw new RuntimeException ( e );
154
+ catch (Exception e ) {
155
+ throw new MethodResolutionException ( "Unable to locate JDK-variant constructor for `" + concreteClass . getName () + "`" , e );
149
156
}
150
157
}
151
158
152
- public JdkCreator (Constructor <C > constructor ) {
159
+ public JdkCreator (MethodHandle constructor , Class <C > concreteClass ) {
153
160
this .constructor = constructor ;
161
+ this .concreteClass = concreteClass ;
154
162
}
155
163
156
164
public C createUsage (A jdkAnnotation , SourceModelBuildingContext context ) {
157
165
try {
158
- return constructor .newInstance ( jdkAnnotation , context );
166
+ //noinspection unchecked
167
+ return (C ) constructor .invoke ( jdkAnnotation , context );
159
168
}
160
- catch (InvocationTargetException | InstantiationException | IllegalAccessException e ) {
161
- throw new RuntimeException ( e );
169
+ catch (Throwable e ) {
170
+ throw new MethodInvocationException ( "Unable to invoke JDK-variant constructor for `" + concreteClass . getName () + "`" , e );
162
171
}
163
172
}
164
173
}
165
174
166
175
public static class DeTypedCreator <A extends Annotation , C extends A > {
167
- private final Constructor <C > constructor ;
176
+ private final MethodHandle constructor ;
177
+ private final Class <C > concreteClass ;
168
178
169
179
public DeTypedCreator (Class <A > annotationType , Class <C > concreteClass ) {
170
- this ( resolveConstructor ( concreteClass ) );
180
+ this ( resolveConstructor ( concreteClass ), concreteClass );
171
181
}
172
182
173
- private static <A extends Annotation , C extends A > Constructor < C > resolveConstructor (Class <C > concreteClass ) {
183
+ private static <A extends Annotation , C extends A > MethodHandle resolveConstructor (Class <C > concreteClass ) {
174
184
try {
175
- return concreteClass .getDeclaredConstructor ( Map .class , SourceModelBuildingContext .class );
185
+ final MethodType methodType = MethodType .methodType ( void .class , AnnotationInstance .class , SourceModelBuildingContext .class );
186
+ return MethodHandles .publicLookup ().findConstructor ( concreteClass , methodType );
176
187
}
177
- catch (NoSuchMethodException e ) {
178
- throw new RuntimeException ( e );
188
+ catch (Exception e ) {
189
+ throw new MethodResolutionException ( "Unable to locate Jandex-variant constructor for `" + concreteClass . getName () + "`" , e );
179
190
}
180
191
}
181
192
182
- public DeTypedCreator (Constructor <C > constructor ) {
193
+ public DeTypedCreator (MethodHandle constructor , Class <C > concreteClass ) {
183
194
this .constructor = constructor ;
195
+ this .concreteClass = concreteClass ;
184
196
}
185
197
186
198
public C createUsage (Map <String ,?> attributeValues , SourceModelBuildingContext context ) {
187
199
try {
188
- return constructor .newInstance ( attributeValues , context );
200
+ //noinspection unchecked
201
+ return (C ) constructor .invoke ( attributeValues , context );
189
202
}
190
- catch (InvocationTargetException | InstantiationException | IllegalAccessException e ) {
191
- throw new RuntimeException ( e );
203
+ catch (Throwable e ) {
204
+ throw new MethodInvocationException ( "Unable to invoke Jandex-variant constructor for `" + concreteClass . getName () + "`" , e );
192
205
}
193
206
}
194
207
}
0 commit comments