daniel
7 years ago
15 changed files with 362 additions and 50 deletions
@ -0,0 +1,18 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||||
|
<modelVersion>4.0.0</modelVersion> |
||||||
|
|
||||||
|
<parent> |
||||||
|
<groupId>com.fr.third</groupId> |
||||||
|
<artifactId>base-third-code</artifactId> |
||||||
|
<version>10.0-RELEASE-SNAPSHOT</version> |
||||||
|
</parent> |
||||||
|
|
||||||
|
<groupId>com.fr.third</groupId> |
||||||
|
<artifactId>fine-druid</artifactId> |
||||||
|
<version>10.0-RELEASE-SNAPSHOT</version> |
||||||
|
|
||||||
|
|
||||||
|
</project> |
@ -0,0 +1,18 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||||
|
<modelVersion>4.0.0</modelVersion> |
||||||
|
|
||||||
|
<parent> |
||||||
|
<groupId>com.fr.third</groupId> |
||||||
|
<artifactId>base-third-code</artifactId> |
||||||
|
<version>10.0-RELEASE-SNAPSHOT</version> |
||||||
|
</parent> |
||||||
|
|
||||||
|
<groupId>com.fr.third</groupId> |
||||||
|
<artifactId>fine-hibernate</artifactId> |
||||||
|
<version>10.0-RELEASE-SNAPSHOT</version> |
||||||
|
|
||||||
|
|
||||||
|
</project> |
@ -0,0 +1,116 @@ |
|||||||
|
/* |
||||||
|
* 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 com.fr.third.org.hibernate.property.access.spi; |
||||||
|
|
||||||
|
import com.fr.third.org.hibernate.engine.spi.SessionImplementor; |
||||||
|
import com.fr.third.org.hibernate.property.access.internal.AbstractFieldSerialForm; |
||||||
|
import sun.misc.Unsafe; |
||||||
|
import sun.reflect.FieldAccessor; |
||||||
|
import sun.reflect.ReflectionFactory; |
||||||
|
|
||||||
|
import java.io.ObjectStreamException; |
||||||
|
import java.io.Serializable; |
||||||
|
import java.lang.reflect.Field; |
||||||
|
import java.lang.reflect.Member; |
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.lang.reflect.Modifier; |
||||||
|
import java.security.AccessController; |
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* Field-based implementation of Getter |
||||||
|
* |
||||||
|
* @author Steve Ebersole |
||||||
|
*/ |
||||||
|
public class UnsafeGetterFieldImpl implements Getter { |
||||||
|
private final Class containerClass; |
||||||
|
private final String propertyName; |
||||||
|
private final Field field; |
||||||
|
private final FieldAccessor accessor; |
||||||
|
|
||||||
|
static ReflectionFactory reflectionFactory = |
||||||
|
AccessController.doPrivileged( |
||||||
|
new sun.reflect.ReflectionFactory.GetReflectionFactoryAction()); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public UnsafeGetterFieldImpl(Class containerClass, String propertyName, Field field) { |
||||||
|
this.containerClass = containerClass; |
||||||
|
this.propertyName = propertyName; |
||||||
|
this.field = field; |
||||||
|
accessor = reflectionFactory.newFieldAccessor(field, false); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object get(Object owner) { |
||||||
|
if(accessor != null){ |
||||||
|
return accessor.get(owner); |
||||||
|
} |
||||||
|
try { |
||||||
|
return field.get( owner ); |
||||||
|
} |
||||||
|
catch (Exception e) { |
||||||
|
throw new PropertyAccessException( |
||||||
|
String.format( |
||||||
|
Locale.ROOT, |
||||||
|
"Error accessing field [%s] by reflection for persistent property [%s#%s] : %s", |
||||||
|
field.toGenericString(), |
||||||
|
containerClass.getName(), |
||||||
|
propertyName, |
||||||
|
owner |
||||||
|
), |
||||||
|
e |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getForInsert(Object owner, Map mergeMap, SessionImplementor session) { |
||||||
|
return get( owner ); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class getReturnType() { |
||||||
|
return field.getType(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Member getMember() { |
||||||
|
return field; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getMethodName() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Method getMethod() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
private Object writeReplace() throws ObjectStreamException { |
||||||
|
return new SerialForm( containerClass, propertyName, field ); |
||||||
|
} |
||||||
|
|
||||||
|
private static class SerialForm extends AbstractFieldSerialForm implements Serializable { |
||||||
|
private final Class containerClass; |
||||||
|
private final String propertyName; |
||||||
|
|
||||||
|
private SerialForm(Class containerClass, String propertyName, Field field) { |
||||||
|
super( field ); |
||||||
|
this.containerClass = containerClass; |
||||||
|
this.propertyName = propertyName; |
||||||
|
} |
||||||
|
|
||||||
|
private Object readResolve() { |
||||||
|
return new UnsafeGetterFieldImpl( containerClass, propertyName, resolveField() ); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,160 @@ |
|||||||
|
/* |
||||||
|
* 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 com.fr.third.org.hibernate.property.access.spi; |
||||||
|
|
||||||
|
import com.fr.third.org.hibernate.PropertyAccessException; |
||||||
|
import com.fr.third.org.hibernate.PropertySetterAccessException; |
||||||
|
import com.fr.third.org.hibernate.engine.spi.SessionFactoryImplementor; |
||||||
|
import com.fr.third.org.hibernate.internal.CoreMessageLogger; |
||||||
|
|
||||||
|
import java.io.ObjectStreamException; |
||||||
|
import java.io.Serializable; |
||||||
|
import java.lang.reflect.InvocationTargetException; |
||||||
|
import java.lang.reflect.Method; |
||||||
|
|
||||||
|
import static com.fr.third.org.hibernate.internal.CoreLogging.messageLogger; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Steve Ebersole |
||||||
|
*/ |
||||||
|
public class UnsafeSetterMethodImpl implements Setter { |
||||||
|
private static final CoreMessageLogger LOG = messageLogger( UnsafeSetterMethodImpl.class ); |
||||||
|
|
||||||
|
private final Class containerClass; |
||||||
|
private final String propertyName; |
||||||
|
private final Method setterMethod; |
||||||
|
|
||||||
|
private final boolean isPrimitive; |
||||||
|
|
||||||
|
public UnsafeSetterMethodImpl(Class containerClass, String propertyName, Method setterMethod) { |
||||||
|
this.containerClass = containerClass; |
||||||
|
this.propertyName = propertyName; |
||||||
|
this.setterMethod = setterMethod; |
||||||
|
|
||||||
|
this.isPrimitive = setterMethod.getParameterTypes()[0].isPrimitive(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void set(Object target, Object value, SessionFactoryImplementor factory) { |
||||||
|
try { |
||||||
|
setterMethod.invoke( target, value ); |
||||||
|
} |
||||||
|
catch (NullPointerException npe) { |
||||||
|
if ( value == null && isPrimitive ) { |
||||||
|
throw new PropertyAccessException( |
||||||
|
npe, |
||||||
|
"Null value was assigned to a property of primitive type", |
||||||
|
true, |
||||||
|
containerClass, |
||||||
|
propertyName |
||||||
|
); |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new PropertyAccessException( |
||||||
|
npe, |
||||||
|
"NullPointerException occurred while calling", |
||||||
|
true, |
||||||
|
containerClass, |
||||||
|
propertyName |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (InvocationTargetException ite) { |
||||||
|
throw new PropertyAccessException( |
||||||
|
ite, |
||||||
|
"Exception occurred inside", |
||||||
|
true, |
||||||
|
containerClass, |
||||||
|
propertyName |
||||||
|
); |
||||||
|
} |
||||||
|
catch (IllegalAccessException iae) { |
||||||
|
throw new PropertyAccessException( |
||||||
|
iae, |
||||||
|
"IllegalAccessException occurred while calling", |
||||||
|
true, |
||||||
|
containerClass, |
||||||
|
propertyName |
||||||
|
); |
||||||
|
//cannot occur
|
||||||
|
} |
||||||
|
catch (IllegalArgumentException iae) { |
||||||
|
if ( value == null && isPrimitive ) { |
||||||
|
throw new PropertyAccessException( |
||||||
|
iae, |
||||||
|
"Null value was assigned to a property of primitive type", |
||||||
|
true, |
||||||
|
containerClass, |
||||||
|
propertyName |
||||||
|
); |
||||||
|
} |
||||||
|
else { |
||||||
|
final Class expectedType = setterMethod.getParameterTypes()[0]; |
||||||
|
LOG.illegalPropertySetterArgument( containerClass.getName(), propertyName ); |
||||||
|
LOG.expectedType( expectedType.getName(), value == null ? null : value.getClass().getName() ); |
||||||
|
throw new PropertySetterAccessException( |
||||||
|
iae, |
||||||
|
containerClass, |
||||||
|
propertyName, |
||||||
|
expectedType, |
||||||
|
target, |
||||||
|
value |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getMethodName() { |
||||||
|
return setterMethod.getName(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Method getMethod() { |
||||||
|
return setterMethod; |
||||||
|
} |
||||||
|
|
||||||
|
private Object writeReplace() throws ObjectStreamException { |
||||||
|
return new SerialForm( containerClass, propertyName, setterMethod ); |
||||||
|
} |
||||||
|
|
||||||
|
private static class SerialForm implements Serializable { |
||||||
|
private final Class containerClass; |
||||||
|
private final String propertyName; |
||||||
|
|
||||||
|
private final Class declaringClass; |
||||||
|
private final String methodName; |
||||||
|
private final Class argumentType; |
||||||
|
|
||||||
|
private SerialForm(Class containerClass, String propertyName, Method method) { |
||||||
|
this.containerClass = containerClass; |
||||||
|
this.propertyName = propertyName; |
||||||
|
this.declaringClass = method.getDeclaringClass(); |
||||||
|
this.methodName = method.getName(); |
||||||
|
this.argumentType = method.getParameterTypes()[0]; |
||||||
|
} |
||||||
|
|
||||||
|
private Object readResolve() { |
||||||
|
return new UnsafeSetterMethodImpl( containerClass, propertyName, resolveMethod() ); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
private Method resolveMethod() { |
||||||
|
try { |
||||||
|
final Method method = declaringClass.getDeclaredMethod( methodName, argumentType ); |
||||||
|
method.setAccessible( true ); |
||||||
|
return method; |
||||||
|
} |
||||||
|
catch (NoSuchMethodException e) { |
||||||
|
throw new PropertyAccessSerializationException( |
||||||
|
"Unable to resolve setter method on deserialization : " + declaringClass.getName() + "#" |
||||||
|
+ methodName + "(" + argumentType.getName() + ")" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue