INT-1382 added support for 'expression' sub-elements in the core schema
This commit is contained in:
@@ -16,8 +16,13 @@
|
||||
|
||||
package org.springframework.integration.aggregator;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.SpelParserConfiguration;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link CorrelationStrategy} implementation that evaluates an expression.
|
||||
@@ -26,12 +31,23 @@ import org.springframework.integration.handler.ExpressionEvaluatingMessageProces
|
||||
*/
|
||||
public class ExpressionEvaluatingCorrelationStrategy implements CorrelationStrategy {
|
||||
|
||||
private static final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
|
||||
|
||||
private final ExpressionEvaluatingMessageProcessor<Object> processor;
|
||||
|
||||
public ExpressionEvaluatingCorrelationStrategy(String expression) {
|
||||
|
||||
public ExpressionEvaluatingCorrelationStrategy(String expressionString) {
|
||||
Assert.hasText(expressionString, "expressionString must not be empty");
|
||||
Expression expression = expressionParser.parseExpression(expressionString);
|
||||
this.processor = new ExpressionEvaluatingMessageProcessor<Object>(expression, Object.class);
|
||||
}
|
||||
|
||||
public ExpressionEvaluatingCorrelationStrategy(Expression expression) {
|
||||
this.processor = new ExpressionEvaluatingMessageProcessor<Object>(expression, Object.class);
|
||||
}
|
||||
|
||||
|
||||
public Object getCorrelationKey(Message<?> message) {
|
||||
return processor.processMessage(message);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.aggregator;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -15,12 +31,16 @@ import org.springframework.integration.store.MessageGroup;
|
||||
*
|
||||
* @author Alex Peters
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class ExpressionEvaluatingMessageGroupProcessor extends AbstractAggregatingMessageGroupProcessor implements BeanFactoryAware {
|
||||
|
||||
|
||||
private final ExpressionEvaluatingMessageListProcessor processor;
|
||||
|
||||
|
||||
public ExpressionEvaluatingMessageGroupProcessor(String expression) {
|
||||
processor = new ExpressionEvaluatingMessageListProcessor(expression);
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
processor.setBeanFactory(beanFactory);
|
||||
}
|
||||
@@ -33,10 +53,6 @@ public class ExpressionEvaluatingMessageGroupProcessor extends AbstractAggregati
|
||||
processor.setExpectedType(expectedType);
|
||||
}
|
||||
|
||||
public ExpressionEvaluatingMessageGroupProcessor(String expression) {
|
||||
processor = new ExpressionEvaluatingMessageListProcessor(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the expression provided on the unmarked messages (a collection) in the group, and delegate to the
|
||||
* {@link MessagingTemplate} to send downstream.
|
||||
|
||||
@@ -22,6 +22,10 @@ import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.SpelParserConfiguration;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.handler.AbstractMessageHandler;
|
||||
@@ -38,13 +42,16 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
abstract class AbstractMessageHandlerFactoryBean implements FactoryBean<MessageHandler>, BeanFactoryAware {
|
||||
|
||||
private static final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
|
||||
|
||||
private volatile MessageHandler handler;
|
||||
|
||||
private volatile Object targetObject;
|
||||
|
||||
private volatile String targetMethodName;
|
||||
|
||||
private volatile String expression;
|
||||
private volatile Expression expression;
|
||||
|
||||
private volatile MessageChannel outputChannel;
|
||||
|
||||
@@ -65,7 +72,11 @@ abstract class AbstractMessageHandlerFactoryBean implements FactoryBean<MessageH
|
||||
this.targetMethodName = targetMethodName;
|
||||
}
|
||||
|
||||
public void setExpression(String expression) {
|
||||
public void setExpressionString(String expressionString) {
|
||||
this.expression = expressionParser.parseExpression(expressionString);
|
||||
}
|
||||
|
||||
public void setExpression(Expression expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@@ -158,7 +169,7 @@ abstract class AbstractMessageHandlerFactoryBean implements FactoryBean<MessageH
|
||||
*/
|
||||
abstract MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName);
|
||||
|
||||
MessageHandler createExpressionEvaluatingHandler(String expression) {
|
||||
MessageHandler createExpressionEvaluatingHandler(Expression expression) {
|
||||
throw new UnsupportedOperationException(this.getClass().getName() + " does not support expressions.");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.core.MessageSelector;
|
||||
@@ -67,7 +68,7 @@ public class FilterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createExpressionEvaluatingHandler(String expression) {
|
||||
MessageHandler createExpressionEvaluatingHandler(Expression expression) {
|
||||
return this.createFilter(new ExpressionEvaluatingSelector(expression));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.aop.TargetSource;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.router.AbstractChannelNameResolvingMessageRouter;
|
||||
@@ -123,7 +124,7 @@ public class RouterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createExpressionEvaluatingHandler(String expression) {
|
||||
MessageHandler createExpressionEvaluatingHandler(Expression expression) {
|
||||
return this.configureRouter(new ExpressionEvaluatingRouter(expression));
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
|
||||
import org.springframework.integration.handler.MessageProcessor;
|
||||
@@ -51,7 +52,7 @@ public class ServiceActivatorFactoryBean extends AbstractMessageHandlerFactoryBe
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createExpressionEvaluatingHandler(String expression) {
|
||||
MessageHandler createExpressionEvaluatingHandler(Expression expression) {
|
||||
ExpressionEvaluatingMessageProcessor<Object> processor = new ExpressionEvaluatingMessageProcessor<Object>(expression);
|
||||
processor.setBeanFactory(this.getBeanFactory());
|
||||
return this.configureHandler(new ServiceActivatingHandler(processor));
|
||||
|
||||
@@ -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.
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.splitter.AbstractMessageSplitter;
|
||||
import org.springframework.integration.splitter.DefaultMessageSplitter;
|
||||
@@ -31,12 +32,22 @@ import org.springframework.util.StringUtils;
|
||||
public class SplitterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
|
||||
private volatile Long sendTimeout;
|
||||
|
||||
private volatile boolean requiresReply;
|
||||
|
||||
|
||||
public void setSendTimeout(Long sendTimeout) {
|
||||
this.sendTimeout = sendTimeout;
|
||||
}
|
||||
|
||||
public boolean isRequiresReply() {
|
||||
return requiresReply;
|
||||
}
|
||||
|
||||
public void setRequiresReply(boolean requiresReply) {
|
||||
this.requiresReply = requiresReply;
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName) {
|
||||
AbstractMessageSplitter splitter = null;
|
||||
@@ -52,7 +63,7 @@ public class SplitterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createExpressionEvaluatingHandler(String expression) {
|
||||
MessageHandler createExpressionEvaluatingHandler(Expression expression) {
|
||||
return this.configureSplitter(new ExpressionEvaluatingSplitter(expression));
|
||||
}
|
||||
|
||||
@@ -68,11 +79,5 @@ public class SplitterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
splitter.setRequiresReply(requiresReply);
|
||||
return splitter;
|
||||
}
|
||||
public boolean isRequiresReply() {
|
||||
return requiresReply;
|
||||
}
|
||||
|
||||
public void setRequiresReply(boolean requiresReply) {
|
||||
this.requiresReply = requiresReply;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.config;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.transformer.ExpressionEvaluatingTransformer;
|
||||
import org.springframework.integration.transformer.MessageTransformingHandler;
|
||||
@@ -54,7 +55,7 @@ public class TransformerFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createExpressionEvaluatingHandler(String expression) {
|
||||
MessageHandler createExpressionEvaluatingHandler(Expression expression) {
|
||||
Transformer transformer = new ExpressionEvaluatingTransformer(expression);
|
||||
return this.createHandler(transformer);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ abstract class AbstractDelegatingConsumerEndpointParser extends AbstractConsumer
|
||||
|
||||
@Override
|
||||
protected final BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
|
||||
Object source = parserContext.extractSource(element);
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(this.getFactoryBeanClassName());
|
||||
BeanComponentDefinition innerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext);
|
||||
String ref = element.getAttribute(REF_ATTRIBUTE);
|
||||
@@ -45,23 +46,43 @@ abstract class AbstractDelegatingConsumerEndpointParser extends AbstractConsumer
|
||||
boolean hasRef = StringUtils.hasText(ref);
|
||||
boolean hasExpression = StringUtils.hasText(expression);
|
||||
Element scriptElement = DomUtils.getChildElementByTagName(element, "script");
|
||||
Element expressionElement = DomUtils.getChildElementByTagName(element, "expression");
|
||||
if (innerDefinition != null) {
|
||||
if (hasRef || hasExpression) {
|
||||
if (hasRef || hasExpression || expressionElement != null) {
|
||||
parserContext.getReaderContext().error(
|
||||
"Neither 'ref' nor 'expression' are permitted when an inner bean (<bean/>) is configured.", element);
|
||||
"Neither 'ref' nor 'expression' are permitted when an inner bean (<bean/>) is configured.", source);
|
||||
return null;
|
||||
}
|
||||
builder.addPropertyValue("targetObject", innerDefinition);
|
||||
}
|
||||
else if (scriptElement != null) {
|
||||
if (hasRef || hasExpression || expressionElement != null) {
|
||||
parserContext.getReaderContext().error(
|
||||
"Neither 'ref' nor 'expression' are permitted when an inner script element is configured.", source);
|
||||
return null;
|
||||
}
|
||||
BeanDefinition scriptBeanDefinition = parserContext.getDelegate().parseCustomElement(scriptElement, builder.getBeanDefinition());
|
||||
builder.addPropertyValue("targetObject", scriptBeanDefinition);
|
||||
}
|
||||
else if (expressionElement != null) {
|
||||
if (hasRef || hasExpression) {
|
||||
parserContext.getReaderContext().error(
|
||||
"Neither 'ref' nor 'expression' are permitted when an inner 'expression' element is configured.", source);
|
||||
return null;
|
||||
}
|
||||
BeanDefinitionBuilder dynamicExpressionBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.expression.DynamicExpression");
|
||||
String key = expressionElement.getAttribute("key");
|
||||
String expressionSourceReference = expressionElement.getAttribute("source");
|
||||
dynamicExpressionBuilder.addConstructorArgValue(key);
|
||||
dynamicExpressionBuilder.addConstructorArgReference(expressionSourceReference);
|
||||
builder.addPropertyValue("expression", dynamicExpressionBuilder.getBeanDefinition());
|
||||
}
|
||||
else if (hasRef) {
|
||||
builder.addPropertyReference("targetObject", ref);
|
||||
}
|
||||
else if (hasExpression) {
|
||||
builder.addPropertyValue("expression", expression);
|
||||
}
|
||||
else if (scriptElement != null) {
|
||||
BeanDefinition scriptBeanDefinition = parserContext.getDelegate().parseCustomElement(scriptElement, builder.getBeanDefinition());
|
||||
builder.addPropertyValue("targetObject", scriptBeanDefinition);
|
||||
builder.addPropertyValue("expressionString", expression);
|
||||
}
|
||||
else if (!this.hasDefaultOption()) {
|
||||
parserContext.getReaderContext().error("Exactly one of the 'ref' attribute, 'expression' attribute, " +
|
||||
|
||||
@@ -68,15 +68,15 @@ public class DynamicExpression implements Expression {
|
||||
}
|
||||
|
||||
public Object getValue(EvaluationContext context, Object rootObject) throws EvaluationException {
|
||||
return this.getValue(context, rootObject);
|
||||
return this.resolveExpression().getValue(context, rootObject);
|
||||
}
|
||||
|
||||
public <T> T getValue(EvaluationContext context, Class<T> desiredResultType) throws EvaluationException {
|
||||
return this.getValue(context, desiredResultType);
|
||||
return this.resolveExpression().getValue(context, desiredResultType);
|
||||
}
|
||||
|
||||
public <T> T getValue(EvaluationContext context, Object rootObject, Class<T> desiredResultType) throws EvaluationException {
|
||||
return this.getValue(context, rootObject, desiredResultType);
|
||||
return this.resolveExpression().getValue(context, rootObject, desiredResultType);
|
||||
}
|
||||
|
||||
public Class<?> getValueType() throws EvaluationException {
|
||||
@@ -120,7 +120,7 @@ public class DynamicExpression implements Expression {
|
||||
}
|
||||
|
||||
public boolean isWritable(Object rootObject) throws EvaluationException {
|
||||
return this.isWritable(rootObject);
|
||||
return this.resolveExpression().isWritable(rootObject);
|
||||
}
|
||||
|
||||
public void setValue(EvaluationContext context, Object value) throws EvaluationException {
|
||||
@@ -141,7 +141,9 @@ public class DynamicExpression implements Expression {
|
||||
|
||||
private Expression resolveExpression() {
|
||||
Locale locale = LocaleContextHolder.getLocale();
|
||||
return this.expressionSource.getExpression(this.key, locale);
|
||||
Expression expression = this.expressionSource.getExpression(this.key, locale);
|
||||
Assert.state(expression != null, "Unable to resolve Expression with key '" + this.key + "'");
|
||||
return expression;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
package org.springframework.integration.filter;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.SpelParserConfiguration;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.core.MessageSelector;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
|
||||
|
||||
@@ -28,7 +32,14 @@ import org.springframework.integration.handler.ExpressionEvaluatingMessageProces
|
||||
*/
|
||||
public class ExpressionEvaluatingSelector extends AbstractMessageProcessingSelector {
|
||||
|
||||
public ExpressionEvaluatingSelector(String expression) {
|
||||
private static final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
|
||||
|
||||
public ExpressionEvaluatingSelector(String expressionString) {
|
||||
super(new ExpressionEvaluatingMessageProcessor<Boolean>(expressionParser.parseExpression(expressionString), Boolean.class));
|
||||
}
|
||||
|
||||
public ExpressionEvaluatingSelector(Expression expression) {
|
||||
super(new ExpressionEvaluatingMessageProcessor<Boolean>(expression, Boolean.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -18,10 +18,7 @@ package org.springframework.integration.handler;
|
||||
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.ParseException;
|
||||
import org.springframework.expression.spel.SpelParserConfiguration;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -34,25 +31,27 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class ExpressionEvaluatingMessageProcessor<T> extends AbstractMessageProcessor<T> {
|
||||
|
||||
private final ExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
|
||||
private final Expression expression;
|
||||
|
||||
private final Class<T> expectedType;
|
||||
|
||||
|
||||
public ExpressionEvaluatingMessageProcessor(String expression) {
|
||||
/**
|
||||
* Create an {@link ExpressionEvaluatingMessageProcessor} for the given expression.
|
||||
*/
|
||||
public ExpressionEvaluatingMessageProcessor(Expression expression) {
|
||||
this(expression, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create an {@link ExpressionEvaluatingMessageProcessor} for the given expression String.
|
||||
* Create an {@link ExpressionEvaluatingMessageProcessor} for the given expression
|
||||
* and expected type for its evaluation result.
|
||||
*/
|
||||
public ExpressionEvaluatingMessageProcessor(String expression, Class<T> expectedType) {
|
||||
Assert.hasLength(expression, "The expression must be non empty");
|
||||
public ExpressionEvaluatingMessageProcessor(Expression expression, Class<T> expectedType) {
|
||||
Assert.notNull(expression, "The expression must not be null");
|
||||
try {
|
||||
this.expression = parser.parseExpression(expression);
|
||||
this.expression = expression;
|
||||
this.getEvaluationContext().addPropertyAccessor(new MapAccessor());
|
||||
this.expectedType = expectedType;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.router;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
|
||||
|
||||
/**
|
||||
@@ -28,7 +29,7 @@ import org.springframework.integration.handler.ExpressionEvaluatingMessageProces
|
||||
*/
|
||||
public class ExpressionEvaluatingRouter extends AbstractMessageProcessingRouter {
|
||||
|
||||
public ExpressionEvaluatingRouter(String expression) {
|
||||
public ExpressionEvaluatingRouter(Expression expression) {
|
||||
super(new ExpressionEvaluatingMessageProcessor<Object>(expression));
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.integration.splitter;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
|
||||
|
||||
/**
|
||||
@@ -32,7 +33,7 @@ import org.springframework.integration.handler.ExpressionEvaluatingMessageProces
|
||||
public class ExpressionEvaluatingSplitter extends AbstractMessageProcessingSplitter {
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public ExpressionEvaluatingSplitter(String expression) {
|
||||
public ExpressionEvaluatingSplitter(Expression expression) {
|
||||
super(new ExpressionEvaluatingMessageProcessor(expression, Collection.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.transformer;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
|
||||
|
||||
/**
|
||||
@@ -28,7 +29,7 @@ import org.springframework.integration.handler.ExpressionEvaluatingMessageProces
|
||||
*/
|
||||
public class ExpressionEvaluatingTransformer extends AbstractMessageProcessingTransformer {
|
||||
|
||||
public ExpressionEvaluatingTransformer(String expression) {
|
||||
public ExpressionEvaluatingTransformer(Expression expression) {
|
||||
super(new ExpressionEvaluatingMessageProcessor<Object>(expression));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,12 @@ import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.SpelParserConfiguration;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
|
||||
@@ -168,15 +171,17 @@ public class HeaderEnricher implements Transformer {
|
||||
|
||||
static class ExpressionEvaluatingHeaderValueMessageProcessor<T> extends AbstractHeaderValueMessageProcessor<T> implements BeanFactoryAware {
|
||||
|
||||
private static final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
|
||||
private final ExpressionEvaluatingMessageProcessor<T> targetProcessor;
|
||||
|
||||
/**
|
||||
* Create a header value processor for the given expression String and the expected type
|
||||
* Create a header value processor for the given expression string and the expected type
|
||||
* of the expression evaluation result. The expectedType may be null if unknown.
|
||||
*/
|
||||
public ExpressionEvaluatingHeaderValueMessageProcessor(String expressionString, Class<T> expectedType) {
|
||||
this.targetProcessor = new ExpressionEvaluatingMessageProcessor<T>(expressionString, expectedType);
|
||||
//this.targetProcessor.setExpectedType(expectedType);
|
||||
Expression expression = expressionParser.parseExpression(expressionString);
|
||||
this.targetProcessor = new ExpressionEvaluatingMessageProcessor<T>(expression, expectedType);
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
|
||||
@@ -2357,7 +2357,12 @@ Name of the header whose value to use.
|
||||
|
||||
<xsd:complexType name="expressionOrInnerEndpointDefinitionAware">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="innerEndpointDefinitionAware">
|
||||
<xsd:extension base="handlerEndpointType">
|
||||
<xsd:choice minOccurs="0" maxOccurs="2">
|
||||
<xsd:element name="poller" type="innerPollerType" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="expression" type="innerExpressionType" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:any namespace="##other" processContents="strict" minOccurs="0" maxOccurs="1" />
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -2369,6 +2374,28 @@ Name of the header whose value to use.
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="innerExpressionType">
|
||||
<xsd:attribute name="key" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The key for retrieving the expression from an ExpressionSource.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="source" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The reference to an ExpressionSource.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.expression.ExpressionSource" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="innerEndpointDefinitionAware">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="handlerEndpointType">
|
||||
|
||||
@@ -1,20 +1,36 @@
|
||||
/*
|
||||
* 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. 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.aggregator;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.SpelParserConfiguration;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
|
||||
/**
|
||||
* @author Alex Peters
|
||||
*
|
||||
*/
|
||||
public class ExpressionEvaluatingCorrelationStrategyTests {
|
||||
|
||||
private ExpressionEvaluatingCorrelationStrategy strategy;
|
||||
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCreateInstanceWithEmptyExpressionFails() throws Exception {
|
||||
strategy = new ExpressionEvaluatingCorrelationStrategy("");
|
||||
@@ -22,12 +38,15 @@ public class ExpressionEvaluatingCorrelationStrategyTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCreateInstanceWithNullExpressionFails() throws Exception {
|
||||
strategy = new ExpressionEvaluatingCorrelationStrategy(null);
|
||||
Expression nullExpression = null;
|
||||
strategy = new ExpressionEvaluatingCorrelationStrategy(nullExpression);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrelationKeyWithMethodInvokingExpression() throws Exception {
|
||||
strategy = new ExpressionEvaluatingCorrelationStrategy("payload.substring(0,1)");
|
||||
ExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
Expression expression = parser.parseExpression("payload.substring(0,1)");
|
||||
strategy = new ExpressionEvaluatingCorrelationStrategy(expression);
|
||||
Object correlationKey = strategy.getCorrelationKey(new GenericMessage<String>("bla"));
|
||||
assertThat(correlationKey, is(String.class));
|
||||
assertThat((String) correlationKey, is("b"));
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<channel id="positives">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<channel id="negatives">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<filter input-channel="input" output-channel="positives" discard-channel="negatives">
|
||||
<expression key="filter.positive" source="testExpressionSource"/>
|
||||
</filter>
|
||||
|
||||
<beans:bean id="testExpressionSource" class="org.springframework.integration.expression.ReloadableResourceBundleExpressionSource">
|
||||
<beans:property name="basename" value="org/springframework/integration/filter/expressions"/>
|
||||
</beans:bean>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.filter;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class DynamicExpressionFilterIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel input;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel positives;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel negatives;
|
||||
|
||||
|
||||
@Test
|
||||
public void simpleExpressionBasedFilter() {
|
||||
this.input.send(new GenericMessage<Integer>(1));
|
||||
this.input.send(new GenericMessage<Integer>(0));
|
||||
this.input.send(new GenericMessage<Integer>(99));
|
||||
this.input.send(new GenericMessage<Integer>(-99));
|
||||
assertEquals(new Integer(1), positives.receive(0).getPayload());
|
||||
assertEquals(new Integer(99), positives.receive(0).getPayload());
|
||||
assertEquals(new Integer(0), negatives.receive(0).getPayload());
|
||||
assertEquals(new Integer(-99), negatives.receive(0).getPayload());
|
||||
assertNull(positives.receive(0));
|
||||
assertNull(negatives.receive(0));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
filter.positive=payload > 0
|
||||
@@ -32,6 +32,10 @@ import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.SpelParserConfiguration;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
|
||||
/**
|
||||
@@ -43,6 +47,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ExpressionEvaluatingMessageProcessorTests.class);
|
||||
|
||||
private static final ExpressionParser expressionParser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
|
||||
|
||||
@Rule
|
||||
public ExpectedException expected = ExpectedException.none();
|
||||
@@ -50,7 +56,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
|
||||
@Test
|
||||
public void testProcessMessage() {
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload");
|
||||
Expression expression = expressionParser.parseExpression("payload");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
assertEquals("foo", processor.processMessage(new GenericMessage<String>("foo")));
|
||||
}
|
||||
|
||||
@@ -62,7 +69,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
return number+"";
|
||||
}
|
||||
}
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("#target.stringify(payload)");
|
||||
Expression expression = expressionParser.parseExpression("#target.stringify(payload)");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
processor.getEvaluationContext().setVariable("target", new TestTarget());
|
||||
assertEquals("2", processor.processMessage(new GenericMessage<String>("2")));
|
||||
}
|
||||
@@ -74,7 +82,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
public void ping(String input) {
|
||||
}
|
||||
}
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("#target.ping(payload)");
|
||||
Expression expression = expressionParser.parseExpression("#target.ping(payload)");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
processor.getEvaluationContext().setVariable("target", new TestTarget());
|
||||
assertEquals(null, processor.processMessage(new GenericMessage<String>("2")));
|
||||
}
|
||||
@@ -88,7 +97,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
}
|
||||
|
||||
}
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("#target.find(payload)");
|
||||
Expression expression = expressionParser.parseExpression("#target.find(payload)");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
processor.setBeanFactory(new GenericApplicationContext().getBeanFactory());
|
||||
processor.getEvaluationContext().setVariable("target", new TestTarget());
|
||||
String result = (String) processor.processMessage(new GenericMessage<String>("classpath:*.properties"));
|
||||
@@ -97,21 +107,24 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
|
||||
@Test
|
||||
public void testProcessMessageWithDollarInBrackets() {
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("headers['$id']");
|
||||
Expression expression = expressionParser.parseExpression("headers['$id']");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
GenericMessage<String> message = new GenericMessage<String>("foo");
|
||||
assertEquals(message.getHeaders().getId(), processor.processMessage(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessageWithDollarPropertyAccess() {
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("headers.$id");
|
||||
Expression expression = expressionParser.parseExpression("headers.$id");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
GenericMessage<String> message = new GenericMessage<String>("foo");
|
||||
assertEquals(message.getHeaders().getId(), processor.processMessage(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessageWithStaticKey() {
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("headers[headers.ID]");
|
||||
Expression expression = expressionParser.parseExpression("headers[headers.ID]");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
GenericMessage<String> message = new GenericMessage<String>("foo");
|
||||
assertEquals(message.getHeaders().getId(), processor.processMessage(message));
|
||||
}
|
||||
@@ -122,7 +135,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
BeanDefinition beanDefinition = new RootBeanDefinition(String.class);
|
||||
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("bar");
|
||||
context.registerBeanDefinition("testString", beanDefinition);
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.concat(@testString)");
|
||||
Expression expression = expressionParser.parseExpression("payload.concat(@testString)");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
processor.setBeanFactory(context);
|
||||
GenericMessage<String> message = new GenericMessage<String>("foo");
|
||||
assertEquals("foobar", processor.processMessage(message));
|
||||
@@ -134,7 +148,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
BeanDefinition beanDefinition = new RootBeanDefinition(String.class);
|
||||
beanDefinition.getConstructorArgumentValues().addGenericArgumentValue("bar");
|
||||
context.registerBeanDefinition("testString", beanDefinition);
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("@testString.concat(payload)");
|
||||
Expression expression = expressionParser.parseExpression("@testString.concat(payload)");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
processor.setBeanFactory(context);
|
||||
GenericMessage<String> message = new GenericMessage<String>("foo");
|
||||
assertEquals("barfoo", processor.processMessage(message));
|
||||
@@ -154,7 +169,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
description.appendText("cause to be EvaluationException but was ").appendValue(cause);
|
||||
}
|
||||
});
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.fixMe()");
|
||||
Expression expression = expressionParser.parseExpression("payload.fixMe()");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
assertEquals("foo", processor.processMessage(new GenericMessage<String>("foo")));
|
||||
}
|
||||
|
||||
@@ -172,7 +188,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
description.appendText("cause to be UnsupportedOperationException but was ").appendValue(cause);
|
||||
}
|
||||
});
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.throwRuntimeException()");
|
||||
Expression expression = expressionParser.parseExpression("payload.throwRuntimeException()");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
assertEquals("foo", processor.processMessage(new GenericMessage<TestPayload>(new TestPayload())));
|
||||
}
|
||||
|
||||
@@ -190,7 +207,8 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
description.appendText("cause to be CheckedException but was ").appendValue(cause);
|
||||
}
|
||||
});
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("payload.throwCheckedException()");
|
||||
Expression expression = expressionParser.parseExpression("payload.throwCheckedException()");
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
assertEquals("foo", processor.processMessage(new GenericMessage<TestPayload>(new TestPayload())));
|
||||
}
|
||||
|
||||
@@ -213,5 +231,5 @@ public class ExpressionEvaluatingMessageProcessorTests {
|
||||
super(string);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,355 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.http;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.multipart.MultipartResolver;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link InboundRequestMapper} for inbound HttpServletRequests.
|
||||
* The request will be mapped according to the following rules:
|
||||
* <ul>
|
||||
* <li>For a GET request or a POST request with a Content-Type of
|
||||
* "application/x-www-form-urlencoded", the parameter Map will be copied as the
|
||||
* payload. The map will be an instance of {@link MultiValueMap} where the keys are
|
||||
* Strings and the values are Lists of Strings. Those Lists are populated from the
|
||||
* String array values of the original request parameter Map as described for the
|
||||
* {@link ServletRequest#getParameterMap()} method.</li>
|
||||
* <li>If a MultipartResolver has been provided, and a multipart request is
|
||||
* detected, the multipart file content will be converted to String for any
|
||||
* "text" content type, or byte arrays otherwise.</li>
|
||||
* <li>For other request types, the request body will be used as the payload
|
||||
* and the type will depend on the Content-Type header value. If it begins with
|
||||
* "text", a String will be created. If the Content-Type is
|
||||
* "application/x-java-serialized-object", the request body will be expected to
|
||||
* contain a Serializable Object, and that will be used as the message payload.
|
||||
* Otherwise, the payload will be a byte array.</li>
|
||||
* </ul>
|
||||
* In all cases, the original request headers will be passed in the
|
||||
* MessageHeaders. Likewise, the following headers will be added:
|
||||
* <ul>
|
||||
* <li>{@link HttpHeaders#REQUEST_URL}</li>
|
||||
* <li>{@link HttpHeaders#REQUEST_METHOD}</li>
|
||||
* <li>{@link HttpHeaders#USER_PRINCIPAL} (if available)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public class DefaultInboundRequestMapper implements InboundRequestMapper {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private volatile MultipartResolver multipartResolver;
|
||||
|
||||
private volatile String multipartCharset = null;
|
||||
|
||||
private volatile boolean copyUploadedFiles;
|
||||
|
||||
|
||||
/**
|
||||
* Specify the {@link MultipartResolver} to use when checking requests.
|
||||
* If no resolver is provided, this mapper will not support multipart
|
||||
* requests.
|
||||
*/
|
||||
public void setMultipartResolver(MultipartResolver multipartResolver) {
|
||||
this.multipartResolver = multipartResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the charset name to use when converting multipart file content
|
||||
* into Strings.
|
||||
*/
|
||||
public void setMultipartCharset(String multipartCharset) {
|
||||
this.multipartCharset = multipartCharset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether uploaded multipart files should be copied to a temporary
|
||||
* file on the server. If this is set to 'true', the payload map will
|
||||
* contain a File instance as the value for each multipart file entry.
|
||||
* Otherwise the uploaded file's content will be converted to either a
|
||||
* String or byte array based on the content-type (String for "text/*" and
|
||||
* byte array otherwise). The default value is false.
|
||||
*/
|
||||
public void setCopyUploadedFiles(boolean copyUploadedFiles) {
|
||||
this.copyUploadedFiles = copyUploadedFiles;
|
||||
}
|
||||
|
||||
public Message<?> toMessage(HttpServletRequest request) throws Exception {
|
||||
try {
|
||||
request = this.checkMultipart(request);
|
||||
Object payload = createPayloadFromRequest(request);
|
||||
MessageBuilder<?> builder = MessageBuilder.withPayload(payload);
|
||||
this.populateHeaders(request, builder);
|
||||
return builder.build();
|
||||
}
|
||||
finally {
|
||||
this.cleanupMultipart(request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the request into a multipart request to make multiparts available.
|
||||
* If no multipart resolver is set, simply use the existing request.
|
||||
* @param request current HTTP request
|
||||
* @return the processed request (multipart wrapper if necessary)
|
||||
* @see MultipartResolver#resolveMultipart
|
||||
*/
|
||||
private HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
|
||||
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
|
||||
if (request instanceof MultipartHttpServletRequest) {
|
||||
logger.debug("Request is already a MultipartHttpServletRequest");
|
||||
}
|
||||
else {
|
||||
return this.multipartResolver.resolveMultipart(request);
|
||||
}
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up any resources used by the given multipart request (if any).
|
||||
* @param request current HTTP request
|
||||
* @see MultipartResolver#cleanupMultipart
|
||||
*/
|
||||
private void cleanupMultipart(HttpServletRequest request) {
|
||||
if (this.multipartResolver != null && request instanceof MultipartHttpServletRequest) {
|
||||
this.multipartResolver.cleanupMultipart((MultipartHttpServletRequest) request);
|
||||
}
|
||||
}
|
||||
|
||||
private Object createPayloadFromRequest(HttpServletRequest request) throws Exception {
|
||||
Object payload = null;
|
||||
String contentType = request.getContentType() != null ? request.getContentType() : "";
|
||||
if (request instanceof MultipartHttpServletRequest) {
|
||||
payload = this.createPayloadFromMultipartRequest((MultipartHttpServletRequest) request);
|
||||
}
|
||||
else if (contentType.startsWith("multipart/form-data")) {
|
||||
throw new IllegalArgumentException("Content-Type of 'multipart/form-data' requires a MultipartResolver." +
|
||||
" Try configuring a MultipartResolver within the ApplicationContext.");
|
||||
}
|
||||
else if (request.getMethod().equals("GET")) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("received GET request, using parameter map as payload");
|
||||
}
|
||||
payload = this.createPayloadFromParameterMap(request);
|
||||
}
|
||||
else if (contentType.startsWith("application/x-www-form-urlencoded")) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("received " + request.getMethod()
|
||||
+ " request with form data, using parameter map as payload");
|
||||
}
|
||||
payload = createPayloadFromParameterMap(request);
|
||||
}
|
||||
else if (contentType.startsWith("text")) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("received " + request.getMethod()
|
||||
+ " request, creating payload with text content");
|
||||
}
|
||||
payload = createPayloadFromTextContent(request);
|
||||
}
|
||||
else if (contentType.startsWith("application/x-java-serialized-object")) {
|
||||
payload = createPayloadFromSerializedObject(request);
|
||||
}
|
||||
else {
|
||||
payload = createPayloadFromInputStream(request);
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object createPayloadFromMultipartRequest(MultipartHttpServletRequest multipartRequest) {
|
||||
Map<String, Object> payloadMap = new HashMap<String, Object>(multipartRequest.getParameterMap());
|
||||
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
|
||||
for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
|
||||
MultipartFile multipartFile = entry.getValue();
|
||||
if (multipartFile.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (this.copyUploadedFiles) {
|
||||
File tmpFile = File.createTempFile("si_", null);
|
||||
multipartFile.transferTo(tmpFile);
|
||||
payloadMap.put(entry.getKey(), tmpFile);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("copied uploaded file [" + multipartFile.getOriginalFilename() +
|
||||
"] to temporary file [" + tmpFile.getAbsolutePath() + "]");
|
||||
}
|
||||
}
|
||||
else if (multipartFile.getContentType() != null && multipartFile.getContentType().startsWith("text")) {
|
||||
String multipartFileAsString = this.multipartCharset != null ?
|
||||
new String(multipartFile.getBytes(), this.multipartCharset) :
|
||||
new String(multipartFile.getBytes());
|
||||
payloadMap.put(entry.getKey(), multipartFileAsString);
|
||||
}
|
||||
else {
|
||||
payloadMap.put(entry.getKey(), multipartFile.getBytes());
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalArgumentException("Cannot read contents of multipart file", e);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableMap(payloadMap);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object createPayloadFromParameterMap(HttpServletRequest request) {
|
||||
return new UnmodifiableRequestParameterMap(request.getParameterMap());
|
||||
}
|
||||
|
||||
private Object createPayloadFromTextContent(HttpServletRequest request) throws IOException {
|
||||
String charset = request.getCharacterEncoding() != null ? request.getCharacterEncoding() : "utf-8";
|
||||
return new String(FileCopyUtils.copyToByteArray(request.getInputStream()), charset);
|
||||
}
|
||||
|
||||
private Object createPayloadFromSerializedObject(HttpServletRequest request) {
|
||||
try {
|
||||
return new ObjectInputStream(request.getInputStream()).readObject();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalArgumentException("failed to deserialize Object in request", e);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] createPayloadFromInputStream(HttpServletRequest request) throws Exception {
|
||||
InputStream stream = request.getInputStream();
|
||||
int length = request.getContentLength();
|
||||
if (length == -1) {
|
||||
throw new ResponseStatusCodeException(HttpServletResponse.SC_LENGTH_REQUIRED);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("received " + request.getMethod() + " request, "
|
||||
+ "creating byte array payload with content lenth: " + length);
|
||||
}
|
||||
byte[] bytes = new byte[length];
|
||||
stream.read(bytes, 0, length);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private void populateHeaders(HttpServletRequest request, MessageBuilder<?> builder) {
|
||||
Enumeration<?> headerNames = request.getHeaderNames();
|
||||
if (headerNames != null) {
|
||||
while (headerNames.hasMoreElements()) {
|
||||
String headerName = (String) headerNames.nextElement();
|
||||
Enumeration<?> headerEnum = request.getHeaders(headerName);
|
||||
if (headerEnum != null) {
|
||||
List<Object> headers = new ArrayList<Object>();
|
||||
while (headerEnum.hasMoreElements()) {
|
||||
headers.add(headerEnum.nextElement());
|
||||
}
|
||||
if (headers.size() == 1) {
|
||||
builder.setHeader(headerName, headers.get(0));
|
||||
}
|
||||
else if (headers.size() > 1) {
|
||||
builder.setHeader(headerName, headers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.setHeader(HttpHeaders.REQUEST_URL, request.getRequestURL().toString());
|
||||
builder.setHeader(HttpHeaders.REQUEST_METHOD, request.getMethod());
|
||||
builder.setHeader(HttpHeaders.USER_PRINCIPAL, request.getUserPrincipal());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Map class that extends {@link LinkedMultiValueMap} and implements Serializable.
|
||||
* The contents of the map are unmodifiable, so calling any modification operation
|
||||
* (e.g. put, add, or remove) will result in an UnsupportedOperationException.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class UnmodifiableRequestParameterMap
|
||||
extends LinkedMultiValueMap<String, String> implements Serializable { // TODO: in 3.0.1 LMVM implements Serializable
|
||||
|
||||
UnmodifiableRequestParameterMap(Map<String, String[]> parameters) {
|
||||
for (Map.Entry<String, String[]> entry : parameters.entrySet()) {
|
||||
super.put(entry.getKey(), Arrays.asList(entry.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(String key, String value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> put(String key, List<String> value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends String, ? extends List<String>> m) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> remove(Object key) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String key, String value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAll(Map<String, String> values) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> toSingleValueMap() {
|
||||
return Collections.unmodifiableMap(super.toSingleValueMap());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,127 +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.http;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author Iwein Fuld
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class DefaultInboundRequestMapperTests {
|
||||
|
||||
private static final String SIMPLE_STRING = "just ascii";
|
||||
|
||||
private static final String COMPLEX_STRING = "A\u00ea\u00f1\u00fcC";
|
||||
|
||||
private DefaultInboundRequestMapper mapper = new DefaultInboundRequestMapper();
|
||||
|
||||
@Test
|
||||
public void simpleUtf8TextMapping() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text");
|
||||
request.setCharacterEncoding("utf-8");
|
||||
byte[] bytes = SIMPLE_STRING.getBytes("utf-8");
|
||||
request.setContent(bytes);
|
||||
Message<String> message = (Message<String>) mapper.toMessage(request);
|
||||
assertThat(message.getPayload(), is(SIMPLE_STRING));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complexUtf8TextMapping() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text");
|
||||
// don't forget to specify the character encoding on the request or you
|
||||
// will end up with unpredictable results!
|
||||
request.setCharacterEncoding("utf-8");
|
||||
byte[] bytes = COMPLEX_STRING.getBytes("utf-8");
|
||||
request.setContent(bytes);
|
||||
Message<String> message = (Message<String>) mapper.toMessage(request);
|
||||
assertThat(message.getPayload(), is(COMPLEX_STRING));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newlineTest() throws Exception {
|
||||
String content = "foo\nbar\n";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text");
|
||||
byte[] bytes = content.getBytes();
|
||||
request.setContent(bytes);
|
||||
Message<String> message = (Message<String>) mapper.toMessage(request);
|
||||
assertThat(message.getPayload(), is(content));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyStringTest() throws Exception {
|
||||
String content = "";
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text");
|
||||
byte[] bytes = content.getBytes();
|
||||
request.setContent(bytes);
|
||||
Message<String> message = (Message<String>) mapper.toMessage(request);
|
||||
assertThat(message.getPayload(), is(content));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipartUpload() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MultiValueMap<String, MultipartFile> files = new LinkedMultiValueMap<String, MultipartFile>();
|
||||
MultipartFile file = new StubMultipartFile("file", "testFile.txt", "foo");
|
||||
files.add("file", file);
|
||||
Map<String, String[]> params = new HashMap<String, String[]>();
|
||||
MultipartHttpServletRequest multipartRequest = new DefaultMultipartHttpServletRequest(request, files, params);
|
||||
mapper.setCopyUploadedFiles(true);
|
||||
Message<?> result = mapper.toMessage(multipartRequest);
|
||||
File tmpFile = (File) ((Map) result.getPayload()).get("file");
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
FileCopyUtils.copy(new FileInputStream(tmpFile), baos);
|
||||
assertThat(baos.toString(), is("foo"));
|
||||
tmpFile.deleteOnExit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessageWithDollar() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text");
|
||||
request.setCharacterEncoding("utf-8");
|
||||
byte[] bytes = SIMPLE_STRING.getBytes("utf-8");
|
||||
request.setContent(bytes);
|
||||
Message<String> message = (Message<String>) mapper.toMessage(request);
|
||||
ExpressionEvaluatingMessageProcessor processor = new ExpressionEvaluatingMessageProcessor("headers['$http_requestUrl']");
|
||||
assertEquals(message.getHeaders().get(HttpHeaders.REQUEST_URL), processor.processMessage(message));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user