HHH-17970 Remove support for running under a SecurityManager
This commit is contained in:
parent
0b770f9b17
commit
1f5d2fb417
|
@ -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]]
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 ) );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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() ) ) {
|
||||
|
@ -99,10 +98,8 @@ public final class EventType<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 );
|
||||
|
|
|
@ -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
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue