@ -1,5 +1,5 @@
/ *
/ *
* Copyright 2002 - 2014 the original author or authors .
* Copyright 2002 - 2015 the original author or authors .
*
*
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* you may not use this file except in compliance with the License .
@ -58,7 +58,10 @@ import org.springframework.util.StringUtils;
* /
* /
public class ReflectivePropertyAccessor implements PropertyAccessor {
public class ReflectivePropertyAccessor implements PropertyAccessor {
private static final Set < Class < ? > > ANY_TYPES = Collections . emptySet ( ) ;
private static final Set < Class < ? > > BOOLEAN_TYPES ;
private static final Set < Class < ? > > BOOLEAN_TYPES ;
static {
static {
Set < Class < ? > > booleanTypes = new HashSet < Class < ? > > ( ) ;
Set < Class < ? > > booleanTypes = new HashSet < Class < ? > > ( ) ;
booleanTypes . add ( Boolean . class ) ;
booleanTypes . add ( Boolean . class ) ;
@ -66,8 +69,6 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
BOOLEAN_TYPES = Collections . unmodifiableSet ( booleanTypes ) ;
BOOLEAN_TYPES = Collections . unmodifiableSet ( booleanTypes ) ;
}
}
private static final Set < Class < ? > > ANY_TYPES = Collections . emptySet ( ) ;
private final Map < CacheKey , InvokerPair > readerCache = new ConcurrentHashMap < CacheKey , InvokerPair > ( 64 ) ;
private final Map < CacheKey , InvokerPair > readerCache = new ConcurrentHashMap < CacheKey , InvokerPair > ( 64 ) ;
@ -120,9 +121,9 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
}
}
return false ;
return false ;
}
}
public Member getLastReadInvokerPair ( ) {
public Member getLastReadInvokerPair ( ) {
return lastReadInvokerPair . member ;
return this . lastReadInvokerPair . member ;
}
}
@Override
@Override
@ -165,7 +166,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return new TypedValue ( value , invoker . typeDescriptor . narrow ( value ) ) ;
return new TypedValue ( value , invoker . typeDescriptor . narrow ( value ) ) ;
}
}
catch ( Exception ex ) {
catch ( Exception ex ) {
throw new AccessException ( "Unable to access property '" + name + "' through getter" , ex ) ;
throw new AccessException ( "Unable to access property '" + name + "' through getter method " , ex ) ;
}
}
}
}
}
}
@ -187,12 +188,12 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return new TypedValue ( value , invoker . typeDescriptor . narrow ( value ) ) ;
return new TypedValue ( value , invoker . typeDescriptor . narrow ( value ) ) ;
}
}
catch ( Exception ex ) {
catch ( Exception ex ) {
throw new AccessException ( "Unable to access field: " + name , ex ) ;
throw new AccessException ( "Unable to access field ' " + name + "'" , ex ) ;
}
}
}
}
}
}
throw new AccessException ( "Neither getter nor field found for property '" + name + "'" ) ;
throw new AccessException ( "Neither getter method nor field found for property '" + name + "'" ) ;
}
}
@Override
@Override
@ -240,7 +241,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
newValue , TypeDescriptor . forObject ( newValue ) , typeDescriptor ) ;
newValue , TypeDescriptor . forObject ( newValue ) , typeDescriptor ) ;
}
}
catch ( EvaluationException evaluationException ) {
catch ( EvaluationException evaluationException ) {
throw new AccessException ( "Type conversion failure" , evaluationException ) ;
throw new AccessException ( "Type conversion failure" , evaluationException ) ;
}
}
}
}
CacheKey cacheKey = new CacheKey ( type , name , target instanceof Class ) ;
CacheKey cacheKey = new CacheKey ( type , name , target instanceof Class ) ;
@ -262,7 +263,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return ;
return ;
}
}
catch ( Exception ex ) {
catch ( Exception ex ) {
throw new AccessException ( "Unable to access property '" + name + "' through setter" , ex ) ;
throw new AccessException ( "Unable to access property '" + name + "' through setter method " , ex ) ;
}
}
}
}
}
}
@ -283,12 +284,12 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return ;
return ;
}
}
catch ( Exception ex ) {
catch ( Exception ex ) {
throw new AccessException ( "Unable to access field: " + name , ex ) ;
throw new AccessException ( "Unable to access field ' " + name + "'" , ex ) ;
}
}
}
}
}
}
throw new AccessException ( "Neither setter nor field found for property '" + name + "'" ) ;
throw new AccessException ( "Neither setter method nor field found for property '" + name + "'" ) ;
}
}
private TypeDescriptor getTypeDescriptor ( EvaluationContext context , Object target , String name ) {
private TypeDescriptor getTypeDescriptor ( EvaluationContext context , Object target , String name ) {
@ -469,11 +470,11 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
InvokerPair invocationTarget = this . readerCache . get ( cacheKey ) ;
InvokerPair invocationTarget = this . readerCache . get ( cacheKey ) ;
if ( invocationTarget = = null | | invocationTarget . member instanceof Method ) {
if ( invocationTarget = = null | | invocationTarget . member instanceof Method ) {
Method method = ( Method ) ( invocationTarget = = null ? null : invocationTarget . member ) ;
Method method = ( Method ) ( invocationTarget ! = null ? invocationTarget . member : null ) ;
if ( method = = null ) {
if ( method = = null ) {
method = findGetterForProperty ( name , type , target ) ;
method = findGetterForProperty ( name , type , target ) ;
if ( method ! = null ) {
if ( method ! = null ) {
invocationTarget = new InvokerPair ( method , new TypeDescriptor ( new MethodParameter ( method , - 1 ) ) ) ;
invocationTarget = new InvokerPair ( method , new TypeDescriptor ( new MethodParameter ( method , - 1 ) ) ) ;
ReflectionUtils . makeAccessible ( method ) ;
ReflectionUtils . makeAccessible ( method ) ;
this . readerCache . put ( cacheKey , invocationTarget ) ;
this . readerCache . put ( cacheKey , invocationTarget ) ;
}
}
@ -497,6 +498,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return new OptimalPropertyAccessor ( invocationTarget ) ;
return new OptimalPropertyAccessor ( invocationTarget ) ;
}
}
}
}
return this ;
return this ;
}
}
@ -577,16 +579,8 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
OptimalPropertyAccessor ( InvokerPair target ) {
OptimalPropertyAccessor ( InvokerPair target ) {
this . member = target . member ;
this . member = target . member ;
this . typeDescriptor = target . typeDescriptor ;
this . typeDescriptor = target . typeDescriptor ;
if ( this . member instanceof Field ) {
this . needsToBeMadeAccessible = ( ! Modifier . isPublic ( this . member . getModifiers ( ) ) | |
Field field = ( Field ) this . member ;
! Modifier . isPublic ( this . member . getDeclaringClass ( ) . getModifiers ( ) ) ) ;
this . needsToBeMadeAccessible = ( ! Modifier . isPublic ( field . getModifiers ( ) ) | |
! Modifier . isPublic ( field . getDeclaringClass ( ) . getModifiers ( ) ) ) & & ! field . isAccessible ( ) ;
}
else {
Method method = ( Method ) this . member ;
this . needsToBeMadeAccessible = ( ( ! Modifier . isPublic ( method . getModifiers ( ) ) | |
! Modifier . isPublic ( method . getDeclaringClass ( ) . getModifiers ( ) ) ) & & ! method . isAccessible ( ) ) ;
}
}
}
@Override
@Override
@ -599,10 +593,12 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
if ( target = = null ) {
if ( target = = null ) {
return false ;
return false ;
}
}
Class < ? > type = ( target instanceof Class ? ( Class < ? > ) target : target . getClass ( ) ) ;
Class < ? > type = ( target instanceof Class ? ( Class < ? > ) target : target . getClass ( ) ) ;
if ( type . isArray ( ) ) {
if ( type . isArray ( ) ) {
return false ;
return false ;
}
}
if ( this . member instanceof Method ) {
if ( this . member instanceof Method ) {
Method method = ( Method ) this . member ;
Method method = ( Method ) this . member ;
String getterName = "get" + StringUtils . capitalize ( name ) ;
String getterName = "get" + StringUtils . capitalize ( name ) ;
@ -621,30 +617,31 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
@Override
@Override
public TypedValue read ( EvaluationContext context , Object target , String name ) throws AccessException {
public TypedValue read ( EvaluationContext context , Object target , String name ) throws AccessException {
if ( this . member instanceof Method ) {
if ( this . member instanceof Method ) {
Method method = ( Method ) this . member ;
try {
try {
if ( this . needsToBeMadeAccessible ) {
if ( this . needsToBeMadeAccessible & & ! method . isAccessible ( ) ) {
ReflectionUtils . makeAccessible ( ( Method ) this . member ) ;
method . setAccessible ( true ) ;
}
}
Object value = ( ( Method ) this . member ) . invoke ( target ) ;
Object value = method . invoke ( target ) ;
return new TypedValue ( value , this . typeDescriptor . narrow ( value ) ) ;
return new TypedValue ( value , this . typeDescriptor . narrow ( value ) ) ;
}
}
catch ( Exception ex ) {
catch ( Exception ex ) {
throw new AccessException ( "Unable to access property '" + name + "' through getter" , ex ) ;
throw new AccessException ( "Unable to access property '" + name + "' through getter method " , ex ) ;
}
}
}
}
if ( this . member instanceof Field ) {
else {
Field field = ( Field ) this . member ;
try {
try {
if ( this . needsToBeMadeAccessible ) {
if ( this . needsToBeMadeAccessible & & ! field . isAccessible ( ) ) {
ReflectionUtils . makeAccessible ( ( Field ) this . member ) ;
field . setAccessible ( true ) ;
}
}
Object value = ( ( Field ) this . member ) . get ( target ) ;
Object value = field . get ( target ) ;
return new TypedValue ( value , this . typeDescriptor . narrow ( value ) ) ;
return new TypedValue ( value , this . typeDescriptor . narrow ( value ) ) ;
}
}
catch ( Exception ex ) {
catch ( Exception ex ) {
throw new AccessException ( "Unable to access field: " + name , ex ) ;
throw new AccessException ( "Unable to access field ' " + name + "'" , ex ) ;
}
}
}
}
throw new AccessException ( "Neither getter nor field found for property '" + name + "'" ) ;
}
}
@Override
@Override
@ -656,7 +653,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
public void write ( EvaluationContext context , Object target , String name , Object newValue ) {
public void write ( EvaluationContext context , Object target , String name , Object newValue ) {
throw new UnsupportedOperationException ( "Should not be called on an OptimalPropertyAccessor" ) ;
throw new UnsupportedOperationException ( "Should not be called on an OptimalPropertyAccessor" ) ;
}
}
@Override
@Override
public boolean isCompilable ( ) {
public boolean isCompilable ( ) {
return ( Modifier . isPublic ( this . member . getModifiers ( ) ) & &
return ( Modifier . isPublic ( this . member . getModifiers ( ) ) & &
@ -665,11 +662,11 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
@Override
@Override
public Class < ? > getPropertyType ( ) {
public Class < ? > getPropertyType ( ) {
if ( this . member instanceof Fiel d) {
if ( this . member instanceof Metho d) {
return ( ( Fiel d) this . member ) . getType ( ) ;
return ( ( Metho d) this . member ) . getReturn Type ( ) ;
}
}
else {
else {
return ( ( Metho d) this . member ) . getReturn Type ( ) ;
return ( ( Fiel d) this . member ) . getType ( ) ;
}
}
}
}
@ -677,22 +674,31 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
public void generateCode ( String propertyName , MethodVisitor mv , CodeFlow cf ) {
public void generateCode ( String propertyName , MethodVisitor mv , CodeFlow cf ) {
boolean isStatic = Modifier . isStatic ( this . member . getModifiers ( ) ) ;
boolean isStatic = Modifier . isStatic ( this . member . getModifiers ( ) ) ;
String descriptor = cf . lastDescriptor ( ) ;
String descriptor = cf . lastDescriptor ( ) ;
String memberDeclaringClassSlashedDescriptor = this . member . getDeclaringClass ( ) . getName ( ) . replace ( '.' , '/' ) ;
String classDesc = this . member . getDeclaringClass ( ) . getName ( ) . replace ( '.' , '/' ) ;
if ( ! isStatic ) {
if ( ! isStatic ) {
if ( descriptor = = null ) {
if ( descriptor = = null ) {
cf . loadTarget ( mv ) ;
cf . loadTarget ( mv ) ;
}
}
if ( descriptor = = null | | ! memberDe claringCla ssSlashed Descriptor . equals ( descriptor . substring ( 1 ) ) ) {
if ( descriptor = = null | | ! classDesc . equals ( descriptor . substring ( 1 ) ) ) {
mv . visitTypeInsn ( CHECKCAST , memberDe claringCla ssSlashed Descriptor ) ;
mv . visitTypeInsn ( CHECKCAST , classDesc ) ;
}
}
}
}
if ( this . member instanceof Field ) {
else {
mv . visitFieldInsn ( isStatic ? GETSTATIC : GETFIELD , memberDeclaringClassSlashedDescriptor ,
if ( descriptor ! = null ) {
this . member . getName ( ) , CodeFlow . toJvmDescriptor ( ( ( Field ) this . member ) . getType ( ) ) ) ;
// A static field/method call will not consume what is on the stack,
// it needs to be popped off.
mv . visitInsn ( POP ) ;
}
}
if ( this . member instanceof Method ) {
mv . visitMethodInsn ( ( isStatic ? INVOKESTATIC : INVOKEVIRTUAL ) , classDesc , this . member . getName ( ) ,
CodeFlow . createSignatureDescriptor ( ( Method ) this . member ) , false ) ;
}
}
else {
else {
mv . visitMethodInsn ( isStatic ? INVOKESTATIC : INVOKEVIRTUAL , memberDeclaringClassSlashedDescriptor ,
mv . visitFieldInsn ( ( isStatic ? GETSTATIC : GETFIELD ) , classDesc , this . member . getName ( ) ,
this . member . getName ( ) , CodeFlow . createSignatureDescriptor ( ( Method ) this . member ) , false ) ;
CodeFlow . toJvmDescriptor ( ( ( Field ) this . member ) . getType ( ) ) ) ;
}
}
}
}
}
}