changed tabs to spaces

master
Abhinav Sarkar 2010-05-26 19:22:11 +05:30
parent 5ce9a8a5d4
commit bf09c40c7f
9 changed files with 285 additions and 285 deletions

View File

@ -24,7 +24,7 @@ final class ExtensionFunctions {
} }
public static <K,V> Map<K,V> map(final List<? extends K> keys, public static <K,V> Map<K,V> map(final List<? extends K> keys,
final List<? extends V> values) { final List<? extends V> values) {
Assert.isTrue(keys.size() == values.size(), Assert.isTrue(keys.size() == values.size(),
"There should equal number of keys and values"); "There should equal number of keys and values");
Map<K,V> map = new HashMap<K,V>(); Map<K,V> map = new HashMap<K,V>();

View File

@ -17,18 +17,18 @@ final class ImplicitConstructorResolver implements
private final ReflectiveConstructorResolver delegate = new ReflectiveConstructorResolver(); private final ReflectiveConstructorResolver delegate = new ReflectiveConstructorResolver();
public ConstructorExecutor resolve(final EvaluationContext context, public ConstructorExecutor resolve(final EvaluationContext context,
final String typeName, final Class<?>[] argumentTypes) throws AccessException { final String typeName, final Class<?>[] argumentTypes) throws AccessException {
try { try {
return delegate.resolve(context, typeName, argumentTypes); return delegate.resolve(context, typeName, argumentTypes);
} catch (AccessException ex) { } catch (AccessException ex) {
Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY)) Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY))
.lookupImplicitConstructor(typeName + Arrays.toString(argumentTypes)); .lookupImplicitConstructor(typeName + Arrays.toString(argumentTypes));
if (variable instanceof Constructor<?>) { if (variable instanceof Constructor<?>) {
Constructor<?> constructor = (Constructor<?>) variable; Constructor<?> constructor = (Constructor<?>) variable;
return delegate.resolve(context, constructor.getDeclaringClass().getName(), argumentTypes); return delegate.resolve(context, constructor.getDeclaringClass().getName(), argumentTypes);
} }
return null; return null;
} }
} }
} }

View File

@ -16,83 +16,83 @@ import org.springframework.expression.spel.support.ReflectiveMethodResolver;
public final class ImplicitMethodResolver implements MethodResolver { public final class ImplicitMethodResolver implements MethodResolver {
private static final ConcurrentHashMap<String, MethodExecutor> cache = private static final ConcurrentHashMap<String, MethodExecutor> cache =
new ConcurrentHashMap<String, MethodExecutor>(); new ConcurrentHashMap<String, MethodExecutor>();
private static final MethodExecutor NULL_ME = new MethodExecutor() { private static final MethodExecutor NULL_ME = new MethodExecutor() {
public TypedValue execute(final EvaluationContext context, final Object target, public TypedValue execute(final EvaluationContext context, final Object target,
final Object... arguments) throws AccessException { final Object... arguments) throws AccessException {
return null; return null;
} }
}; };
private static final class ImplicitMethodExecutor implements private static final class ImplicitMethodExecutor implements
MethodExecutor { MethodExecutor {
private final MethodExecutor executor; private final MethodExecutor executor;
private ImplicitMethodExecutor(final MethodExecutor executor) { private ImplicitMethodExecutor(final MethodExecutor executor) {
this.executor = executor; this.executor = executor;
} }
public TypedValue execute(final EvaluationContext context, final Object target, public TypedValue execute(final EvaluationContext context, final Object target,
final Object... arguments) throws AccessException { final Object... arguments) throws AccessException {
Object[] modifiedArguments = new Object[arguments.length + 1]; Object[] modifiedArguments = new Object[arguments.length + 1];
modifiedArguments[0] = target; modifiedArguments[0] = target;
System.arraycopy(arguments, 0, modifiedArguments, 1, arguments.length); System.arraycopy(arguments, 0, modifiedArguments, 1, arguments.length);
return executor.execute(context, null, modifiedArguments); return executor.execute(context, null, modifiedArguments);
} }
} }
public MethodExecutor resolve(final EvaluationContext context, public MethodExecutor resolve(final EvaluationContext context,
final Object targetObject, final String name, final Class<?>[] argumentTypes) final Object targetObject, final String name, final Class<?>[] argumentTypes)
throws AccessException { throws AccessException {
if (targetObject == null) { if (targetObject == null) {
return null; return null;
} }
Class<?> type = targetObject.getClass(); Class<?> type = targetObject.getClass();
String cacheKey = type.getName() + "." + name; String cacheKey = type.getName() + "." + name;
if (cache.containsKey(cacheKey)) { if (cache.containsKey(cacheKey)) {
MethodExecutor executor = cache.get(cacheKey); MethodExecutor executor = cache.get(cacheKey);
return executor == NULL_ME ? null : executor; return executor == NULL_ME ? null : executor;
} }
Method method = lookupMethod(context, type, name); Method method = lookupMethod(context, type, name);
if (method != null) { if (method != null) {
int modifiers = method.getModifiers(); int modifiers = method.getModifiers();
if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) { if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) {
Class<?>[] parameterTypes = method.getParameterTypes(); Class<?>[] parameterTypes = method.getParameterTypes();
Class<?> firstParameterType = parameterTypes[0]; Class<?> firstParameterType = parameterTypes[0];
if (parameterTypes.length > 0 if (parameterTypes.length > 0
&& firstParameterType.isAssignableFrom(type)) { && firstParameterType.isAssignableFrom(type)) {
Class<?>[] modifiedArgumentTypes = new Class[argumentTypes.length + 1]; Class<?>[] modifiedArgumentTypes = new Class[argumentTypes.length + 1];
modifiedArgumentTypes[0] = firstParameterType; modifiedArgumentTypes[0] = firstParameterType;
System.arraycopy(argumentTypes, 0, modifiedArgumentTypes, System.arraycopy(argumentTypes, 0, modifiedArgumentTypes,
1, argumentTypes.length); 1, argumentTypes.length);
MethodExecutor executor = new ReflectiveMethodResolver() MethodExecutor executor = new ReflectiveMethodResolver()
.resolve(context, method.getDeclaringClass(), name, .resolve(context, method.getDeclaringClass(), name,
modifiedArgumentTypes); modifiedArgumentTypes);
MethodExecutor wrappedExecutor = executor == null ? null MethodExecutor wrappedExecutor = executor == null ? null
: new ImplicitMethodExecutor(executor); : new ImplicitMethodExecutor(executor);
cache.putIfAbsent(cacheKey, wrappedExecutor); cache.putIfAbsent(cacheKey, wrappedExecutor);
return wrappedExecutor; return wrappedExecutor;
} }
} }
} }
cache.putIfAbsent(cacheKey, NULL_ME); cache.putIfAbsent(cacheKey, NULL_ME);
return null; return null;
} }
private static Method lookupMethod(final EvaluationContext context, private static Method lookupMethod(final EvaluationContext context,
final Class<?> type, final String name) { final Class<?> type, final String name) {
for (Class<?> clazz : InheritenceUtil.getInheritance(type)) { for (Class<?> clazz : InheritenceUtil.getInheritance(type)) {
Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY)) Object variable = ((SpelHelper) context.lookupVariable(SpelHelper.CONTEXT_LOOKUP_KEY))
.lookupImplicitMethod(clazz.getName() + "." + name); .lookupImplicitMethod(clazz.getName() + "." + name);
if (variable instanceof Method) { if (variable instanceof Method) {
return (Method) variable; return (Method) variable;
} }
} }
return null; return null;
} }
} }

View File

@ -12,28 +12,28 @@ import java.util.Set;
final class ImplicitMethods { final class ImplicitMethods {
public static <T> Set<T> distinct(final List<? extends T> list) { public static <T> Set<T> distinct(final List<? extends T> list) {
return unmodifiableSet(new HashSet<T>(list)); return unmodifiableSet(new HashSet<T>(list));
} }
public static <T extends Comparable<? super T>> List<T> sorted( public static <T extends Comparable<? super T>> List<T> sorted(
final List<? extends T> list) { final List<? extends T> list) {
List<T> temp = new ArrayList<T>(list); List<T> temp = new ArrayList<T>(list);
Collections.sort(temp); Collections.sort(temp);
return unmodifiableList(temp); return unmodifiableList(temp);
} }
public static <T> List<T> reversed(final List<? extends T> list) { public static <T> List<T> reversed(final List<? extends T> list) {
List<T> temp = new ArrayList<T>(list); List<T> temp = new ArrayList<T>(list);
Collections.reverse(temp); Collections.reverse(temp);
return unmodifiableList(temp); return unmodifiableList(temp);
} }
public static <T> List<T> take(final List<T> list, final int n) { public static <T> List<T> take(final List<T> list, final int n) {
return unmodifiableList(list.subList(0, n)); return unmodifiableList(list.subList(0, n));
} }
public static <T> List<T> drop(final List<T> list, final int n) { public static <T> List<T> drop(final List<T> list, final int n) {
return unmodifiableList(list.subList(n, list.size())); return unmodifiableList(list.subList(n, list.size()));
} }
} }

View File

@ -15,39 +15,39 @@ import org.springframework.util.Assert;
public final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor { public final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor {
private static final ConcurrentHashMap<String, MethodExecutor> cache = private static final ConcurrentHashMap<String, MethodExecutor> cache =
new ConcurrentHashMap<String, MethodExecutor>(); new ConcurrentHashMap<String, MethodExecutor>();
public boolean canRead(final EvaluationContext context, public boolean canRead(final EvaluationContext context,
final Object target, final String name) final Object target, final String name)
throws AccessException { throws AccessException {
Assert.notNull(target, "target is null"); Assert.notNull(target, "target is null");
String cacheKey = target.getClass().getName() + "." + name; String cacheKey = target.getClass().getName() + "." + name;
if (cache.containsKey(cacheKey)) { if (cache.containsKey(cacheKey)) {
return cache.get(cacheKey) != null; return cache.get(cacheKey) != null;
} }
for (MethodResolver mr : context.getMethodResolvers()) { for (MethodResolver mr : context.getMethodResolvers()) {
MethodExecutor me = mr.resolve(context, target, name, new Class[0]); MethodExecutor me = mr.resolve(context, target, name, new Class[0]);
if (me != null) { if (me != null) {
cache.putIfAbsent(cacheKey, me); cache.putIfAbsent(cacheKey, me);
return true; return true;
} }
} }
cache.putIfAbsent(cacheKey, null); cache.putIfAbsent(cacheKey, null);
return false; return false;
} }
public TypedValue read(final EvaluationContext context, public TypedValue read(final EvaluationContext context,
final Object target, final String name) final Object target, final String name)
throws AccessException { throws AccessException {
if (canRead(context, target, name)) { if (canRead(context, target, name)) {
String cacheKey = target.getClass().getName() + "." + name; String cacheKey = target.getClass().getName() + "." + name;
return cache.get(cacheKey).execute(context, target, new Object[0]); return cache.get(cacheKey).execute(context, target, new Object[0]);
} }
throw new AccessException(MessageFormat.format( throw new AccessException(MessageFormat.format(
"Cannot read property: {0} of target: {1}", name, target)); "Cannot read property: {0} of target: {1}", name, target));
} }
} }

View File

@ -5,62 +5,62 @@ import java.util.Set;
final class InheritenceUtil { final class InheritenceUtil {
public static Set<Class<?>> getInheritance(final Class<?> in) { public static Set<Class<?>> getInheritance(final Class<?> in) {
LinkedHashSet<Class<?>> result = new LinkedHashSet<Class<?>>(); LinkedHashSet<Class<?>> result = new LinkedHashSet<Class<?>>();
result.add(in); result.add(in);
getInheritance(in, result); getInheritance(in, result);
return result; return result;
} }
/** /**
* Get inheritance of type. * Get inheritance of type.
* *
* @param in * @param in
* @param result * @param result
*/ */
private static void getInheritance(final Class<?> in, final Set<Class<?>> result) { private static void getInheritance(final Class<?> in, final Set<Class<?>> result) {
Class<?> superclass = getSuperclass(in); Class<?> superclass = getSuperclass(in);
if (superclass != null) { if (superclass != null) {
result.add(superclass); result.add(superclass);
getInheritance(superclass, result); getInheritance(superclass, result);
} }
getInterfaceInheritance(in, result); getInterfaceInheritance(in, result);
} }
/** /**
* Get interfaces that the type inherits from. * Get interfaces that the type inherits from.
* *
* @param in * @param in
* @param result * @param result
*/ */
private static void getInterfaceInheritance(final Class<?> in, private static void getInterfaceInheritance(final Class<?> in,
final Set<Class<?>> result) { final Set<Class<?>> result) {
for (Class<?> c : in.getInterfaces()) { for (Class<?> c : in.getInterfaces()) {
result.add(c); result.add(c);
getInterfaceInheritance(c, result); getInterfaceInheritance(c, result);
} }
} }
/** /**
* Get superclass of class. * Get superclass of class.
* *
* @param in * @param in
* @return * @return
*/ */
private static Class<?> getSuperclass(final Class<?> in) { private static Class<?> getSuperclass(final Class<?> in) {
if (in == null) { if (in == null) {
return null; return null;
} }
if (in.isArray() && in != Object[].class) { if (in.isArray() && in != Object[].class) {
Class<?> type = in.getComponentType(); Class<?> type = in.getComponentType();
while (type.isArray()) { while (type.isArray()) {
type = type.getComponentType(); type = type.getComponentType();
} }
return type; return type;
} }
return in.getSuperclass(); return in.getSuperclass();
} }
} }

View File

@ -7,22 +7,22 @@ import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor; import org.springframework.expression.PropertyAccessor;
public abstract class ReadOnlyGenericPropertyAccessor implements public abstract class ReadOnlyGenericPropertyAccessor implements
PropertyAccessor { PropertyAccessor {
public final boolean canWrite(final EvaluationContext context, public final boolean canWrite(final EvaluationContext context,
final Object target, final String name) throws AccessException { final Object target, final String name) throws AccessException {
return false; return false;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public final Class[] getSpecificTargetClasses() { public final Class[] getSpecificTargetClasses() {
return null; return null;
} }
public final void write(final EvaluationContext context, final Object target, public final void write(final EvaluationContext context, final Object target,
final String name, final Object newValue) throws AccessException { final String name, final Object newValue) throws AccessException {
throw new AccessException(MessageFormat.format( throw new AccessException(MessageFormat.format(
"Cannot write property: {0} of target: {1}", name, target)); "Cannot write property: {0} of target: {1}", name, target));
} }
} }

View File

@ -22,110 +22,110 @@ import org.springframework.util.Assert;
public final class SpelHelper { public final class SpelHelper {
public static final String CONTEXT_LOOKUP_KEY = SpelHelper.class.getName(); public static final String CONTEXT_LOOKUP_KEY = SpelHelper.class.getName();
private static final ExpressionParser PARSER = new SpelExpressionParser(); private static final ExpressionParser PARSER = new SpelExpressionParser();
private static final ThreadLocal<EvaluationContext> currentContext = private static final ThreadLocal<EvaluationContext> currentContext =
new ThreadLocal<EvaluationContext>(); new ThreadLocal<EvaluationContext>();
private volatile EvaluationContext context; private volatile EvaluationContext context;
private final Set<Method> registeredFunctions = new HashSet<Method>(); private final Set<Method> registeredFunctions = new HashSet<Method>();
private final Map<String,Method> registeredMethods = private final Map<String,Method> registeredMethods =
new ConcurrentHashMap<String, Method>(); new ConcurrentHashMap<String, Method>();
private final Map<String,Constructor<?>> registeredConstructors = private final Map<String,Constructor<?>> registeredConstructors =
new ConcurrentHashMap<String, Constructor<?>>(); new ConcurrentHashMap<String, Constructor<?>>();
{ {
registerFunctionsFromClass(ExtensionFunctions.class); registerFunctionsFromClass(ExtensionFunctions.class);
registerImplicitMethodsFromClass(ImplicitMethods.class); registerImplicitMethodsFromClass(ImplicitMethods.class);
} }
public SpelHelper registerImplicitMethodsFromClass(final Class<?> clazz) { public SpelHelper registerImplicitMethodsFromClass(final Class<?> clazz) {
for (Method method : filterMethods(clazz)) { for (Method method : filterMethods(clazz)) {
registeredMethods.put(String.format( registeredMethods.put(String.format(
"%s.%s", method.getParameterTypes()[0].getName(), method.getName()), "%s.%s", method.getParameterTypes()[0].getName(), method.getName()),
method); method);
} }
return this; return this;
} }
public SpelHelper registerFunctionsFromClass(final Class<?> clazz) { public SpelHelper registerFunctionsFromClass(final Class<?> clazz) {
registeredFunctions.addAll(filterMethods(clazz)); registeredFunctions.addAll(filterMethods(clazz));
context = null; context = null;
return this; return this;
} }
public SpelHelper registerImplicitConstructorsFromClass(final Class<?> clazz) { public SpelHelper registerImplicitConstructorsFromClass(final Class<?> clazz) {
for (Constructor<?> constructor : asList(clazz.getConstructors())) { for (Constructor<?> constructor : asList(clazz.getConstructors())) {
registeredConstructors.put( registeredConstructors.put(
constructor.getDeclaringClass().getSimpleName() constructor.getDeclaringClass().getSimpleName()
+ Arrays.toString(constructor.getParameterTypes()), + Arrays.toString(constructor.getParameterTypes()),
constructor); constructor);
} }
return this; return this;
} }
public <T> T evalExpression(final String expressionString, public <T> T evalExpression(final String expressionString,
final Object rootElement, final Class<T> desiredType) { final Object rootElement, final Class<T> desiredType) {
EvaluationContext evaluationContext = getEvaluationContext(rootElement); EvaluationContext evaluationContext = getEvaluationContext(rootElement);
currentContext.set(evaluationContext); currentContext.set(evaluationContext);
T value = evalExpression(expressionString, evaluationContext, desiredType); T value = evalExpression(expressionString, evaluationContext, desiredType);
currentContext.set(null); currentContext.set(null);
return value; return value;
} }
public <T> T evalExpression(final String expressionString, public <T> T evalExpression(final String expressionString,
final EvaluationContext evaluationContext, final Class<T> desiredType) { final EvaluationContext evaluationContext, final Class<T> desiredType) {
return PARSER.parseExpression(expressionString) return PARSER.parseExpression(expressionString)
.getValue(evaluationContext, desiredType); .getValue(evaluationContext, desiredType);
} }
public <T> T evalExpressions(final String[] expressionStrings, public <T> T evalExpressions(final String[] expressionStrings,
final Object rootElement, final Class<T> desiredType) { final Object rootElement, final Class<T> desiredType) {
int length = expressionStrings.length; int length = expressionStrings.length;
Assert.isTrue(length > 0, Assert.isTrue(length > 0,
"expressionStrings should have length more than 0"); "expressionStrings should have length more than 0");
for (int i = 0; i < length - 1; i++) { for (int i = 0; i < length - 1; i++) {
evalExpression(expressionStrings[i], rootElement, Object.class); evalExpression(expressionStrings[i], rootElement, Object.class);
} }
return evalExpression(expressionStrings[length - 1], return evalExpression(expressionStrings[length - 1],
rootElement, desiredType); rootElement, desiredType);
} }
private EvaluationContext getEvaluationContext(final Object rootObject) { private EvaluationContext getEvaluationContext(final Object rootObject) {
if (context == null) { if (context == null) {
synchronized (PARSER) { synchronized (PARSER) {
if (context == null) { if (context == null) {
StandardEvaluationContext newContext = new StandardEvaluationContext(rootObject); StandardEvaluationContext newContext = new StandardEvaluationContext(rootObject);
newContext.getMethodResolvers().add(new ImplicitMethodResolver()); newContext.getMethodResolvers().add(new ImplicitMethodResolver());
newContext.getPropertyAccessors().add(new ImplicitPropertyAccessor()); newContext.getPropertyAccessors().add(new ImplicitPropertyAccessor());
newContext.setConstructorResolvers( newContext.setConstructorResolvers(
asList((ConstructorResolver) new ImplicitConstructorResolver())); asList((ConstructorResolver) new ImplicitConstructorResolver()));
for (Method method : registeredFunctions) { for (Method method : registeredFunctions) {
newContext.setVariable(method.getName(), method); newContext.setVariable(method.getName(), method);
} }
newContext.setVariable(CONTEXT_LOOKUP_KEY, this); newContext.setVariable(CONTEXT_LOOKUP_KEY, this);
context = newContext; context = newContext;
} }
} }
} }
return context; return context;
}
public Method lookupImplicitMethod(final String lookup) {
Assert.notNull(lookup);
return registeredMethods.get(lookup);
} }
public Constructor<?> lookupImplicitConstructor(final String lookup) { public Method lookupImplicitMethod(final String lookup) {
Assert.notNull(lookup); Assert.notNull(lookup);
return registeredConstructors.get(lookup); return registeredMethods.get(lookup);
} }
public static EvaluationContext getCurrentContext() { public Constructor<?> lookupImplicitConstructor(final String lookup) {
return currentContext.get(); Assert.notNull(lookup);
} return registeredConstructors.get(lookup);
}
public static EvaluationContext getCurrentContext() {
return currentContext.get();
}
private static List<Method> filterMethods(final Class<?> clazz) { private static List<Method> filterMethods(final Class<?> clazz) {
List<Method> allowedMethods = new ArrayList<Method>(); List<Method> allowedMethods = new ArrayList<Method>();

View File

@ -8,36 +8,36 @@ import org.junit.Test;
public class SpelHelperTest { public class SpelHelperTest {
@Test @Test
public void testRegisteredFunction() { public void testRegisteredFunction() {
Assert.assertEquals( Assert.assertEquals(
Arrays.asList("abhinav", "mini", "dan"), Arrays.asList("abhinav", "mini", "dan"),
new SpelHelper().evalExpression( new SpelHelper().evalExpression(
"#list('abhinav','mini','dan')", new Object(), List.class)); "#list('abhinav','mini','dan')", new Object(), List.class));
} }
@Test @Test
public void testImplicitMethod() { public void testImplicitMethod() {
Assert.assertEquals( Assert.assertEquals(
Arrays.asList("abhinav", "dan", "mini"), Arrays.asList("abhinav", "dan", "mini"),
new SpelHelper().evalExpression( new SpelHelper().evalExpression(
"#list('abhinav','mini','dan').sorted", new Object(), List.class)); "#list('abhinav','mini','dan').sorted", new Object(), List.class));
} }
public static final class ConstructorTest { public static final class ConstructorTest {
@Override @Override
public boolean equals(final Object o) { public boolean equals(final Object o) {
return o instanceof ConstructorTest; return o instanceof ConstructorTest;
} }
} }
@Test @Test
public void testImplicitConstructor() { public void testImplicitConstructor() {
Assert.assertEquals( Assert.assertEquals(
new ConstructorTest(), new ConstructorTest(),
new SpelHelper() new SpelHelper()
.registerImplicitConstructorsFromClass(ConstructorTest.class) .registerImplicitConstructorsFromClass(ConstructorTest.class)
.evalExpression("new ConstructorTest()", new Object(), ConstructorTest.class)); .evalExpression("new ConstructorTest()", new Object(), ConstructorTest.class));
} }
} }