diff --git a/.gitignore b/.gitignore index d472d78..d92172f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ target/* +.pmd diff --git a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethodResolver.java b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethodResolver.java index a5ae9cb..a3c49b7 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethodResolver.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethodResolver.java @@ -30,7 +30,7 @@ import org.springframework.expression.spel.support.ReflectiveMethodResolver; final class ImplicitMethodResolver implements MethodResolver { - private static final ConcurrentHashMap cache = + private static final ConcurrentHashMap CACHE = new ConcurrentHashMap(); private static final MethodExecutor NULL_ME = new MethodExecutor() { @@ -44,7 +44,7 @@ final class ImplicitMethodResolver implements MethodResolver { MethodExecutor { private final MethodExecutor executor; - private ImplicitMethodExecutor(final MethodExecutor executor) { + public ImplicitMethodExecutor(final MethodExecutor executor) { this.executor = executor; } @@ -65,8 +65,8 @@ final class ImplicitMethodResolver implements MethodResolver { } Class type = targetObject.getClass(); String cacheKey = type.getName() + "." + name; - if (cache.containsKey(cacheKey)) { - MethodExecutor executor = cache.get(cacheKey); + if (CACHE.containsKey(cacheKey)) { + MethodExecutor executor = CACHE.get(cacheKey); return executor == NULL_ME ? null : executor; } @@ -75,25 +75,24 @@ final class ImplicitMethodResolver implements MethodResolver { int modifiers = method.getModifiers(); if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)) { Class[] parameterTypes = method.getParameterTypes(); - Class firstParameterType = parameterTypes[0]; + Class firstParamType = parameterTypes[0]; if (parameterTypes.length > 0 - && firstParameterType.isAssignableFrom(type)) { - - Class[] modifiedArgumentTypes = new Class[argumentTypes.length + 1]; - modifiedArgumentTypes[0] = firstParameterType; - System.arraycopy(argumentTypes, 0, modifiedArgumentTypes, + && firstParamType.isAssignableFrom(type)) { + Class[] newArgumentTypes = new Class[argumentTypes.length + 1]; + newArgumentTypes[0] = firstParamType; + System.arraycopy(argumentTypes, 0, newArgumentTypes, 1, argumentTypes.length); MethodExecutor executor = new ReflectiveMethodResolver() .resolve(context, method.getDeclaringClass(), name, - modifiedArgumentTypes); + newArgumentTypes); MethodExecutor wrappedExecutor = executor == null ? null : new ImplicitMethodExecutor(executor); - cache.putIfAbsent(cacheKey, wrappedExecutor); + CACHE.putIfAbsent(cacheKey, wrappedExecutor); return wrappedExecutor; } } } - cache.putIfAbsent(cacheKey, NULL_ME); + CACHE.putIfAbsent(cacheKey, NULL_ME); return null; } diff --git a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethods.java b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethods.java index e2109bb..4eb33d8 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethods.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitMethods.java @@ -33,6 +33,9 @@ import java.util.Set; */ public final class ImplicitMethods { + private ImplicitMethods() { + } + /** * Provides implicit method `distinct` on the {@link List} class. * diff --git a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitPropertyAccessor.java b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitPropertyAccessor.java index a06a760..bdb98ce 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/ImplicitPropertyAccessor.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/ImplicitPropertyAccessor.java @@ -29,7 +29,7 @@ import org.springframework.util.Assert; final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor { - private static final ConcurrentHashMap cache = + private static final ConcurrentHashMap CACHE = new ConcurrentHashMap(); public boolean canRead(final EvaluationContext context, @@ -37,19 +37,19 @@ final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor { throws AccessException { Assert.notNull(target, "target is null"); String cacheKey = target.getClass().getName() + "." + name; - if (cache.containsKey(cacheKey)) { - return cache.get(cacheKey) != null; + if (CACHE.containsKey(cacheKey)) { + return CACHE.get(cacheKey) != null; } for (MethodResolver mr : context.getMethodResolvers()) { MethodExecutor me = mr.resolve(context, target, name, new Class[0]); if (me != null) { - cache.putIfAbsent(cacheKey, me); + CACHE.putIfAbsent(cacheKey, me); return true; } } - cache.putIfAbsent(cacheKey, null); + CACHE.putIfAbsent(cacheKey, null); return false; } @@ -58,7 +58,7 @@ final class ImplicitPropertyAccessor extends ReadOnlyGenericPropertyAccessor { throws AccessException { if (canRead(context, target, 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( "Cannot read property: {0} of target: {1}", name, target)); diff --git a/src/main/java/net/abhinavsarkar/spelhelper/InheritenceUtil.java b/src/main/java/net/abhinavsarkar/spelhelper/InheritenceUtil.java index 7555664..4a183a5 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/InheritenceUtil.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/InheritenceUtil.java @@ -22,39 +22,42 @@ import java.util.Set; final class InheritenceUtil { - public static Set> getInheritance(final Class in) { + private InheritenceUtil() { + } + + public static Set> getInheritance(final Class clazz) { LinkedHashSet> result = new LinkedHashSet>(); - result.add(in); - getInheritance(in, result); + result.add(clazz); + getInheritance(clazz, result); return result; } /** * Get inheritance of type. * - * @param in + * @param clazz * @param result */ - private static void getInheritance(final Class in, final Set> result) { - Class superclass = getSuperclass(in); + private static void getInheritance(final Class clazz, final Set> result) { + Class superclass = getSuperclass(clazz); if (superclass != null) { result.add(superclass); getInheritance(superclass, result); } - getInterfaceInheritance(in, result); + getInterfaceInheritance(clazz, result); } /** * Get interfaces that the type inherits from. * - * @param in + * @param clazz * @param result */ - private static void getInterfaceInheritance(final Class in, + private static void getInterfaceInheritance(final Class clazz, final Set> result) { - for (Class c : in.getInterfaces()) { + for (Class c : clazz.getInterfaces()) { result.add(c); getInterfaceInheritance(c, result); } @@ -63,21 +66,21 @@ final class InheritenceUtil { /** * Get superclass of class. * - * @param in + * @param clazz * @return */ - private static Class getSuperclass(final Class in) { - if (in == null) { + private static Class getSuperclass(final Class clazz) { + if (clazz == null) { return null; } - if (in.isArray() && in != Object[].class) { - Class type = in.getComponentType(); + if (clazz.isArray() && clazz != Object[].class) { + Class type = clazz.getComponentType(); while (type.isArray()) { type = type.getComponentType(); } return type; } - return in.getSuperclass(); + return clazz.getSuperclass(); } } diff --git a/src/main/java/net/abhinavsarkar/spelhelper/SpelHelper.java b/src/main/java/net/abhinavsarkar/spelhelper/SpelHelper.java index 6713415..644e4b3 100644 --- a/src/main/java/net/abhinavsarkar/spelhelper/SpelHelper.java +++ b/src/main/java/net/abhinavsarkar/spelhelper/SpelHelper.java @@ -126,10 +126,10 @@ public final class SpelHelper { static final String CONTEXT_LOOKUP_KEY = SpelHelper.class.getName(); private static final ExpressionParser PARSER = new SpelExpressionParser(); - private static final ThreadLocal currentContext = + private static final ThreadLocal CURRENT_CONTEXT = new ThreadLocal(); - private volatile EvaluationContext context; + private EvaluationContext context; private final Set registeredFunctions = new HashSet(); private final Map registeredMethods = new ConcurrentHashMap(); @@ -177,7 +177,9 @@ public final class SpelHelper { */ public SpelHelper registerFunctionsFromClass(final Class clazz) { registeredFunctions.addAll(filterFunctions(clazz)); - context = null; + synchronized (PARSER) { + context = null; + } return this; } @@ -214,9 +216,9 @@ public final class SpelHelper { public T evalExpression(final String expressionString, final Object rootElement, final Class desiredType) { EvaluationContext evaluationContext = getEvaluationContext(rootElement); - currentContext.set(evaluationContext); + CURRENT_CONTEXT.set(evaluationContext); T value = evalExpression(expressionString, evaluationContext, desiredType); - currentContext.set(null); + CURRENT_CONTEXT.set(null); return value; } @@ -320,7 +322,7 @@ public final class SpelHelper { * Looks up an implicit constructor registered with this instance. * @param lookup key to lookup which should be of form: * `constructor.getDeclaringClass().getSimpleName()` - * `+ Arrays.toString(constructor.getParameterTypes())` + * `+ Arrays.toString(constructor.getParameterTypes())` * @return The registered constructor if found, else null. */ public Constructor lookupImplicitConstructor(final String lookup) { @@ -333,7 +335,7 @@ public final class SpelHelper { * @return The current evaluation context. */ public static EvaluationContext getCurrentContext() { - return currentContext.get(); + return CURRENT_CONTEXT.get(); } private static List filterMethods(final Class clazz) {