55package org .hibernate .models .internal ;
66
77import 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 ;
1011import java .util .Collections ;
1112import java .util .List ;
1213import java .util .Map ;
2223 * does not collect annotations from the annotation class as we never care about
2324 * meta-annotations in these cases.
2425 *
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+ *
2529 * @author Steve Ebersole
2630 */
2731public class OrmAnnotationDescriptor <A extends Annotation , C extends A >
@@ -30,8 +34,8 @@ public class OrmAnnotationDescriptor<A extends Annotation, C extends A>
3034 private final Class <C > concreteClass ;
3135 private final List <AttributeDescriptor <?>> attributeDescriptors ;
3236
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 ;
3539 private DeTypedCreator <A ,C > deTypedCreator ;
3640
3741 public OrmAnnotationDescriptor (
@@ -53,6 +57,9 @@ public OrmAnnotationDescriptor(
5357
5458 this .concreteClass = concreteClass ;
5559 this .attributeDescriptors = AnnotationDescriptorBuilding .extractAttributeDescriptors ( annotationType );
60+
61+ this .dynamicCreator = new DynamicCreator <>( annotationType , concreteClass );
62+ this .jdkCreator = new JdkCreator <>( annotationType , concreteClass );
5663 }
5764
5865 @ Override
@@ -69,17 +76,11 @@ public Class<C> getMutableAnnotationType() {
6976
7077 @ Override
7178 public C createUsage (SourceModelBuildingContext context ) {
72- if ( dynamicCreator == null ) {
73- dynamicCreator = new DynamicCreator <>( getAnnotationType (), concreteClass );
74- }
7579 return dynamicCreator .createUsage ( context );
7680 }
7781
7882 @ Override
7983 public C createUsage (A jdkAnnotation , SourceModelBuildingContext context ) {
80- if ( jdkCreator == null ) {
81- jdkCreator = new JdkCreator <>( getAnnotationType (), concreteClass );
82- }
8384 return jdkCreator .createUsage ( jdkAnnotation , context );
8485 }
8586
@@ -102,93 +103,105 @@ public String toString() {
102103 }
103104
104105 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 ;
106108
107109 public DynamicCreator (Class <A > annotationType , Class <C > concreteClass ) {
108- this ( resolveConstructor ( concreteClass ) );
110+ this ( resolveConstructor ( concreteClass ), concreteClass );
109111 }
110112
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 ) {
112114 try {
113- return concreteClass .getDeclaredConstructor ( SourceModelBuildingContext .class );
115+ final MethodType methodType = MethodType .methodType ( void .class , SourceModelBuildingContext .class );
116+ return MethodHandles .publicLookup ().findConstructor ( concreteClass , methodType );
114117 }
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 );
117120 }
118121 }
119122
120- public DynamicCreator (Constructor <C > constructor ) {
123+ public DynamicCreator (MethodHandle constructor , Class <C > concreteClass ) {
121124 this .constructor = constructor ;
125+ this .concreteClass = concreteClass ;
122126 }
123127
124128 public C createUsage (SourceModelBuildingContext context ) {
125129 try {
126- return constructor .newInstance ( context );
130+ //noinspection unchecked
131+ return (C ) constructor .invoke ( context );
127132 }
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 );
130135 }
131136 }
132137 }
133138
134139 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 ;
136142
137143 public JdkCreator (Class <A > annotationType , Class <C > concreteClass ) {
138- this ( resolveConstructor ( annotationType , concreteClass ) );
144+ this ( resolveConstructor ( annotationType , concreteClass ), concreteClass );
139145 }
140146
141- private static <A extends Annotation , C extends A > Constructor < C > resolveConstructor (
147+ private static <A extends Annotation , C extends A > MethodHandle resolveConstructor (
142148 Class <A > annotationType ,
143149 Class <C > concreteClass ) {
144150 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 );
146153 }
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 );
149156 }
150157 }
151158
152- public JdkCreator (Constructor <C > constructor ) {
159+ public JdkCreator (MethodHandle constructor , Class <C > concreteClass ) {
153160 this .constructor = constructor ;
161+ this .concreteClass = concreteClass ;
154162 }
155163
156164 public C createUsage (A jdkAnnotation , SourceModelBuildingContext context ) {
157165 try {
158- return constructor .newInstance ( jdkAnnotation , context );
166+ //noinspection unchecked
167+ return (C ) constructor .invoke ( jdkAnnotation , context );
159168 }
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 );
162171 }
163172 }
164173 }
165174
166175 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 ;
168178
169179 public DeTypedCreator (Class <A > annotationType , Class <C > concreteClass ) {
170- this ( resolveConstructor ( concreteClass ) );
180+ this ( resolveConstructor ( concreteClass ), concreteClass );
171181 }
172182
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 ) {
174184 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 );
176187 }
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 );
179190 }
180191 }
181192
182- public DeTypedCreator (Constructor <C > constructor ) {
193+ public DeTypedCreator (MethodHandle constructor , Class <C > concreteClass ) {
183194 this .constructor = constructor ;
195+ this .concreteClass = concreteClass ;
184196 }
185197
186198 public C createUsage (Map <String ,?> attributeValues , SourceModelBuildingContext context ) {
187199 try {
188- return constructor .newInstance ( attributeValues , context );
200+ //noinspection unchecked
201+ return (C ) constructor .invoke ( attributeValues , context );
189202 }
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 );
192205 }
193206 }
194207 }
0 commit comments