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.
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.
[[entity-pojo-accessors]]

View File

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

View File

@ -21,8 +21,6 @@ import java.io.File;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
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.engine.spi.PrimeAmongSecondarySupertypes;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.proxy.ProxyConfiguration;
import org.hibernate.proxy.ProxyFactory;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.TypeCache;
import net.bytebuddy.asm.AsmVisitorWrapper.ForDeclaredMethods;
import net.bytebuddy.asm.MemberSubstitution;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.DynamicType.Unloaded;
@ -51,7 +46,6 @@ import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bytecode.assign.Assigner;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.pool.TypePool;
/**
@ -90,16 +84,8 @@ public final class ByteBuddyState {
ByteBuddyState(ClassFileVersion classFileVersion) {
this.byteBuddy = new ByteBuddy( classFileVersion ).with( TypeValidation.DISABLED );
this.proxyCache = 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(
referenceClass.getClassLoader(),
cacheKey,
() -> {
PrivilegedAction<Class<?>> delegateToPrivilegedAction = new PrivilegedAction<Class<?>>() {
@Override
public Class<?> run() {
return make( makeProxyFunction.apply( byteBuddy ) )
() -> make( makeProxyFunction.apply( byteBuddy ) )
.load(
referenceClass.getClassLoader(),
resolveClassLoadingStrategy( referenceClass )
)
.getLoaded();
}
};
return SystemSecurityManager.isSecurityManagerEnabled() ? AccessController.doPrivileged(
delegateToPrivilegedAction ) :
delegateToPrivilegedAction.run();
},
.getLoaded(),
cache
);
}
@ -233,8 +209,6 @@ public final class ByteBuddyState {
}
private Unloaded<?> make(TypePool typePool, DynamicType.Builder<?> builder) {
builder = classRewriter.installReflectionMethodVisitors( builder );
Unloaded<?> unloadedClass;
if ( typePool != null ) {
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 );
}
}
classRewriter.registerAuthorizedClass( unloadedClass );
return unloadedClass;
}
@ -315,33 +286,11 @@ public final class ByteBuddyState {
toFullyIgnore.add( isDeclaredBy( m.getReturnType() ).and( named( m.getName() ) ).and( takesNoArguments() ) );
}
PrivilegedAction<MethodDelegation> delegateToInterceptorDispatcherMethodDelegationPrivilegedAction =
new PrivilegedAction<MethodDelegation>() {
this.delegateToInterceptorDispatcherMethodDelegation = MethodDelegation.to( ProxyConfiguration.InterceptorDispatcher.class );
@Override
public MethodDelegation run() {
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 )
this.interceptorFieldAccessor = 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() {
return groovyGetMetaClassFilter;
@ -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) {
try {
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;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.Connection;
import java.sql.Driver;
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.DatabaseConnectionInfo;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.service.UnknownUnwrapTypeException;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.ServiceException;
@ -614,22 +611,7 @@ public class DriverManagerConnectionProviderImpl
ConnectionInfoLogger.INSTANCE.cleaningUpConnectionPool( pool.getUrl() );
active = false;
if ( executorService != null ) {
PrivilegedAction delegateToPrivilegedAction =
new PrivilegedAction() {
@Override
public Object run() {
executorService.shutdown();
return null;
}
};
if ( SystemSecurityManager.isSecurityManagerEnabled() ) {
AccessController.doPrivileged(
delegateToPrivilegedAction );
}
else {
delegateToPrivilegedAction.run();
}
}
executorService = null;
try {

View File

@ -7,8 +7,6 @@
package org.hibernate.event.spi;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -85,8 +83,9 @@ public final class EventType<T> {
* Maintain a map of {@link EventType} instances keyed by name for lookup by name as well as {@link #values()}
* resolution.
*/
private static final Map<String,EventType<?>> STANDARD_TYPE_BY_NAME_MAP = AccessController.doPrivileged(
(PrivilegedAction<Map<String, EventType<?>>>) () -> {
private static final Map<String,EventType<?>> STANDARD_TYPE_BY_NAME_MAP = initStandardTypeNameMap();
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() ) ) {
@ -94,15 +93,13 @@ public final class EventType<T> {
final EventType<?> typeField = (EventType<?>) field.get( null );
typeByNameMap.put( typeField.eventName(), typeField );
}
catch (Exception t) {
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) {
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.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -26,14 +25,12 @@ import org.hibernate.collection.spi.LazyInitializable;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import static jakarta.persistence.spi.LoadState.LOADED;
import static jakarta.persistence.spi.LoadState.NOT_LOADED;
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.isPersistentAttributeInterceptable;
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
@ -353,7 +350,6 @@ public final class PersistenceUtilHelper {
}
private AttributeAccess buildAttributeAccess(final String attributeName) {
final PrivilegedAction<AttributeAccess> action = () -> {
for ( Class<?> clazz : classHierarchy ) {
try {
return new FieldAttributeAccess( clazz.getDeclaredField( attributeName ) );
@ -367,8 +363,6 @@ public final class PersistenceUtilHelper {
}
//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.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Set;
import org.hibernate.HibernateException;
@ -18,7 +16,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.ProxyConfiguration;
import org.hibernate.proxy.ProxyFactory;
@ -109,18 +106,11 @@ public class ByteBuddyProxyFactory implements ProxyFactory, Serializable {
/**
* 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
* invoker to perform the narrowing
*/
private PrimeAmongSecondarySupertypes getHibernateProxyInternal()
throws HibernateException {
final PrivilegedAction<PrimeAmongSecondarySupertypes> action = new PrivilegedAction<PrimeAmongSecondarySupertypes>() {
@Override
public PrimeAmongSecondarySupertypes run() {
private PrimeAmongSecondarySupertypes getHibernateProxyInternal() throws HibernateException {
try {
return (PrimeAmongSecondarySupertypes) proxyClass.getConstructor().newInstance();
}
@ -134,10 +124,6 @@ public class ByteBuddyProxyFactory implements ProxyFactory, Serializable {
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.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.function.Supplier;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.internal.entities.PropertyData;
import org.hibernate.envers.internal.tools.ReflectionTools;
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.Setter;
import org.hibernate.service.ServiceRegistry;
@ -28,22 +24,6 @@ import org.hibernate.service.ServiceRegistry;
*/
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.
*
@ -55,10 +35,8 @@ public abstract class AbstractMapper {
*/
@SuppressWarnings("unchecked")
protected <T> T getValueFromObject(PropertyData propertyData, Object object, ServiceRegistry serviceRegistry) {
return doPrivileged( () -> {
final Getter getter = ReflectionTools.getGetter( object.getClass(), propertyData, serviceRegistry );
return (T) getter.get( object );
} );
}
/**
@ -66,17 +44,15 @@ public abstract class AbstractMapper {
*
* @param propertyName the property name, 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 <T> the return type
* @return the value read from the object, may be {@literal null}
*/
@SuppressWarnings("unchecked")
protected <T> T getValueFromObject(String propertyName, String accessType, Object object, ServiceRegistry serviceRegistry) {
return doPrivileged( () -> {
final Getter getter = ReflectionTools.getGetter( object.getClass(), propertyName, accessType, serviceRegistry );
return (T) getter.get( object );
} );
}
/**
@ -88,11 +64,8 @@ public abstract class AbstractMapper {
* @param serviceRegistry the service registry, should not be {@literal null}
*/
protected void setValueOnObject(PropertyData propertyData, Object object, Object value, ServiceRegistry serviceRegistry) {
doPrivileged( () -> {
final Setter setter = ReflectionTools.getSetter(object.getClass(), propertyData, serviceRegistry );
setter.set( object, value );
return null;
} );
}
/**
@ -104,12 +77,9 @@ public abstract class AbstractMapper {
* @param serviceRegistry the service registry, should not be {@literal null}
*/
protected void getAndSetValue(PropertyData propertyData, Object source, Object destination, ServiceRegistry serviceRegistry) {
doPrivileged( () -> {
final Getter getter = ReflectionTools.getGetter( source.getClass(), propertyData, serviceRegistry );
final Setter setter = ReflectionTools.getSetter( destination.getClass(), propertyData, serviceRegistry );
setter.set( destination, getter.get( source ) );
return null;
} );
}
/**
@ -121,7 +91,6 @@ public abstract class AbstractMapper {
* @return a new instance of the class
*/
protected <T> T newObjectInstance(Class<T> clazz, Object... args) {
return doPrivileged( () -> {
try {
final Constructor<T> constructor = ReflectHelper.getDefaultConstructor( clazz );
if ( constructor == null ) {
@ -132,6 +101,5 @@ public abstract class AbstractMapper {
catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new AuditException( e );
}
} );
}
}

View File

@ -125,7 +125,6 @@ public class ComponentPropertyMapper extends AbstractPropertyMapper implements C
return;
}
doPrivileged( () -> {
try {
if ( isDynamicComponentMap() ) {
@ -184,9 +183,6 @@ public class ComponentPropertyMapper extends AbstractPropertyMapper implements C
catch ( Exception e ) {
throw new AuditException( e );
}
return null;
} );
}
@Override
@ -202,7 +198,6 @@ public class ComponentPropertyMapper extends AbstractPropertyMapper implements C
return null;
}
return doPrivileged( () -> {
try {
final Object subObj;
if ( isDynamicComponentMap() ) {
@ -252,7 +247,6 @@ public class ComponentPropertyMapper extends AbstractPropertyMapper implements C
catch ( Exception e ) {
throw new AuditException( e );
}
} );
}
private boolean isAllPropertiesNull(Map data) {

View File

@ -103,7 +103,6 @@ public class MultiPropertyMapper extends AbstractPropertyMapper implements Exten
final Map<String, Object> data,
final Object newObj,
final Object oldObj) {
return doPrivileged( () -> {
boolean ret = false;
for ( Map.Entry<PropertyData, PropertyMapper> entry : properties.entrySet() ) {
final PropertyData propertyData = entry.getKey();
@ -140,7 +139,6 @@ public class MultiPropertyMapper extends AbstractPropertyMapper implements Exten
);
}
return ret;
} );
}
@Override
@ -149,7 +147,6 @@ public class MultiPropertyMapper extends AbstractPropertyMapper implements Exten
final Map<String, Object> data,
final Object newObj,
final Object oldObj) {
doPrivileged( () -> {
for ( Map.Entry<PropertyData, PropertyMapper> entry : properties.entrySet() ) {
final PropertyData propertyData = entry.getKey();
final PropertyMapper propertyMapper = entry.getValue();
@ -184,9 +181,6 @@ public class MultiPropertyMapper extends AbstractPropertyMapper implements Exten
oldObj == null ? null : getter.get( oldObj )
);
}
return null;
} );
}
@Override

View File

@ -107,7 +107,6 @@ public class SinglePropertyMapper extends AbstractPropertyMapper implements Simp
map.put( propertyData.getBeanName(), value );
}
else {
doPrivileged( () -> {
final Setter setter = ReflectionTools.getSetter(
obj.getClass(),
propertyData,
@ -118,9 +117,6 @@ public class SinglePropertyMapper extends AbstractPropertyMapper implements Simp
if ( value != null || !isPrimitive( setter, propertyData, obj.getClass() ) ) {
setter.set( obj, value );
}
return null;
} );
}
}

View File

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

View File

@ -58,7 +58,6 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
return false;
}
return doPrivileged( () -> {
final Setter setter = ReflectionTools.getSetter( obj.getClass(), idPropertyData, getServiceRegistry() );
try {
final Object subObj = instantiateCompositeId();
@ -77,7 +76,6 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
catch (Exception e) {
throw new AuditException( e );
}
} );
}
@Override

View File

@ -63,7 +63,6 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
return;
}
doPrivileged( () -> {
final Getter getter = ReflectionTools.getGetter(
objFrom.getClass(),
propertyData,
@ -79,7 +78,7 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
// Get the value from the containing entity
final Object value = getter.get( objFrom );
if ( value == null ) {
return null;
return;
}
if ( !value.getClass().equals( propertyData.getVirtualReturnClass() ) ) {
@ -89,9 +88,6 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
// This means we're setting the object
setter.set( objTo, value );
}
return null;
} );
}
@Override
@ -105,7 +101,6 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
return false;
}
return doPrivileged( () -> {
final Setter setter = ReflectionTools.getSetter(
obj.getClass(),
propertyData,
@ -125,7 +120,6 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
}
return true;
} );
}
@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.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List;
import java.util.function.Supplier;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
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.reader.AuditReaderImplementor;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.securitymanager.SystemSecurityManager;
/**
* Initializes a persistent collection.
@ -67,22 +63,6 @@ public abstract class AbstractCollectionInitializor<T> implements Initializor<T>
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.
*
@ -92,7 +72,6 @@ public abstract class AbstractCollectionInitializor<T> implements Initializor<T>
* @return a new instance of the class
*/
protected <R> R newObjectInstance(Class<R> clazz, Object... args) {
return doPrivileged( () -> {
try {
final Constructor<R> constructor = ReflectHelper.getDefaultConstructor( clazz );
if ( constructor == null ) {
@ -103,6 +82,5 @@ public abstract class AbstractCollectionInitializor<T> implements Initializor<T>
catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new AuditException( e );
}
} );
}
}

View File

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

View File

@ -52,7 +52,6 @@ public class SortedSetCollectionInitializor extends BasicCollectionInitializor<S
if ( comparator == null ) {
return super.initializeCollection( size );
}
return doPrivileged( () -> {
try {
return collectionClass.getConstructor( Comparator.class ).newInstance(comparator);
}
@ -68,6 +67,5 @@ public class SortedSetCollectionInitializor extends BasicCollectionInitializor<S
catch (InvocationTargetException e) {
throw new AuditException( e );
}
} );
}
}