Fixed an NPE in ImplicitPropertyAccessor due to putting null value in ConcurrentHashMap
This commit is contained in:
parent
2c3d0f10d9
commit
410dcdada2
|
@ -27,8 +27,7 @@ import org.springframework.expression.ConstructorResolver;
|
|||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.support.ReflectiveConstructorResolver;
|
||||
|
||||
final class ImplicitConstructorResolver implements
|
||||
ConstructorResolver {
|
||||
final class ImplicitConstructorResolver implements ConstructorResolver {
|
||||
|
||||
private final ReflectiveConstructorResolver delegate = new ReflectiveConstructorResolver();
|
||||
|
||||
|
|
|
@ -39,20 +39,21 @@ final class ImplicitMethodResolver implements MethodResolver {
|
|||
private final ReflectiveMethodResolver delegate = new ReflectiveMethodResolver();
|
||||
|
||||
private static final MethodExecutor NULL_ME = new MethodExecutor() {
|
||||
@Override
|
||||
public TypedValue execute(final EvaluationContext context, final Object target,
|
||||
final Object... arguments) throws AccessException {
|
||||
return null;
|
||||
throw new UnsupportedOperationException("This method should never be called");
|
||||
}
|
||||
};
|
||||
|
||||
private static final class ImplicitMethodExecutor implements
|
||||
MethodExecutor {
|
||||
private static final class ImplicitMethodExecutor implements MethodExecutor {
|
||||
private final MethodExecutor executor;
|
||||
|
||||
public ImplicitMethodExecutor(final MethodExecutor executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedValue execute(final EvaluationContext context, final Object target,
|
||||
final Object... arguments) throws AccessException {
|
||||
Object[] modifiedArguments = new Object[arguments.length + 1];
|
||||
|
@ -66,7 +67,7 @@ final class ImplicitMethodResolver implements MethodResolver {
|
|||
public MethodExecutor resolve(
|
||||
final EvaluationContext context, final Object targetObject,
|
||||
final String name, final List<TypeDescriptor> argumentTypes)
|
||||
throws AccessException {
|
||||
throws AccessException {
|
||||
if (targetObject == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -34,13 +34,22 @@ final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor {
|
|||
private static final ConcurrentHashMap<String, MethodExecutor> CACHE =
|
||||
new ConcurrentHashMap<String, MethodExecutor>();
|
||||
|
||||
private static final MethodExecutor NULL_ME = new MethodExecutor() {
|
||||
@Override
|
||||
public TypedValue execute(final EvaluationContext context, final Object target,
|
||||
final Object... arguments) throws AccessException {
|
||||
throw new UnsupportedOperationException("This method should never be called");
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean canRead(final EvaluationContext context,
|
||||
final Object target, final String name)
|
||||
throws AccessException {
|
||||
Assert.notNull(target, "target is null");
|
||||
String cacheKey = target.getClass().getName() + "." + name;
|
||||
if (CACHE.containsKey(cacheKey)) {
|
||||
return CACHE.get(cacheKey) != null;
|
||||
return CACHE.get(cacheKey) != NULL_ME;
|
||||
}
|
||||
|
||||
for (MethodResolver mr : context.getMethodResolvers()) {
|
||||
|
@ -52,10 +61,11 @@ final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor {
|
|||
}
|
||||
}
|
||||
|
||||
CACHE.putIfAbsent(cacheKey, null);
|
||||
CACHE.putIfAbsent(cacheKey, NULL_ME);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedValue read(final EvaluationContext context,
|
||||
final Object target, final String name)
|
||||
throws AccessException {
|
||||
|
|
|
@ -23,19 +23,21 @@ import org.springframework.expression.AccessException;
|
|||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
|
||||
abstract class ReadOnlyGenericPropertyAccessor implements
|
||||
PropertyAccessor {
|
||||
abstract class ReadOnlyGenericPropertyAccessor implements PropertyAccessor {
|
||||
|
||||
@Override
|
||||
public final boolean canWrite(final EvaluationContext context,
|
||||
final Object target, final String name) throws AccessException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public final Class[] getSpecificTargetClasses() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void write(final EvaluationContext context, final Object target,
|
||||
final String name, final Object newValue) throws AccessException {
|
||||
throw new AccessException(MessageFormat.format(
|
||||
|
|
Loading…
Reference in New Issue