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