HHH-17970 Remove support for running under a SecurityManager

This commit is contained in:
Sanne Grinovero 2024-04-16 23:29:44 +01:00 committed by Steve Ebersole
parent 0b770f9b17
commit 1f5d2fb417
20 changed files with 325 additions and 844 deletions

View File

@ -67,7 +67,7 @@ See the <<chapters/pc/BytecodeEnhancement.adoc#BytecodeEnhancement,Bytecode Enha
The entity class should have a no-argument constructor. Both Hibernate and Jakarta Persistence require this. The entity class should have a no-argument constructor. Both Hibernate and Jakarta Persistence require this.
Jakarta Persistence requires that this constructor be defined as public or protected. Jakarta Persistence requires that this constructor be defined as public or protected.
Hibernate, for the most part, does not care about the constructor visibility, as long as the system SecurityManager allows overriding the visibility setting. Hibernate, for the most part, does not care about the constructor visibility, and will override the visibility setting.
That said, the constructor should be defined with at least package visibility if you wish to leverage runtime proxy generation. That said, the constructor should be defined with at least package visibility if you wish to leverage runtime proxy generation.
[[entity-pojo-accessors]] [[entity-pojo-accessors]]

View File

@ -10,8 +10,6 @@ import java.io.InputStream;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.net.URL; import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -83,11 +81,7 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
orderedClassLoaderSet.add( ClassLoaderServiceImpl.class.getClassLoader() ); orderedClassLoaderSet.add( ClassLoaderServiceImpl.class.getClassLoader() );
// now build the aggregated class loader... // now build the aggregated class loader...
this.aggregatedClassLoader = AccessController.doPrivileged( new PrivilegedAction<AggregatedClassLoader>() { this.aggregatedClassLoader = new AggregatedClassLoader( orderedClassLoaderSet, lookupPrecedence );
public AggregatedClassLoader run() {
return new AggregatedClassLoader( orderedClassLoaderSet, lookupPrecedence );
}
} );
} }
/** /**

View File

@ -21,8 +21,6 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
@ -33,15 +31,12 @@ import org.hibernate.bytecode.enhance.spi.EnhancerConstants;
import org.hibernate.bytecode.spi.BasicProxyFactory; import org.hibernate.bytecode.spi.BasicProxyFactory;
import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes; import org.hibernate.engine.spi.PrimeAmongSecondarySupertypes;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.proxy.ProxyConfiguration; import org.hibernate.proxy.ProxyConfiguration;
import org.hibernate.proxy.ProxyFactory; import org.hibernate.proxy.ProxyFactory;
import net.bytebuddy.ByteBuddy; import net.bytebuddy.ByteBuddy;
import net.bytebuddy.ClassFileVersion; import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.TypeCache; import net.bytebuddy.TypeCache;
import net.bytebuddy.asm.AsmVisitorWrapper.ForDeclaredMethods;
import net.bytebuddy.asm.MemberSubstitution;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.DynamicType.Unloaded; import net.bytebuddy.dynamic.DynamicType.Unloaded;
@ -51,7 +46,6 @@ import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.pool.TypePool; import net.bytebuddy.pool.TypePool;
/** /**
@ -90,16 +84,8 @@ public final class ByteBuddyState {
ByteBuddyState(ClassFileVersion classFileVersion) { ByteBuddyState(ClassFileVersion classFileVersion) {
this.byteBuddy = new ByteBuddy( classFileVersion ).with( TypeValidation.DISABLED ); this.byteBuddy = new ByteBuddy( classFileVersion ).with( TypeValidation.DISABLED );
this.proxyCache = new TypeCache( TypeCache.Sort.WEAK ); this.proxyCache = new TypeCache( TypeCache.Sort.WEAK );
this.basicProxyCache = new TypeCache( TypeCache.Sort.WEAK ); this.basicProxyCache = new TypeCache( TypeCache.Sort.WEAK );
if ( SystemSecurityManager.isSecurityManagerEnabled() ) {
this.classRewriter = new SecurityManagerClassRewriter();
}
else {
this.classRewriter = new StandardClassRewriter();
}
} }
/** /**
@ -200,22 +186,12 @@ public final class ByteBuddyState {
return cache.findOrInsert( return cache.findOrInsert(
referenceClass.getClassLoader(), referenceClass.getClassLoader(),
cacheKey, cacheKey,
() -> { () -> make( makeProxyFunction.apply( byteBuddy ) )
PrivilegedAction<Class<?>> delegateToPrivilegedAction = new PrivilegedAction<Class<?>>() { .load(
@Override referenceClass.getClassLoader(),
public Class<?> run() { resolveClassLoadingStrategy( referenceClass )
return make( makeProxyFunction.apply( byteBuddy ) ) )
.load( .getLoaded(),
referenceClass.getClassLoader(),
resolveClassLoadingStrategy( referenceClass )
)
.getLoaded();
}
};
return SystemSecurityManager.isSecurityManagerEnabled() ? AccessController.doPrivileged(
delegateToPrivilegedAction ) :
delegateToPrivilegedAction.run();
},
cache cache
); );
} }
@ -233,8 +209,6 @@ public final class ByteBuddyState {
} }
private Unloaded<?> make(TypePool typePool, DynamicType.Builder<?> builder) { private Unloaded<?> make(TypePool typePool, DynamicType.Builder<?> builder) {
builder = classRewriter.installReflectionMethodVisitors( builder );
Unloaded<?> unloadedClass; Unloaded<?> unloadedClass;
if ( typePool != null ) { if ( typePool != null ) {
unloadedClass = builder.make( typePool ); unloadedClass = builder.make( typePool );
@ -251,9 +225,6 @@ public final class ByteBuddyState {
LOG.warn( "Unable to save generated class %1$s", unloadedClass.getTypeDescription().getName(), e ); LOG.warn( "Unable to save generated class %1$s", unloadedClass.getTypeDescription().getName(), e );
} }
} }
classRewriter.registerAuthorizedClass( unloadedClass );
return unloadedClass; return unloadedClass;
} }
@ -315,32 +286,10 @@ public final class ByteBuddyState {
toFullyIgnore.add( isDeclaredBy( m.getReturnType() ).and( named( m.getName() ) ).and( takesNoArguments() ) ); toFullyIgnore.add( isDeclaredBy( m.getReturnType() ).and( named( m.getName() ) ).and( takesNoArguments() ) );
} }
PrivilegedAction<MethodDelegation> delegateToInterceptorDispatcherMethodDelegationPrivilegedAction = this.delegateToInterceptorDispatcherMethodDelegation = MethodDelegation.to( ProxyConfiguration.InterceptorDispatcher.class );
new PrivilegedAction<MethodDelegation>() {
@Override this.interceptorFieldAccessor = FieldAccessor.ofField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME )
public MethodDelegation run() { .withAssigner( Assigner.DEFAULT, Assigner.Typing.DYNAMIC );
return MethodDelegation.to( ProxyConfiguration.InterceptorDispatcher.class );
}
};
this.delegateToInterceptorDispatcherMethodDelegation = SystemSecurityManager.isSecurityManagerEnabled()
? AccessController.doPrivileged( delegateToInterceptorDispatcherMethodDelegationPrivilegedAction )
: delegateToInterceptorDispatcherMethodDelegationPrivilegedAction.run();
PrivilegedAction<FieldAccessor.PropertyConfigurable> interceptorFieldAccessorPrivilegedAction =
new PrivilegedAction<FieldAccessor.PropertyConfigurable>() {
@Override
public FieldAccessor.PropertyConfigurable run() {
return FieldAccessor.ofField( ProxyConfiguration.INTERCEPTOR_FIELD_NAME )
.withAssigner( Assigner.DEFAULT, Assigner.Typing.DYNAMIC );
}
};
this.interceptorFieldAccessor = SystemSecurityManager.isSecurityManagerEnabled()
? AccessController.doPrivileged( interceptorFieldAccessorPrivilegedAction )
: interceptorFieldAccessorPrivilegedAction.run();
} }
public ElementMatcher<? super MethodDescription> getGroovyGetMetaClassFilter() { public ElementMatcher<? super MethodDescription> getGroovyGetMetaClassFilter() {
@ -371,71 +320,6 @@ public final class ByteBuddyState {
} }
} }
private interface ClassRewriter {
DynamicType.Builder<?> installReflectionMethodVisitors(DynamicType.Builder<?> builder);
void registerAuthorizedClass(Unloaded<?> unloadedClass);
}
private static class SecurityManagerClassRewriter implements ClassRewriter {
private final ForDeclaredMethods getDeclaredMethodMemberSubstitution;
private final ForDeclaredMethods getMethodMemberSubstitution;
private SecurityManagerClassRewriter() {
this.getDeclaredMethodMemberSubstitution = getDeclaredMethodMemberSubstitution();
this.getMethodMemberSubstitution = getMethodMemberSubstitution();
}
@Override
public DynamicType.Builder<?> installReflectionMethodVisitors(DynamicType.Builder<?> builder) {
builder = builder.visit( getDeclaredMethodMemberSubstitution );
return builder.visit( getMethodMemberSubstitution );
}
@Override
public void registerAuthorizedClass(Unloaded<?> unloadedClass) {
// we authorize the proxy class to access the method lookup dispatcher
HibernateMethodLookupDispatcher.registerAuthorizedClass( unloadedClass.getTypeDescription().getName() );
}
private static ForDeclaredMethods getDeclaredMethodMemberSubstitution() {
// this should only be called if the security manager is enabled, thus the privileged calls
return MemberSubstitution.relaxed()
.method( ElementMatchers.is( AccessController.doPrivileged( new GetDeclaredMethodAction( Class.class,
"getDeclaredMethod", String.class, Class[].class ) ) ) )
.replaceWith(
AccessController.doPrivileged( new GetDeclaredMethodAction( HibernateMethodLookupDispatcher.class,
"getDeclaredMethod", Class.class, String.class, Class[].class ) ) )
.on( ElementMatchers.isTypeInitializer() );
}
private static ForDeclaredMethods getMethodMemberSubstitution() {
// this should only be called if the security manager is enabled, thus the privileged calls
return MemberSubstitution.relaxed()
.method( ElementMatchers.is( AccessController.doPrivileged( new GetDeclaredMethodAction( Class.class,
"getMethod", String.class, Class[].class ) ) ) )
.replaceWith(
AccessController.doPrivileged( new GetDeclaredMethodAction( HibernateMethodLookupDispatcher.class,
"getMethod", Class.class, String.class, Class[].class ) ) )
.on( ElementMatchers.isTypeInitializer() );
}
}
private static class StandardClassRewriter implements ClassRewriter {
@Override
public DynamicType.Builder<?> installReflectionMethodVisitors(DynamicType.Builder<?> builder) {
// do nothing
return builder;
}
@Override
public void registerAuthorizedClass(Unloaded<?> unloadedClass) {
// do nothing
}
}
private static ClassLoadingStrategy<ClassLoader> resolveClassLoadingStrategy(Class<?> originalClass) { private static ClassLoadingStrategy<ClassLoader> resolveClassLoadingStrategy(Class<?> originalClass) {
try { try {
return ClassLoadingStrategy.UsingLookup.of( MethodHandles.privateLookupIn( originalClass, LOOKUP ) ); return ClassLoadingStrategy.UsingLookup.of( MethodHandles.privateLookupIn( originalClass, LOOKUP ) );

View File

@ -1,182 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.internal.bytebuddy;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Stream;
import org.hibernate.HibernateException;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
/**
* This dispatcher analyzes the stack frames to detect if a particular call should be authorized.
* <p>
* Authorized classes are registered when creating the ByteBuddy proxies.
* <p>
* It should only be used when the Security Manager is enabled.
*/
public class HibernateMethodLookupDispatcher {
/**
* The minimum number of stack frames to drop before we can hope to find the caller frame.
*/
private static final int MIN_STACK_FRAMES = 3;
/**
* The maximum number of stack frames to explore to find the caller frame.
* <p>
* Beyond that, we give up and throw an exception.
*/
private static final int MAX_STACK_FRAMES = 16;
private static final PrivilegedAction<Class<?>[]> GET_CALLER_STACK_ACTION;
// Currently, the bytecode provider is created statically and shared between all the session factories. Thus we
// can't clear this set when we close a session factory as we might remove elements coming from another one.
// Considering we can't clear these elements, we use the class names instead of the classes themselves to avoid
// issues.
private static Set<String> authorizedClasses = ConcurrentHashMap.newKeySet();
public static Method getDeclaredMethod(Class<?> type, String name, Class<?>[] parameters) {
PrivilegedAction<Method> getDeclaredMethodAction = new PrivilegedAction<Method>() {
@Override
public Method run() {
try {
return type.getDeclaredMethod( name, parameters );
}
catch (NoSuchMethodException | SecurityException e) {
return null;
}
}
};
return doPrivilegedAction( getDeclaredMethodAction );
}
public static Method getMethod(Class<?> type, String name, Class<?>[] parameters) {
PrivilegedAction<Method> getMethodAction = new PrivilegedAction<Method>() {
@Override
public Method run() {
try {
return type.getMethod( name, parameters );
}
catch (NoSuchMethodException | SecurityException e) {
return null;
}
}
};
return doPrivilegedAction( getMethodAction );
}
private static Method doPrivilegedAction(PrivilegedAction<Method> privilegedAction) {
Class<?> callerClass = getCallerClass();
if ( !authorizedClasses.contains( callerClass.getName() ) ) {
throw new SecurityException( "Unauthorized call by class " + callerClass );
}
return SystemSecurityManager.isSecurityManagerEnabled() ? AccessController.doPrivileged( privilegedAction ) :
privilegedAction.run();
}
static void registerAuthorizedClass(String className) {
authorizedClasses.add( className );
}
static {
// The action below will return the action used at runtime to retrieve the caller stack
PrivilegedAction<PrivilegedAction<Class<?>[]>> initializeGetCallerStackAction = new PrivilegedAction<PrivilegedAction<Class<?>[]>>() {
@Override
public PrivilegedAction<Class<?>[]> run() {
try {
return new StackWalkerGetCallerStackAction(StackWalker.getInstance( StackWalker.Option.RETAIN_CLASS_REFERENCE) );
}
catch (Throwable e) {
throw new HibernateException( "Unable to initialize the stack walker", e );
}
}
};
GET_CALLER_STACK_ACTION = SystemSecurityManager.isSecurityManagerEnabled()
? AccessController.doPrivileged( initializeGetCallerStackAction )
: initializeGetCallerStackAction.run();
}
private static Class<?> getCallerClass() {
Class<?>[] stackTrace = SystemSecurityManager.isSecurityManagerEnabled()
? AccessController.doPrivileged( GET_CALLER_STACK_ACTION )
: GET_CALLER_STACK_ACTION.run();
// this shouldn't happen but let's be safe
if ( stackTrace.length <= MIN_STACK_FRAMES ) {
throw new SecurityException( "Unable to determine the caller class" );
}
boolean hibernateMethodLookupDispatcherDetected = false;
// start at the 4th frame and limit that to the MAX_STACK_FRAMES first frames
int maxFrames = Math.min( MAX_STACK_FRAMES, stackTrace.length );
for ( int i = MIN_STACK_FRAMES; i < maxFrames; i++ ) {
if ( stackTrace[i].getName().equals( HibernateMethodLookupDispatcher.class.getName() ) ) {
hibernateMethodLookupDispatcherDetected = true;
continue;
}
if ( hibernateMethodLookupDispatcherDetected ) {
return stackTrace[i];
}
}
throw new SecurityException( "Unable to determine the caller class" );
}
/**
* A privileged action that retrieves the caller stack using a stack walker.
*/
private static class StackWalkerGetCallerStackAction implements PrivilegedAction<Class<?>[]> {
private final StackWalker stackWalker;
StackWalkerGetCallerStackAction(StackWalker stackWalker) {
this.stackWalker = stackWalker;
}
@Override
public Class<?>[] run() {
try {
return stackWalker.walk( stackFrameExtractFunction );
}
catch (RuntimeException e) {
throw new SecurityException( "Unable to determine the caller class", e );
}
}
private final Function<Stream<StackWalker.StackFrame>, Class<?>[]> stackFrameExtractFunction = new Function<>() {
@Override
public Class<?>[] apply(Stream<StackWalker.StackFrame> stream) {
return stream.map( stackFrameGetDeclaringClassFunction )
.limit( MAX_STACK_FRAMES )
.toArray( Class<?>[]::new );
}
};
private final Function<StackWalker.StackFrame, Class<?>> stackFrameGetDeclaringClassFunction = new Function<>() {
@Override
public Class<?> apply(StackWalker.StackFrame frame) {
try {
return frame.getDeclaringClass();
}
catch (RuntimeException e) {
throw new HibernateException( "Unable to get stack frame declaring class", e );
}
}
};
}
}

View File

@ -6,8 +6,6 @@
*/ */
package org.hibernate.engine.jdbc.connections.internal; package org.hibernate.engine.jdbc.connections.internal;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.Connection; import java.sql.Connection;
import java.sql.Driver; import java.sql.Driver;
import java.sql.DriverManager; import java.sql.DriverManager;
@ -34,7 +32,6 @@ import org.hibernate.dialect.SimpleDatabaseVersion;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.DatabaseConnectionInfo; import org.hibernate.engine.jdbc.connections.spi.DatabaseConnectionInfo;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.service.UnknownUnwrapTypeException; import org.hibernate.service.UnknownUnwrapTypeException;
import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.ServiceException; import org.hibernate.service.spi.ServiceException;
@ -614,22 +611,7 @@ public class DriverManagerConnectionProviderImpl
ConnectionInfoLogger.INSTANCE.cleaningUpConnectionPool( pool.getUrl() ); ConnectionInfoLogger.INSTANCE.cleaningUpConnectionPool( pool.getUrl() );
active = false; active = false;
if ( executorService != null ) { if ( executorService != null ) {
PrivilegedAction delegateToPrivilegedAction = executorService.shutdown();
new PrivilegedAction() {
@Override
public Object run() {
executorService.shutdown();
return null;
}
};
if ( SystemSecurityManager.isSecurityManagerEnabled() ) {
AccessController.doPrivileged(
delegateToPrivilegedAction );
}
else {
delegateToPrivilegedAction.run();
}
} }
executorService = null; executorService = null;
try { try {

View File

@ -7,8 +7,6 @@
package org.hibernate.event.spi; package org.hibernate.event.spi;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -85,24 +83,23 @@ public final class EventType<T> {
* Maintain a map of {@link EventType} instances keyed by name for lookup by name as well as {@link #values()} * Maintain a map of {@link EventType} instances keyed by name for lookup by name as well as {@link #values()}
* resolution. * resolution.
*/ */
private static final Map<String,EventType<?>> STANDARD_TYPE_BY_NAME_MAP = AccessController.doPrivileged( private static final Map<String,EventType<?>> STANDARD_TYPE_BY_NAME_MAP = initStandardTypeNameMap();
(PrivilegedAction<Map<String, EventType<?>>>) () -> {
final Map<String, EventType<?>> typeByNameMap = new HashMap<>();
for ( Field field : EventType.class.getDeclaredFields() ) {
if ( EventType.class.isAssignableFrom( field.getType() ) ) {
try {
final EventType<?> typeField = (EventType<?>) field.get( null );
typeByNameMap.put( typeField.eventName(), typeField );
}
catch (Exception t) {
throw new HibernateException( "Unable to initialize EventType map", t );
}
}
}
return Collections.unmodifiableMap( typeByNameMap ); private static Map<String, EventType<?>> initStandardTypeNameMap() {
final Map<String, EventType<?>> typeByNameMap = new HashMap<>();
for ( Field field : EventType.class.getDeclaredFields() ) {
if ( EventType.class.isAssignableFrom( field.getType() ) ) {
try {
final EventType<?> typeField = (EventType<?>) field.get( null );
typeByNameMap.put( typeField.eventName(), typeField );
}
catch ( Exception t ) {
throw new HibernateException( "Unable to initialize EventType map", t );
}
} }
); }
return Collections.unmodifiableMap( typeByNameMap );
}
private static <T> EventType<T> create(String name, Class<T> listenerRole) { private static <T> EventType<T> create(String name, Class<T> listenerRole) {
return new EventType<>( name, listenerRole, STANDARD_TYPE_COUNTER.getAndIncrement(), true ); return new EventType<>( name, listenerRole, STANDARD_TYPE_COUNTER.getAndIncrement(), true );

View File

@ -1,32 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.internal.util.securitymanager;
/**
* Encapsulates access to {@link System#getSecurityManager()},
* in preparation of it being phased out by the JDK.
*
* Since JDK 17 the security manager can be disabled by setting
* the system property {@code java.security.manager} to {@code disallow};
* to prepare for this we also offer the option of setting
* {@code org.hibernate.internal.util.securitymanager.FULLY_DISABLE} to {@code true}
* to have the same effect, although limited to the Hibernate ORM code.
*/
public final class SystemSecurityManager {
public static final String FULLY_DISABLE_PROP_NAME = "org.hibernate.internal.util.securitymanager.FULLY_DISABLE";
private static final boolean disabledForced = Boolean.getBoolean( FULLY_DISABLE_PROP_NAME );
private static final boolean SM_IS_ENABLED = (!disabledForced) && (System.getSecurityManager() != null );
public static boolean isSecurityManagerEnabled() {
return SM_IS_ENABLED;
}
//N.B. do not expose a "doPrivileged" helper as that would introduce a security problem
}

View File

@ -11,7 +11,6 @@ import java.io.Serializable;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.security.PrivilegedAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -26,14 +25,12 @@ import org.hibernate.collection.spi.LazyInitializable;
import org.hibernate.collection.spi.PersistentCollection; import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer; import org.hibernate.proxy.LazyInitializer;
import static jakarta.persistence.spi.LoadState.LOADED; import static jakarta.persistence.spi.LoadState.LOADED;
import static jakarta.persistence.spi.LoadState.NOT_LOADED; import static jakarta.persistence.spi.LoadState.NOT_LOADED;
import static jakarta.persistence.spi.LoadState.UNKNOWN; import static jakarta.persistence.spi.LoadState.UNKNOWN;
import static java.security.AccessController.doPrivileged;
import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
@ -353,22 +350,19 @@ public final class PersistenceUtilHelper {
} }
private AttributeAccess buildAttributeAccess(final String attributeName) { private AttributeAccess buildAttributeAccess(final String attributeName) {
final PrivilegedAction<AttributeAccess> action = () -> { for ( Class<?> clazz : classHierarchy ) {
for ( Class<?> clazz : classHierarchy ) { try {
try { return new FieldAttributeAccess( clazz.getDeclaredField( attributeName ) );
return new FieldAttributeAccess( clazz.getDeclaredField( attributeName ) ); }
} catch ( NoSuchFieldException e ) {
catch ( NoSuchFieldException e ) { final Method method = getMethod( clazz, attributeName );
final Method method = getMethod( clazz, attributeName ); if ( method != null ) {
if ( method != null ) { return new MethodAttributeAccess( attributeName, method );
return new MethodAttributeAccess( attributeName, method );
}
} }
} }
//we could not find any match }
return new NoSuchAttributeAccess( specifiedClass, attributeName ); //we could not find any match
}; return new NoSuchAttributeAccess( specifiedClass, attributeName );
return SystemSecurityManager.isSecurityManagerEnabled() ? doPrivileged( action ) : action.run();
} }
} }

View File

@ -8,8 +8,6 @@ package org.hibernate.proxy.pojo.bytebuddy;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Set; import java.util.Set;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -18,7 +16,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.ProxyConfiguration; import org.hibernate.proxy.ProxyConfiguration;
import org.hibernate.proxy.ProxyFactory; import org.hibernate.proxy.ProxyFactory;
@ -109,35 +106,24 @@ public class ByteBuddyProxyFactory implements ProxyFactory, Serializable {
/** /**
* This technically returns a HibernateProxy, but declaring that type as the return * This technically returns a HibernateProxy, but declaring that type as the return
* type for the privileged action triggers an implicit case of type pollution. * type for the newInstance() action triggers an implicit case of type pollution.
* We therefore declare it as PrimeAmongSecondarySupertypes, and require the * We therefore declare it as PrimeAmongSecondarySupertypes, and require the
* invoker to perform the narrowing * invoker to perform the narrowing
*/ */
private PrimeAmongSecondarySupertypes getHibernateProxyInternal() private PrimeAmongSecondarySupertypes getHibernateProxyInternal() throws HibernateException {
throws HibernateException { try {
return (PrimeAmongSecondarySupertypes) proxyClass.getConstructor().newInstance();
final PrivilegedAction<PrimeAmongSecondarySupertypes> action = new PrivilegedAction<PrimeAmongSecondarySupertypes>() { }
catch (NoSuchMethodException e) {
@Override String logMessage = LOG.bytecodeEnhancementFailedBecauseOfDefaultConstructor( entityName );
public PrimeAmongSecondarySupertypes run() { LOG.error( logMessage, e );
throw new HibernateException( logMessage, e );
try { }
return (PrimeAmongSecondarySupertypes) proxyClass.getConstructor().newInstance(); catch (Throwable t) {
} String logMessage = LOG.bytecodeEnhancementFailed( entityName );
catch (NoSuchMethodException e) { LOG.error( logMessage, t );
String logMessage = LOG.bytecodeEnhancementFailedBecauseOfDefaultConstructor( entityName ); throw new HibernateException( logMessage, t );
LOG.error( logMessage, e ); }
throw new HibernateException( logMessage, e );
}
catch (Throwable t) {
String logMessage = LOG.bytecodeEnhancementFailed( entityName );
LOG.error( logMessage, t );
throw new HibernateException( logMessage, t );
}
}
};
return SystemSecurityManager.isSecurityManagerEnabled() ? AccessController.doPrivileged( action ) : action.run();
} }
} }

View File

@ -1,58 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.bytecode.internal.bytebuddy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.lang.reflect.Method;
import org.junit.Test;
public class HibernateMethodLookupDispatcherTest {
@Test
public void testAuthorizedClass() {
HibernateMethodLookupDispatcher.registerAuthorizedClass( AuthorizedClass.class.getName() );
AuthorizedClass authorizedClass = new AuthorizedClass();
assertNotNull( authorizedClass.declaredMethod );
assertEquals( "myMethod", authorizedClass.declaredMethod.getName() );
}
@Test( expected = SecurityException.class )
public void testUnauthorizedClass() {
new UnauthorizedClass();
}
public static class AuthorizedClass {
private Method declaredMethod;
public AuthorizedClass() {
declaredMethod = HibernateMethodLookupDispatcher.getDeclaredMethod( AuthorizedClass.class, "myMethod",
new Class<?>[]{ String.class } );
}
public void myMethod(String myParameter) {
}
}
public static class UnauthorizedClass {
@SuppressWarnings("unused")
private Method declaredMethod;
public UnauthorizedClass() {
declaredMethod = HibernateMethodLookupDispatcher.getDeclaredMethod( AuthorizedClass.class, "myMethod",
new Class<?>[]{ String.class } );
}
public void myMethod(String myParameter) {
}
}
}

View File

@ -8,15 +8,11 @@ package org.hibernate.envers.internal.entities.mapper;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.function.Supplier;
import org.hibernate.envers.exception.AuditException; import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.internal.entities.PropertyData; import org.hibernate.envers.internal.entities.PropertyData;
import org.hibernate.envers.internal.tools.ReflectionTools; import org.hibernate.envers.internal.tools.ReflectionTools;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.property.access.spi.Getter; import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.Setter; import org.hibernate.property.access.spi.Setter;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
@ -28,22 +24,6 @@ import org.hibernate.service.ServiceRegistry;
*/ */
public abstract class AbstractMapper { public abstract class AbstractMapper {
/**
* Perform an action in a privileged block.
*
* @param block the lambda to executed in privileged.
* @param <T> the return type
* @return the result of the privileged call, may be {@literal null}
*/
protected <T> T doPrivileged(Supplier<T> block) {
if ( SystemSecurityManager.isSecurityManagerEnabled() ) {
return AccessController.doPrivileged( (PrivilegedAction<T>) block::get );
}
else {
return block.get();
}
}
/** /**
* Get a value from the specified object. * Get a value from the specified object.
* *
@ -55,10 +35,8 @@ public abstract class AbstractMapper {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected <T> T getValueFromObject(PropertyData propertyData, Object object, ServiceRegistry serviceRegistry) { protected <T> T getValueFromObject(PropertyData propertyData, Object object, ServiceRegistry serviceRegistry) {
return doPrivileged( () -> { final Getter getter = ReflectionTools.getGetter( object.getClass(), propertyData, serviceRegistry );
final Getter getter = ReflectionTools.getGetter( object.getClass(), propertyData, serviceRegistry ); return (T) getter.get( object );
return (T) getter.get( object );
} );
} }
/** /**
@ -66,17 +44,15 @@ public abstract class AbstractMapper {
* *
* @param propertyName the property name, should not be {@literal null} * @param propertyName the property name, should not be {@literal null}
* @param accessType the property access type, should not be {@literal null} * @param accessType the property access type, should not be {@literal null}
* @param object the object for hwich the value should be read, should not be {@literal null} * @param object the object for which the value should be read, should not be {@literal null}
* @param serviceRegistry the service registry, should not be {@literal null} * @param serviceRegistry the service registry, should not be {@literal null}
* @param <T> the return type * @param <T> the return type
* @return the value read from the object, may be {@literal null} * @return the value read from the object, may be {@literal null}
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected <T> T getValueFromObject(String propertyName, String accessType, Object object, ServiceRegistry serviceRegistry) { protected <T> T getValueFromObject(String propertyName, String accessType, Object object, ServiceRegistry serviceRegistry) {
return doPrivileged( () -> { final Getter getter = ReflectionTools.getGetter( object.getClass(), propertyName, accessType, serviceRegistry );
final Getter getter = ReflectionTools.getGetter( object.getClass(), propertyName, accessType, serviceRegistry ); return (T) getter.get( object );
return (T) getter.get( object );
} );
} }
/** /**
@ -88,11 +64,8 @@ public abstract class AbstractMapper {
* @param serviceRegistry the service registry, should not be {@literal null} * @param serviceRegistry the service registry, should not be {@literal null}
*/ */
protected void setValueOnObject(PropertyData propertyData, Object object, Object value, ServiceRegistry serviceRegistry) { protected void setValueOnObject(PropertyData propertyData, Object object, Object value, ServiceRegistry serviceRegistry) {
doPrivileged( () -> { final Setter setter = ReflectionTools.getSetter(object.getClass(), propertyData, serviceRegistry );
final Setter setter = ReflectionTools.getSetter(object.getClass(), propertyData, serviceRegistry ); setter.set( object, value );
setter.set( object, value );
return null;
} );
} }
/** /**
@ -104,12 +77,9 @@ public abstract class AbstractMapper {
* @param serviceRegistry the service registry, should not be {@literal null} * @param serviceRegistry the service registry, should not be {@literal null}
*/ */
protected void getAndSetValue(PropertyData propertyData, Object source, Object destination, ServiceRegistry serviceRegistry) { protected void getAndSetValue(PropertyData propertyData, Object source, Object destination, ServiceRegistry serviceRegistry) {
doPrivileged( () -> { final Getter getter = ReflectionTools.getGetter( source.getClass(), propertyData, serviceRegistry );
final Getter getter = ReflectionTools.getGetter( source.getClass(), propertyData, serviceRegistry ); final Setter setter = ReflectionTools.getSetter( destination.getClass(), propertyData, serviceRegistry );
final Setter setter = ReflectionTools.getSetter( destination.getClass(), propertyData, serviceRegistry ); setter.set( destination, getter.get( source ) );
setter.set( destination, getter.get( source ) );
return null;
} );
} }
/** /**
@ -121,17 +91,15 @@ public abstract class AbstractMapper {
* @return a new instance of the class * @return a new instance of the class
*/ */
protected <T> T newObjectInstance(Class<T> clazz, Object... args) { protected <T> T newObjectInstance(Class<T> clazz, Object... args) {
return doPrivileged( () -> { try {
try { final Constructor<T> constructor = ReflectHelper.getDefaultConstructor( clazz );
final Constructor<T> constructor = ReflectHelper.getDefaultConstructor( clazz ); if ( constructor == null ) {
if ( constructor == null ) { throw new AuditException( "Failed to locate default constructor for class: " + clazz.getName() );
throw new AuditException( "Failed to locate default constructor for class: " + clazz.getName() );
}
return constructor.newInstance( args );
} }
catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { return constructor.newInstance( args );
throw new AuditException( e ); }
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
} ); throw new AuditException( e );
}
} }
} }

View File

@ -125,68 +125,64 @@ public class ComponentPropertyMapper extends AbstractPropertyMapper implements C
return; return;
} }
doPrivileged( () -> { try {
try {
if ( isDynamicComponentMap() ) { if ( isDynamicComponentMap() ) {
final Object subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance(); final Object subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
( (Map) obj ).put( propertyData.getBeanName(), subObj ); ( (Map) obj ).put( propertyData.getBeanName(), subObj );
delegate.mapToEntityFromMap( enversService, subObj, data, primaryKey, versionsReader, revision ); delegate.mapToEntityFromMap( enversService, subObj, data, primaryKey, versionsReader, revision );
}
else {
final Setter setter = ReflectionTools.getSetter(
obj.getClass(),
propertyData,
enversService.getServiceRegistry()
);
if ( isAllPropertiesNull( data ) ) {
// single property, but default value need not be null, so we'll set it to null anyway
setter.set( obj, null );
} }
else { else {
final Setter setter = ReflectionTools.getSetter( final Object subObj;
obj.getClass(), if ( embeddableInstantiator != null ) {
propertyData, final Object[] values = new Object[delegate.properties.size()];
enversService.getServiceRegistry() int i = 0;
); for ( Map.Entry<PropertyData, PropertyMapper> entry : delegate.properties.entrySet() ) {
values[i] = entry.getValue().mapToEntityFromMap(
if ( isAllPropertiesNull( data ) ) {
// single property, but default value need not be null, so we'll set it to null anyway
setter.set( obj, null );
}
else {
final Object subObj;
if ( embeddableInstantiator != null ) {
final Object[] values = new Object[delegate.properties.size()];
int i = 0;
for ( Map.Entry<PropertyData, PropertyMapper> entry : delegate.properties.entrySet() ) {
values[i] = entry.getValue().mapToEntityFromMap(
enversService,
data,
primaryKey,
versionsReader,
revision
);
i++;
}
subObj = embeddableInstantiator.instantiate(
() -> values,
versionsReader.getSessionImplementor()
.getSessionFactory()
);
}
else {
subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
delegate.mapToEntityFromMap(
enversService, enversService,
subObj,
data, data,
primaryKey, primaryKey,
versionsReader, versionsReader,
revision revision
); );
i++;
} }
// set the component subObj = embeddableInstantiator.instantiate(
setter.set( obj, subObj ); () -> values,
versionsReader.getSessionImplementor()
.getSessionFactory()
);
} }
else {
subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
delegate.mapToEntityFromMap(
enversService,
subObj,
data,
primaryKey,
versionsReader,
revision
);
}
// set the component
setter.set( obj, subObj );
} }
} }
catch ( Exception e ) { }
throw new AuditException( e ); catch ( Exception e ) {
} throw new AuditException( e );
}
return null;
} );
} }
@Override @Override
@ -202,57 +198,55 @@ public class ComponentPropertyMapper extends AbstractPropertyMapper implements C
return null; return null;
} }
return doPrivileged( () -> { try {
try { final Object subObj;
final Object subObj; if ( isDynamicComponentMap() ) {
if ( isDynamicComponentMap() ) { subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance(); delegate.mapToEntityFromMap( enversService, subObj, data, primaryKey, versionsReader, revision );
delegate.mapToEntityFromMap( enversService, subObj, data, primaryKey, versionsReader, revision ); }
else {
if ( isAllPropertiesNull( data ) ) {
// single property, but default value need not be null, so we'll set it to null anyway
subObj = null;
} }
else { else {
if ( isAllPropertiesNull( data ) ) { if ( embeddableInstantiator != null ) {
// single property, but default value need not be null, so we'll set it to null anyway final Object[] values = new Object[delegate.properties.size()];
subObj = null; int i = 0;
} for ( Map.Entry<PropertyData, PropertyMapper> entry : delegate.properties.entrySet() ) {
else { values[i] = entry.getValue().mapToEntityFromMap(
if ( embeddableInstantiator != null ) {
final Object[] values = new Object[delegate.properties.size()];
int i = 0;
for ( Map.Entry<PropertyData, PropertyMapper> entry : delegate.properties.entrySet() ) {
values[i] = entry.getValue().mapToEntityFromMap(
enversService,
data,
primaryKey,
versionsReader,
revision
);
i++;
}
subObj = embeddableInstantiator.instantiate(
() -> values,
versionsReader.getSessionImplementor()
.getSessionFactory()
);
}
else {
subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
delegate.mapToEntityFromMap(
enversService, enversService,
subObj,
data, data,
primaryKey, primaryKey,
versionsReader, versionsReader,
revision revision
); );
i++;
} }
subObj = embeddableInstantiator.instantiate(
() -> values,
versionsReader.getSessionImplementor()
.getSessionFactory()
);
}
else {
subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
delegate.mapToEntityFromMap(
enversService,
subObj,
data,
primaryKey,
versionsReader,
revision
);
} }
} }
return subObj;
} }
catch ( Exception e ) { return subObj;
throw new AuditException( e ); }
} catch ( Exception e ) {
} ); throw new AuditException( e );
}
} }
private boolean isAllPropertiesNull(Map data) { private boolean isAllPropertiesNull(Map data) {

View File

@ -103,44 +103,42 @@ public class MultiPropertyMapper extends AbstractPropertyMapper implements Exten
final Map<String, Object> data, final Map<String, Object> data,
final Object newObj, final Object newObj,
final Object oldObj) { final Object oldObj) {
return doPrivileged( () -> { boolean ret = false;
boolean ret = false; for ( Map.Entry<PropertyData, PropertyMapper> entry : properties.entrySet() ) {
for ( Map.Entry<PropertyData, PropertyMapper> entry : properties.entrySet() ) { final PropertyData propertyData = entry.getKey();
final PropertyData propertyData = entry.getKey(); final PropertyMapper propertyMapper = entry.getValue();
final PropertyMapper propertyMapper = entry.getValue();
// synthetic properties are not part of the entity model; therefore they should be ignored. // synthetic properties are not part of the entity model; therefore they should be ignored.
if ( propertyData.isSynthetic() ) { if ( propertyData.isSynthetic() ) {
continue; continue;
} }
Getter getter; Getter getter;
if ( newObj != null ) { if ( newObj != null ) {
getter = ReflectionTools.getGetter( getter = ReflectionTools.getGetter(
newObj.getClass(), newObj.getClass(),
propertyData, propertyData,
session.getFactory().getServiceRegistry() session.getFactory().getServiceRegistry()
);
}
else if ( oldObj != null ) {
getter = ReflectionTools.getGetter(
oldObj.getClass(),
propertyData,
session.getFactory().getServiceRegistry()
);
}
else {
return false;
}
ret |= propertyMapper.mapToMapFromEntity(
session, data,
newObj == null ? null : getter.get( newObj ),
oldObj == null ? null : getter.get( oldObj )
); );
} }
return ret; else if ( oldObj != null ) {
} ); getter = ReflectionTools.getGetter(
oldObj.getClass(),
propertyData,
session.getFactory().getServiceRegistry()
);
}
else {
return false;
}
ret |= propertyMapper.mapToMapFromEntity(
session, data,
newObj == null ? null : getter.get( newObj ),
oldObj == null ? null : getter.get( oldObj )
);
}
return ret;
} }
@Override @Override
@ -149,44 +147,40 @@ public class MultiPropertyMapper extends AbstractPropertyMapper implements Exten
final Map<String, Object> data, final Map<String, Object> data,
final Object newObj, final Object newObj,
final Object oldObj) { final Object oldObj) {
doPrivileged( () -> { for ( Map.Entry<PropertyData, PropertyMapper> entry : properties.entrySet() ) {
for ( Map.Entry<PropertyData, PropertyMapper> entry : properties.entrySet() ) { final PropertyData propertyData = entry.getKey();
final PropertyData propertyData = entry.getKey(); final PropertyMapper propertyMapper = entry.getValue();
final PropertyMapper propertyMapper = entry.getValue();
// synthetic properties are not part of the entity model; therefore they should be ignored. // synthetic properties are not part of the entity model; therefore they should be ignored.
if ( propertyData.isSynthetic() ) { if ( propertyData.isSynthetic() ) {
continue; continue;
}
Getter getter;
if ( newObj != null ) {
getter = ReflectionTools.getGetter(
newObj.getClass(),
propertyData,
session.getFactory().getServiceRegistry()
);
}
else if ( oldObj != null ) {
getter = ReflectionTools.getGetter(
oldObj.getClass(),
propertyData,
session.getFactory().getServiceRegistry()
);
}
else {
break;
}
propertyMapper.mapModifiedFlagsToMapFromEntity(
session, data,
newObj == null ? null : getter.get( newObj ),
oldObj == null ? null : getter.get( oldObj )
);
} }
return null; Getter getter;
} ); if ( newObj != null ) {
getter = ReflectionTools.getGetter(
newObj.getClass(),
propertyData,
session.getFactory().getServiceRegistry()
);
}
else if ( oldObj != null ) {
getter = ReflectionTools.getGetter(
oldObj.getClass(),
propertyData,
session.getFactory().getServiceRegistry()
);
}
else {
break;
}
propertyMapper.mapModifiedFlagsToMapFromEntity(
session, data,
newObj == null ? null : getter.get( newObj ),
oldObj == null ? null : getter.get( oldObj )
);
}
} }
@Override @Override

View File

@ -107,20 +107,16 @@ public class SinglePropertyMapper extends AbstractPropertyMapper implements Simp
map.put( propertyData.getBeanName(), value ); map.put( propertyData.getBeanName(), value );
} }
else { else {
doPrivileged( () -> { final Setter setter = ReflectionTools.getSetter(
final Setter setter = ReflectionTools.getSetter( obj.getClass(),
obj.getClass(), propertyData,
propertyData, enversService.getServiceRegistry()
enversService.getServiceRegistry() );
);
// We only set a null value if the field is not primitive. Otherwise, we leave it intact. // We only set a null value if the field is not primitive. Otherwise, we leave it intact.
if ( value != null || !isPrimitive( setter, propertyData, obj.getClass() ) ) { if ( value != null || !isPrimitive( setter, propertyData, obj.getClass() ) ) {
setter.set( obj, value ); setter.set( obj, value );
} }
return null;
} );
} }
} }

View File

@ -64,13 +64,11 @@ public abstract class AbstractCompositeIdMapper extends AbstractIdMapper impleme
} }
protected Object instantiateCompositeId() { protected Object instantiateCompositeId() {
return doPrivileged( () -> { try {
try { return ReflectHelper.getDefaultConstructor( compositeIdClass ).newInstance();
return ReflectHelper.getDefaultConstructor( compositeIdClass ).newInstance(); }
} catch ( Exception e ) {
catch ( Exception e ) { throw new AuditException( e );
throw new AuditException( e ); }
}
} );
} }
} }

View File

@ -58,26 +58,24 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
return false; return false;
} }
return doPrivileged( () -> { final Setter setter = ReflectionTools.getSetter( obj.getClass(), idPropertyData, getServiceRegistry() );
final Setter setter = ReflectionTools.getSetter( obj.getClass(), idPropertyData, getServiceRegistry() ); try {
try { final Object subObj = instantiateCompositeId();
final Object subObj = instantiateCompositeId();
boolean ret = true; boolean ret = true;
for ( IdMapper idMapper : ids.values() ) { for ( IdMapper idMapper : ids.values() ) {
ret &= idMapper.mapToEntityFromMap( subObj, data ); ret &= idMapper.mapToEntityFromMap( subObj, data );
}
if ( ret ) {
setter.set( obj, subObj );
}
return ret;
} }
catch (Exception e) {
throw new AuditException( e ); if ( ret ) {
setter.set( obj, subObj );
} }
} );
return ret;
}
catch (Exception e) {
throw new AuditException( e );
}
} }
@Override @Override

View File

@ -63,35 +63,31 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
return; return;
} }
doPrivileged( () -> { final Getter getter = ReflectionTools.getGetter(
final Getter getter = ReflectionTools.getGetter( objFrom.getClass(),
objFrom.getClass(), propertyData,
propertyData, getServiceRegistry()
getServiceRegistry() );
);
final Setter setter = ReflectionTools.getSetter( final Setter setter = ReflectionTools.getSetter(
objTo.getClass(), objTo.getClass(),
propertyData, propertyData,
getServiceRegistry() getServiceRegistry()
); );
// Get the value from the containing entity // Get the value from the containing entity
final Object value = getter.get( objFrom ); final Object value = getter.get( objFrom );
if ( value == null ) { if ( value == null ) {
return null; return;
} }
if ( !value.getClass().equals( propertyData.getVirtualReturnClass() ) ) { if ( !value.getClass().equals( propertyData.getVirtualReturnClass() ) ) {
setter.set( objTo, getAssociatedEntityIdMapper().mapToIdFromEntity( value ) ); setter.set( objTo, getAssociatedEntityIdMapper().mapToIdFromEntity( value ) );
} }
else { else {
// This means we're setting the object // This means we're setting the object
setter.set( objTo, value ); setter.set( objTo, value );
} }
return null;
} );
} }
@Override @Override
@ -105,27 +101,25 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
return false; return false;
} }
return doPrivileged( () -> { final Setter setter = ReflectionTools.getSetter(
final Setter setter = ReflectionTools.getSetter( obj.getClass(),
obj.getClass(), propertyData,
propertyData, getServiceRegistry()
getServiceRegistry() );
); final Class<?> paramClass = ReflectionTools.getType(
final Class<?> paramClass = ReflectionTools.getType( obj.getClass(),
obj.getClass(), propertyData,
propertyData, getServiceRegistry()
getServiceRegistry() );
);
if ( paramClass != null && paramClass.equals( propertyData.getVirtualReturnClass() ) ) { if ( paramClass != null && paramClass.equals( propertyData.getVirtualReturnClass() ) ) {
setter.set( obj, getAssociatedEntityIdMapper().mapToIdFromEntity( value ) ); setter.set( obj, getAssociatedEntityIdMapper().mapToIdFromEntity( value ) );
} }
else { else {
setter.set( obj, value ); setter.set( obj, value );
} }
return true; return true;
} );
} }
@Override @Override

View File

@ -8,10 +8,7 @@ package org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.envers.boot.internal.EnversService; import org.hibernate.envers.boot.internal.EnversService;
@ -20,7 +17,6 @@ import org.hibernate.envers.internal.entities.EntityInstantiator;
import org.hibernate.envers.internal.entities.mapper.relation.query.RelationQueryGenerator; import org.hibernate.envers.internal.entities.mapper.relation.query.RelationQueryGenerator;
import org.hibernate.envers.internal.reader.AuditReaderImplementor; import org.hibernate.envers.internal.reader.AuditReaderImplementor;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
/** /**
* Initializes a persistent collection. * Initializes a persistent collection.
@ -67,22 +63,6 @@ public abstract class AbstractCollectionInitializor<T> implements Initializor<T>
return collection; return collection;
} }
/**
* Perform an action in a privileged block.
*
* @param block the lambda to executed in privileged.
* @param <R> the return type
* @return the result of the privileged call, may be {@literal null}
*/
protected <R> R doPrivileged(Supplier<R> block) {
if ( SystemSecurityManager.isSecurityManagerEnabled() ) {
return AccessController.doPrivileged( (PrivilegedAction<R>) block::get );
}
else {
return block.get();
}
}
/** /**
* Creates a new object based on the specified class with the given constructor arguments. * Creates a new object based on the specified class with the given constructor arguments.
* *
@ -92,17 +72,15 @@ public abstract class AbstractCollectionInitializor<T> implements Initializor<T>
* @return a new instance of the class * @return a new instance of the class
*/ */
protected <R> R newObjectInstance(Class<R> clazz, Object... args) { protected <R> R newObjectInstance(Class<R> clazz, Object... args) {
return doPrivileged( () -> { try {
try { final Constructor<R> constructor = ReflectHelper.getDefaultConstructor( clazz );
final Constructor<R> constructor = ReflectHelper.getDefaultConstructor( clazz ); if ( constructor == null ) {
if ( constructor == null ) { throw new AuditException( "Failed to locate default constructor for class: " + clazz.getName() );
throw new AuditException( "Failed to locate default constructor for class: " + clazz.getName() );
}
return constructor.newInstance( args );
} }
catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { return constructor.newInstance( args );
throw new AuditException( e ); }
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
} ); throw new AuditException( e );
}
} }
} }

View File

@ -51,23 +51,21 @@ public class SortedMapCollectionInitializor extends MapCollectionInitializor<Sor
if ( comparator == null ) { if ( comparator == null ) {
return super.initializeCollection( size ); return super.initializeCollection( size );
} }
return doPrivileged( () -> { try {
try { return collectionClass.getConstructor( Comparator.class ).newInstance( comparator );
return collectionClass.getConstructor( Comparator.class ).newInstance( comparator ); }
} catch (InstantiationException e) {
catch (InstantiationException e) { throw new AuditException( e );
throw new AuditException( e ); }
} catch (IllegalAccessException e) {
catch (IllegalAccessException e) { throw new AuditException( e );
throw new AuditException( e ); }
} catch (NoSuchMethodException e) {
catch (NoSuchMethodException e) { throw new AuditException( e );
throw new AuditException( e ); }
} catch (InvocationTargetException e) {
catch (InvocationTargetException e) { throw new AuditException( e );
throw new AuditException( e ); }
}
} );
} }
} }

View File

@ -52,22 +52,20 @@ public class SortedSetCollectionInitializor extends BasicCollectionInitializor<S
if ( comparator == null ) { if ( comparator == null ) {
return super.initializeCollection( size ); return super.initializeCollection( size );
} }
return doPrivileged( () -> { try {
try { return collectionClass.getConstructor( Comparator.class ).newInstance(comparator);
return collectionClass.getConstructor( Comparator.class ).newInstance(comparator); }
} catch (InstantiationException e) {
catch (InstantiationException e) { throw new AuditException( e );
throw new AuditException( e ); }
} catch (IllegalAccessException e) {
catch (IllegalAccessException e) { throw new AuditException( e );
throw new AuditException( e ); }
} catch (NoSuchMethodException e) {
catch (NoSuchMethodException e) { throw new AuditException( e );
throw new AuditException( e ); }
} catch (InvocationTargetException e) {
catch (InvocationTargetException e) { throw new AuditException( e );
throw new AuditException( e ); }
}
} );
} }
} }