DATACMNS-1066 - ClassGeneratingPropertyAccessorFactory now opts out on failed access to ClassLoader.
We now eagerly check the accessibility of the defineClass(…) method on the class loader to be used for a PersistentEntity. This will then cause the clients to use a different PropertyAccessorFactory (as things stand today: the one using reflection) and not fail to create the class later on.
This commit is contained in:
@@ -91,8 +91,8 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
* Checks whether an accessor class can be generated.
|
||||
*
|
||||
* @param entity
|
||||
* @return {@literal true} if the runtime is equal or greater to Java 1.7, property name hash codes are unique and the
|
||||
* type has a class loader we can use to re-inject types.
|
||||
* @return {@literal true} if the runtime is equal or greater to Java 1.7, we can access the ClassLoader, the property
|
||||
* name hash codes are unique and the type has a class loader we can use to re-inject types.
|
||||
* @see PersistentPropertyAccessorFactory#isSupported(PersistentEntity)
|
||||
*/
|
||||
@Override
|
||||
@@ -104,6 +104,12 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
Evil.getClassLoaderMethod(entity);
|
||||
} catch (Exception o_O) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entity.getType().getClassLoader() == null || entity.getType().getPackage().getName().startsWith("java")) {
|
||||
return false;
|
||||
}
|
||||
@@ -1446,6 +1452,7 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
* accessed from a class in the same class loader.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@UtilityClass
|
||||
private static class Evil {
|
||||
@@ -1460,25 +1467,30 @@ public class ClassGeneratingPropertyAccessorFactory implements PersistentPropert
|
||||
* @param persistentEntity
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
Class<?> defineClass(String name, byte[] bytes, int offset, int len, PersistentEntity<?, ?> persistentEntity) {
|
||||
|
||||
ClassLoader classLoader = persistentEntity.getType().getClassLoader();
|
||||
Class<?> classLoaderClass = classLoader.getClass();
|
||||
|
||||
try {
|
||||
|
||||
Class<? extends PersistentEntity> persistentEntityClass = persistentEntity.getClass();
|
||||
Method defineClass = ReflectionUtils.findMethod(classLoaderClass, "defineClass", String.class, byte[].class,
|
||||
Integer.TYPE, Integer.TYPE, ProtectionDomain.class);
|
||||
Method defineClass = getClassLoaderMethod(persistentEntity);
|
||||
defineClass.setAccessible(true);
|
||||
|
||||
return (Class<?>) defineClass.invoke(classLoader, name, bytes, offset, len,
|
||||
persistentEntityClass.getProtectionDomain());
|
||||
persistentEntity.getClass().getProtectionDomain());
|
||||
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Method getClassLoaderMethod(PersistentEntity<?, ?> entity) {
|
||||
|
||||
ClassLoader classLoader = entity.getType().getClassLoader();
|
||||
Class<?> classLoaderClass = classLoader.getClass();
|
||||
|
||||
return ReflectionUtils.findMethod(classLoaderClass, "defineClass", String.class, byte[].class, Integer.TYPE,
|
||||
Integer.TYPE, ProtectionDomain.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user