61
61
* @author Mark Paluch
62
62
* @author Oliver Gierke
63
63
* @author Christoph Strobl
64
+ * @author Jens Schauder
64
65
* @since 1.13
65
66
*/
66
67
public class ClassGeneratingPropertyAccessorFactory implements PersistentPropertyAccessorFactory {
@@ -91,7 +92,7 @@ public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> ent
91
92
/**
92
93
* Checks whether an accessor class can be generated.
93
94
*
94
- * @param entity
95
+ * @param entity must not be {@literal null}.
95
96
* @return {@literal true} if the runtime is equal or greater to Java 1.7, we can access the ClassLoader, the property
96
97
* name hash codes are unique and the type has a class loader we can use to re-inject types.
97
98
* @see PersistentPropertyAccessorFactory#isSupported(PersistentEntity)
@@ -101,15 +102,27 @@ public boolean isSupported(PersistentEntity<?, ?> entity) {
101
102
102
103
Assert .notNull (entity , "PersistentEntity must not be null!" );
103
104
104
- return isClassLoaderDefineClassAccessible (entity ) //
105
- && isTypeInjectable (entity ) //
106
- && arePropertyHashCodesUnique (entity );
105
+ return isClassLoaderDefineClassAccessible (entity ) && isTypeInjectable (entity ) && hasUniquePropertyHashCodes (entity );
106
+ }
107
+
108
+ private static boolean isClassLoaderDefineClassAccessible (PersistentEntity <?, ?> entity ) {
109
+
110
+ try {
111
+ Evil .getClassLoaderMethod (entity );
112
+ } catch (Exception o_O ) {
113
+ return false ;
114
+ }
115
+ return true ;
116
+ }
117
+
118
+ private static boolean isTypeInjectable (PersistentEntity <?, ?> entity ) {
119
+ return entity .getType ().getClassLoader () != null && !entity .getType ().getPackage ().getName ().startsWith ("java" );
107
120
}
108
121
109
- private boolean arePropertyHashCodesUnique (PersistentEntity <?, ?> entity ) {
122
+ private boolean hasUniquePropertyHashCodes (PersistentEntity <?, ?> entity ) {
110
123
111
- final Set <Integer > hashCodes = new HashSet <>();
112
- final AtomicInteger propertyCount = new AtomicInteger ();
124
+ Set <Integer > hashCodes = new HashSet <>();
125
+ AtomicInteger propertyCount = new AtomicInteger ();
113
126
114
127
entity .doWithProperties ((SimplePropertyHandler ) property -> {
115
128
@@ -129,23 +142,8 @@ private boolean arePropertyHashCodesUnique(PersistentEntity<?, ?> entity) {
129
142
return hashCodes .size () == propertyCount .get ();
130
143
}
131
144
132
- private static boolean isTypeInjectable (PersistentEntity <?, ?> entity ) {
133
- return entity .getType ().getClassLoader () != null && !entity .getType ().getPackage ().getName ().startsWith ("java" );
134
- }
135
-
136
- private static boolean isClassLoaderDefineClassAccessible (PersistentEntity <?, ?> entity ) {
137
-
138
- try {
139
- Evil .getClassLoaderMethod (entity );
140
- } catch (Exception o_O ) {
141
- return false ;
142
- }
143
- return true ;
144
- }
145
-
146
145
/**
147
146
* @param entity must not be {@literal null}.
148
- * @return
149
147
*/
150
148
private synchronized Class <PersistentPropertyAccessor > potentiallyCreateAndRegisterPersistentPropertyAccessorClass (
151
149
PersistentEntity <?, ?> entity ) {
@@ -277,28 +275,19 @@ static class PropertyAccessorClassGenerator {
277
275
278
276
/**
279
277
* Generate a new class for the given {@link PersistentEntity}.
280
- *
281
- * @param entity
282
- * @return
283
278
*/
284
- public static Class <?> generateCustomAccessorClass (PersistentEntity <?, ?> entity ) {
279
+ static Class <?> generateCustomAccessorClass (PersistentEntity <?, ?> entity ) {
285
280
286
281
String className = generateClassName (entity );
287
282
byte [] bytecode = generateBytecode (className .replace ('.' , '/' ), entity );
288
283
289
- Class <?> accessorClass = Evil .defineClass (className , bytecode , 0 , bytecode .length , entity );
290
-
291
- return accessorClass ;
284
+ return Evil .defineClass (className , bytecode , 0 , bytecode .length , entity );
292
285
}
293
286
294
287
/**
295
288
* Generate a new class for the given {@link PersistentEntity}.
296
- *
297
- * @param internalClassName
298
- * @param entity
299
- * @return
300
289
*/
301
- public static byte [] generateBytecode (String internalClassName , PersistentEntity <?, ?> entity ) {
290
+ static byte [] generateBytecode (String internalClassName , PersistentEntity <?, ?> entity ) {
302
291
303
292
ClassWriter cw = new ClassWriter (ClassWriter .COMPUTE_MAXS );
304
293
cw .visit (Opcodes .V1_6 , ACC_PUBLIC + ACC_SUPER , internalClassName , null , JAVA_LANG_OBJECT , IMPLEMENTED_INTERFACES );
@@ -344,10 +333,6 @@ private static List<PersistentProperty<?>> getPersistentProperties(PersistentEnt
344
333
* // ...
345
334
* }
346
335
* </pre>
347
- *
348
- * @param entity
349
- * @param persistentProperties
350
- * @param cw
351
336
*/
352
337
private static void visitFields (PersistentEntity <?, ?> entity , List <PersistentProperty <?>> persistentProperties ,
353
338
ClassWriter cw ) {
@@ -394,10 +379,6 @@ private static void visitFields(PersistentEntity<?, ?> entity, List<PersistentPr
394
379
* }
395
380
* }
396
381
* </pre>
397
- *
398
- * @param entity
399
- * @param internalClassName
400
- * @param cw
401
382
*/
402
383
private static void visitDefaultConstructor (PersistentEntity <?, ?> entity , String internalClassName ,
403
384
ClassWriter cw ) {
@@ -466,11 +447,6 @@ private static void visitDefaultConstructor(PersistentEntity<?, ?> entity, Strin
466
447
* // ...
467
448
* }
468
449
* </pre>
469
- *
470
- * @param entity
471
- * @param persistentProperties
472
- * @param internalClassName
473
- * @param cw
474
450
*/
475
451
private static void visitStaticInitializer (PersistentEntity <?, ?> entity ,
476
452
List <PersistentProperty <?>> persistentProperties , String internalClassName , ClassWriter cw ) {
@@ -532,9 +508,6 @@ private static void visitStaticInitializer(PersistentEntity<?, ?> entity,
532
508
/**
533
509
* Retrieve all classes which are involved in property/getter/setter declarations as these elements may be
534
510
* distributed across the type hierarchy.
535
- *
536
- * @param persistentProperties
537
- * @return
538
511
*/
539
512
private static List <Class <?>> getPropertyDeclaratingClasses (List <PersistentProperty <?>> persistentProperties ) {
540
513
@@ -549,11 +522,6 @@ private static List<Class<?>> getPropertyDeclaratingClasses(List<PersistentPrope
549
522
550
523
/**
551
524
* Generate property getter initializer.
552
- *
553
- * @param property
554
- * @param mv
555
- * @param entityClasses
556
- * @param internalClassName
557
525
*/
558
526
private static void visitPropertyGetterInitializer (PersistentProperty <?> property , MethodVisitor mv ,
559
527
List <Class <?>> entityClasses , String internalClassName ) {
@@ -594,11 +562,6 @@ private static void visitPropertyGetterInitializer(PersistentProperty<?> propert
594
562
595
563
/**
596
564
* Generate property setter initializer.
597
- *
598
- * @param property
599
- * @param mv
600
- * @param entityClasses
601
- * @param internalClassName
602
565
*/
603
566
private static void visitPropertySetterInitializer (PersistentProperty <?> property , MethodVisitor mv ,
604
567
List <Class <?>> entityClasses , String internalClassName ) {
@@ -653,11 +616,6 @@ private static void visitPropertySetterInitializer(PersistentProperty<?> propert
653
616
654
617
/**
655
618
* Generate field getter and setter initializers.
656
- *
657
- * @param property
658
- * @param mv
659
- * @param entityClasses
660
- * @param internalClassName
661
619
*/
662
620
private static void visitFieldGetterSetterInitializer (PersistentProperty <?> property , MethodVisitor mv ,
663
621
List <Class <?>> entityClasses , String internalClassName ) {
@@ -744,11 +702,6 @@ private static void visitBeanGetter(PersistentEntity<?, ?> entity, String intern
744
702
* }
745
703
* }
746
704
* </pre>
747
- *
748
- * @param entity
749
- * @param persistentProperties
750
- * @param internalClassName
751
- * @param cw
752
705
*/
753
706
private static void visitGetProperty (PersistentEntity <?, ?> entity ,
754
707
List <PersistentProperty <?>> persistentProperties , String internalClassName , ClassWriter cw ) {
@@ -795,11 +748,6 @@ private static void visitGetProperty(PersistentEntity<?, ?> entity,
795
748
796
749
/**
797
750
* Generate the {@code switch(hashcode) {label: }} block.
798
- *
799
- * @param entity
800
- * @param persistentProperties
801
- * @param internalClassName
802
- * @param mv
803
751
*/
804
752
private static void visitGetPropertySwitch (PersistentEntity <?, ?> entity ,
805
753
List <PersistentProperty <?>> persistentProperties , String internalClassName , MethodVisitor mv ) {
@@ -846,11 +794,6 @@ private static void visitGetPropertySwitch(PersistentEntity<?, ?> entity,
846
794
* Generate property read access using a {@link java.lang.invoke.MethodHandle}.
847
795
* {@link java.lang.invoke.MethodHandle#invoke(Object...)} have a {@code @PolymorphicSignature} so {@code invoke} is
848
796
* called as if the method had the expected signature and not array/varargs.
849
- *
850
- * @param entity
851
- * @param property
852
- * @param mv
853
- * @param internalClassName
854
797
*/
855
798
private static void visitGetProperty0 (PersistentEntity <?, ?> entity , PersistentProperty <?> property ,
856
799
MethodVisitor mv , String internalClassName ) {
@@ -912,7 +855,7 @@ private static void visitGetProperty0(PersistentEntity<?, ?> entity, PersistentP
912
855
}
913
856
914
857
/**
915
- * Generate the {@link PersistentPropertyAccessor#setProperty(PersistentProperty, Object )} method. *
858
+ * Generate the {@link PersistentPropertyAccessor#setProperty(PersistentProperty, Optional )} method. *
916
859
*
917
860
* <pre>
918
861
* {
@@ -930,11 +873,6 @@ private static void visitGetProperty0(PersistentEntity<?, ?> entity, PersistentP
930
873
* }
931
874
* }
932
875
* </pre>
933
- *
934
- * @param entity
935
- * @param persistentProperties
936
- * @param internalClassName
937
- * @param cw
938
876
*/
939
877
private static void visitSetProperty (PersistentEntity <?, ?> entity ,
940
878
List <PersistentProperty <?>> persistentProperties , String internalClassName , ClassWriter cw ) {
@@ -996,11 +934,6 @@ private static void visitUnwrapValue(MethodVisitor mv) {
996
934
997
935
/**
998
936
* Generate the {@code switch(hashcode) {label: }} block.
999
- *
1000
- * @param entity
1001
- * @param persistentProperties
1002
- * @param internalClassName
1003
- * @param mv
1004
937
*/
1005
938
private static void visitSetPropertySwitch (PersistentEntity <?, ?> entity ,
1006
939
List <PersistentProperty <?>> persistentProperties , String internalClassName , MethodVisitor mv ) {
@@ -1045,11 +978,6 @@ private static void visitSetPropertySwitch(PersistentEntity<?, ?> entity,
1045
978
* Generate property write access using a {@link java.lang.invoke.MethodHandle}. NOTE:
1046
979
* {@link java.lang.invoke.MethodHandle#invoke(Object...)} have a {@code @PolymorphicSignature} so {@code invoke} is
1047
980
* called as if the method had the expected signature and not array/varargs.
1048
- *
1049
- * @param entity
1050
- * @param property
1051
- * @param mv
1052
- * @param internalClassName
1053
981
*/
1054
982
private static void visitSetProperty0 (PersistentEntity <?, ?> entity , PersistentProperty <?> property ,
1055
983
MethodVisitor mv , String internalClassName ) {
@@ -1178,11 +1106,7 @@ private static boolean isAccessible(int modifiers) {
1178
1106
1179
1107
private static boolean isDefault (int modifiers ) {
1180
1108
1181
- if (Modifier .isPrivate (modifiers ) || Modifier .isProtected (modifiers ) || Modifier .isPublic (modifiers )) {
1182
- return false ;
1183
- }
1184
-
1185
- return true ;
1109
+ return !(Modifier .isPrivate (modifiers ) || Modifier .isProtected (modifiers ) || Modifier .isPublic (modifiers ));
1186
1110
}
1187
1111
1188
1112
private static boolean generateSetterMethodHandle (PersistentEntity <?, ?> entity , Field field ) {
@@ -1193,10 +1117,6 @@ private static boolean generateSetterMethodHandle(PersistentEntity<?, ?> entity,
1193
1117
* Check whether to generate {@link java.lang.invoke.MethodHandle} access. Checks visibility rules of the member and
1194
1118
* its declaring class. Use also {@link java.lang.invoke.MethodHandle} if visibility is protected/package-default
1195
1119
* and packages of the declaring types are different.
1196
- *
1197
- * @param entity
1198
- * @param member
1199
- * @return
1200
1120
*/
1201
1121
private static boolean generateMethodHandle (PersistentEntity <?, ?> entity , Member member ) {
1202
1122
@@ -1217,19 +1137,11 @@ private static boolean generateMethodHandle(PersistentEntity<?, ?> entity, Membe
1217
1137
1218
1138
/**
1219
1139
* Retrieves the class variable index with an offset of {@code 4}.
1220
- *
1221
- * @param list
1222
- * @param item
1223
- * @return
1224
1140
*/
1225
1141
private static int classVariableIndex4 (List <Class <?>> list , Class <?> item ) {
1226
1142
return 4 + list .indexOf (item );
1227
1143
}
1228
1144
1229
- /**
1230
- * @param entity
1231
- * @return
1232
- */
1233
1145
private static String generateClassName (PersistentEntity <?, ?> entity ) {
1234
1146
return entity .getType ().getName () + TAG + Integer .toString (entity .hashCode (), 36 );
1235
1147
}
@@ -1259,9 +1171,6 @@ private static Map<String, PropertyStackAddress> createPropertyStackMap(
1259
1171
1260
1172
/**
1261
1173
* Returns the appropriate autoboxing type.
1262
- *
1263
- * @param unboxed
1264
- * @return
1265
1174
*/
1266
1175
private static Class <?> autoboxType (Class <?> unboxed ) {
1267
1176
@@ -1380,9 +1289,6 @@ private static void autoboxIfNeeded(Class<?> in, Class<?> out, MethodVisitor vis
1380
1289
1381
1290
/**
1382
1291
* Returns the signature type for a {@link Class} including primitives.
1383
- *
1384
- * @param type must not be {@literal null}.
1385
- * @return
1386
1292
*/
1387
1293
private static String signatureTypeName (Class <?> type ) {
1388
1294
@@ -1459,13 +1365,6 @@ private static class Evil {
1459
1365
1460
1366
/**
1461
1367
* Define a Class in the {@link ClassLoader} of the {@link PersistentEntity} type.
1462
- *
1463
- * @param name
1464
- * @param bytes
1465
- * @param offset
1466
- * @param len
1467
- * @param persistentEntity
1468
- * @return
1469
1368
*/
1470
1369
Class <?> defineClass (String name , byte [] bytes , int offset , int len , PersistentEntity <?, ?> persistentEntity ) {
1471
1370
@@ -1488,15 +1387,8 @@ static Method getClassLoaderMethod(PersistentEntity<?, ?> entity) {
1488
1387
ClassLoader classLoader = entity .getType ().getClassLoader ();
1489
1388
Class <?> classLoaderClass = classLoader .getClass ();
1490
1389
1491
- Method defineClass = ReflectionUtils .findMethod ( //
1492
- classLoaderClass , //
1493
- "defineClass" , //
1494
- String .class , //
1495
- byte [].class , //
1496
- Integer .TYPE , //
1497
- Integer .TYPE , //
1498
- ProtectionDomain .class //
1499
- );
1390
+ Method defineClass = ReflectionUtils .findMethod (classLoaderClass , "defineClass" , String .class , byte [].class ,
1391
+ Integer .TYPE , Integer .TYPE , ProtectionDomain .class );
1500
1392
1501
1393
defineClass .setAccessible (true );
1502
1394
0 commit comments