HHH-13361 Refactor mappers

This commit is contained in:
Chris Cranford 2021-12-18 18:50:36 -05:00 committed by Chris Cranford
parent b5755b6945
commit aa5bdab6ec
26 changed files with 463 additions and 529 deletions

View File

@ -0,0 +1,136 @@
/*
* 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.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.property.access.spi.Getter;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.service.ServiceRegistry;
/**
* A base class for all entity mapper implementations.
*
* @author Chris Cranford
*/
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 ( System.getSecurityManager() != null ) {
return AccessController.doPrivileged( (PrivilegedAction<T>) block::get );
}
else {
return block.get();
}
}
/**
* Get a value from the specified object.
*
* @param propertyData the property data, 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(PropertyData propertyData, Object object, ServiceRegistry serviceRegistry) {
return doPrivileged( () -> {
final Getter getter = ReflectionTools.getGetter( object.getClass(), propertyData, serviceRegistry );
return (T) getter.get( object );
} );
}
/**
* Get a value from the specified object.
*
* @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 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 );
} );
}
/**
* Set the specified value on the object.
*
* @param propertyData the property data, should not be {@literal null}
* @param object the object for which the value should be set, should not be {@literal null}
* @param value the value ot be set, may be {@literal null}
* @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;
} );
}
/**
* Gets the value from the source object and sets the value in the destination object.
*
* @param propertyData the property data, should not be {@literal null}
* @param source the source object, should not be {@literal null}
* @param destination the destination object, 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) {
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;
} );
}
/**
* Creates a new object based on the specified class with the given constructor arguments.
*
* @param clazz the class, must not be {@literal null}
* @param args the variadic constructor arguments, may be omitted.
* @param <T> the return class type
* @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 ) {
throw new AuditException( "Failed to locate default constructor for class: " + clazz.getName() );
}
return constructor.newInstance( args );
}
catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new AuditException( e );
}
} );
}
}

View File

@ -11,7 +11,7 @@ package org.hibernate.envers.internal.entities.mapper;
* *
* @author Chris Cranford * @author Chris Cranford
*/ */
public abstract class AbstractPropertyMapper implements PropertyMapper { public abstract class AbstractPropertyMapper extends AbstractMapper implements PropertyMapper {
private boolean map; private boolean map;
@Override @Override

View File

@ -7,8 +7,6 @@
package org.hibernate.envers.internal.entities.mapper; package org.hibernate.envers.internal.entities.mapper;
import java.io.Serializable; import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -118,43 +116,38 @@ public class ComponentPropertyMapper extends AbstractPropertyMapper implements C
return; return;
} }
AccessController.doPrivileged( doPrivileged( () -> {
new PrivilegedAction<Object>() { try {
@Override final Object subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
public Object run() {
try {
final Object subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
if ( isDynamicComponentMap() ) { if ( isDynamicComponentMap() ) {
( (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 { else {
final Setter setter = ReflectionTools.getSetter( final Setter setter = ReflectionTools.getSetter(
obj.getClass(), obj.getClass(),
propertyData, propertyData,
enversService.getServiceRegistry() enversService.getServiceRegistry()
); );
if ( isAllPropertiesNull( data ) ) { if ( isAllPropertiesNull( data ) ) {
// single property, but default value need not be null, so we'll set it to null anyway // single property, but default value need not be null, so we'll set it to null anyway
setter.set( obj, null ); setter.set( obj, null );
} }
else { else {
// set the component // set the component
setter.set( obj, subObj ); setter.set( obj, subObj );
delegate.mapToEntityFromMap( enversService, subObj, data, primaryKey, versionsReader, revision ); delegate.mapToEntityFromMap( enversService, subObj, data, primaryKey, versionsReader, revision );
}
}
}
catch ( Exception e ) {
throw new AuditException( e );
}
return null;
} }
} }
); }
catch ( Exception e ) {
throw new AuditException( e );
}
return null;
} );
} }
private boolean isAllPropertiesNull(Map data) { private boolean isAllPropertiesNull(Map data) {

View File

@ -7,8 +7,6 @@
package org.hibernate.envers.internal.entities.mapper; package org.hibernate.envers.internal.entities.mapper;
import java.io.Serializable; import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -101,49 +99,44 @@ 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 AccessController.doPrivileged( return doPrivileged( () -> {
new PrivilegedAction<Boolean>() { boolean ret = false;
@Override for ( Map.Entry<PropertyData, PropertyMapper> entry : properties.entrySet() ) {
public Boolean run() { final PropertyData propertyData = entry.getKey();
boolean ret = false; final PropertyMapper propertyMapper = entry.getValue();
for ( Map.Entry<PropertyData, PropertyMapper> entry : properties.entrySet() ) {
final PropertyData propertyData = entry.getKey();
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 {
return false;
}
ret |= propertyMapper.mapToMapFromEntity(
session, data,
newObj == null ? null : getter.get( newObj ),
oldObj == null ? null : getter.get( oldObj )
);
}
return ret;
}
} }
);
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 {
return false;
}
ret |= propertyMapper.mapToMapFromEntity(
session, data,
newObj == null ? null : getter.get( newObj ),
oldObj == null ? null : getter.get( oldObj )
);
}
return ret;
} );
} }
@Override @Override
@ -152,49 +145,44 @@ 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) {
AccessController.doPrivileged( doPrivileged( () -> {
new PrivilegedAction<Object>() { for ( Map.Entry<PropertyData, PropertyMapper> entry : properties.entrySet() ) {
@Override final PropertyData propertyData = entry.getKey();
public Object run() { final PropertyMapper propertyMapper = entry.getValue();
for ( Map.Entry<PropertyData, PropertyMapper> entry : properties.entrySet() ) {
final PropertyData propertyData = entry.getKey();
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 )
);
}
return null;
} );
} }
@Override @Override

View File

@ -7,8 +7,6 @@
package org.hibernate.envers.internal.entities.mapper; package org.hibernate.envers.internal.entities.mapper;
import java.io.Serializable; import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -105,25 +103,20 @@ public class SinglePropertyMapper extends AbstractPropertyMapper implements Simp
map.put( propertyData.getBeanName(), value ); map.put( propertyData.getBeanName(), value );
} }
else { else {
AccessController.doPrivileged( doPrivileged( () -> {
new PrivilegedAction<Object>() { final Setter setter = ReflectionTools.getSetter(
@Override obj.getClass(),
public Object run() { propertyData,
final Setter setter = ReflectionTools.getSetter( enversService.getServiceRegistry()
obj.getClass(), );
propertyData,
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; return null;
} } );
}
);
} }
} }

View File

@ -6,8 +6,6 @@
*/ */
package org.hibernate.envers.internal.entities.mapper.id; package org.hibernate.envers.internal.entities.mapper.id;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map; import java.util.Map;
import org.hibernate.envers.exception.AuditException; import org.hibernate.envers.exception.AuditException;
@ -66,18 +64,13 @@ public abstract class AbstractCompositeIdMapper extends AbstractIdMapper impleme
} }
protected Object instantiateCompositeId() { protected Object instantiateCompositeId() {
return AccessController.doPrivileged( return doPrivileged( () -> {
new PrivilegedAction<Object>() { try {
@Override return ReflectHelper.getDefaultConstructor( compositeIdClass ).newInstance();
public Object run() { }
try { catch ( Exception e ) {
return ReflectHelper.getDefaultConstructor( compositeIdClass ).newInstance(); throw new AuditException( e );
} }
catch ( Exception e ) { } );
throw new AuditException( e );
}
}
}
);
} }
} }

View File

@ -9,6 +9,8 @@ package org.hibernate.envers.internal.entities.mapper.id;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import org.hibernate.envers.internal.entities.PropertyData;
import org.hibernate.envers.internal.entities.mapper.AbstractMapper;
import org.hibernate.envers.internal.tools.query.Parameters; import org.hibernate.envers.internal.tools.query.Parameters;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
@ -18,7 +20,7 @@ import org.hibernate.service.ServiceRegistry;
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
* @author Chris Cranford * @author Chris Cranford
*/ */
public abstract class AbstractIdMapper implements IdMapper { public abstract class AbstractIdMapper extends AbstractMapper implements IdMapper {
private final ServiceRegistry serviceRegistry; private final ServiceRegistry serviceRegistry;
public AbstractIdMapper(ServiceRegistry serviceRegistry) { public AbstractIdMapper(ServiceRegistry serviceRegistry) {
@ -143,6 +145,18 @@ public abstract class AbstractIdMapper implements IdMapper {
public abstract void mapToEntityFromEntity(Object objectTo, Object objectFrom); public abstract void mapToEntityFromEntity(Object objectTo, Object objectFrom);
protected <T> T getValueFromObject(PropertyData propertyData, Object object) {
return getValueFromObject( propertyData, object, getServiceRegistry() );
}
protected void setValueOnObject(PropertyData propertyData, Object object, Object value) {
setValueOnObject( propertyData, object, value, getServiceRegistry() );
}
protected void getAndSetValue(PropertyData propertyData, Object source, Object destination) {
getAndSetValue( propertyData, source, destination, getServiceRegistry() );
}
private void handleNullValue(Parameters parameters, String alias, String propertyName, boolean equals) { private void handleNullValue(Parameters parameters, String alias, String propertyName, boolean equals) {
if ( equals ) { if ( equals ) {
parameters.addNullRestriction( alias, propertyName ); parameters.addNullRestriction( alias, propertyName );

View File

@ -6,8 +6,6 @@
*/ */
package org.hibernate.envers.internal.entities.mapper.id; package org.hibernate.envers.internal.entities.mapper.id;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -17,7 +15,6 @@ 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.mapping.Component; import org.hibernate.mapping.Component;
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;
@ -52,22 +49,7 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
if ( obj == null ) { if ( obj == null ) {
return; return;
} }
mapToMapFromId( data, getValueFromObject( idPropertyData, obj ) );
final Object value = AccessController.doPrivileged(
new PrivilegedAction<Object>() {
@Override
public Object run() {
final Getter getter = ReflectionTools.getGetter(
obj.getClass(),
idPropertyData,
getServiceRegistry()
);
return getter.get( obj );
}
}
);
mapToMapFromId( data, value );
} }
@Override @Override
@ -76,32 +58,26 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
return false; return false;
} }
return AccessController.doPrivileged( return doPrivileged( () -> {
new PrivilegedAction<Boolean>() { final Setter setter = ReflectionTools.getSetter( obj.getClass(), idPropertyData, getServiceRegistry() );
@Override try {
public Boolean run() { final Object subObj = instantiateCompositeId();
final Setter setter = ReflectionTools.getSetter( obj.getClass(), idPropertyData, getServiceRegistry() );
try { boolean ret = true;
final Object subObj = instantiateCompositeId(); for ( IdMapper idMapper : ids.values() ) {
ret &= idMapper.mapToEntityFromMap( subObj, data );
boolean ret = true;
for ( IdMapper idMapper : ids.values() ) {
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
@ -122,19 +98,7 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
return null; return null;
} }
return AccessController.doPrivileged( return getValueFromObject( idPropertyData, data );
new PrivilegedAction<Object>() {
@Override
public Object run() {
final Getter getter = ReflectionTools.getGetter(
data.getClass(),
idPropertyData,
getServiceRegistry()
);
return getter.get( data );
}
}
);
} }
@Override @Override

View File

@ -6,17 +6,12 @@
*/ */
package org.hibernate.envers.internal.entities.mapper.id; package org.hibernate.envers.internal.entities.mapper.id;
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.Map; import java.util.Map;
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.property.access.spi.Getter;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
@ -63,20 +58,8 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
return false; return false;
} }
return AccessController.doPrivileged( setValueOnObject( propertyData, obj, value );
new PrivilegedAction<Boolean>() { return true;
@Override
public Boolean run() {
final Setter setter = ReflectionTools.getSetter(
obj.getClass(),
propertyData,
getServiceRegistry()
);
setter.set( obj, value );
return true;
}
}
);
} }
@Override @Override
@ -99,19 +82,7 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
return hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier(); return hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier();
} }
else { else {
return AccessController.doPrivileged( return getValueFromObject( propertyData, data );
new PrivilegedAction<Object>() {
@Override
public Object run() {
final Getter getter = ReflectionTools.getGetter(
data.getClass(),
propertyData,
getServiceRegistry()
);
return getter.get( data );
}
}
);
} }
} }
@ -133,19 +104,7 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
data.put( propertyData.getName(), hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier() ); data.put( propertyData.getName(), hibernateProxy.getHibernateLazyInitializer().getInternalIdentifier() );
} }
else { else {
final Object value = AccessController.doPrivileged( final Object value = getValueFromObject( propertyData, obj );
new PrivilegedAction<Object>() {
@Override
public Object run() {
final Getter getter = ReflectionTools.getGetter(
obj.getClass(),
propertyData,
getServiceRegistry()
);
return getter.get( obj );
}
}
);
data.put( propertyData.getName(), value ); data.put( propertyData.getName(), value );
} }
} }
@ -156,28 +115,7 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
if ( objTo == null || objFrom == null ) { if ( objTo == null || objFrom == null ) {
return; return;
} }
getAndSetValue(propertyData, objFrom, objTo );
AccessController.doPrivileged(
new PrivilegedAction<Object>() {
@Override
public Object run() {
final Getter getter = ReflectionTools.getGetter(
objFrom.getClass(),
propertyData,
getServiceRegistry()
);
final Setter setter = ReflectionTools.getSetter(
objTo.getClass(),
propertyData,
getServiceRegistry()
);
setter.set( objTo, getter.get( objFrom ) );
return null;
}
}
);
} }
@Override @Override

View File

@ -6,9 +6,6 @@
*/ */
package org.hibernate.envers.internal.entities.mapper.id; package org.hibernate.envers.internal.entities.mapper.id;
import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map; import java.util.Map;
import org.hibernate.Session; import org.hibernate.Session;
@ -48,19 +45,7 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
@Override @Override
public void mapToMapFromId(Session session, Map<String, Object> data, Object obj) { public void mapToMapFromId(Session session, Map<String, Object> data, Object obj) {
final Serializable value = AccessController.doPrivileged( final Object value = getValueFromObject( propertyData, obj );
new PrivilegedAction<Serializable>() {
@Override
public Serializable run() {
final Getter getter = ReflectionTools.getGetter(
obj.getClass(),
propertyData,
getServiceRegistry()
);
return (Serializable) getter.get( obj );
}
}
);
// Either loads the entity from the session's 1LC if it already exists or potentially creates a // Either loads the entity from the session's 1LC if it already exists or potentially creates a
// proxy object to represent the entity by identifier so that we can reference it in the map. // proxy object to represent the entity by identifier so that we can reference it in the map.
@ -74,40 +59,35 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
return; return;
} }
AccessController.doPrivileged( doPrivileged( () -> {
new PrivilegedAction<Object>() { final Getter getter = ReflectionTools.getGetter(
@Override objFrom.getClass(),
public Object run() { propertyData,
final Getter getter = ReflectionTools.getGetter( getServiceRegistry()
objFrom.getClass(), );
propertyData,
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 null;
} }
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; return null;
} } );
}
);
} }
@Override @Override
@ -121,32 +101,27 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
return false; return false;
} }
return AccessController.doPrivileged( return doPrivileged( () -> {
new PrivilegedAction<Boolean>() { final Setter setter = ReflectionTools.getSetter(
@Override obj.getClass(),
public Boolean run() { propertyData,
final Setter setter = ReflectionTools.getSetter( getServiceRegistry()
obj.getClass(), );
propertyData, final Class<?> paramClass = ReflectionTools.getType(
getServiceRegistry() obj.getClass(),
); propertyData,
final Class<?> paramClass = ReflectionTools.getType( getServiceRegistry()
obj.getClass(), );
propertyData,
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
@ -160,19 +135,7 @@ public class VirtualEntitySingleIdMapper extends SingleIdMapper {
data.put( propertyData.getName(), proxy.getHibernateLazyInitializer().getInternalIdentifier() ); data.put( propertyData.getName(), proxy.getHibernateLazyInitializer().getInternalIdentifier() );
} }
else { else {
final Object value = AccessController.doPrivileged( final Object value = getValueFromObject( propertyData, obj );
new PrivilegedAction<Object>() {
@Override
public Object run() {
final Getter getter = ReflectionTools.getGetter(
obj.getClass(),
propertyData,
getServiceRegistry()
);
return getter.get( obj );
}
}
);
if ( propertyData.getVirtualReturnClass().isInstance( value ) ) { if ( propertyData.getVirtualReturnClass().isInstance( value ) ) {
// The value is the primary key, need to map it via IdMapper // The value is the primary key, need to map it via IdMapper

View File

@ -8,8 +8,6 @@ package org.hibernate.envers.internal.entities.mapper.relation;
import java.io.Serializable; import java.io.Serializable;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -30,9 +28,7 @@ import org.hibernate.envers.internal.entities.mapper.AbstractPropertyMapper;
import org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData; import org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData;
import org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor.Initializor; import org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor.Initializor;
import org.hibernate.envers.internal.reader.AuditReaderImplementor; import org.hibernate.envers.internal.reader.AuditReaderImplementor;
import org.hibernate.envers.internal.tools.ReflectionTools;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.property.access.spi.Setter;
/** /**
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
@ -306,22 +302,7 @@ public abstract class AbstractCollectionMapper<T> extends AbstractPropertyMapper
map.put( collectionPropertyData.getBeanName(), collectionProxy ); map.put( collectionPropertyData.getBeanName(), collectionProxy );
} }
else { else {
AccessController.doPrivileged( setValueOnObject( collectionPropertyData, obj, collectionProxy, enversService.getServiceRegistry() );
new PrivilegedAction<Object>() {
@Override
public Object run() {
final Setter setter = ReflectionTools.getSetter(
obj.getClass(),
collectionPropertyData,
enversService.getServiceRegistry()
);
setter.set( obj, collectionProxy );
return null;
}
}
);
} }
} }

View File

@ -7,8 +7,6 @@
package org.hibernate.envers.internal.entities.mapper.relation; package org.hibernate.envers.internal.entities.mapper.relation;
import java.io.Serializable; import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -21,7 +19,6 @@ import org.hibernate.envers.internal.entities.mapper.AbstractPropertyMapper;
import org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData; import org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData;
import org.hibernate.envers.internal.reader.AuditReaderImplementor; import org.hibernate.envers.internal.reader.AuditReaderImplementor;
import org.hibernate.envers.internal.tools.ReflectionTools; import org.hibernate.envers.internal.tools.ReflectionTools;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
/** /**
@ -96,21 +93,7 @@ public abstract class AbstractToOneMapper extends AbstractPropertyMapper {
map.put( propertyData.getBeanName(), value ); map.put( propertyData.getBeanName(), value );
} }
else { else {
AccessController.doPrivileged( setValueOnObject( propertyData, targetObject, value, serviceRegistry );
new PrivilegedAction<Object>() {
@Override
public Object run() {
final Setter setter = ReflectionTools.getSetter(
targetObject.getClass(),
propertyData,
serviceRegistry
);
setter.set( targetObject, value );
return null;
}
}
);
} }
} }

View File

@ -0,0 +1,18 @@
/*
* 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.envers.internal.entities.mapper.relation.component;
import org.hibernate.envers.internal.entities.mapper.AbstractMapper;
/**
* An abstract base class for all middle component mappers.
*
* @author Chris Cranford
*/
public abstract class AbstractMiddleComponentMapper extends AbstractMapper implements MiddleComponentMapper {
}

View File

@ -15,7 +15,7 @@ import org.hibernate.envers.internal.tools.query.Parameters;
/** /**
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
*/ */
public final class MiddleDummyComponentMapper implements MiddleComponentMapper { public final class MiddleDummyComponentMapper extends AbstractMiddleComponentMapper {
public Object mapToObjectFromFullMap( public Object mapToObjectFromFullMap(
EntityInstantiator entityInstantiator, Map<String, Object> data, EntityInstantiator entityInstantiator, Map<String, Object> data,
Object dataObject, Number revision) { Object dataObject, Number revision) {

View File

@ -6,9 +6,6 @@
*/ */
package org.hibernate.envers.internal.entities.mapper.relation.component; package org.hibernate.envers.internal.entities.mapper.relation.component;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map; import java.util.Map;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
@ -20,16 +17,16 @@ import org.hibernate.envers.internal.entities.mapper.MultiPropertyMapper;
import org.hibernate.envers.internal.entities.mapper.PropertyMapper; import org.hibernate.envers.internal.entities.mapper.PropertyMapper;
import org.hibernate.envers.internal.entities.mapper.relation.ToOneIdMapper; import org.hibernate.envers.internal.entities.mapper.relation.ToOneIdMapper;
import org.hibernate.envers.internal.tools.query.Parameters; import org.hibernate.envers.internal.tools.query.Parameters;
import org.hibernate.internal.util.ReflectHelper;
/** /**
* @author Kristoffer Lundberg (kristoffer at cambio dot se) * @author Kristoffer Lundberg (kristoffer at cambio dot se)
*/ */
public class MiddleEmbeddableComponentMapper implements MiddleComponentMapper, CompositeMapperBuilder { public class MiddleEmbeddableComponentMapper extends AbstractMiddleComponentMapper implements CompositeMapperBuilder {
private final MultiPropertyMapper delegate;
private final Class componentClass;
public MiddleEmbeddableComponentMapper(MultiPropertyMapper delegate, Class componentClass) { private final MultiPropertyMapper delegate;
private final Class<?> componentClass;
public MiddleEmbeddableComponentMapper(MultiPropertyMapper delegate, Class<?> componentClass) {
this.delegate = delegate; this.delegate = delegate;
this.componentClass = componentClass; this.componentClass = componentClass;
} }
@ -65,26 +62,7 @@ public class MiddleEmbeddableComponentMapper implements MiddleComponentMapper, C
if ( dataObject != null ) { if ( dataObject != null ) {
return dataObject; return dataObject;
} }
return newObjectInstance( componentClass );
return AccessController.doPrivileged(
new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
return ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
}
catch ( InstantiationException e ) {
throw new AuditException( e );
}
catch ( IllegalAccessException e ) {
throw new AuditException( e );
}
catch ( InvocationTargetException e ) {
throw new AuditException( e );
}
}
}
);
} }
@Override @Override

View File

@ -28,7 +28,7 @@ import org.hibernate.envers.internal.tools.query.Parameters;
* *
* @author Chris Cranford * @author Chris Cranford
*/ */
public class MiddleMapElementNotKeyComponentMapper implements MiddleComponentMapper { public class MiddleMapElementNotKeyComponentMapper extends AbstractMiddleComponentMapper {
private final String propertyName; private final String propertyName;
public MiddleMapElementNotKeyComponentMapper(String propertyName) { public MiddleMapElementNotKeyComponentMapper(String propertyName) {

View File

@ -22,7 +22,7 @@ import org.hibernate.envers.internal.tools.query.Parameters;
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
* @author Chris Cranford * @author Chris Cranford
*/ */
public final class MiddleMapKeyIdComponentMapper implements MiddleComponentMapper { public final class MiddleMapKeyIdComponentMapper extends AbstractMiddleComponentMapper {
private final Configuration configuration; private final Configuration configuration;
private final IdMapper relatedIdMapper; private final IdMapper relatedIdMapper;

View File

@ -6,15 +6,11 @@
*/ */
package org.hibernate.envers.internal.entities.mapper.relation.component; package org.hibernate.envers.internal.entities.mapper.relation.component;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map; import java.util.Map;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.envers.internal.entities.EntityInstantiator; import org.hibernate.envers.internal.entities.EntityInstantiator;
import org.hibernate.envers.internal.tools.ReflectionTools;
import org.hibernate.envers.internal.tools.query.Parameters; import org.hibernate.envers.internal.tools.query.Parameters;
import org.hibernate.property.access.spi.Getter;
/** /**
* A component mapper for the @MapKey mapping with the name parameter specified: the value of the map's key * A component mapper for the @MapKey mapping with the name parameter specified: the value of the map's key
@ -23,7 +19,7 @@ import org.hibernate.property.access.spi.Getter;
* *
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
*/ */
public class MiddleMapKeyPropertyComponentMapper implements MiddleComponentMapper { public class MiddleMapKeyPropertyComponentMapper extends AbstractMiddleComponentMapper {
private final String propertyName; private final String propertyName;
private final String accessType; private final String accessType;
@ -39,19 +35,11 @@ public class MiddleMapKeyPropertyComponentMapper implements MiddleComponentMappe
final Object dataObject, final Object dataObject,
Number revision) { Number revision) {
// dataObject is not null, as this mapper can only be used in an index. // dataObject is not null, as this mapper can only be used in an index.
return AccessController.doPrivileged( return getValueFromObject(
new PrivilegedAction<Object>() { propertyName,
@Override accessType,
public Object run() { dataObject,
final Getter getter = ReflectionTools.getGetter( entityInstantiator.getEnversService().getServiceRegistry()
dataObject.getClass(),
propertyName,
accessType,
entityInstantiator.getEnversService().getServiceRegistry()
);
return getter.get( dataObject );
}
}
); );
} }

View File

@ -16,7 +16,7 @@ import org.hibernate.envers.internal.tools.query.Parameters;
/** /**
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
*/ */
public final class MiddleRelatedComponentMapper implements MiddleComponentMapper { public final class MiddleRelatedComponentMapper extends AbstractMiddleComponentMapper {
private final MiddleIdData relatedIdData; private final MiddleIdData relatedIdData;
public MiddleRelatedComponentMapper(MiddleIdData relatedIdData) { public MiddleRelatedComponentMapper(MiddleIdData relatedIdData) {

View File

@ -17,7 +17,7 @@ import org.hibernate.envers.internal.tools.query.Parameters;
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
* @author Chris Cranford * @author Chris Cranford
*/ */
public final class MiddleSimpleComponentMapper implements MiddleComponentMapper { public final class MiddleSimpleComponentMapper extends AbstractMiddleComponentMapper {
private final Configuration configuration; private final Configuration configuration;
private final String propertyName; private final String propertyName;

View File

@ -18,7 +18,7 @@ import org.hibernate.envers.internal.tools.query.Parameters;
* *
* @author Adam Warski (adam at warski dot org) * @author Adam Warski (adam at warski dot org)
*/ */
public final class MiddleStraightComponentMapper implements MiddleComponentMapper { public final class MiddleStraightComponentMapper extends AbstractMiddleComponentMapper {
private final String propertyName; private final String propertyName;
public MiddleStraightComponentMapper(String propertyName) { public MiddleStraightComponentMapper(String propertyName) {

View File

@ -6,13 +6,20 @@
*/ */
package org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor; 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.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;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.internal.entities.EntityInstantiator; 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;
/** /**
* Initializes a persistent collection. * Initializes a persistent collection.
@ -58,4 +65,43 @@ 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 ( System.getSecurityManager() != null ) {
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.
*
* @param clazz the class, must not be {@literal null}
* @param args the variadic constructor arguments, may be omitted.
* @param <R> the return class type
* @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 ) {
throw new AuditException( "Failed to locate default constructor for class: " + clazz.getName() );
}
return constructor.newInstance( args );
}
catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
throw new AuditException( e );
}
} );
}
} }

View File

@ -6,19 +6,14 @@
*/ */
package org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor; package org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.hibernate.envers.boot.internal.EnversService; import org.hibernate.envers.boot.internal.EnversService;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData; import org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData;
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;
/** /**
* Initializes a non-indexed java collection (set or list, eventually sorted). * Initializes a non-indexed java collection (set or list, eventually sorted).
@ -45,25 +40,7 @@ public class BasicCollectionInitializor<T extends Collection> extends AbstractCo
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected T initializeCollection(int size) { protected T initializeCollection(int size) {
return AccessController.doPrivileged( return newObjectInstance( collectionClass );
new PrivilegedAction<T>() {
@Override
public T run() {
try {
return (T) ReflectHelper.getDefaultConstructor( collectionClass ).newInstance();
}
catch (InstantiationException e) {
throw new AuditException( e );
}
catch (IllegalAccessException e) {
throw new AuditException( e );
}
catch (InvocationTargetException e) {
throw new AuditException( e );
}
}
}
);
} }
@Override @Override

View File

@ -6,18 +6,13 @@
*/ */
package org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor; package org.hibernate.envers.internal.entities.mapper.relation.lazy.initializor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.hibernate.envers.boot.internal.EnversService; import org.hibernate.envers.boot.internal.EnversService;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData; import org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData;
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;
/** /**
* Initializes a map. * Initializes a map.
@ -47,25 +42,7 @@ public class MapCollectionInitializor<T extends Map> extends AbstractCollectionI
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected T initializeCollection(int size) { protected T initializeCollection(int size) {
return AccessController.doPrivileged( return newObjectInstance( collectionClass );
new PrivilegedAction<T>() {
@Override
public T run() {
try {
return (T) ReflectHelper.getDefaultConstructor( collectionClass ).newInstance();
}
catch (InstantiationException e) {
throw new AuditException( e );
}
catch (IllegalAccessException e) {
throw new AuditException( e );
}
catch (InvocationTargetException e) {
throw new AuditException( e );
}
}
}
);
} }
@Override @Override

View File

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

View File

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