88package org .hibernate .models .internal ;
99
1010import java .lang .annotation .Annotation ;
11- import java .lang .reflect .Constructor ;
12- import java .lang .reflect .InvocationTargetException ;
11+ import java .lang .invoke .MethodHandle ;
12+ import java .lang .invoke .MethodHandles ;
13+ import java .lang .invoke .MethodType ;
1314import java .util .Collections ;
1415import java .util .List ;
1516import java .util .Map ;
2627 * does not collect annotations from the annotation class as we never care about
2728 * meta-annotations in these cases.
2829 *
30+ * @implNote There are a few cases in Hibernate ORM e.g. where we do care about meta-annotations,
31+ * but those are handled specially there.
32+ *
2933 * @author Steve Ebersole
3034 */
3135public class OrmAnnotationDescriptor <A extends Annotation , C extends A > extends AbstractAnnotationDescriptor <A > {
3236 private final Class <C > concreteClass ;
3337 private final List <AttributeDescriptor <?>> attributeDescriptors ;
3438
35- private DynamicCreator <A ,C > dynamicCreator ;
36- private JdkCreator <A ,C > jdkCreator ;
39+ private final DynamicCreator <A ,C > dynamicCreator ;
40+ private final JdkCreator <A ,C > jdkCreator ;
3741 private JandexCreator <A ,C > jandexCreator ;
3842
3943 public OrmAnnotationDescriptor (
@@ -55,6 +59,9 @@ public OrmAnnotationDescriptor(
5559
5660 this .concreteClass = concreteClass ;
5761 this .attributeDescriptors = AnnotationDescriptorBuilding .extractAttributeDescriptors ( annotationType );
62+
63+ this .dynamicCreator = new DynamicCreator <>( annotationType , concreteClass );
64+ this .jdkCreator = new JdkCreator <>( annotationType , concreteClass );
5865 }
5966
6067 @ Override
@@ -66,17 +73,11 @@ public OrmAnnotationDescriptor(
6673
6774 @ Override
6875 public C createUsage (SourceModelBuildingContext context ) {
69- if ( dynamicCreator == null ) {
70- dynamicCreator = new DynamicCreator <>( getAnnotationType (), concreteClass );
71- }
7276 return dynamicCreator .createUsage ( context );
7377 }
7478
7579 @ Override
7680 public C createUsage (A jdkAnnotation , SourceModelBuildingContext context ) {
77- if ( jdkCreator == null ) {
78- jdkCreator = new JdkCreator <>( getAnnotationType (), concreteClass );
79- }
8081 return jdkCreator .createUsage ( jdkAnnotation , context );
8182 }
8283
@@ -99,93 +100,105 @@ public String toString() {
99100 }
100101
101102 public static class DynamicCreator <A extends Annotation , C extends A > {
102- private final Constructor <C > constructor ;
103+ private final MethodHandle constructor ;
104+ private final Class <C > concreteClass ;
103105
104106 public DynamicCreator (Class <A > annotationType , Class <C > concreteClass ) {
105- this ( resolveConstructor ( concreteClass ) );
107+ this ( resolveConstructor ( concreteClass ), concreteClass );
106108 }
107109
108- private static <A extends Annotation , C extends A > Constructor < C > resolveConstructor (Class <C > concreteClass ) {
110+ private static <A extends Annotation , C extends A > MethodHandle resolveConstructor (Class <C > concreteClass ) {
109111 try {
110- return concreteClass .getDeclaredConstructor ( SourceModelBuildingContext .class );
112+ final MethodType methodType = MethodType .methodType ( void .class , SourceModelBuildingContext .class );
113+ return MethodHandles .publicLookup ().findConstructor ( concreteClass , methodType );
111114 }
112- catch (NoSuchMethodException e ) {
113- throw new RuntimeException ( e );
115+ catch (Exception e ) {
116+ throw new MethodResolutionException ( "Unable to locate default-variant constructor for `" + concreteClass . getName () + "`" , e );
114117 }
115118 }
116119
117- public DynamicCreator (Constructor <C > constructor ) {
120+ public DynamicCreator (MethodHandle constructor , Class <C > concreteClass ) {
118121 this .constructor = constructor ;
122+ this .concreteClass = concreteClass ;
119123 }
120124
121125 public C createUsage (SourceModelBuildingContext context ) {
122126 try {
123- return constructor .newInstance ( context );
127+ //noinspection unchecked
128+ return (C ) constructor .invoke ( context );
124129 }
125- catch (InvocationTargetException | InstantiationException | IllegalAccessException e ) {
126- throw new RuntimeException ( e );
130+ catch (Throwable e ) {
131+ throw new MethodInvocationException ( "Unable to invoke default-variant constructor for `" + concreteClass . getName () + "`" , e );
127132 }
128133 }
129134 }
130135
131136 public static class JdkCreator <A extends Annotation , C extends A > {
132- private final Constructor <C > constructor ;
137+ private final MethodHandle constructor ;
138+ private final Class <C > concreteClass ;
133139
134140 public JdkCreator (Class <A > annotationType , Class <C > concreteClass ) {
135- this ( resolveConstructor ( annotationType , concreteClass ) );
141+ this ( resolveConstructor ( annotationType , concreteClass ), concreteClass );
136142 }
137143
138- private static <A extends Annotation , C extends A > Constructor < C > resolveConstructor (
144+ private static <A extends Annotation , C extends A > MethodHandle resolveConstructor (
139145 Class <A > annotationType ,
140146 Class <C > concreteClass ) {
141147 try {
142- return concreteClass .getDeclaredConstructor ( annotationType , SourceModelBuildingContext .class );
148+ final MethodType methodType = MethodType .methodType ( void .class , annotationType , SourceModelBuildingContext .class );
149+ return MethodHandles .publicLookup ().findConstructor ( concreteClass , methodType );
143150 }
144- catch (NoSuchMethodException e ) {
145- throw new RuntimeException ( e );
151+ catch (Exception e ) {
152+ throw new MethodResolutionException ( "Unable to locate JDK-variant constructor for `" + concreteClass . getName () + "`" , e );
146153 }
147154 }
148155
149- public JdkCreator (Constructor <C > constructor ) {
156+ public JdkCreator (MethodHandle constructor , Class <C > concreteClass ) {
150157 this .constructor = constructor ;
158+ this .concreteClass = concreteClass ;
151159 }
152160
153161 public C createUsage (A jdkAnnotation , SourceModelBuildingContext context ) {
154162 try {
155- return constructor .newInstance ( jdkAnnotation , context );
163+ //noinspection unchecked
164+ return (C ) constructor .invoke ( jdkAnnotation , context );
156165 }
157- catch (InvocationTargetException | InstantiationException | IllegalAccessException e ) {
158- throw new RuntimeException ( e );
166+ catch (Throwable e ) {
167+ throw new MethodInvocationException ( "Unable to invoke JDK-variant constructor for `" + concreteClass . getName () + "`" , e );
159168 }
160169 }
161170 }
162171
163172 public static class JandexCreator <A extends Annotation , C extends A > {
164- private final Constructor <C > constructor ;
173+ private final MethodHandle constructor ;
174+ private final Class <C > concreteClass ;
165175
166176 public JandexCreator (Class <C > concreteClass ) {
167- this ( resolveConstructor ( concreteClass ) );
177+ this ( resolveConstructor ( concreteClass ), concreteClass );
168178 }
169179
170- private static <A extends Annotation , C extends A > Constructor < C > resolveConstructor (Class <C > concreteClass ) {
180+ private static <A extends Annotation , C extends A > MethodHandle resolveConstructor (Class <C > concreteClass ) {
171181 try {
172- return concreteClass .getDeclaredConstructor ( AnnotationInstance .class , SourceModelBuildingContext .class );
182+ final MethodType methodType = MethodType .methodType ( void .class , AnnotationInstance .class , SourceModelBuildingContext .class );
183+ return MethodHandles .publicLookup ().findConstructor ( concreteClass , methodType );
173184 }
174- catch (NoSuchMethodException e ) {
175- throw new RuntimeException ( e );
185+ catch (Exception e ) {
186+ throw new MethodResolutionException ( "Unable to locate Jandex-variant constructor for `" + concreteClass . getName () + "`" , e );
176187 }
177188 }
178189
179- public JandexCreator (Constructor <C > constructor ) {
190+ public JandexCreator (MethodHandle constructor , Class <C > concreteClass ) {
180191 this .constructor = constructor ;
192+ this .concreteClass = concreteClass ;
181193 }
182194
183195 public C createUsage (AnnotationInstance jandexAnnotation , SourceModelBuildingContext context ) {
184196 try {
185- return constructor .newInstance ( jandexAnnotation , context );
197+ //noinspection unchecked
198+ return (C ) constructor .invoke ( jandexAnnotation , context );
186199 }
187- catch (InvocationTargetException | InstantiationException | IllegalAccessException e ) {
188- throw new RuntimeException ( e );
200+ catch (Throwable e ) {
201+ throw new MethodInvocationException ( "Unable to invoke Jandex-variant constructor for `" + concreteClass . getName () + "`" , e );
189202 }
190203 }
191204 }
0 commit comments