Skip to content

Commit

Permalink
DATACMNS-1066 - ClassGeneratingPropertyAccessorFactory now opts out o…
Browse files Browse the repository at this point in the history
…n 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.
  • Loading branch information
odrotbohm committed May 16, 2017
1 parent f558a6c commit 679f30e
Showing 1 changed file with 20 additions and 8 deletions.
Expand Up @@ -91,8 +91,8 @@ public PersistentPropertyAccessor getPropertyAccessor(PersistentEntity<?, ?> ent
* 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
Expand All @@ -104,6 +104,12 @@ public boolean isSupported(PersistentEntity<?, ?> entity) {
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;
}
Expand Down Expand Up @@ -1446,6 +1452,7 @@ public int compareTo(PropertyStackAddress o) {
* accessed from a class in the same class loader.
*
* @author Mark Paluch
* @author Oliver Gierke
*/
@UtilityClass
private static class Evil {
Expand All @@ -1460,25 +1467,30 @@ private static class Evil {
* @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);
}
}
}

0 comments on commit 679f30e

Please sign in to comment.