Skip to content

Commit aa5bdab

Browse files
committed
HHH-13361 Refactor mappers
1 parent b5755b6 commit aa5bdab

26 files changed

+470
-536
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.envers.internal.entities.mapper;
8+
9+
import java.lang.reflect.Constructor;
10+
import java.lang.reflect.InvocationTargetException;
11+
import java.security.AccessController;
12+
import java.security.PrivilegedAction;
13+
import java.util.function.Supplier;
14+
15+
import org.hibernate.envers.exception.AuditException;
16+
import org.hibernate.envers.internal.entities.PropertyData;
17+
import org.hibernate.envers.internal.tools.ReflectionTools;
18+
import org.hibernate.internal.util.ReflectHelper;
19+
import org.hibernate.property.access.spi.Getter;
20+
import org.hibernate.property.access.spi.Setter;
21+
import org.hibernate.service.ServiceRegistry;
22+
23+
/**
24+
* A base class for all entity mapper implementations.
25+
*
26+
* @author Chris Cranford
27+
*/
28+
public abstract class AbstractMapper {
29+
30+
/**
31+
* Perform an action in a privileged block.
32+
*
33+
* @param block the lambda to executed in privileged.
34+
* @param <T> the return type
35+
* @return the result of the privileged call, may be {@literal null}
36+
*/
37+
protected <T> T doPrivileged(Supplier<T> block) {
38+
if ( System.getSecurityManager() != null ) {
39+
return AccessController.doPrivileged( (PrivilegedAction<T>) block::get );
40+
}
41+
else {
42+
return block.get();
43+
}
44+
}
45+
46+
/**
47+
* Get a value from the specified object.
48+
*
49+
* @param propertyData the property data, should not be {@literal null}
50+
* @param object the object for which the value should be read, should not be {@literal null}
51+
* @param serviceRegistry the service registry, should not be {@literal null}
52+
* @param <T> the return type
53+
* @return the value read from the object, may be {@literal null}
54+
*/
55+
@SuppressWarnings("unchecked")
56+
protected <T> T getValueFromObject(PropertyData propertyData, Object object, ServiceRegistry serviceRegistry) {
57+
return doPrivileged( () -> {
58+
final Getter getter = ReflectionTools.getGetter( object.getClass(), propertyData, serviceRegistry );
59+
return (T) getter.get( object );
60+
} );
61+
}
62+
63+
/**
64+
* Get a value from the specified object.
65+
*
66+
* @param propertyName the property name, should not be {@literal null}
67+
* @param accessType the property access type, should not be {@literal null}
68+
* @param object the object for hwich the value should be read, should not be {@literal null}
69+
* @param serviceRegistry the service registry, should not be {@literal null}
70+
* @param <T> the return type
71+
* @return the value read from the object, may be {@literal null}
72+
*/
73+
@SuppressWarnings("unchecked")
74+
protected <T> T getValueFromObject(String propertyName, String accessType, Object object, ServiceRegistry serviceRegistry) {
75+
return doPrivileged( () -> {
76+
final Getter getter = ReflectionTools.getGetter( object.getClass(), propertyName, accessType, serviceRegistry );
77+
return (T) getter.get( object );
78+
} );
79+
}
80+
81+
/**
82+
* Set the specified value on the object.
83+
*
84+
* @param propertyData the property data, should not be {@literal null}
85+
* @param object the object for which the value should be set, should not be {@literal null}
86+
* @param value the value ot be set, may be {@literal null}
87+
* @param serviceRegistry the service registry, should not be {@literal null}
88+
*/
89+
protected void setValueOnObject(PropertyData propertyData, Object object, Object value, ServiceRegistry serviceRegistry) {
90+
doPrivileged( () -> {
91+
final Setter setter = ReflectionTools.getSetter(object.getClass(), propertyData, serviceRegistry );
92+
setter.set( object, value );
93+
return null;
94+
} );
95+
}
96+
97+
/**
98+
* Gets the value from the source object and sets the value in the destination object.
99+
*
100+
* @param propertyData the property data, should not be {@literal null}
101+
* @param source the source object, should not be {@literal null}
102+
* @param destination the destination object, should not be {@literal null}
103+
* @param serviceRegistry the service registry, should not be {@literal null}
104+
*/
105+
protected void getAndSetValue(PropertyData propertyData, Object source, Object destination, ServiceRegistry serviceRegistry) {
106+
doPrivileged( () -> {
107+
final Getter getter = ReflectionTools.getGetter( source.getClass(), propertyData, serviceRegistry );
108+
final Setter setter = ReflectionTools.getSetter( destination.getClass(), propertyData, serviceRegistry );
109+
setter.set( destination, getter.get( source ) );
110+
return null;
111+
} );
112+
}
113+
114+
/**
115+
* Creates a new object based on the specified class with the given constructor arguments.
116+
*
117+
* @param clazz the class, must not be {@literal null}
118+
* @param args the variadic constructor arguments, may be omitted.
119+
* @param <T> the return class type
120+
* @return a new instance of the class
121+
*/
122+
protected <T> T newObjectInstance(Class<T> clazz, Object... args) {
123+
return doPrivileged( () -> {
124+
try {
125+
final Constructor<T> constructor = ReflectHelper.getDefaultConstructor( clazz );
126+
if ( constructor == null ) {
127+
throw new AuditException( "Failed to locate default constructor for class: " + clazz.getName() );
128+
}
129+
return constructor.newInstance( args );
130+
}
131+
catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
132+
throw new AuditException( e );
133+
}
134+
} );
135+
}
136+
}

hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/AbstractPropertyMapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
* @author Chris Cranford
1313
*/
14-
public abstract class AbstractPropertyMapper implements PropertyMapper {
14+
public abstract class AbstractPropertyMapper extends AbstractMapper implements PropertyMapper {
1515
private boolean map;
1616

1717
@Override

hibernate-envers/src/main/java/org/hibernate/envers/internal/entities/mapper/ComponentPropertyMapper.java

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
package org.hibernate.envers.internal.entities.mapper;
88

99
import java.io.Serializable;
10-
import java.security.AccessController;
11-
import java.security.PrivilegedAction;
1210
import java.util.HashMap;
1311
import java.util.List;
1412
import java.util.Map;
@@ -118,43 +116,38 @@ public void mapToEntityFromMap(
118116
return;
119117
}
120118

121-
AccessController.doPrivileged(
122-
new PrivilegedAction<Object>() {
123-
@Override
124-
public Object run() {
125-
try {
126-
final Object subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
127-
128-
if ( isDynamicComponentMap() ) {
129-
( (Map) obj ).put( propertyData.getBeanName(), subObj );
130-
delegate.mapToEntityFromMap( enversService, subObj, data, primaryKey, versionsReader, revision );
131-
}
132-
else {
133-
final Setter setter = ReflectionTools.getSetter(
134-
obj.getClass(),
135-
propertyData,
136-
enversService.getServiceRegistry()
137-
);
138-
139-
if ( isAllPropertiesNull( data ) ) {
140-
// single property, but default value need not be null, so we'll set it to null anyway
141-
setter.set( obj, null );
142-
}
143-
else {
144-
// set the component
145-
setter.set( obj, subObj );
146-
delegate.mapToEntityFromMap( enversService, subObj, data, primaryKey, versionsReader, revision );
147-
}
148-
}
149-
}
150-
catch ( Exception e ) {
151-
throw new AuditException( e );
152-
}
153-
154-
return null;
119+
doPrivileged( () -> {
120+
try {
121+
final Object subObj = ReflectHelper.getDefaultConstructor( componentClass ).newInstance();
122+
123+
if ( isDynamicComponentMap() ) {
124+
( (Map) obj ).put( propertyData.getBeanName(), subObj );
125+
delegate.mapToEntityFromMap( enversService, subObj, data, primaryKey, versionsReader, revision );
126+
}
127+
else {
128+
final Setter setter = ReflectionTools.getSetter(
129+
obj.getClass(),
130+
propertyData,
131+
enversService.getServiceRegistry()
132+
);
133+
134+
if ( isAllPropertiesNull( data ) ) {
135+
// single property, but default value need not be null, so we'll set it to null anyway
136+
setter.set( obj, null );
137+
}
138+
else {
139+
// set the component
140+
setter.set( obj, subObj );
141+
delegate.mapToEntityFromMap( enversService, subObj, data, primaryKey, versionsReader, revision );
155142
}
156143
}
157-
);
144+
}
145+
catch ( Exception e ) {
146+
throw new AuditException( e );
147+
}
148+
149+
return null;
150+
} );
158151
}
159152

160153
private boolean isAllPropertiesNull(Map data) {

0 commit comments

Comments
 (0)