From 9c615030327360d4b283f01ffc647154db8f7acb Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 19 Feb 2010 23:52:28 +0000 Subject: [PATCH] INT-991 Now using Spring 3.0.1 SpEL MethodFilters --- .../FilteringReflectiveMethodResolver.java | 158 ------------------ .../handler/FixedHandlerMethodFilter.java | 19 ++- .../handler/HandlerMethodFilter.java | 8 +- .../integration/handler/MethodFilter.java | 31 ---- .../MethodInvokingMessageProcessor.java | 18 +- 5 files changed, 25 insertions(+), 209 deletions(-) delete mode 100644 org.springframework.integration/src/main/java/org/springframework/integration/handler/FilteringReflectiveMethodResolver.java delete mode 100644 org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodFilter.java diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/FilteringReflectiveMethodResolver.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/FilteringReflectiveMethodResolver.java deleted file mode 100644 index 2394e73856..0000000000 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/FilteringReflectiveMethodResolver.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2002-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.integration.handler; - -import java.lang.reflect.Method; - -import org.springframework.core.MethodParameter; -import org.springframework.core.convert.TypeDescriptor; -import org.springframework.expression.AccessException; -import org.springframework.expression.EvaluationContext; -import org.springframework.expression.EvaluationException; -import org.springframework.expression.MethodExecutor; -import org.springframework.expression.MethodResolver; -import org.springframework.expression.TypeConverter; -import org.springframework.expression.TypedValue; -import org.springframework.expression.spel.SpelEvaluationException; -import org.springframework.expression.spel.SpelMessage; -import org.springframework.expression.spel.support.ReflectionHelper; -import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; - -/** - * An adaptation of the SpEL ReflectiveMethodResolver with the simple addition of a {@link MethodFilter}. - * - * @author Andy Clement - * @author Mark Fisher - * @since 2.0 - */ -class FilteringReflectiveMethodResolver implements MethodResolver { - - private final MethodFilter methodFilter; - - private final Class[] filteredTypes; - - - public FilteringReflectiveMethodResolver(MethodFilter methodFilter, Class ... filteredTypes) { - Assert.notNull(methodFilter, "methodFilter must not be null"); - this.methodFilter = methodFilter; - this.filteredTypes = filteredTypes; - } - - - public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, Class[] argumentTypes) throws AccessException { - try { - TypeConverter typeConverter = context.getTypeConverter(); - Class type = (targetObject instanceof Class ? (Class) targetObject : targetObject.getClass()); - - // this is the only addition for this implementation: - Method[] methods = ObjectUtils.containsElement(this.filteredTypes, type) ? - this.methodFilter.filter(type.getMethods()) : type.getMethods(); - - Method closeMatch = null; - int[] argsToConvert = null; - boolean multipleOptions = false; - Method matchRequiringConversion = null; - for (Method method : methods) { - if (method.isBridge()) { - continue; - } - if (method.getName().equals(name)) { - ReflectionHelper.ArgumentsMatchInfo matchInfo = null; - if (method.isVarArgs() && argumentTypes.length >= (method.getParameterTypes().length - 1)) { - // *sigh* complicated - matchInfo = ReflectionHelper.compareArgumentsVarargs(method.getParameterTypes(), argumentTypes, typeConverter); - } else if (method.getParameterTypes().length == argumentTypes.length) { - // name and parameter number match, check the arguments - matchInfo = ReflectionHelper.compareArguments(method.getParameterTypes(), argumentTypes, typeConverter); - } - if (matchInfo != null) { - if (matchInfo.kind == ReflectionHelper.ArgsMatchKind.EXACT) { - return new ReflectiveMethodExecutor(method, null); - } - else if (matchInfo.kind == ReflectionHelper.ArgsMatchKind.CLOSE) { - closeMatch = method; - } - else if (matchInfo.kind == ReflectionHelper.ArgsMatchKind.REQUIRES_CONVERSION) { - if (matchRequiringConversion != null) { - multipleOptions = true; - } - argsToConvert = matchInfo.argsRequiringConversion; - matchRequiringConversion = method; - } - } - } - } - if (closeMatch != null) { - return new ReflectiveMethodExecutor(closeMatch, null); - } - else if (matchRequiringConversion != null) { - if (multipleOptions) { - throw new SpelEvaluationException(SpelMessage.MULTIPLE_POSSIBLE_METHODS, name); - } - return new ReflectiveMethodExecutor(matchRequiringConversion, argsToConvert); - } - else { - return null; - } - } - catch (EvaluationException ex) { - throw new AccessException("Failed to resolve method", ex); - } - } - - - /** - * This class is copied also, since the original has package-only access. - * - * @author Andy Clement - */ - private static class ReflectiveMethodExecutor implements MethodExecutor { - - private final Method method; - - // When the method was found, we will have determined if arguments need to be converted for it - // to be invoked. Conversion won't be cheap so let's only do it if necessary. - private final int[] argsRequiringConversion; - - - public ReflectiveMethodExecutor(Method theMethod, int[] argumentsRequiringConversion) { - this.method = theMethod; - this.argsRequiringConversion = argumentsRequiringConversion; - } - - - public TypedValue execute(EvaluationContext context, Object target, Object... arguments) throws AccessException { - try { - if (this.argsRequiringConversion != null && arguments != null) { - ReflectionHelper.convertArguments(this.method.getParameterTypes(), this.method.isVarArgs(), - context.getTypeConverter(), this.argsRequiringConversion, arguments); - } - if (this.method.isVarArgs()) { - arguments = ReflectionHelper.setupArgumentsForVarargsInvocation(this.method.getParameterTypes(), arguments); - } - ReflectionUtils.makeAccessible(this.method); - return new TypedValue(this.method.invoke(target, arguments), new TypeDescriptor(new MethodParameter(method,-1))); - } catch (Exception ex) { - throw new AccessException("Problem invoking method: " + this.method, ex); - } - } - - } - -} diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/FixedHandlerMethodFilter.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/FixedHandlerMethodFilter.java index 476f47ae9a..7bdfa9e014 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/FixedHandlerMethodFilter.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/handler/FixedHandlerMethodFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,11 +17,18 @@ package org.springframework.integration.handler; import java.lang.reflect.Method; +import java.util.Collections; +import java.util.List; +import org.springframework.expression.MethodFilter; import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; /** + * A {@link MethodFilter} implementation that will always return + * the same Method instance within a single-element list if it is + * present in the candidate list. If the Method is not present + * in the candidate list, it will return an empty list. + * * @author Mark Fisher * @since 2.0 */ @@ -36,11 +43,11 @@ class FixedHandlerMethodFilter implements MethodFilter { } - public Method[] filter(Method[] methods) { - if (ObjectUtils.containsElement(methods, this.method)) { - return new Method[] { this.method }; + public List filter(List methods) { + if (methods != null && methods.contains(this.method)) { + return Collections.singletonList(this.method); } - return new Method[0]; + return Collections.emptyList(); } } diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/HandlerMethodFilter.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/HandlerMethodFilter.java index 74a4323438..5dcd282ce7 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/HandlerMethodFilter.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/handler/HandlerMethodFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.expression.MethodFilter; import org.springframework.util.StringUtils; /** @@ -52,7 +53,7 @@ class HandlerMethodFilter implements MethodFilter { } - public Method[] filter(Method[] methods) { + public List filter(List methods) { List annotatedCandidates = new ArrayList(); List fallbackCandidates = new ArrayList(); for (Method method : methods) { @@ -72,8 +73,7 @@ class HandlerMethodFilter implements MethodFilter { fallbackCandidates.add(method); } } - return (!annotatedCandidates.isEmpty() ? annotatedCandidates.toArray(new Method[annotatedCandidates.size()]) - : fallbackCandidates.toArray(new Method[fallbackCandidates.size()])); + return (!annotatedCandidates.isEmpty()) ? annotatedCandidates : fallbackCandidates; } } diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodFilter.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodFilter.java deleted file mode 100644 index 393e93d63c..0000000000 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodFilter.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2009 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.integration.handler; - -import java.lang.reflect.Method; - -/** - * Strategy interface for filtering the available Methods prior to resolution. - * - * @author Mark Fisher - * @since 2.0 - */ -interface MethodFilter { - - Method[] filter(Method[] methods); - -} diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java index 28ac4b2d23..9811327d4b 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/handler/MethodInvokingMessageProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.aop.support.AopUtils; import org.springframework.context.expression.MapAccessor; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; @@ -106,7 +107,7 @@ public class MethodInvokingMessageProcessor implements MessageProcessor { Assert.notNull(targetObject, "targetObject must not be null"); this.targetObject = targetObject; this.handlerMethods = Collections., HandlerMethod>singletonMap(handlerMethod.getTargetParameterType(), handlerMethod); - this.evaluationContext = this.createEvaluationContext(targetObject, method, annotationType); + this.evaluationContext = this.createEvaluationContext(method, annotationType); this.setDisplayString(targetObject, method); } @@ -119,7 +120,7 @@ public class MethodInvokingMessageProcessor implements MessageProcessor { this.targetObject = targetObject; this.requiresReply = requiresReply; this.handlerMethods = this.findHandlerMethodsForTarget(targetObject, annotationType, methodName, requiresReply); - this.evaluationContext = this.createEvaluationContext(targetObject, methodName, annotationType); + this.evaluationContext = this.createEvaluationContext(methodName, annotationType); this.setDisplayString(targetObject, methodName); } @@ -135,18 +136,15 @@ public class MethodInvokingMessageProcessor implements MessageProcessor { this.displayString = sb.toString() + "]"; } - private EvaluationContext createEvaluationContext(Object targetObject, Object method, Class annotationType) { + private EvaluationContext createEvaluationContext(Object method, Class annotationType) { StandardEvaluationContext context = new StandardEvaluationContext(); - // TODO: StandardEvaluationContext may soon provide a better way to *replace* the MethodResolver - context.getMethodResolvers().clear(); Class targetType = AopUtils.getTargetClass(this.targetObject); if (method instanceof Method) { - context.getMethodResolvers().add(new FilteringReflectiveMethodResolver( - new FixedHandlerMethodFilter((Method) method), targetType)); + context.registerMethodFilter(targetType, new FixedHandlerMethodFilter((Method) method)); } else if (method == null || method instanceof String) { - context.getMethodResolvers().add(new FilteringReflectiveMethodResolver( - new HandlerMethodFilter(annotationType, (String) method, this.requiresReply), targetType)); + context.registerMethodFilter(targetType, + new HandlerMethodFilter(annotationType, (String) method, this.requiresReply)); } context.addPropertyAccessor(new MapAccessor()); // TODO: Enable configuration of an integration ConversionService bean to be used here,