From 97f9b8e61851488d2a87efceb5146c898fbbf998 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 9 Dec 2009 16:55:34 +0000 Subject: [PATCH] internal refactoring --- .../handler/ArgumentArrayMessageMapper.java | 201 ++++++++---------- 1 file changed, 93 insertions(+), 108 deletions(-) diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/handler/ArgumentArrayMessageMapper.java b/org.springframework.integration/src/main/java/org/springframework/integration/handler/ArgumentArrayMessageMapper.java index 477c37ad83..2bad588730 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/handler/ArgumentArrayMessageMapper.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/handler/ArgumentArrayMessageMapper.java @@ -19,6 +19,7 @@ package org.springframework.integration.handler; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Date; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; @@ -29,7 +30,6 @@ import org.springframework.context.expression.MapAccessor; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.core.MethodParameter; import org.springframework.core.ParameterNameDiscoverer; -import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.converter.Converter; @@ -155,19 +155,18 @@ public class ArgumentArrayMessageMapper implements InboundMessageMapper messageArgumentsMap = this.mapArgumentsToMessage(arguments, null); - return this.buildMessageFromArgumentMap(messageArgumentsMap); + return this.mapArgumentsToMessage(arguments); } private Object[] mapMessageToArguments(Message message) { final Map messageArgumentsMap = new LinkedHashMap(); for (MethodParameter methodParameter : this.parameterList) { String parameterName = methodParameter.getParameterName(); - String[] expressions = null; Annotation mappingAnnotation = null; Object value = null; mappingAnnotation = this.findMappingAnnotation(methodParameter.getParameterAnnotations()); if (mappingAnnotation == null) { + String[] expressions = null; if ("headers".equals(parameterName) || "payload".equals(parameterName)) { expressions = new String[] { parameterName }; } @@ -181,14 +180,15 @@ public class ArgumentArrayMessageMapper implements InboundMessageMapper mapArgumentsToMessage(Object[] arguments) { + Object messageOrPayload = null; + boolean foundPayloadAnnotation = false; + Map headers = new HashMap(); + for (int i = 0; i < this.parameterList.size(); i++) { + Object argumentValue = arguments[i]; + MethodParameter methodParameter = (MethodParameter) this.parameterList.get(i); + Annotation annotation = this.findMappingAnnotation(methodParameter.getParameterAnnotations()); + if (annotation != null) { + if (annotation.annotationType().equals(Payload.class)) { + if (((Payload) annotation).value().length() != 0) { + throw new MessagingException( + "The Payload annotation does not support an expression when mapping to a Message."); + } + if (messageOrPayload != null) { + this.throwExceptionForMultipleMessageOrPayloadParameters(methodParameter); + } + foundPayloadAnnotation = true; + messageOrPayload = argumentValue; + } + else if (annotation.annotationType().equals(Header.class)) { + Header headerAnnotation = (Header) annotation; + String headerName = this.determineHeaderName(headerAnnotation, methodParameter); + if (headerAnnotation.required() && argumentValue == null) { + throw new IllegalArgumentException("Received null argument value for required header: '" + headerName + "'"); + } + headers.put(headerName, argumentValue); + } + else if (annotation.annotationType().equals(Headers.class)) { + if (argumentValue != null) { + if (!(argumentValue instanceof Map)) { + throw new IllegalArgumentException("@Headers annotation is only valid for Map-typed parameters"); + } + for (Object key : ((Map) argumentValue).keySet()) { + Assert.isInstanceOf(String.class, key, "Invalid header name [" + key + + "], name type must be String."); + Object value = ((Map) argumentValue).get(key); + headers.put((String) key, value); + } + } + } + } + else if (messageOrPayload == null) { + messageOrPayload = argumentValue; + } + else if (Map.class.isAssignableFrom(methodParameter.getParameterType())) { + if (messageOrPayload instanceof Map && !foundPayloadAnnotation) { + throw new MessagingException("Ambiguous method parameters; found more than one " + + "Map-typed parameter and neither one contains a @Payload annotation"); + } + this.copyHeaders((Map) argumentValue, headers); + } + else { + this.throwExceptionForMultipleMessageOrPayloadParameters(methodParameter); + } + } + Assert.isTrue(messageOrPayload != null, "unable to determine a Message or payload parameter on method [" + method + "]"); + MessageBuilder builder = (messageOrPayload instanceof Message) + ? MessageBuilder.fromMessage((Message) messageOrPayload) + : MessageBuilder.withPayload(messageOrPayload); + builder.copyHeadersIfAbsent(headers); + return builder.build(); + } + private Annotation findMappingAnnotation(Annotation[] annotations) { if (annotations == null || annotations.length == 0) { return null; @@ -226,64 +291,15 @@ public class ArgumentArrayMessageMapper implements InboundMessageMapper mapArgumentsToMessage(Object[] arguments, Message message) { - MethodParameter messageOrPayloadParameter = null; - Map messageArgumentsMap = new LinkedHashMap(); - for (int i = 0; i < this.parameterList.size(); i++) { - Object argumentValue = arguments[i]; - MethodParameter methodParameter = (MethodParameter) this.parameterList.get(i); - Annotation annotation = this.findMappingAnnotation(methodParameter.getParameterAnnotations()); - if (annotation != null) { - if (annotation.annotationType().equals(Payload.class)) { - if (((Payload) annotation).value().length() != 0) { - throw new MessagingException( - "The Payload annotation does not support an expression when mapping to a Message."); - } - messageArgumentsMap.put("payload", argumentValue); - if (messageOrPayloadParameter != null) { - this.throwExceptionForMultipleMessageOrPayloadParameters(methodParameter); - } - messageOrPayloadParameter = methodParameter; - } - else if (annotation.annotationType().equals(Header.class)) { - Object[] header = this.mapHeaderThruAnnotation(annotation, message, methodParameter, argumentValue); - messageArgumentsMap.put((String) header[0], header[1]); - } - else if (annotation.annotationType().equals(Headers.class)) { - if (argumentValue != null) { - messageArgumentsMap.putAll(((Map) argumentValue)); - for (Object key : ((Map) argumentValue).keySet()) { - Assert.isInstanceOf(String.class, key, "Invalid header name [" + key + - "], name type must be String."); - Object value = ((Map) argumentValue).get(key); - messageArgumentsMap.put((String) key, value); - } - } - } - } - else if (messageOrPayloadParameter == null) { - if (argumentValue instanceof Message) { - messageArgumentsMap.put("message", argumentValue); - } - else { - messageArgumentsMap.put("payload", argumentValue); - } - messageOrPayloadParameter = methodParameter; - } - else if (Map.class.isAssignableFrom(methodParameter.getParameterType())) { - if (Map.class.isAssignableFrom(messageOrPayloadParameter.getParameterType()) - && messageOrPayloadParameter.getParameterAnnotation(Payload.class) == null) { - throw new MessagingException("Ambiguous method parameters; found more than one " + - "Map-typed parameter and neither one contains a @Payload annotation"); - } - messageArgumentsMap.put("headers", argumentValue); - } - else { - this.throwExceptionForMultipleMessageOrPayloadParameters(methodParameter); + private void copyHeaders(Map argumentValue, Map headers) { + for (Object key : argumentValue.keySet()) { + if (!(key instanceof String)) { + throw new IllegalArgumentException("Invalid header name [" + key + + "], name type must be String."); } + Object value = argumentValue.get(key); + headers.put((String) key, value); } - Assert.isTrue(messageOrPayloadParameter != null, "unable to determine a Message or payload parameter on method [" + method + "]"); - return messageArgumentsMap; } private void throwExceptionForMultipleMessageOrPayloadParameters(MethodParameter methodParameter) { @@ -292,55 +308,24 @@ public class ArgumentArrayMessageMapper implements InboundMessageMapper buildMessageFromArgumentMap(Map messageArgumentsMap) { - MessageBuilder builder = null; - Message message = (Message) messageArgumentsMap.get("message"); - if (message != null) { - builder = MessageBuilder.fromMessage(message); - } - else { - builder = MessageBuilder.withPayload(messageArgumentsMap.get("payload")); - } - Object headers = messageArgumentsMap.get("headers"); - if (headers != null && headers instanceof Map) { - builder.copyHeadersIfAbsent((Map) headers); - } - for (Object headerName : messageArgumentsMap.keySet()) { - if (!headerName.equals("payload") && !headerName.equals("message") && !headerName.equals("headers")) { - // everything else is a header - builder.setHeader((String) headerName, messageArgumentsMap.get(headerName)); - } - } - return builder.build(); - } - - /** - * @param header - * @param message - * @param methodParameter - * @param headerValue = will be present when mapping from Arg to Message and will be null the other way - * @return - */ - private Object[] mapHeaderThruAnnotation(Annotation header, Message message, MethodParameter methodParameter, Object headerValue) { - String valueAttribute = (String) AnnotationUtils.getValue(header); - String headerName = StringUtils.hasText(valueAttribute) ? valueAttribute : methodParameter.getParameterName(); - Assert.notNull(headerName, "Cannot determine header name. Possible reasons: -debug is " + - "disabled or header name is not explicitly provided via @Header annotation."); + private Object[] retrieveHeaderFromMessage(Header headerAnnotation, Message message, MethodParameter methodParameter) { + Object headerValue = null; + String headerName = this.determineHeaderName(headerAnnotation, methodParameter); if (message != null) { headerValue = this.getValueFromMessageBasedOnEL(message, methodParameter.getParameterType(), false, "headers." + headerName); } - this.evaluateHeader(header, headerName, headerValue, message); - return new Object[]{headerName, headerValue}; + if (headerAnnotation.required() && headerValue == null) { + throw new MessageHandlingException(message, "Message is missing required header: '" + headerName + "'"); + } + return new Object[] {headerName, headerValue}; } - private void evaluateHeader(Annotation headerAnnotation, String headerName, Object headerValue, Message message) { - boolean required = ((Boolean) AnnotationUtils.getAnnotationAttributes(headerAnnotation).get("required")).booleanValue(); - if (required && headerValue == null) { - if (message != null) { - throw new MessageHandlingException(message, "Message is missing required header: '" + headerName + "'"); - } - throw new IllegalArgumentException("Argument is missing required header: '" + headerName + "'"); - } + private String determineHeaderName(Header headerAnnotation, MethodParameter methodParameter) { + String valueAttribute = headerAnnotation.value(); + String headerName = StringUtils.hasText(valueAttribute) ? valueAttribute : methodParameter.getParameterName(); + Assert.notNull(headerName, "Cannot determine header name. Possible reasons: -debug is " + + "disabled or header name is not explicitly provided via @Header annotation."); + return headerName; } @SuppressWarnings("unchecked")