Search in sources :

Example 1 with PropertyAccessor

use of org.springframework.expression.PropertyAccessor in project spring-framework by spring-projects.

the class PropertyOrFieldReference method readProperty.

/**
	 * Attempt to read the named property from the current context object.
	 * @return the value of the property
	 * @throws EvaluationException if any problem accessing the property or it cannot be found
	 */
private TypedValue readProperty(TypedValue contextObject, EvaluationContext evalContext, String name) throws EvaluationException {
    Object targetObject = contextObject.getValue();
    if (targetObject == null && this.nullSafe) {
        return TypedValue.NULL;
    }
    PropertyAccessor accessorToUse = this.cachedReadAccessor;
    if (accessorToUse != null) {
        try {
            return accessorToUse.read(evalContext, contextObject.getValue(), name);
        } catch (Exception ex) {
            // This is OK - it may have gone stale due to a class change,
            // let's try to get a new one and call it before giving up...
            this.cachedReadAccessor = null;
        }
    }
    List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObject.getValue(), evalContext.getPropertyAccessors());
    // then ask them to read it
    if (accessorsToTry != null) {
        try {
            for (PropertyAccessor accessor : accessorsToTry) {
                if (accessor.canRead(evalContext, contextObject.getValue(), name)) {
                    if (accessor instanceof ReflectivePropertyAccessor) {
                        accessor = ((ReflectivePropertyAccessor) accessor).createOptimalAccessor(evalContext, contextObject.getValue(), name);
                    }
                    this.cachedReadAccessor = accessor;
                    return accessor.read(evalContext, contextObject.getValue(), name);
                }
            }
        } catch (Exception ex) {
            throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_DURING_PROPERTY_READ, name, ex.getMessage());
        }
    }
    if (contextObject.getValue() == null) {
        throw new SpelEvaluationException(SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL, name);
    } else {
        throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE, name, FormatHelper.formatClassNameForMessage(getObjectClass(contextObject.getValue())));
    }
}
Also used : SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) ReflectivePropertyAccessor(org.springframework.expression.spel.support.ReflectivePropertyAccessor) PropertyAccessor(org.springframework.expression.PropertyAccessor) CompilablePropertyAccessor(org.springframework.expression.spel.CompilablePropertyAccessor) ReflectivePropertyAccessor(org.springframework.expression.spel.support.ReflectivePropertyAccessor) SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) EvaluationException(org.springframework.expression.EvaluationException) AccessException(org.springframework.expression.AccessException) InvocationTargetException(java.lang.reflect.InvocationTargetException)

Example 2 with PropertyAccessor

use of org.springframework.expression.PropertyAccessor in project spring-framework by spring-projects.

the class PropertyOrFieldReference method writeProperty.

private void writeProperty(TypedValue contextObject, EvaluationContext evalContext, String name, Object newValue) throws EvaluationException {
    if (contextObject.getValue() == null && this.nullSafe) {
        return;
    }
    PropertyAccessor accessorToUse = this.cachedWriteAccessor;
    if (accessorToUse != null) {
        try {
            accessorToUse.write(evalContext, contextObject.getValue(), name, newValue);
            return;
        } catch (Exception ex) {
            // This is OK - it may have gone stale due to a class change,
            // let's try to get a new one and call it before giving up...
            this.cachedWriteAccessor = null;
        }
    }
    List<PropertyAccessor> accessorsToTry = getPropertyAccessorsToTry(contextObject.getValue(), evalContext.getPropertyAccessors());
    if (accessorsToTry != null) {
        try {
            for (PropertyAccessor accessor : accessorsToTry) {
                if (accessor.canWrite(evalContext, contextObject.getValue(), name)) {
                    this.cachedWriteAccessor = accessor;
                    accessor.write(evalContext, contextObject.getValue(), name, newValue);
                    return;
                }
            }
        } catch (AccessException ex) {
            throw new SpelEvaluationException(getStartPosition(), ex, SpelMessage.EXCEPTION_DURING_PROPERTY_WRITE, name, ex.getMessage());
        }
    }
    if (contextObject.getValue() == null) {
        throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL, name);
    } else {
        throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_WRITABLE, name, FormatHelper.formatClassNameForMessage(getObjectClass(contextObject.getValue())));
    }
}
Also used : SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) ReflectivePropertyAccessor(org.springframework.expression.spel.support.ReflectivePropertyAccessor) PropertyAccessor(org.springframework.expression.PropertyAccessor) CompilablePropertyAccessor(org.springframework.expression.spel.CompilablePropertyAccessor) AccessException(org.springframework.expression.AccessException) SpelEvaluationException(org.springframework.expression.spel.SpelEvaluationException) EvaluationException(org.springframework.expression.EvaluationException) AccessException(org.springframework.expression.AccessException) InvocationTargetException(java.lang.reflect.InvocationTargetException)

Example 3 with PropertyAccessor

use of org.springframework.expression.PropertyAccessor in project spring-framework by spring-projects.

the class PropertyOrFieldReference method getValueInternal.

@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
    TypedValue tv = getValueInternal(state.getActiveContextObject(), state.getEvaluationContext(), state.getConfiguration().isAutoGrowNullReferences());
    PropertyAccessor accessorToUse = this.cachedReadAccessor;
    if (accessorToUse instanceof CompilablePropertyAccessor) {
        CompilablePropertyAccessor accessor = (CompilablePropertyAccessor) accessorToUse;
        this.exitTypeDescriptor = CodeFlow.toDescriptor(accessor.getPropertyType());
    }
    return tv;
}
Also used : ReflectivePropertyAccessor(org.springframework.expression.spel.support.ReflectivePropertyAccessor) PropertyAccessor(org.springframework.expression.PropertyAccessor) CompilablePropertyAccessor(org.springframework.expression.spel.CompilablePropertyAccessor) CompilablePropertyAccessor(org.springframework.expression.spel.CompilablePropertyAccessor) TypedValue(org.springframework.expression.TypedValue)

Example 4 with PropertyAccessor

use of org.springframework.expression.PropertyAccessor in project spring-framework by spring-projects.

the class PropertyOrFieldReference method getPropertyAccessorsToTry.

/**
	 * Determines the set of property resolvers that should be used to try and access a property
	 * on the specified target type. The resolvers are considered to be in an ordered list,
	 * however in the returned list any that are exact matches for the input target type (as
	 * opposed to 'general' resolvers that could work for any type) are placed at the start of the
	 * list. In addition, there are specific resolvers that exactly name the class in question
	 * and resolvers that name a specific class but it is a supertype of the class we have.
	 * These are put at the end of the specific resolvers set and will be tried after exactly
	 * matching accessors but before generic accessors.
	 * @param contextObject the object upon which property access is being attempted
	 * @return a list of resolvers that should be tried in order to access the property
	 */
private List<PropertyAccessor> getPropertyAccessorsToTry(Object contextObject, List<PropertyAccessor> propertyAccessors) {
    Class<?> targetType = (contextObject != null ? contextObject.getClass() : null);
    List<PropertyAccessor> specificAccessors = new ArrayList<>();
    List<PropertyAccessor> generalAccessors = new ArrayList<>();
    for (PropertyAccessor resolver : propertyAccessors) {
        Class<?>[] targets = resolver.getSpecificTargetClasses();
        if (targets == null) {
            // generic resolver that says it can be used for any type
            generalAccessors.add(resolver);
        } else if (targetType != null) {
            for (Class<?> clazz : targets) {
                if (clazz == targetType) {
                    specificAccessors.add(resolver);
                    break;
                } else if (clazz.isAssignableFrom(targetType)) {
                    generalAccessors.add(resolver);
                }
            }
        }
    }
    List<PropertyAccessor> resolvers = new ArrayList<>();
    resolvers.addAll(specificAccessors);
    generalAccessors.removeAll(specificAccessors);
    resolvers.addAll(generalAccessors);
    return resolvers;
}
Also used : ReflectivePropertyAccessor(org.springframework.expression.spel.support.ReflectivePropertyAccessor) PropertyAccessor(org.springframework.expression.PropertyAccessor) CompilablePropertyAccessor(org.springframework.expression.spel.CompilablePropertyAccessor) ArrayList(java.util.ArrayList)

Example 5 with PropertyAccessor

use of org.springframework.expression.PropertyAccessor in project spring-framework by spring-projects.

the class PropertyAccessTests method testAddingRemovingAccessors.

@Test
public void testAddingRemovingAccessors() {
    StandardEvaluationContext ctx = new StandardEvaluationContext();
    // reflective property accessor is the only one by default
    List<PropertyAccessor> propertyAccessors = ctx.getPropertyAccessors();
    assertEquals(1, propertyAccessors.size());
    StringyPropertyAccessor spa = new StringyPropertyAccessor();
    ctx.addPropertyAccessor(spa);
    assertEquals(2, ctx.getPropertyAccessors().size());
    List<PropertyAccessor> copy = new ArrayList<>();
    copy.addAll(ctx.getPropertyAccessors());
    assertTrue(ctx.removePropertyAccessor(spa));
    assertFalse(ctx.removePropertyAccessor(spa));
    assertEquals(1, ctx.getPropertyAccessors().size());
    ctx.setPropertyAccessors(copy);
    assertEquals(2, ctx.getPropertyAccessors().size());
}
Also used : StandardEvaluationContext(org.springframework.expression.spel.support.StandardEvaluationContext) PropertyAccessor(org.springframework.expression.PropertyAccessor) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Aggregations

PropertyAccessor (org.springframework.expression.PropertyAccessor)17 ReflectivePropertyAccessor (org.springframework.expression.spel.support.ReflectivePropertyAccessor)7 Test (org.junit.Test)5 CompilablePropertyAccessor (org.springframework.expression.spel.CompilablePropertyAccessor)5 StandardEvaluationContext (org.springframework.expression.spel.support.StandardEvaluationContext)5 ArrayList (java.util.ArrayList)4 EvaluationContext (org.springframework.expression.EvaluationContext)4 Method (java.lang.reflect.Method)3 Test (org.junit.jupiter.api.Test)3 AccessException (org.springframework.expression.AccessException)3 InvocationTargetException (java.lang.reflect.InvocationTargetException)2 MapAccessor (org.springframework.context.expression.MapAccessor)2 EvaluationException (org.springframework.expression.EvaluationException)2 SpelEvaluationException (org.springframework.expression.spel.SpelEvaluationException)2 List (java.util.List)1 Map (java.util.Map)1 BeansException (org.springframework.beans.BeansException)1 NoSuchBeanDefinitionException (org.springframework.beans.factory.NoSuchBeanDefinitionException)1 SpringBootTest (org.springframework.boot.test.context.SpringBootTest)1 ApplicationContext (org.springframework.context.ApplicationContext)1