Merge branch 'master' of git.springsource.org:spring-integration/spring-integration
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.
|
||||
|
||||
@@ -1,64 +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.channel;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.support.channel.ChannelResolver;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ChannelResolver} implementation that resolves {@link MessageChannel}
|
||||
* instances by matching the channel name against keys within a Map.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MapBasedChannelResolver implements ChannelResolver {
|
||||
|
||||
private volatile Map<String, ? extends MessageChannel> channelMap = new HashMap<String, MessageChannel>();
|
||||
|
||||
/**
|
||||
* Empty constructor for use when providing the channel map via
|
||||
* {@link #setChannelMap(Map)}.
|
||||
*/
|
||||
public MapBasedChannelResolver() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link ChannelResolver} that uses the provided Map.
|
||||
* Each String key will resolve to the associated channel value.
|
||||
*/
|
||||
public MapBasedChannelResolver(Map<String, ? extends MessageChannel> channelMap) {
|
||||
this.setChannelMap(channelMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a map of channels to be used by this resolver.
|
||||
* Each String key will resolve to the associated channel value.
|
||||
*/
|
||||
public void setChannelMap(Map<String, ? extends MessageChannel> channelMap) {
|
||||
Assert.notNull(channelMap, "channelMap must not be null");
|
||||
this.channelMap = channelMap;
|
||||
}
|
||||
|
||||
public MessageChannel resolveChannelName(String channelName) {
|
||||
return this.channelMap.get(channelName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -125,7 +136,7 @@ abstract class AbstractMessageHandlerFactoryBean implements FactoryBean<MessageH
|
||||
if (this.targetObject != null) {
|
||||
Assert.state(this.expression == null,
|
||||
"The 'targetObject' and 'expression' properties are mutually exclusive.");
|
||||
if (this.targetObject instanceof MessageProcessor) {
|
||||
if (this.targetObject instanceof MessageProcessor<?>) {
|
||||
this.handler = this.createMessageProcessingHandler((MessageProcessor<?>) this.targetObject);
|
||||
}
|
||||
else {
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
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;
|
||||
import org.springframework.integration.router.AbstractMessageRouter;
|
||||
import org.springframework.integration.router.ExpressionEvaluatingRouter;
|
||||
import org.springframework.integration.router.MethodInvokingRouter;
|
||||
@@ -31,10 +32,13 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Jonas Partner
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class RouterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
|
||||
private volatile ChannelResolver channelResolver;
|
||||
|
||||
private volatile Map<String, String> channelIdentifierMap;
|
||||
|
||||
private volatile MessageChannel defaultOutputChannel;
|
||||
|
||||
@@ -48,7 +52,6 @@ public class RouterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
|
||||
private volatile Boolean ignoreSendFailures;
|
||||
|
||||
|
||||
public void setChannelResolver(ChannelResolver channelResolver) {
|
||||
this.channelResolver = channelResolver;
|
||||
}
|
||||
@@ -76,36 +79,75 @@ public class RouterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
public void setIgnoreSendFailures(Boolean ignoreSendFailures) {
|
||||
this.ignoreSendFailures = ignoreSendFailures;
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName) {
|
||||
Assert.notNull(targetObject, "target object must not be null");
|
||||
AbstractMessageRouter router = this.createRouter(targetObject, targetMethodName);
|
||||
return this.configureRouter(router);
|
||||
|
||||
public void setChannelIdentifierMap(Map<String, String> channelIdentifierMap) {
|
||||
this.channelIdentifierMap = channelIdentifierMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createExpressionEvaluatingHandler(String expression) {
|
||||
MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName) {
|
||||
|
||||
Assert.notNull(targetObject, "target object must not be null");
|
||||
AbstractMessageRouter router = extractRouter(targetObject);
|
||||
|
||||
if (router == null) {
|
||||
router = this.createRouter(targetObject, targetMethodName);
|
||||
this.configureRouter(router);
|
||||
return router;
|
||||
}
|
||||
|
||||
Assert.isTrue(!StringUtils.hasText(targetMethodName), "target method should not be provided when the target "
|
||||
+ "object is an implementation of AbstractMessageRouter");
|
||||
this.configureRouter(router);
|
||||
|
||||
if (targetObject instanceof MessageHandler) {
|
||||
return (MessageHandler) targetObject;
|
||||
}
|
||||
return router;
|
||||
|
||||
}
|
||||
|
||||
private AbstractMessageRouter extractRouter(Object targetObject) {
|
||||
if (targetObject instanceof AbstractMessageRouter) {
|
||||
return (AbstractMessageRouter) targetObject;
|
||||
}
|
||||
if (targetObject instanceof Advised) {
|
||||
return extractAopTarget((Advised) targetObject);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private AbstractMessageRouter extractAopTarget(Advised advised) {
|
||||
TargetSource targetSource = advised.getTargetSource();
|
||||
if (targetSource == null) {
|
||||
return null;
|
||||
}
|
||||
Object target;
|
||||
try {
|
||||
target = targetSource.getTarget();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
return extractRouter(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createExpressionEvaluatingHandler(Expression expression) {
|
||||
return this.configureRouter(new ExpressionEvaluatingRouter(expression));
|
||||
}
|
||||
|
||||
private AbstractMessageRouter createRouter(Object targetObject, String targetMethodName) {
|
||||
if (targetObject instanceof AbstractMessageRouter) {
|
||||
Assert.isTrue(!StringUtils.hasText(targetMethodName),
|
||||
"target method should not be provided when the target " +
|
||||
"object is an implementation of AbstractMessageRouter");
|
||||
return (AbstractMessageRouter) targetObject;
|
||||
}
|
||||
MethodInvokingRouter router = (StringUtils.hasText(targetMethodName))
|
||||
? new MethodInvokingRouter(targetObject, targetMethodName)
|
||||
: new MethodInvokingRouter(targetObject);
|
||||
MethodInvokingRouter router = (StringUtils.hasText(targetMethodName)) ? new MethodInvokingRouter(targetObject,
|
||||
targetMethodName) : new MethodInvokingRouter(targetObject);
|
||||
return router;
|
||||
}
|
||||
|
||||
private AbstractMessageRouter configureRouter(AbstractMessageRouter router) {
|
||||
if (this.channelResolver != null &&
|
||||
router instanceof AbstractChannelNameResolvingMessageRouter) {
|
||||
((AbstractChannelNameResolvingMessageRouter) router).setChannelResolver(this.channelResolver);
|
||||
if (this.channelResolver != null && router instanceof AbstractMessageRouter) {
|
||||
((AbstractMessageRouter) router).setChannelResolver(this.channelResolver);
|
||||
}
|
||||
if (this.channelIdentifierMap != null && router instanceof AbstractMessageRouter) {
|
||||
((AbstractMessageRouter) router).setChannelIdentifierMap(this.channelIdentifierMap);
|
||||
}
|
||||
if (this.defaultOutputChannel != null) {
|
||||
router.setDefaultOutputChannel(this.defaultOutputChannel);
|
||||
@@ -114,10 +156,11 @@ public class RouterFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
router.setTimeout(timeout.longValue());
|
||||
}
|
||||
if (this.ignoreChannelNameResolutionFailures != null) {
|
||||
Assert.isTrue(router instanceof AbstractChannelNameResolvingMessageRouter,
|
||||
Assert.isTrue(router instanceof AbstractMessageRouter,
|
||||
"The 'ignoreChannelNameResolutionFailures' property can only be set on routers that extend "
|
||||
+ AbstractChannelNameResolvingMessageRouter.class.getName());
|
||||
((AbstractChannelNameResolvingMessageRouter) router).setIgnoreChannelNameResolutionFailures(ignoreChannelNameResolutionFailures);
|
||||
+ AbstractMessageRouter.class.getName());
|
||||
((AbstractMessageRouter) router)
|
||||
.setIgnoreChannelNameResolutionFailures(ignoreChannelNameResolutionFailures);
|
||||
}
|
||||
if (this.applySequence != null) {
|
||||
router.setApplySequence(this.applySequence);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -125,6 +125,11 @@ public class SourcePollingChannelAdapterFactoryBean implements FactoryBean<Sourc
|
||||
Assert.notNull(this.pollerMetadata, "No poller has been defined for channel-adapter '"
|
||||
+ this.beanName + "', and no default poller is available within the context.");
|
||||
}
|
||||
if (this.pollerMetadata.getMaxMessagesPerPoll() < 1){
|
||||
// the default is 1 since a source might return
|
||||
// a non-null and non-interruptable value every time it is invoked
|
||||
this.pollerMetadata.setMaxMessagesPerPoll(1);
|
||||
}
|
||||
spca.setPollerMetadata(this.pollerMetadata);
|
||||
|
||||
spca.setBeanClassLoader(this.beanClassLoader);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,60 +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.config.xml;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
/**
|
||||
* Base parser for routers that create instances that are subclasses of AbstractChannelNameResolvingMessageRouter.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractChannelNameResolvingRouterParser extends AbstractRouterParser {
|
||||
|
||||
@Override
|
||||
protected final BeanDefinition parseRouter(Element element, ParserContext parserContext) {
|
||||
BeanDefinition beanDefinition = this.doParseRouter(element, parserContext);
|
||||
if (beanDefinition != null) {
|
||||
// check if mapping is provided otherwise returned values will be treated as channel names
|
||||
List<Element> childElements = DomUtils.getChildElementsByTagName(element, "mapping");
|
||||
if (childElements != null && childElements.size() > 0) {
|
||||
BeanDefinitionBuilder channelResolverBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationNamespaceUtils.BASE_PACKAGE + ".channel.MapBasedChannelResolver");
|
||||
ManagedMap<String, RuntimeBeanReference> channelMap = new ManagedMap<String, RuntimeBeanReference>();
|
||||
for (Element childElement : childElements) {
|
||||
channelMap.put(childElement.getAttribute("value"),
|
||||
new RuntimeBeanReference(childElement.getAttribute("channel")));
|
||||
}
|
||||
channelResolverBuilder.addPropertyValue("channelMap", channelMap);
|
||||
beanDefinition.getPropertyValues().add("channelResolver", channelResolverBuilder.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
return beanDefinition;
|
||||
}
|
||||
|
||||
protected abstract BeanDefinition doParseRouter(Element element, ParserContext parserContext);
|
||||
|
||||
}
|
||||
@@ -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, " +
|
||||
|
||||
@@ -16,11 +16,17 @@
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
/**
|
||||
* Base parser for routers.
|
||||
@@ -44,6 +50,34 @@ public abstract class AbstractRouterParser extends AbstractConsumerEndpointParse
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected abstract BeanDefinition parseRouter(Element element, ParserContext parserContext);
|
||||
protected final BeanDefinition parseRouter(Element element, ParserContext parserContext) {
|
||||
BeanDefinition beanDefinition = this.doParseRouter(element, parserContext);
|
||||
if (beanDefinition != null) {
|
||||
String channelResolver = element.getAttribute("channel-resolver");
|
||||
if (StringUtils.hasText(channelResolver)){
|
||||
beanDefinition.getPropertyValues().add("channelResolver", new RuntimeBeanReference(channelResolver));
|
||||
}
|
||||
// check if mapping is provided otherwise returned values will be treated as channel names
|
||||
List<Element> childElements = DomUtils.getChildElementsByTagName(element, "mapping");
|
||||
if (childElements != null && childElements.size() > 0) {
|
||||
ManagedMap<String, String> channelMap = new ManagedMap<String, String>();
|
||||
for (Element childElement : childElements) {
|
||||
String beanClassName = beanDefinition.getBeanClassName();
|
||||
String key = null;
|
||||
if (beanClassName.endsWith("PayloadTypeRouter")){
|
||||
key = childElement.getAttribute("type");
|
||||
}
|
||||
else {
|
||||
key = childElement.getAttribute("value");
|
||||
}
|
||||
channelMap.put(key, childElement.getAttribute("channel"));
|
||||
}
|
||||
beanDefinition.getPropertyValues().add("channelIdentifierMap", channelMap);
|
||||
}
|
||||
}
|
||||
return beanDefinition;
|
||||
}
|
||||
|
||||
protected abstract BeanDefinition doParseRouter(Element element, ParserContext parserContext);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,9 +18,6 @@ package org.springframework.integration.config.xml;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
@@ -28,11 +25,13 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for the <router/> element.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class DefaultRouterParser extends AbstractDelegatingConsumerEndpointParser {
|
||||
|
||||
@@ -60,13 +59,12 @@ public class DefaultRouterParser extends AbstractDelegatingConsumerEndpointParse
|
||||
parserContext.extractSource(element));
|
||||
}
|
||||
BeanDefinitionBuilder channelResolverBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationNamespaceUtils.BASE_PACKAGE + ".channel.MapBasedChannelResolver");
|
||||
ManagedMap<String, RuntimeBeanReference> channelMap = new ManagedMap<String, RuntimeBeanReference>();
|
||||
IntegrationNamespaceUtils.BASE_PACKAGE + ".support.channel.BeanFactoryChannelResolver");
|
||||
ManagedMap<String, String> channelMap = new ManagedMap<String, String>();
|
||||
for (Element mappingElement : mappingElements) {
|
||||
channelMap.put(mappingElement.getAttribute("value"),
|
||||
new RuntimeBeanReference(mappingElement.getAttribute("channel")));
|
||||
channelMap.put(mappingElement.getAttribute("value"), mappingElement.getAttribute("channel"));
|
||||
}
|
||||
channelResolverBuilder.addPropertyValue("channelMap", channelMap);
|
||||
builder.addPropertyValue("channelIdentifierMap", channelMap);
|
||||
builder.addPropertyValue(CHANNEL_RESOLVER_PROPERTY, channelResolverBuilder.getBeanDefinition());
|
||||
}
|
||||
else if (StringUtils.hasText(resolverBeanName)) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
/**
|
||||
* Base support class for 'header-enricher' parsers.
|
||||
@@ -110,12 +111,17 @@ public abstract class HeaderEnricherParserSupport extends AbstractTransformerPar
|
||||
if (headerName != null) {
|
||||
String value = headerElement.getAttribute("value");
|
||||
String ref = headerElement.getAttribute("ref");
|
||||
String expression = headerElement.getAttribute("expression");
|
||||
String method = headerElement.getAttribute("method");
|
||||
String expression = headerElement.getAttribute("expression");
|
||||
Element expressionElement = DomUtils.getChildElementByTagName(headerElement, "expression");
|
||||
if (StringUtils.hasText(expression) && expressionElement != null) {
|
||||
parserContext.getReaderContext().error("The 'expression' attribute and sub-element are mutually exclusive", element);
|
||||
return;
|
||||
}
|
||||
boolean isValue = StringUtils.hasText(value);
|
||||
boolean isRef = StringUtils.hasText(ref);
|
||||
boolean isExpression = StringUtils.hasText(expression);
|
||||
boolean hasMethod = StringUtils.hasText(method);
|
||||
boolean isExpression = StringUtils.hasText(expression) || expressionElement != null;
|
||||
if (!(isValue ^ (isRef ^ isExpression))) {
|
||||
parserContext.getReaderContext().error(
|
||||
"Exactly one of the 'ref', 'value', or 'expression' attributes is required.", element);
|
||||
@@ -139,7 +145,16 @@ public abstract class HeaderEnricherParserSupport extends AbstractTransformerPar
|
||||
}
|
||||
valueProcessorBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationNamespaceUtils.BASE_PACKAGE + ".transformer.HeaderEnricher$ExpressionEvaluatingHeaderValueMessageProcessor");
|
||||
valueProcessorBuilder.addConstructorArgValue(expression);
|
||||
if (expressionElement != null) {
|
||||
BeanDefinitionBuilder dynamicExpressionBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.expression.DynamicExpression");
|
||||
dynamicExpressionBuilder.addConstructorArgValue(expressionElement.getAttribute("key"));
|
||||
dynamicExpressionBuilder.addConstructorArgReference(expressionElement.getAttribute("source"));
|
||||
valueProcessorBuilder.addConstructorArgValue(dynamicExpressionBuilder.getBeanDefinition());
|
||||
}
|
||||
else {
|
||||
valueProcessorBuilder.addConstructorArgValue(expression);
|
||||
}
|
||||
valueProcessorBuilder.addConstructorArgValue(headerType);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.3
|
||||
*/
|
||||
public class HeaderValueRouterParser extends AbstractChannelNameResolvingRouterParser {
|
||||
public class HeaderValueRouterParser extends AbstractRouterParser {
|
||||
|
||||
@Override
|
||||
protected BeanDefinition doParseRouter(Element element, ParserContext parserContext) {
|
||||
|
||||
@@ -16,18 +16,10 @@
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for the <payload-type-router/> element.
|
||||
@@ -37,27 +29,12 @@ import org.springframework.util.xml.DomUtils;
|
||||
* @since 1.0.3
|
||||
*/
|
||||
public class PayloadTypeRouterParser extends AbstractRouterParser {
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected BeanDefinition parseRouter(Element element, ParserContext parserContext) {
|
||||
protected BeanDefinition doParseRouter(Element element,
|
||||
ParserContext parserContext) {
|
||||
BeanDefinitionBuilder payloadTypeRouterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationNamespaceUtils.BASE_PACKAGE + ".router.PayloadTypeRouter");
|
||||
List<Element> childElements = DomUtils.getChildElementsByTagName(element, "mapping");
|
||||
Assert.notEmpty(childElements,
|
||||
"Type mapping must be provided (e.g., <mapping type=\"X\" channel=\"channel1\"/>)");
|
||||
ManagedMap channelMap = new ManagedMap();
|
||||
for (Element childElement : childElements) {
|
||||
String typeName = childElement.getAttribute("type");
|
||||
ClassLoader classLoader = parserContext.getReaderContext().getBeanClassLoader();
|
||||
if (classLoader == null) {
|
||||
classLoader = ClassUtils.getDefaultClassLoader();
|
||||
}
|
||||
Assert.isTrue(ClassUtils.isPresent(typeName, classLoader), typeName + " can not be loaded");
|
||||
channelMap.put(typeName, new RuntimeBeanReference(childElement.getAttribute("channel")));
|
||||
}
|
||||
payloadTypeRouterBuilder.addPropertyValue("payloadTypeChannelMap", channelMap);
|
||||
return payloadTypeRouterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,10 +53,9 @@ public class PublishingInterceptorParser extends AbstractBeanDefinitionParser {
|
||||
spelSourceBuilder.addPropertyValue("headerExpressionMap", mappings.get("headers"));
|
||||
}
|
||||
BeanDefinitionBuilder chResolverBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.channel.MapBasedChannelResolver");
|
||||
"org.springframework.integration.support.channel.BeanFactoryChannelResolver");
|
||||
if (mappings.get("channels") != null){
|
||||
spelSourceBuilder.addPropertyValue("channelMap", mappings.get("channels"));
|
||||
chResolverBuilder.addConstructorArgValue(mappings.get("resolvableChannels"));
|
||||
}
|
||||
String chResolverName =
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(chResolverBuilder.getBeanDefinition(), parserContext.getRegistry());
|
||||
|
||||
@@ -18,13 +18,13 @@ package org.springframework.integration.endpoint;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.core.task.SyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.channel.MessagePublishingErrorHandler;
|
||||
@@ -43,11 +43,11 @@ import org.springframework.util.ErrorHandler;
|
||||
*/
|
||||
public abstract class AbstractPollingEndpoint extends AbstractEndpoint implements BeanClassLoaderAware {
|
||||
|
||||
private volatile TaskExecutor taskExecutor = new SyncTaskExecutor();
|
||||
private volatile Executor taskExecutor = new SyncTaskExecutor();
|
||||
|
||||
private volatile ErrorHandler errorHandler;
|
||||
|
||||
private volatile PollerMetadata pollerMetadata;
|
||||
private volatile PollerMetadata pollerMetadata = new PollerMetadata();
|
||||
|
||||
private volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||
|
||||
@@ -84,14 +84,14 @@ public abstract class AbstractPollingEndpoint extends AbstractEndpoint implement
|
||||
return;
|
||||
}
|
||||
Assert.notNull(this.pollerMetadata.getTrigger(), "Trigger is required");
|
||||
Assert.notNull(this.getBeanFactory(), "BeanFactory is required");
|
||||
TaskExecutor providedExecutor = this.pollerMetadata.getTaskExecutor();
|
||||
Executor providedExecutor = this.pollerMetadata.getTaskExecutor();
|
||||
if (providedExecutor != null) {
|
||||
this.taskExecutor = providedExecutor;
|
||||
}
|
||||
if (this.taskExecutor != null) {
|
||||
if (!(this.taskExecutor instanceof ErrorHandlingTaskExecutor)) {
|
||||
if (this.errorHandler == null) {
|
||||
Assert.notNull(this.getBeanFactory(), "BeanFactory is required");
|
||||
this.errorHandler = new MessagePublishingErrorHandler(
|
||||
new BeanFactoryChannelResolver(getBeanFactory()));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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.expression;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.EvaluationException;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An implementation of {@link Expression} that delegates to an {@link ExpressionSource}
|
||||
* for resolving the actual Expression instance per-invocation at runtime.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DynamicExpression implements Expression {
|
||||
|
||||
private final String key;
|
||||
|
||||
private final ExpressionSource expressionSource;
|
||||
|
||||
|
||||
public DynamicExpression(String key, ExpressionSource expressionSource) {
|
||||
Assert.notNull(key, "key must not be null");
|
||||
Assert.notNull(expressionSource, "expressionSource must not be null");
|
||||
this.key = key;
|
||||
this.expressionSource = expressionSource;
|
||||
}
|
||||
|
||||
|
||||
public Object getValue() throws EvaluationException {
|
||||
return this.resolveExpression().getValue();
|
||||
}
|
||||
|
||||
public Object getValue(Object rootObject) throws EvaluationException {
|
||||
return this.resolveExpression().getValue(rootObject);
|
||||
}
|
||||
|
||||
public <T> T getValue(Class<T> desiredResultType) throws EvaluationException {
|
||||
return this.resolveExpression().getValue(desiredResultType);
|
||||
}
|
||||
|
||||
public <T> T getValue(Object rootObject, Class<T> desiredResultType) throws EvaluationException {
|
||||
return this.resolveExpression().getValue(rootObject, desiredResultType);
|
||||
}
|
||||
|
||||
public Object getValue(EvaluationContext context) throws EvaluationException {
|
||||
return this.resolveExpression().getValue(context);
|
||||
}
|
||||
|
||||
public Object getValue(EvaluationContext context, Object rootObject) throws EvaluationException {
|
||||
return this.resolveExpression().getValue(context, rootObject);
|
||||
}
|
||||
|
||||
public <T> T getValue(EvaluationContext context, Class<T> desiredResultType) throws EvaluationException {
|
||||
return this.resolveExpression().getValue(context, desiredResultType);
|
||||
}
|
||||
|
||||
public <T> T getValue(EvaluationContext context, Object rootObject, Class<T> desiredResultType) throws EvaluationException {
|
||||
return this.resolveExpression().getValue(context, rootObject, desiredResultType);
|
||||
}
|
||||
|
||||
public Class<?> getValueType() throws EvaluationException {
|
||||
return this.resolveExpression().getValueType();
|
||||
}
|
||||
|
||||
public Class<?> getValueType(Object rootObject) throws EvaluationException {
|
||||
return this.resolveExpression().getValueType(rootObject);
|
||||
}
|
||||
|
||||
public Class<?> getValueType(EvaluationContext context) throws EvaluationException {
|
||||
return this.resolveExpression().getValueType(context);
|
||||
}
|
||||
|
||||
public Class<?> getValueType(EvaluationContext context, Object rootObject) throws EvaluationException {
|
||||
return this.resolveExpression().getValueType(context, rootObject);
|
||||
}
|
||||
|
||||
public TypeDescriptor getValueTypeDescriptor() throws EvaluationException {
|
||||
return this.resolveExpression().getValueTypeDescriptor();
|
||||
}
|
||||
|
||||
public TypeDescriptor getValueTypeDescriptor(Object rootObject) throws EvaluationException {
|
||||
return this.resolveExpression().getValueTypeDescriptor(rootObject);
|
||||
}
|
||||
|
||||
public TypeDescriptor getValueTypeDescriptor(EvaluationContext context) throws EvaluationException {
|
||||
return this.resolveExpression().getValueTypeDescriptor(context);
|
||||
}
|
||||
|
||||
public TypeDescriptor getValueTypeDescriptor(EvaluationContext context, Object rootObject) throws EvaluationException {
|
||||
return this.resolveExpression().getValueTypeDescriptor(context, rootObject);
|
||||
}
|
||||
|
||||
public boolean isWritable(EvaluationContext context) throws EvaluationException {
|
||||
return this.resolveExpression().isWritable(context);
|
||||
}
|
||||
|
||||
public boolean isWritable(EvaluationContext context, Object rootObject) throws EvaluationException {
|
||||
return this.resolveExpression().isWritable(context, rootObject);
|
||||
}
|
||||
|
||||
public boolean isWritable(Object rootObject) throws EvaluationException {
|
||||
return this.resolveExpression().isWritable(rootObject);
|
||||
}
|
||||
|
||||
public void setValue(EvaluationContext context, Object value) throws EvaluationException {
|
||||
this.resolveExpression().setValue(context, value);
|
||||
}
|
||||
|
||||
public void setValue(Object rootObject, Object value) throws EvaluationException {
|
||||
this.resolveExpression().setValue(rootObject, value);
|
||||
}
|
||||
|
||||
public void setValue(EvaluationContext context, Object rootObject, Object value) throws EvaluationException {
|
||||
this.resolveExpression().setValue(context, rootObject, value);
|
||||
}
|
||||
|
||||
public String getExpressionString() {
|
||||
return this.resolveExpression().getExpressionString();
|
||||
}
|
||||
|
||||
private Expression resolveExpression() {
|
||||
Locale locale = LocaleContextHolder.getLocale();
|
||||
Expression expression = this.expressionSource.getExpression(this.key, locale);
|
||||
Assert.state(expression != null, "Unable to resolve Expression with key '" + this.key + "'");
|
||||
return expression;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.
|
||||
@@ -14,12 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.xml.router;
|
||||
package org.springframework.integration.expression;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import java.util.Locale;
|
||||
|
||||
public interface XmlValidator {
|
||||
|
||||
public boolean isValid(Source source) ;
|
||||
import org.springframework.expression.Expression;
|
||||
|
||||
/**
|
||||
* Strategy interface for retrieving Expressions.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface ExpressionSource {
|
||||
|
||||
Expression getExpression(String key, Locale locale);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
* 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.expression;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
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.util.Assert;
|
||||
import org.springframework.util.DefaultPropertiesPersister;
|
||||
import org.springframework.util.PropertiesPersister;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link ExpressionSource} implementation that accesses resource bundles using specified basenames.
|
||||
* This class uses {@link java.util.Properties} instances as its custom data structure for expressions,
|
||||
* loading them via a {@link org.springframework.util.PropertiesPersister} strategy: The default
|
||||
* strategy is capable of loading properties files with a specific character encoding, if desired.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
* @see #setCacheSeconds
|
||||
* @see #setBasenames
|
||||
* @see #setDefaultEncoding
|
||||
* @see #setFileEncodings
|
||||
* @see #setPropertiesPersister
|
||||
* @see #setResourceLoader
|
||||
* @see org.springframework.util.DefaultPropertiesPersister
|
||||
* @see org.springframework.core.io.DefaultResourceLoader
|
||||
* @see java.util.ResourceBundle
|
||||
*/
|
||||
public class ReloadableResourceBundleExpressionSource implements ExpressionSource, ResourceLoaderAware {
|
||||
|
||||
private static final String PROPERTIES_SUFFIX = ".properties";
|
||||
|
||||
private static final String XML_SUFFIX = ".xml";
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ReloadableResourceBundleExpressionSource.class);
|
||||
|
||||
|
||||
private volatile String[] basenames = new String[0];
|
||||
|
||||
private volatile String defaultEncoding;
|
||||
|
||||
private volatile Properties fileEncodings;
|
||||
|
||||
private volatile boolean fallbackToSystemLocale = true;
|
||||
|
||||
private volatile long cacheMillis = -1;
|
||||
|
||||
private volatile PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();
|
||||
|
||||
private volatile ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||
|
||||
/** Cache to hold filename lists per Locale */
|
||||
private final Map<String, Map<Locale, List<String>>> cachedFilenames =
|
||||
new HashMap<String, Map<Locale, List<String>>>();
|
||||
|
||||
/** Cache to hold already loaded properties per filename */
|
||||
private final Map<String, PropertiesHolder> cachedProperties = new HashMap<String, PropertiesHolder>();
|
||||
|
||||
/** Cache to hold merged loaded properties per locale */
|
||||
private final Map<Locale, PropertiesHolder> cachedMergedProperties = new HashMap<Locale, PropertiesHolder>();
|
||||
|
||||
private final ExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
|
||||
|
||||
/**
|
||||
* Set a single basename, following the basic ResourceBundle convention of
|
||||
* not specifying file extension or language codes, but referring to a Spring
|
||||
* resource location: e.g. "META-INF/expressions" for "META-INF/expressions.properties",
|
||||
* "META-INF/expressions_en.properties", etc.
|
||||
* <p>XML properties files are also supported: .g. "META-INF/expressions" will find
|
||||
* and load "META-INF/expressions.xml", "META-INF/expressions_en.xml", etc as well.
|
||||
* @param basename the single basename
|
||||
* @see #setBasenames
|
||||
* @see org.springframework.core.io.ResourceEditor
|
||||
* @see java.util.ResourceBundle
|
||||
*/
|
||||
public void setBasename(String basename) {
|
||||
setBasenames(new String[] {basename});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an array of basenames, each following the basic ResourceBundle convention
|
||||
* of not specifying file extension or language codes, but referring to a Spring
|
||||
* resource location: e.g. "META-INF/expressions" for "META-INF/expressions.properties",
|
||||
* "META-INF/expressions_en.properties", etc.
|
||||
* <p>XML properties files are also supported: .g. "META-INF/expressions" will find
|
||||
* and load "META-INF/expressions.xml", "META-INF/expressions_en.xml", etc as well.
|
||||
* <p>The associated resource bundles will be checked sequentially when resolving
|
||||
* an expression key. Note that expression definitions in a <i>previous</i> resource
|
||||
* bundle will override ones in a later bundle, due to the sequential lookup.
|
||||
* @param basenames an array of basenames
|
||||
* @see #setBasename
|
||||
* @see java.util.ResourceBundle
|
||||
*/
|
||||
public void setBasenames(String[] basenames) {
|
||||
if (basenames != null) {
|
||||
this.basenames = new String[basenames.length];
|
||||
for (int i = 0; i < basenames.length; i++) {
|
||||
String basename = basenames[i];
|
||||
Assert.hasText(basename, "Basename must not be empty");
|
||||
this.basenames[i] = basename.trim();
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.basenames = new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default charset to use for parsing properties files.
|
||||
* Used if no file-specific charset is specified for a file.
|
||||
* <p>Default is none, using the <code>java.util.Properties</code>
|
||||
* default encoding.
|
||||
* <p>Only applies to classic properties files, not to XML files.
|
||||
* @param defaultEncoding the default charset
|
||||
* @see #setFileEncodings
|
||||
* @see org.springframework.util.PropertiesPersister#load
|
||||
*/
|
||||
public void setDefaultEncoding(String defaultEncoding) {
|
||||
this.defaultEncoding = defaultEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set per-file charsets to use for parsing properties files.
|
||||
* <p>Only applies to classic properties files, not to XML files.
|
||||
* @param fileEncodings Properties with filenames as keys and charset
|
||||
* names as values. Filenames have to match the basename syntax,
|
||||
* with optional locale-specific appendices: e.g. "META-INF/expressions"
|
||||
* or "META-INF/expressions_en".
|
||||
* @see #setBasenames
|
||||
* @see org.springframework.util.PropertiesPersister#load
|
||||
*/
|
||||
public void setFileEncodings(Properties fileEncodings) {
|
||||
this.fileEncodings = fileEncodings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to fall back to the system Locale if no files for a specific
|
||||
* Locale have been found. Default is "true"; if this is turned off, the only
|
||||
* fallback will be the default file (e.g. "expressions.properties" for
|
||||
* basename "expressions").
|
||||
* <p>Falling back to the system Locale is the default behavior of
|
||||
* <code>java.util.ResourceBundle</code>. However, this is often not
|
||||
* desirable in an application server environment, where the system Locale
|
||||
* is not relevant to the application at all: Set this flag to "false"
|
||||
* in such a scenario.
|
||||
*/
|
||||
public void setFallbackToSystemLocale(boolean fallbackToSystemLocale) {
|
||||
this.fallbackToSystemLocale = fallbackToSystemLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of seconds to cache loaded properties files.
|
||||
* <ul>
|
||||
* <li>Default is "-1", indicating to cache forever (just like
|
||||
* <code>java.util.ResourceBundle</code>).
|
||||
* <li>A positive number will cache loaded properties files for the given
|
||||
* number of seconds. This is essentially the interval between refresh checks.
|
||||
* Note that a refresh attempt will first check the last-modified timestamp
|
||||
* of the file before actually reloading it; so if files don't change, this
|
||||
* interval can be set rather low, as refresh attempts will not actually reload.
|
||||
* <li>A value of "0" will check the last-modified timestamp of the file on
|
||||
* every expression access. <b>Do not use this in a production environment!</b>
|
||||
* </ul>
|
||||
*/
|
||||
public void setCacheSeconds(int cacheSeconds) {
|
||||
this.cacheMillis = (cacheSeconds * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PropertiesPersister to use for parsing properties files.
|
||||
* <p>The default is a DefaultPropertiesPersister.
|
||||
* @see org.springframework.util.DefaultPropertiesPersister
|
||||
*/
|
||||
public void setPropertiesPersister(PropertiesPersister propertiesPersister) {
|
||||
this.propertiesPersister =
|
||||
(propertiesPersister != null ? propertiesPersister : new DefaultPropertiesPersister());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ResourceLoader to use for loading bundle properties files.
|
||||
* <p>The default is a DefaultResourceLoader. Will get overridden by the
|
||||
* ApplicationContext if running in a context, as it implements the
|
||||
* ResourceLoaderAware interface. Can be manually overridden when
|
||||
* running outside of an ApplicationContext.
|
||||
* @see org.springframework.core.io.DefaultResourceLoader
|
||||
* @see org.springframework.context.ResourceLoaderAware
|
||||
*/
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resolves the given key in the retrieved bundle files to an Expression.
|
||||
*/
|
||||
public Expression getExpression(String key, Locale locale) {
|
||||
String expressionString = this.getExpressionString(key, locale);
|
||||
if (expressionString != null) {
|
||||
return this.parser.parseExpression(expressionString);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getExpressionString(String key, Locale locale) {
|
||||
if (this.cacheMillis < 0) {
|
||||
PropertiesHolder propHolder = getMergedProperties(locale);
|
||||
String result = propHolder.getProperty(key);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (String basename : this.basenames) {
|
||||
List<String> filenames = calculateAllFilenames(basename, locale);
|
||||
for (String filename : filenames) {
|
||||
PropertiesHolder propHolder = getProperties(filename);
|
||||
String result = propHolder.getProperty(key);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a PropertiesHolder that contains the actually visible properties
|
||||
* for a Locale, after merging all specified resource bundles.
|
||||
* Either fetches the holder from the cache or freshly loads it.
|
||||
* <p>Only used when caching resource bundle contents forever, i.e.
|
||||
* with cacheSeconds < 0. Therefore, merged properties are always
|
||||
* cached forever.
|
||||
*/
|
||||
private PropertiesHolder getMergedProperties(Locale locale) {
|
||||
synchronized (this.cachedMergedProperties) {
|
||||
PropertiesHolder mergedHolder = this.cachedMergedProperties.get(locale);
|
||||
if (mergedHolder != null) {
|
||||
return mergedHolder;
|
||||
}
|
||||
Properties mergedProps = new Properties();
|
||||
mergedHolder = new PropertiesHolder(mergedProps, -1);
|
||||
for (int i = this.basenames.length - 1; i >= 0; i--) {
|
||||
List<String> filenames = calculateAllFilenames(this.basenames[i], locale);
|
||||
for (int j = filenames.size() - 1; j >= 0; j--) {
|
||||
String filename = filenames.get(j);
|
||||
PropertiesHolder propHolder = getProperties(filename);
|
||||
if (propHolder.getProperties() != null) {
|
||||
mergedProps.putAll(propHolder.getProperties());
|
||||
}
|
||||
}
|
||||
}
|
||||
this.cachedMergedProperties.put(locale, mergedHolder);
|
||||
return mergedHolder;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate all filenames for the given bundle basename and Locale.
|
||||
* Will calculate filenames for the given Locale, the system Locale
|
||||
* (if applicable), and the default file.
|
||||
* @param basename the basename of the bundle
|
||||
* @param locale the locale
|
||||
* @return the List of filenames to check
|
||||
* @see #setFallbackToSystemLocale
|
||||
* @see #calculateFilenamesForLocale
|
||||
*/
|
||||
private List<String> calculateAllFilenames(String basename, Locale locale) {
|
||||
synchronized (this.cachedFilenames) {
|
||||
Map<Locale, List<String>> localeMap = this.cachedFilenames.get(basename);
|
||||
if (localeMap != null) {
|
||||
List<String> filenames = localeMap.get(locale);
|
||||
if (filenames != null) {
|
||||
return filenames;
|
||||
}
|
||||
}
|
||||
List<String> filenames = new ArrayList<String>(7);
|
||||
filenames.addAll(calculateFilenamesForLocale(basename, locale));
|
||||
if (this.fallbackToSystemLocale && !locale.equals(Locale.getDefault())) {
|
||||
List<String> fallbackFilenames = calculateFilenamesForLocale(basename, Locale.getDefault());
|
||||
for (String fallbackFilename : fallbackFilenames) {
|
||||
if (!filenames.contains(fallbackFilename)) {
|
||||
// Entry for fallback locale that isn't already in filenames list.
|
||||
filenames.add(fallbackFilename);
|
||||
}
|
||||
}
|
||||
}
|
||||
filenames.add(basename);
|
||||
if (localeMap != null) {
|
||||
localeMap.put(locale, filenames);
|
||||
}
|
||||
else {
|
||||
localeMap = new HashMap<Locale, List<String>>();
|
||||
localeMap.put(locale, filenames);
|
||||
this.cachedFilenames.put(basename, localeMap);
|
||||
}
|
||||
return filenames;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the filenames for the given bundle basename and Locale,
|
||||
* appending language code, country code, and variant code.
|
||||
* E.g.: basename "expressions", Locale "de_AT_oo" -> "expressions_de_AT_OO",
|
||||
* "expressions_de_AT", "expressions_de".
|
||||
* <p>Follows the rules defined by {@link java.util.Locale#toString()}.
|
||||
* @param basename the basename of the bundle
|
||||
* @param locale the locale
|
||||
* @return the List of filenames to check
|
||||
*/
|
||||
private List<String> calculateFilenamesForLocale(String basename, Locale locale) {
|
||||
List<String> result = new ArrayList<String>(3);
|
||||
String language = locale.getLanguage();
|
||||
String country = locale.getCountry();
|
||||
String variant = locale.getVariant();
|
||||
StringBuilder temp = new StringBuilder(basename);
|
||||
|
||||
temp.append('_');
|
||||
if (language.length() > 0) {
|
||||
temp.append(language);
|
||||
result.add(0, temp.toString());
|
||||
}
|
||||
|
||||
temp.append('_');
|
||||
if (country.length() > 0) {
|
||||
temp.append(country);
|
||||
result.add(0, temp.toString());
|
||||
}
|
||||
|
||||
if (variant.length() > 0 && (language.length() > 0 || country.length() > 0)) {
|
||||
temp.append('_').append(variant);
|
||||
result.add(0, temp.toString());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a PropertiesHolder for the given filename, either from the
|
||||
* cache or freshly loaded.
|
||||
* @param filename the bundle filename (basename + Locale)
|
||||
* @return the current PropertiesHolder for the bundle
|
||||
*/
|
||||
private PropertiesHolder getProperties(String filename) {
|
||||
synchronized (this.cachedProperties) {
|
||||
PropertiesHolder propHolder = this.cachedProperties.get(filename);
|
||||
if (propHolder != null &&
|
||||
(propHolder.getRefreshTimestamp() < 0 ||
|
||||
propHolder.getRefreshTimestamp() > System.currentTimeMillis() - this.cacheMillis)) {
|
||||
return propHolder;
|
||||
}
|
||||
return refreshProperties(filename, propHolder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the PropertiesHolder for the given bundle filename.
|
||||
* The holder can be <code>null</code> if not cached before, or a timed-out cache entry
|
||||
* (potentially getting re-validated against the current last-modified timestamp).
|
||||
* @param filename the bundle filename (basename + Locale)
|
||||
* @param propHolder the current PropertiesHolder for the bundle
|
||||
*/
|
||||
private PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
|
||||
long refreshTimestamp = (this.cacheMillis < 0) ? -1 : System.currentTimeMillis();
|
||||
|
||||
Resource resource = this.resourceLoader.getResource(filename + PROPERTIES_SUFFIX);
|
||||
if (!resource.exists()) {
|
||||
resource = this.resourceLoader.getResource(filename + XML_SUFFIX);
|
||||
}
|
||||
|
||||
if (resource.exists()) {
|
||||
long fileTimestamp = -1;
|
||||
if (this.cacheMillis >= 0) {
|
||||
// Last-modified timestamp of file will just be read if caching with timeout.
|
||||
try {
|
||||
fileTimestamp = resource.lastModified();
|
||||
if (propHolder != null && propHolder.getFileTimestamp() == fileTimestamp) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Re-caching properties for filename [" + filename + "] - file hasn't been modified");
|
||||
}
|
||||
propHolder.setRefreshTimestamp(refreshTimestamp);
|
||||
return propHolder;
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// Probably a class path resource: cache it forever.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(
|
||||
resource + " could not be resolved in the file system - assuming that is hasn't changed", ex);
|
||||
}
|
||||
fileTimestamp = -1;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Properties props = loadProperties(resource, filename);
|
||||
propHolder = new PropertiesHolder(props, fileTimestamp);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Could not parse properties file [" + resource.getFilename() + "]", ex);
|
||||
}
|
||||
// Empty holder representing "not valid".
|
||||
propHolder = new PropertiesHolder();
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
// Resource does not exist.
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No properties file found for [" + filename + "] - neither plain properties nor XML");
|
||||
}
|
||||
// Empty holder representing "not found".
|
||||
propHolder = new PropertiesHolder();
|
||||
}
|
||||
|
||||
propHolder.setRefreshTimestamp(refreshTimestamp);
|
||||
this.cachedProperties.put(filename, propHolder);
|
||||
return propHolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the properties from the given resource.
|
||||
* @param resource the resource to load from
|
||||
* @param filename the original bundle filename (basename + Locale)
|
||||
* @return the populated Properties instance
|
||||
* @throws IOException if properties loading failed
|
||||
*/
|
||||
private Properties loadProperties(Resource resource, String filename) throws IOException {
|
||||
InputStream is = resource.getInputStream();
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
if (resource.getFilename().endsWith(XML_SUFFIX)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loading properties [" + resource.getFilename() + "]");
|
||||
}
|
||||
this.propertiesPersister.loadFromXml(props, is);
|
||||
}
|
||||
else {
|
||||
String encoding = null;
|
||||
if (this.fileEncodings != null) {
|
||||
encoding = this.fileEncodings.getProperty(filename);
|
||||
}
|
||||
if (encoding == null) {
|
||||
encoding = this.defaultEncoding;
|
||||
}
|
||||
if (encoding != null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loading properties [" + resource.getFilename() + "] with encoding '" + encoding + "'");
|
||||
}
|
||||
this.propertiesPersister.load(props, new InputStreamReader(is, encoding));
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Loading properties [" + resource.getFilename() + "]");
|
||||
}
|
||||
this.propertiesPersister.load(props, is);
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
finally {
|
||||
is.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the resource bundle cache.
|
||||
* Subsequent resolve calls will lead to reloading of the properties files.
|
||||
*/
|
||||
public void clearCache() {
|
||||
logger.debug("Clearing entire resource bundle cache");
|
||||
synchronized (this.cachedProperties) {
|
||||
this.cachedProperties.clear();
|
||||
}
|
||||
synchronized (this.cachedMergedProperties) {
|
||||
this.cachedMergedProperties.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + ": basenames=[" + StringUtils.arrayToCommaDelimitedString(this.basenames) + "]";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* PropertiesHolder for caching.
|
||||
* Stores the last-modified timestamp of the source file for efficient
|
||||
* change detection, and the timestamp of the last refresh attempt
|
||||
* (updated every time the cache entry gets re-validated).
|
||||
*/
|
||||
private class PropertiesHolder {
|
||||
|
||||
private Properties properties;
|
||||
|
||||
private long fileTimestamp = -1;
|
||||
|
||||
private long refreshTimestamp = -1;
|
||||
|
||||
|
||||
public PropertiesHolder(Properties properties, long fileTimestamp) {
|
||||
this.properties = properties;
|
||||
this.fileTimestamp = fileTimestamp;
|
||||
}
|
||||
|
||||
public PropertiesHolder() {
|
||||
}
|
||||
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public long getFileTimestamp() {
|
||||
return fileTimestamp;
|
||||
}
|
||||
|
||||
public void setRefreshTimestamp(long refreshTimestamp) {
|
||||
this.refreshTimestamp = refreshTimestamp;
|
||||
}
|
||||
|
||||
public long getRefreshTimestamp() {
|
||||
return refreshTimestamp;
|
||||
}
|
||||
|
||||
public String getProperty(String code) {
|
||||
if (this.properties == null) {
|
||||
return null;
|
||||
}
|
||||
return this.properties.getProperty(code);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -100,14 +100,24 @@ public class MessageFilter extends AbstractReplyProducingMessageHandler {
|
||||
|
||||
@Override
|
||||
protected Object handleRequestMessage(Message<?> message) {
|
||||
if (this.selector.accept(message)) {
|
||||
return message;
|
||||
}
|
||||
Throwable filterException = null;
|
||||
try {
|
||||
if (this.selector.accept(message)) {
|
||||
return message;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
filterException = e;
|
||||
}
|
||||
if (this.discardChannel != null) {
|
||||
this.getMessagingTemplate().send(this.discardChannel, message);
|
||||
}
|
||||
if (this.throwExceptionOnRejection) {
|
||||
throw new MessageRejectedException(message);
|
||||
if (filterException != null){
|
||||
throw new MessageRejectedException(message, "MessageFilter '" + this.getComponentName() + "' rejected Message", filterException);
|
||||
}
|
||||
else {
|
||||
throw new MessageRejectedException(message, "MessageFilter '" + this.getComponentName() + "' rejected Message");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.integration.MessageHeaders;
|
||||
import org.springframework.integration.context.IntegrationContextUtils;
|
||||
import org.springframework.integration.context.IntegrationObjectSupport;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.core.MessageProducer;
|
||||
import org.springframework.integration.core.MessagingTemplate;
|
||||
import org.springframework.integration.message.ErrorMessage;
|
||||
import org.springframework.integration.store.MessageStore;
|
||||
@@ -70,7 +71,7 @@ import org.springframework.util.Assert;
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.3
|
||||
*/
|
||||
public class DelayHandler extends IntegrationObjectSupport implements MessageHandler, Ordered, DisposableBean {
|
||||
public class DelayHandler extends IntegrationObjectSupport implements MessageHandler, MessageProducer, Ordered, DisposableBean {
|
||||
|
||||
private final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
@@ -25,20 +23,22 @@ import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.dispatcher.AggregateMessageDeliveryException;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* MessageHandler implementation that simply logs the Message or its payload
|
||||
* depending on the value of the 'shouldLogFullMessage' property. If logging
|
||||
* the payload, and it is assignable to Throwable, it will log the stack trace.
|
||||
* By default, it will log the payload only.
|
||||
* MessageHandler implementation that simply logs the Message or its payload depending on the value of the
|
||||
* 'shouldLogFullMessage' property. If logging the payload, and it is assignable to Throwable, it will log the stack
|
||||
* trace. By default, it will log the payload only.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.1
|
||||
*/
|
||||
public class LoggingHandler extends AbstractMessageHandler {
|
||||
|
||||
private static enum Level { FATAL, ERROR, WARN, INFO, DEBUG, TRACE }
|
||||
private static enum Level {
|
||||
FATAL, ERROR, WARN, INFO, DEBUG, TRACE
|
||||
}
|
||||
|
||||
private static final SpelExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
|
||||
|
||||
@@ -48,18 +48,18 @@ public class LoggingHandler extends AbstractMessageHandler {
|
||||
|
||||
private final EvaluationContext evaluationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create a LoggingHandler with the given log level (case-insensitive).
|
||||
* <p>The valid levels are: FATAL, ERROR, WARN, INFO, DEBUG, or TRACE
|
||||
* <p>
|
||||
* The valid levels are: FATAL, ERROR, WARN, INFO, DEBUG, or TRACE
|
||||
*/
|
||||
public LoggingHandler(String level) {
|
||||
try {
|
||||
this.level = Level.valueOf(level.toUpperCase());
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Invalid log level '" + level +
|
||||
"'. The (case-insensitive) supported values are: " + StringUtils.arrayToCommaDelimitedString(Level.values()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Invalid log level '" + level
|
||||
+ "'. The (case-insensitive) supported values are: "
|
||||
+ StringUtils.arrayToCommaDelimitedString(Level.values()));
|
||||
}
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
||||
evaluationContext.addPropertyAccessor(new MapAccessor());
|
||||
@@ -67,18 +67,17 @@ public class LoggingHandler extends AbstractMessageHandler {
|
||||
this.expression = EXPRESSION_PARSER.parseExpression("payload");
|
||||
}
|
||||
|
||||
|
||||
public void setExpression(String expressionString) {
|
||||
this.expression = EXPRESSION_PARSER.parseExpression(expressionString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to log the full Message. Otherwise, only the payload
|
||||
* will be logged. This value is <code>false</code> by default.
|
||||
* Specify whether to log the full Message. Otherwise, only the payload will be logged. This value is
|
||||
* <code>false</code> by default.
|
||||
*/
|
||||
public void setShouldLogFullMessage(boolean shouldLogFullMessage) {
|
||||
this.expression = (shouldLogFullMessage) ? EXPRESSION_PARSER.parseExpression("#root")
|
||||
: EXPRESSION_PARSER.parseExpression("payload");
|
||||
this.expression = (shouldLogFullMessage) ? EXPRESSION_PARSER.parseExpression("#root") : EXPRESSION_PARSER
|
||||
.parseExpression("payload");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,40 +90,47 @@ public class LoggingHandler extends AbstractMessageHandler {
|
||||
Object logMessage = this.expression.getValue(this.evaluationContext, message);
|
||||
if (logMessage instanceof Throwable) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
((Throwable) logMessage).printStackTrace(new PrintWriter(stringWriter, true));
|
||||
if (logMessage instanceof AggregateMessageDeliveryException) {
|
||||
stringWriter.append(((Throwable) logMessage).getMessage());
|
||||
for (Exception exception : (List<? extends Exception>) ((AggregateMessageDeliveryException)logMessage).getAggregatedExceptions()) {
|
||||
exception.printStackTrace(new PrintWriter(stringWriter, true));
|
||||
}
|
||||
} else {
|
||||
((Throwable) logMessage).printStackTrace(new PrintWriter(stringWriter, true));
|
||||
}
|
||||
logMessage = stringWriter.toString();
|
||||
}
|
||||
switch (this.level) {
|
||||
case FATAL :
|
||||
if (logger.isFatalEnabled()) {
|
||||
logger.fatal(logMessage);
|
||||
}
|
||||
break;
|
||||
case ERROR :
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(logMessage);
|
||||
}
|
||||
break;
|
||||
case WARN :
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(logMessage);
|
||||
}
|
||||
break;
|
||||
case INFO :
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(logMessage);
|
||||
}
|
||||
break;
|
||||
case DEBUG :
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(logMessage);
|
||||
}
|
||||
break;
|
||||
case TRACE :
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(logMessage);
|
||||
}
|
||||
break;
|
||||
case FATAL:
|
||||
if (logger.isFatalEnabled()) {
|
||||
logger.fatal(logMessage);
|
||||
}
|
||||
break;
|
||||
case ERROR:
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error(logMessage);
|
||||
}
|
||||
break;
|
||||
case WARN:
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(logMessage);
|
||||
}
|
||||
break;
|
||||
case INFO:
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(logMessage);
|
||||
}
|
||||
break;
|
||||
case DEBUG:
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(logMessage);
|
||||
}
|
||||
break;
|
||||
case TRACE:
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(logMessage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,190 +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.router;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
|
||||
import org.springframework.integration.support.channel.ChannelResolutionException;
|
||||
import org.springframework.integration.support.channel.ChannelResolver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A base class for router implementations that return only the channel name(s)
|
||||
* rather than {@link MessageChannel} instances.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Jonas Partner
|
||||
*/
|
||||
public abstract class AbstractChannelNameResolvingMessageRouter extends AbstractMessageRouter {
|
||||
|
||||
private volatile String prefix;
|
||||
|
||||
private volatile String suffix;
|
||||
|
||||
private volatile ChannelResolver channelResolver;
|
||||
|
||||
private volatile boolean ignoreChannelNameResolutionFailures;
|
||||
|
||||
|
||||
/**
|
||||
* Specify the {@link ChannelResolver} strategy to use.
|
||||
* The default is a BeanFactoryChannelResolver.
|
||||
*/
|
||||
public void setChannelResolver(ChannelResolver channelResolver) {
|
||||
Assert.notNull(channelResolver, "'channelResolver' must not be null");
|
||||
this.channelResolver = channelResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a prefix to be added to each channel name prior to resolution.
|
||||
*/
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a suffix to be added to each channel name prior to resolution.
|
||||
*/
|
||||
public void setSuffix(String suffix) {
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether this router should ignore any failure to resolve a channel name to
|
||||
* an actual MessageChannel instance when delegating to the ChannelResolver strategy.
|
||||
*/
|
||||
public void setIgnoreChannelNameResolutionFailures(boolean ignoreChannelNameResolutionFailures) {
|
||||
this.ignoreChannelNameResolutionFailures = ignoreChannelNameResolutionFailures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInit() {
|
||||
BeanFactory beanFactory = this.getBeanFactory();
|
||||
if (this.channelResolver == null && beanFactory != null) {
|
||||
this.channelResolver = new BeanFactoryChannelResolver(beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
private MessageChannel resolveChannelForName(String channelName, Message<?> message) {
|
||||
Assert.state(this.channelResolver != null,
|
||||
"unable to resolve channel names, no ChannelResolver available");
|
||||
MessageChannel channel = null;
|
||||
try {
|
||||
channel = this.channelResolver.resolveChannelName(channelName);
|
||||
}
|
||||
catch (ChannelResolutionException e) {
|
||||
if (!this.ignoreChannelNameResolutionFailures) {
|
||||
throw new MessagingException(message,
|
||||
"failed to resolve channel name '" + channelName + "'", e);
|
||||
}
|
||||
}
|
||||
if (channel == null && !this.ignoreChannelNameResolutionFailures) {
|
||||
throw new MessagingException(message,
|
||||
"failed to resolve channel name '" + channelName + "'");
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
|
||||
this.afterPropertiesSet();
|
||||
Collection<MessageChannel> channels = new ArrayList<MessageChannel>();
|
||||
Collection<Object> channelsReturned = this.getChannelIndicatorList(message);
|
||||
addToCollection(channels, channelsReturned, message);
|
||||
return channels;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addToCollection(Collection<MessageChannel> channels, Collection<?> channelIndicators, Message<?> message) {
|
||||
if (channelIndicators == null) {
|
||||
return;
|
||||
}
|
||||
for (Object channelIndicator : channelIndicators) {
|
||||
if (channelIndicator == null) {
|
||||
continue;
|
||||
}
|
||||
else if (channelIndicator instanceof MessageChannel) {
|
||||
channels.add((MessageChannel) channelIndicator);
|
||||
}
|
||||
else if (channelIndicator instanceof MessageChannel[]) {
|
||||
channels.addAll(Arrays.asList((MessageChannel[]) channelIndicator));
|
||||
}
|
||||
else if (channelIndicator instanceof String) {
|
||||
addChannelFromString(channels, (String) channelIndicator, message);
|
||||
}
|
||||
else if (channelIndicator instanceof String[]) {
|
||||
for (String indicatorName : (String[]) channelIndicator) {
|
||||
addChannelFromString(channels, indicatorName, message);
|
||||
}
|
||||
}
|
||||
else if (channelIndicator instanceof Collection) {
|
||||
addToCollection(channels, (Collection<?>) channelIndicator, message);
|
||||
}
|
||||
else if (this.getRequiredConversionService().canConvert(channelIndicator.getClass(), String.class)) {
|
||||
addChannelFromString(channels,
|
||||
this.getConversionService().convert(channelIndicator, String.class), message);
|
||||
}
|
||||
else {
|
||||
throw new MessagingException(
|
||||
"unsupported return type for router [" + channelIndicator.getClass() + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addChannelFromString(Collection<MessageChannel> channels, String channelName, Message<?> message) {
|
||||
if (channelName.indexOf(',') != -1) {
|
||||
for (String name : StringUtils.commaDelimitedListToStringArray(channelName)) {
|
||||
addChannelFromString(channels, name, message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this.prefix != null) {
|
||||
channelName = this.prefix + channelName;
|
||||
}
|
||||
if (this.suffix != null) {
|
||||
channelName = channelName + suffix;
|
||||
}
|
||||
MessageChannel channel = resolveChannelForName(channelName, message);
|
||||
if (channel != null) {
|
||||
channels.add(channel);
|
||||
}
|
||||
}
|
||||
|
||||
private ConversionService getRequiredConversionService() {
|
||||
if (this.getConversionService() == null) {
|
||||
this.setConversionService(ConversionServiceFactory.createDefaultConversionService());
|
||||
}
|
||||
return this.getConversionService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to return the channel indicators.
|
||||
*/
|
||||
protected abstract List<Object> getChannelIndicatorList(Message<?> message);
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ import org.springframework.util.Assert;
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
class AbstractMessageProcessingRouter extends AbstractChannelNameResolvingMessageRouter {
|
||||
class AbstractMessageProcessingRouter extends AbstractMessageRouter {
|
||||
|
||||
private final MessageProcessor<Object> messageProcessor;
|
||||
|
||||
|
||||
@@ -16,8 +16,16 @@
|
||||
|
||||
package org.springframework.integration.router;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
@@ -25,11 +33,18 @@ import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.core.MessagingTemplate;
|
||||
import org.springframework.integration.handler.AbstractMessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
|
||||
import org.springframework.integration.support.channel.ChannelResolutionException;
|
||||
import org.springframework.integration.support.channel.ChannelResolver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class for Message Routers.
|
||||
* Base class for all Message Routers.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public abstract class AbstractMessageRouter extends AbstractMessageHandler {
|
||||
|
||||
@@ -42,6 +57,67 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
|
||||
private volatile boolean applySequence;
|
||||
|
||||
private final MessagingTemplate messagingTemplate = new MessagingTemplate();
|
||||
|
||||
private volatile String prefix;
|
||||
|
||||
private volatile String suffix;
|
||||
|
||||
private volatile ChannelResolver channelResolver;
|
||||
|
||||
private volatile boolean ignoreChannelNameResolutionFailures;
|
||||
|
||||
protected volatile Map<String, String> channelIdentifierMap = new ConcurrentHashMap<String, String>();
|
||||
|
||||
/**
|
||||
* Specify the {@link ChannelResolver} strategy to use.
|
||||
* The default is a BeanFactoryChannelResolver.
|
||||
*/
|
||||
public void setChannelResolver(ChannelResolver channelResolver) {
|
||||
Assert.notNull(channelResolver, "'channelResolver' must not be null");
|
||||
this.channelResolver = channelResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a prefix to be added to each channel name prior to resolution.
|
||||
*/
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a suffix to be added to each channel name prior to resolution.
|
||||
*/
|
||||
public void setSuffix(String suffix) {
|
||||
this.suffix = suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether this router should ignore any failure to resolve a channel name to
|
||||
* an actual MessageChannel instance when delegating to the ChannelResolver strategy.
|
||||
*/
|
||||
public void setIgnoreChannelNameResolutionFailures(boolean ignoreChannelNameResolutionFailures) {
|
||||
this.ignoreChannelNameResolutionFailures = ignoreChannelNameResolutionFailures;
|
||||
}
|
||||
/**
|
||||
* Allows you to set the map which will map channel identifiers to channel names.
|
||||
* Channel names will be resolve via {@link ChannelResolver}
|
||||
* @param channelIdentifierMap
|
||||
*/
|
||||
public void setChannelIdentifierMap(Map<String, String> channelIdentifierMap) {
|
||||
this.channelIdentifierMap.clear();
|
||||
this.channelIdentifierMap.putAll(channelIdentifierMap);
|
||||
}
|
||||
|
||||
public void setChannelMapping(String channelIdentifier, String channelName){
|
||||
this.channelIdentifierMap.put(channelIdentifier, channelName);
|
||||
}
|
||||
/**
|
||||
* Removes channel mapping for a give channel identifier
|
||||
* @param channelIdentifier
|
||||
*/
|
||||
public void removeChannelMapping(String channelIdentifier){
|
||||
this.channelIdentifierMap.remove(channelIdentifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default channel where Messages should be sent if channel resolution fails to return any channels. If no
|
||||
@@ -99,6 +175,33 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
|
||||
protected MessagingTemplate getMessagingTemplate() {
|
||||
return this.messagingTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInit() {
|
||||
BeanFactory beanFactory = this.getBeanFactory();
|
||||
if (this.channelResolver == null && beanFactory != null) {
|
||||
this.channelResolver = new BeanFactoryChannelResolver(beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
|
||||
this.afterPropertiesSet();
|
||||
Collection<MessageChannel> channels = new ArrayList<MessageChannel>();
|
||||
Collection<Object> channelsReturned = this.getChannelIndicatorList(message);
|
||||
addToCollection(channels, channelsReturned, message);
|
||||
return channels;
|
||||
}
|
||||
|
||||
protected ConversionService getRequiredConversionService() {
|
||||
if (this.getConversionService() == null) {
|
||||
this.setConversionService(ConversionServiceFactory.createDefaultConversionService());
|
||||
}
|
||||
return this.getConversionService();
|
||||
}
|
||||
/**
|
||||
* Subclasses must implement this method to return the channel indicators.
|
||||
*/
|
||||
protected abstract List<Object> getChannelIndicatorList(Message<?> message);
|
||||
|
||||
@Override
|
||||
protected void handleMessageInternal(Message<?> message) {
|
||||
@@ -137,9 +240,89 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to return the target channels for a given Message.
|
||||
*/
|
||||
protected abstract Collection<MessageChannel> determineTargetChannels(Message<?> message);
|
||||
private MessageChannel resolveChannelForName(String channelName, Message<?> message) {
|
||||
Assert.state(this.channelResolver != null,
|
||||
"unable to resolve channel names, no ChannelResolver available");
|
||||
MessageChannel channel = null;
|
||||
try {
|
||||
channel = this.channelResolver.resolveChannelName(channelName);
|
||||
}
|
||||
catch (ChannelResolutionException e) {
|
||||
if (!this.ignoreChannelNameResolutionFailures) {
|
||||
throw new MessagingException(message,
|
||||
"failed to resolve channel name '" + channelName + "'", e);
|
||||
}
|
||||
}
|
||||
if (channel == null && !this.ignoreChannelNameResolutionFailures) {
|
||||
throw new MessagingException(message,
|
||||
"failed to resolve channel name '" + channelName + "'");
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
private void addChannelFromString(Collection<MessageChannel> channels, String channelIdentifier, Message<?> message) {
|
||||
if (channelIdentifier.indexOf(',') != -1) {
|
||||
for (String name : StringUtils.commaDelimitedListToStringArray(channelIdentifier)) {
|
||||
addChannelFromString(channels, name, message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (this.prefix != null) {
|
||||
channelIdentifier = this.prefix + channelIdentifier;
|
||||
}
|
||||
if (this.suffix != null) {
|
||||
channelIdentifier = channelIdentifier + suffix;
|
||||
}
|
||||
/*
|
||||
* Some routers due to their complex nature will already resolve 'channelIdentifier'
|
||||
* to 'channelName' (e.g., PTR, EMETR)
|
||||
*/
|
||||
String channelName = channelIdentifier;
|
||||
if (!CollectionUtils.isEmpty(channelIdentifierMap) && channelIdentifierMap.containsKey(channelIdentifier)){
|
||||
channelName = channelIdentifierMap.get(channelIdentifier);
|
||||
}
|
||||
|
||||
if (this.channelResolver != null){
|
||||
MessageChannel channel = resolveChannelForName(channelName, message);
|
||||
if (channel != null) {
|
||||
channels.add(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addToCollection(Collection<MessageChannel> channels, Collection<?> channelIndicators, Message<?> message) {
|
||||
if (channelIndicators == null) {
|
||||
return;
|
||||
}
|
||||
for (Object channelIndicator : channelIndicators) {
|
||||
if (channelIndicator == null) {
|
||||
continue;
|
||||
}
|
||||
else if (channelIndicator instanceof MessageChannel) {
|
||||
channels.add((MessageChannel) channelIndicator);
|
||||
}
|
||||
else if (channelIndicator instanceof MessageChannel[]) {
|
||||
channels.addAll(Arrays.asList((MessageChannel[]) channelIndicator));
|
||||
}
|
||||
else if (channelIndicator instanceof String) {
|
||||
addChannelFromString(channels, (String) channelIndicator, message);
|
||||
}
|
||||
else if (channelIndicator instanceof String[]) {
|
||||
for (String indicatorName : (String[]) channelIndicator) {
|
||||
addChannelFromString(channels, indicatorName, message);
|
||||
}
|
||||
}
|
||||
else if (channelIndicator instanceof Collection) {
|
||||
addToCollection(channels, (Collection<?>) channelIndicator, message);
|
||||
}
|
||||
else if (this.getRequiredConversionService().canConvert(channelIndicator.getClass(), String.class)) {
|
||||
addChannelFromString(channels,
|
||||
this.getConversionService().convert(channelIndicator, String.class), message);
|
||||
}
|
||||
else {
|
||||
throw new MessagingException(
|
||||
"unsupported return type for router [" + channelIndicator.getClass() + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.springframework.integration.Message;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractSingleChannelNameRouter extends AbstractChannelNameResolvingMessageRouter {
|
||||
public abstract class AbstractSingleChannelNameRouter extends AbstractMessageRouter {
|
||||
|
||||
@Override
|
||||
protected final List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.router;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
|
||||
/**
|
||||
* Extends {@link AbstractMessageRouter} to support router implementations that
|
||||
* always return a single {@link MessageChannel} instance (or null).
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractSingleChannelRouter extends AbstractMessageRouter {
|
||||
|
||||
@Override
|
||||
protected final Collection<MessageChannel> determineTargetChannels(Message<?> message) {
|
||||
MessageChannel channel = this.determineTargetChannel(message);
|
||||
return (channel != null) ? Collections.singletonList(channel) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to return the target channel.
|
||||
*/
|
||||
protected abstract MessageChannel determineTargetChannel(Message<?> message);
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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,12 +16,11 @@
|
||||
|
||||
package org.springframework.integration.router;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A Message Router that resolves the target {@link MessageChannel} for
|
||||
@@ -29,34 +28,26 @@ import org.springframework.util.Assert;
|
||||
* the most specific cause of the error for which a channel-mapping exists.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class ErrorMessageExceptionTypeRouter extends AbstractSingleChannelRouter {
|
||||
|
||||
private volatile Map<Class<? extends Throwable>, MessageChannel> exceptionTypeChannelMap =
|
||||
new ConcurrentHashMap<Class<? extends Throwable>, MessageChannel>();
|
||||
|
||||
|
||||
public void setExceptionTypeChannelMap(Map<Class<? extends Throwable>, MessageChannel> exceptionTypeChannelMap) {
|
||||
Assert.notNull(exceptionTypeChannelMap, "exceptionTypeChannelMap must not be null");
|
||||
this.exceptionTypeChannelMap = exceptionTypeChannelMap;
|
||||
}
|
||||
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class ErrorMessageExceptionTypeRouter extends AbstractMessageRouter {
|
||||
|
||||
@Override
|
||||
protected MessageChannel determineTargetChannel(Message<?> message) {
|
||||
MessageChannel channel = null;
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
String channelName = null;
|
||||
String channelIdentifier = null;
|
||||
Object payload = message.getPayload();
|
||||
if (payload != null && (payload instanceof Throwable)) {
|
||||
Throwable mostSpecificCause = (Throwable) payload;
|
||||
while (mostSpecificCause != null) {
|
||||
MessageChannel mappedChannel = this.exceptionTypeChannelMap.get(mostSpecificCause.getClass());
|
||||
if (mappedChannel != null) {
|
||||
channel = mappedChannel;
|
||||
channelIdentifier = mostSpecificCause.getClass().getName();
|
||||
if (channelIdentifierMap != null){
|
||||
String tempChannelName = channelIdentifierMap.get(channelIdentifier);
|
||||
channelName = tempChannelName == null ? channelName : tempChannelName;
|
||||
}
|
||||
mostSpecificCause = mostSpecificCause.getCause();
|
||||
}
|
||||
}
|
||||
return channel;
|
||||
return Collections.singletonList((Object)channelName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Mark Fisher
|
||||
* @since 1.0.3
|
||||
*/
|
||||
public class HeaderValueRouter extends AbstractChannelNameResolvingMessageRouter {
|
||||
public class HeaderValueRouter extends AbstractMessageRouter {
|
||||
|
||||
private final String headerName;
|
||||
|
||||
|
||||
@@ -16,39 +16,67 @@
|
||||
|
||||
package org.springframework.integration.router;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.util.ClassUtils;
|
||||
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A Message Router that resolves the {@link MessageChannel} based on the
|
||||
* {@link Message Message's} payload type.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class PayloadTypeRouter extends AbstractSingleChannelRouter {
|
||||
|
||||
private volatile Map<Class<?>, MessageChannel> payloadTypeChannelMap =
|
||||
new ConcurrentHashMap<Class<?>, MessageChannel>();
|
||||
|
||||
|
||||
public void setPayloadTypeChannelMap(Map<Class<?>, MessageChannel> payloadTypeChannelMap) {
|
||||
Assert.notNull(payloadTypeChannelMap, "payloadTypeChannelMap must not be null");
|
||||
this.payloadTypeChannelMap = payloadTypeChannelMap;
|
||||
}
|
||||
|
||||
public class PayloadTypeRouter extends AbstractMessageRouter {
|
||||
/**
|
||||
* Will select the most appropriate channel name matching channel identifiers
|
||||
* which are fully qualifies class name to type available while traversing payload type.
|
||||
* To resolve ties and conflicts (e.g., Serializable and String) it will match:
|
||||
* 1. Type name to channel identifier else...
|
||||
* 2. Name of the subclass of the type to channel identifier elc...
|
||||
* 3. Name of the Interface of the type to channel identifier while also
|
||||
* preferring direct interface over in-direct subclass
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected MessageChannel determineTargetChannel(Message<?> message) {
|
||||
Class<?> closestMatch = ClassUtils.findClosestMatch(
|
||||
message.getPayload().getClass(), this.payloadTypeChannelMap.keySet(), true);
|
||||
if (closestMatch != null) {
|
||||
return this.payloadTypeChannelMap.get(closestMatch);
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
Class<?> firstInterfaceMatch = null;
|
||||
Class<?> type = message.getPayload().getClass();
|
||||
|
||||
while (type != null && !CollectionUtils.isEmpty(channelIdentifierMap)) {
|
||||
Class<?>[] interfaces = type.getInterfaces();
|
||||
// first try to find a match amongst the interfaces and also check if there is more then one
|
||||
for (Class<?> interfase : interfaces) {
|
||||
if (channelIdentifierMap.containsKey(interfase.getName())){
|
||||
if (firstInterfaceMatch != null){
|
||||
throw new IllegalStateException("Unresolvable ambiguity while attempting to find closest match for [" +
|
||||
type.getName() + "]. Candidate types [" + firstInterfaceMatch.getName() + "] and [" + interfase.getName() +
|
||||
"] have equal weight.");
|
||||
}
|
||||
else {
|
||||
firstInterfaceMatch = interfase;
|
||||
}
|
||||
}
|
||||
}
|
||||
// the actual type should favor the possible interface match
|
||||
String channelName = channelIdentifierMap.get(type.getName());
|
||||
if (!StringUtils.hasText(channelName)){
|
||||
if (firstInterfaceMatch != null){
|
||||
return Collections.singletonList((Object)channelIdentifierMap.get(firstInterfaceMatch.getName()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Collections.singletonList((Object)channelName);
|
||||
}
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
package org.springframework.integration.router;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
@@ -51,6 +51,7 @@ import org.springframework.util.Assert;
|
||||
* solution.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class RecipientListRouter extends AbstractMessageRouter implements InitializingBean {
|
||||
|
||||
@@ -88,10 +89,10 @@ public class RecipientListRouter extends AbstractMessageRouter implements Initia
|
||||
public final void onInit() {
|
||||
Assert.notEmpty(this.recipients, "a non-empty recipient list is required");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
|
||||
List<MessageChannel> channels = new ArrayList<MessageChannel>();
|
||||
|
||||
@Override
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
List<Object> channels = new ArrayList<Object>();
|
||||
List<Recipient> recipientList = this.recipients;
|
||||
for (Recipient recipient : recipientList) {
|
||||
if (recipient.accept(message)) {
|
||||
@@ -100,8 +101,7 @@ public class RecipientListRouter extends AbstractMessageRouter implements Initia
|
||||
}
|
||||
return channels;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class Recipient {
|
||||
|
||||
private final MessageChannel channel;
|
||||
@@ -125,5 +125,4 @@ public class RecipientListRouter extends AbstractMessageRouter implements Initia
|
||||
return this.channel;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
package org.springframework.integration.scheduling;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
|
||||
@@ -39,7 +39,7 @@ public class PollerMetadata {
|
||||
|
||||
private List<Advice> adviceChain;
|
||||
|
||||
private volatile TaskExecutor taskExecutor;
|
||||
private volatile Executor taskExecutor;
|
||||
|
||||
public void setTrigger(Trigger trigger) {
|
||||
this.trigger = trigger;
|
||||
@@ -82,11 +82,11 @@ public class PollerMetadata {
|
||||
return this.adviceChain;
|
||||
}
|
||||
|
||||
public void setTaskExecutor(TaskExecutor taskExecutor) {
|
||||
public void setTaskExecutor(Executor taskExecutor) {
|
||||
this.taskExecutor = taskExecutor;
|
||||
}
|
||||
|
||||
public TaskExecutor getTaskExecutor() {
|
||||
public Executor getTaskExecutor() {
|
||||
return this.taskExecutor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,25 @@ 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 and the expected type
|
||||
* of the expression evaluation result. The expectedType may be null if unknown.
|
||||
*/
|
||||
public ExpressionEvaluatingHeaderValueMessageProcessor(Expression expression, Class<T> expectedType) {
|
||||
this.targetProcessor = new ExpressionEvaluatingMessageProcessor<T>(expression, expectedType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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,17 +16,25 @@
|
||||
package org.springframework.integration.util;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.SimpleTypeConverter;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.convert.ConversionFailedException;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.ConversionServiceFactory;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
/**
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public class BeanFactoryTypeConverter implements TypeConverter, BeanFactoryAware {
|
||||
|
||||
private SimpleTypeConverter delegate = new SimpleTypeConverter();
|
||||
@@ -89,13 +97,21 @@ public class BeanFactoryTypeConverter implements TypeConverter, BeanFactoryAware
|
||||
if (targetType.getType() == Void.class || targetType.getType() == Void.TYPE) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof Collection<?>
|
||||
&& CollectionUtils.isEmpty((Collection<?>) value)
|
||||
&& Collection.class.isAssignableFrom(targetType.getObjectType())){
|
||||
return value;
|
||||
}
|
||||
if (conversionService.canConvert(sourceType, targetType)) {
|
||||
return conversionService.convert(value, sourceType, targetType);
|
||||
}
|
||||
|
||||
if (!String.class.isAssignableFrom(sourceType.getType())) {
|
||||
PropertyEditor editor = delegate.findCustomEditor(sourceType.getType(), null);
|
||||
editor.setValue(value);
|
||||
return editor.getAsText();
|
||||
if (editor != null){ // INT-1441
|
||||
editor.setValue(value);
|
||||
return editor.getAsText();
|
||||
}
|
||||
}
|
||||
return delegate.convertIfNecessary(value, targetType.getType());
|
||||
}
|
||||
|
||||
@@ -1388,6 +1388,9 @@
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="referenceHeaderType">
|
||||
<xsd:sequence minOccurs="0" maxOccurs="1">
|
||||
<xsd:element name="expression" type="innerExpressionType"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="value" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -1929,6 +1932,7 @@ Name of the header whose value to use.
|
||||
<xsd:extension base="channelNameResolvingRouterType">
|
||||
<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="ref" type="xsd:string">
|
||||
@@ -2357,7 +2361,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 +2378,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" default="expressionSource">
|
||||
<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"));
|
||||
|
||||
@@ -20,17 +20,17 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.channel.MapBasedChannelResolver;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
|
||||
import org.springframework.integration.support.channel.ChannelResolver;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
@@ -39,14 +39,16 @@ import org.springframework.integration.channel.QueueChannel;
|
||||
*/
|
||||
public class MessagePublishingInterceptorTests {
|
||||
|
||||
private final MapBasedChannelResolver channelResolver = new MapBasedChannelResolver();
|
||||
private ChannelResolver channelResolver;
|
||||
|
||||
private final QueueChannel testChannel = new QueueChannel();
|
||||
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
channelResolver.setChannelMap(Collections.singletonMap("c", testChannel));
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
channelResolver = new BeanFactoryChannelResolver(beanFactory);
|
||||
beanFactory.registerSingleton("c", testChannel);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -37,19 +37,19 @@
|
||||
</property>
|
||||
<property name="channelMap">
|
||||
<map>
|
||||
<entry key="setName" value="channel" />
|
||||
<entry key="setName" value="messagePublishingInterceptorUsageTestChannel" />
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
<property name="channelResolver">
|
||||
<bean
|
||||
class="org.springframework.integration.channel.MapBasedChannelResolver">
|
||||
<property name="channelMap">
|
||||
<map>
|
||||
<entry key="channel" value-ref="messagePublishingInterceptorUsageTestChannel" />
|
||||
</map>
|
||||
</property>
|
||||
class="org.springframework.integration.support.channel.BeanFactoryChannelResolver">
|
||||
<!-- <property name="channelMap">-->
|
||||
<!-- <map>-->
|
||||
<!-- <entry key="channel" value-ref="messagePublishingInterceptorUsageTestChannel" />-->
|
||||
<!-- </map>-->
|
||||
<!-- </property>-->
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.channel;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.MessageChannel;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MapBasedChannelResolverTests {
|
||||
|
||||
@Test
|
||||
public void mapContainsChannel() {
|
||||
MessageChannel testChannel = new QueueChannel();
|
||||
Map<String, MessageChannel> channelMap = new HashMap<String, MessageChannel>();
|
||||
channelMap.put("testChannel", testChannel);
|
||||
MapBasedChannelResolver resolver = new MapBasedChannelResolver();
|
||||
resolver.setChannelMap(channelMap);
|
||||
MessageChannel result = resolver.resolveChannelName("testChannel");
|
||||
assertNotNull(result);
|
||||
assertEquals(testChannel, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mapDoesNotContainChannel() {
|
||||
MessageChannel testChannel = new QueueChannel();
|
||||
Map<String, MessageChannel> channelMap = new HashMap<String, MessageChannel>();
|
||||
channelMap.put("testChannel", testChannel);
|
||||
MapBasedChannelResolver resolver = new MapBasedChannelResolver();
|
||||
resolver.setChannelMap(channelMap);
|
||||
MessageChannel result = resolver.resolveChannelName("noSuchChannel");
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyMap() {
|
||||
Map<String, MessageChannel> channelMap = new HashMap<String, MessageChannel>();
|
||||
MapBasedChannelResolver resolver = new MapBasedChannelResolver();
|
||||
resolver.setChannelMap(channelMap);
|
||||
MessageChannel result = resolver.resolveChannelName("testChannel");
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void nullMapRejected() {
|
||||
MapBasedChannelResolver resolver = new MapBasedChannelResolver();
|
||||
resolver.setChannelMap(null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
<bean id="payloadTypeRouter" class="org.springframework.integration.router.PayloadTypeRouter">
|
||||
<property name="resolutionRequired" value="true"/>
|
||||
<property name="payloadTypeChannelMap">
|
||||
<property name="channelIdentifierMap">
|
||||
<map>
|
||||
<entry key="java.lang.String" value-ref="strings"/>
|
||||
<entry key="java.lang.String" value="strings"/>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
@@ -31,12 +31,12 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.channel.AbstractMessageChannel;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.MapBasedChannelResolver;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.endpoint.PollingConsumer;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
@@ -45,7 +45,9 @@ import org.springframework.integration.mapping.OutboundMessageMapper;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.scheduling.PollerMetadata;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
|
||||
import org.springframework.integration.support.channel.ChannelResolutionException;
|
||||
import org.springframework.integration.support.channel.ChannelResolver;
|
||||
import org.springframework.integration.support.converter.SimpleMessageConverter;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.test.util.TestUtils.TestApplicationContext;
|
||||
@@ -306,15 +308,27 @@ public class MessagingTemplateTests {
|
||||
@Test
|
||||
public void sendByChannelNameWithCustomChannelResolver() {
|
||||
QueueChannel testChannel = new QueueChannel();
|
||||
Map<String, MessageChannel> channelMap = new HashMap<String, MessageChannel>();
|
||||
channelMap.put("testChannel", testChannel);
|
||||
MapBasedChannelResolver channelResolver = new MapBasedChannelResolver(channelMap);
|
||||
final QueueChannel anotherChannel = new QueueChannel();
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("testChannel", testChannel);
|
||||
|
||||
MessagingTemplate template = new MessagingTemplate();
|
||||
template.setChannelResolver(channelResolver);
|
||||
template.setBeanFactory(beanFactory);
|
||||
|
||||
template.afterPropertiesSet();
|
||||
Message<?> message = MessageBuilder.withPayload("test").build();
|
||||
template.send("testChannel", message);
|
||||
assertEquals(message, testChannel.receive(0));
|
||||
|
||||
template.setChannelResolver(new ChannelResolver() {
|
||||
public MessageChannel resolveChannelName(String channelName) {
|
||||
return anotherChannel;
|
||||
}
|
||||
});
|
||||
message = MessageBuilder.withPayload("test").build();
|
||||
template.send("testChannel", message);
|
||||
assertEquals(message, anotherChannel.receive(0));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@@ -352,11 +366,11 @@ public class MessagingTemplateTests {
|
||||
@Test
|
||||
public void receiveByChannelNameWithCustomChannelResolver() {
|
||||
QueueChannel testChannel = new QueueChannel();
|
||||
Map<String, MessageChannel> channelMap = new HashMap<String, MessageChannel>();
|
||||
channelMap.put("testChannel", testChannel);
|
||||
MapBasedChannelResolver channelResolver = new MapBasedChannelResolver(channelMap);
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("testChannel", testChannel);
|
||||
|
||||
MessagingTemplate template = new MessagingTemplate();
|
||||
template.setChannelResolver(channelResolver);
|
||||
template.setBeanFactory(beanFactory);
|
||||
template.afterPropertiesSet();
|
||||
Message<?> message = MessageBuilder.withPayload("test").build();
|
||||
testChannel.send(message);
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* 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.endpoint;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.easymock.EasyMock.reset;
|
||||
import static org.mockito.Mockito.atMost;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.config.SourcePollingChannelAdapterFactoryBean;
|
||||
import org.springframework.integration.config.TestErrorHandler;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.core.MessageSource;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.scheduling.PollerMetadata;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.scheduling.support.PeriodicTrigger;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public class PollingLifecycleTests {
|
||||
private ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
private TestErrorHandler errorHandler = new TestErrorHandler();
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
taskScheduler.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensurePollerTaskStops() throws Exception{
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
QueueChannel channel = new QueueChannel();
|
||||
channel.send(new GenericMessage<String>("foo"));
|
||||
|
||||
MessageHandler handler = Mockito.spy(new MessageHandler() {
|
||||
public void handleMessage(Message<?> message) throws MessagingException {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
PollingConsumer consumer = new PollingConsumer(channel, handler);
|
||||
PollerMetadata pollerMetadata = new PollerMetadata();
|
||||
pollerMetadata.setTrigger(new PeriodicTrigger(0));
|
||||
consumer.setPollerMetadata(pollerMetadata);
|
||||
consumer.setErrorHandler(errorHandler);
|
||||
consumer.setTaskScheduler(taskScheduler);
|
||||
consumer.setBeanFactory(mock(BeanFactory.class));
|
||||
consumer.afterPropertiesSet();
|
||||
consumer.start();
|
||||
assertTrue(latch.await(2, TimeUnit.SECONDS));
|
||||
Mockito.verify(handler, times(1)).handleMessage(Mockito.any(Message.class));
|
||||
consumer.stop();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
channel.send(new GenericMessage<String>("foo"));
|
||||
}
|
||||
Thread.sleep(2000); // give enough time for poller to kick in if it didn't stop properly
|
||||
// we'll still have a natural race condition between call to stop() and poller polling
|
||||
// so what we really have to assert is that it doesn't poll for more then once after stop() was called
|
||||
Mockito.reset(handler);
|
||||
Mockito.verify(handler, atMost(1)).handleMessage(Mockito.any(Message.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensurePollerTaskStopsForAdapter() throws Exception{
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
QueueChannel channel = new QueueChannel();
|
||||
|
||||
SourcePollingChannelAdapterFactoryBean adapterFactory = new SourcePollingChannelAdapterFactoryBean();
|
||||
PollerMetadata pollerMetadata = new PollerMetadata();
|
||||
pollerMetadata.setTrigger(new PeriodicTrigger(2000));
|
||||
adapterFactory.setPollerMetadata(pollerMetadata);
|
||||
MessageSource<String> source = spy(new MessageSource<String>() {
|
||||
public Message<String> receive() {
|
||||
latch.countDown();
|
||||
return new GenericMessage<String>("hello");
|
||||
}
|
||||
});
|
||||
adapterFactory.setSource(source);
|
||||
adapterFactory.setOutputChannel(channel);
|
||||
adapterFactory.setBeanFactory(mock(ConfigurableBeanFactory.class));
|
||||
SourcePollingChannelAdapter adapter = adapterFactory.getObject();
|
||||
adapter.setTaskScheduler(taskScheduler);
|
||||
adapter.afterPropertiesSet();
|
||||
adapter.start();
|
||||
assertTrue(latch.await(2, TimeUnit.SECONDS));
|
||||
assertNotNull(channel.receive(100));
|
||||
adapter.stop();
|
||||
assertNull(channel.receive(1000));
|
||||
Mockito.verify(source, times(1)).receive();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.expression;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DynamicExpressionTests {
|
||||
|
||||
private static final String key = "test.greeting";
|
||||
|
||||
private static final String basename = "org/springframework/integration/expression/expressions";
|
||||
|
||||
private static final String filepath = basename + ".properties";
|
||||
|
||||
|
||||
@After
|
||||
public void resetFile() {
|
||||
writeExpressionStringToFile("'Hello World!'");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void expressionUpdate() throws Exception {
|
||||
ReloadableResourceBundleExpressionSource source = new ReloadableResourceBundleExpressionSource();
|
||||
source.setBasename(basename);
|
||||
source.setCacheSeconds(0);
|
||||
DynamicExpression expression = new DynamicExpression(key, source);
|
||||
assertEquals("Hello World!", expression.getValue());
|
||||
writeExpressionStringToFile("toUpperCase()");
|
||||
assertEquals("FOO", expression.getValue("foo"));
|
||||
}
|
||||
|
||||
|
||||
private static void writeExpressionStringToFile(String expressionString) {
|
||||
ClassPathResource resource = new ClassPathResource(filepath);
|
||||
byte[] bytes = new String(key + "=" + expressionString).getBytes();
|
||||
try {
|
||||
new FileOutputStream(resource.getFile()).write(bytes);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException("failed to write expression string to file", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
test.greeting='Hello World!'
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.springframework.integration.handler;
|
||||
|
||||
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.support.MessageBuilder;
|
||||
@@ -42,7 +41,6 @@ public class LoggingHandlerTests {
|
||||
input.send(MessageBuilder.withPayload(bean).setHeader("foo", "bar").build());
|
||||
}
|
||||
|
||||
|
||||
public static class TestBean {
|
||||
|
||||
private final String name;
|
||||
|
||||
@@ -22,20 +22,24 @@ import static org.junit.Assert.assertNull;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.message.ErrorMessage;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class ErrorMessageExceptionTypeRouterTests {
|
||||
|
||||
private DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
|
||||
private QueueChannel illegalArgumentChannel = new QueueChannel();
|
||||
|
||||
@@ -46,6 +50,15 @@ public class ErrorMessageExceptionTypeRouterTests {
|
||||
private QueueChannel messageDeliveryExceptionChannel = new QueueChannel();
|
||||
|
||||
private QueueChannel defaultChannel = new QueueChannel();
|
||||
|
||||
@Before
|
||||
public void prepare(){
|
||||
beanFactory.registerSingleton("illegalArgumentChannel", illegalArgumentChannel);
|
||||
beanFactory.registerSingleton("runtimeExceptionChannel", runtimeExceptionChannel);
|
||||
beanFactory.registerSingleton("messageHandlingExceptionChannel", messageHandlingExceptionChannel);
|
||||
beanFactory.registerSingleton("messageDeliveryExceptionChannel", messageDeliveryExceptionChannel);
|
||||
beanFactory.registerSingleton("defaultChannel", defaultChannel);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@@ -56,12 +69,14 @@ public class ErrorMessageExceptionTypeRouterTests {
|
||||
MessageHandlingException error = new MessageHandlingException(failedMessage, "failed", middleCause);
|
||||
ErrorMessage message = new ErrorMessage(error);
|
||||
ErrorMessageExceptionTypeRouter router = new ErrorMessageExceptionTypeRouter();
|
||||
Map<Class<? extends Throwable>, MessageChannel> exceptionTypeChannelMap =
|
||||
new HashMap<Class<? extends Throwable>, MessageChannel>();
|
||||
exceptionTypeChannelMap.put(IllegalArgumentException.class, illegalArgumentChannel);
|
||||
exceptionTypeChannelMap.put(RuntimeException.class, runtimeExceptionChannel);
|
||||
exceptionTypeChannelMap.put(MessageHandlingException.class, messageHandlingExceptionChannel);
|
||||
router.setExceptionTypeChannelMap(exceptionTypeChannelMap);
|
||||
Map<String, String> exceptionTypeChannelMap = new HashMap<String, String>();
|
||||
exceptionTypeChannelMap.put(IllegalArgumentException.class.getName(), "illegalArgumentChannel");
|
||||
exceptionTypeChannelMap.put(RuntimeException.class.getName(), "runtimeExceptionChannel");
|
||||
exceptionTypeChannelMap.put(MessageHandlingException.class.getName(), "messageHandlingExceptionChannel");
|
||||
router.setChannelIdentifierMap(exceptionTypeChannelMap);
|
||||
|
||||
router.setBeanFactory(beanFactory);
|
||||
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
router.handleMessage(message);
|
||||
assertNotNull(illegalArgumentChannel.receive(1000));
|
||||
@@ -78,11 +93,12 @@ public class ErrorMessageExceptionTypeRouterTests {
|
||||
MessageHandlingException error = new MessageHandlingException(failedMessage, "failed", middleCause);
|
||||
ErrorMessage message = new ErrorMessage(error);
|
||||
ErrorMessageExceptionTypeRouter router = new ErrorMessageExceptionTypeRouter();
|
||||
Map<Class<? extends Throwable>, MessageChannel> exceptionTypeChannelMap =
|
||||
new HashMap<Class<? extends Throwable>, MessageChannel>();
|
||||
exceptionTypeChannelMap.put(RuntimeException.class, runtimeExceptionChannel);
|
||||
exceptionTypeChannelMap.put(MessageHandlingException.class, messageHandlingExceptionChannel);
|
||||
router.setExceptionTypeChannelMap(exceptionTypeChannelMap);
|
||||
Map<String, String> exceptionTypeChannelMap = new HashMap<String, String>();
|
||||
exceptionTypeChannelMap.put(RuntimeException.class.getName(), "runtimeExceptionChannel");
|
||||
exceptionTypeChannelMap.put(MessageHandlingException.class.getName(), "runtimeExceptionChannel");
|
||||
router.setChannelIdentifierMap(exceptionTypeChannelMap);
|
||||
router.setBeanFactory(beanFactory);
|
||||
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
router.handleMessage(message);
|
||||
assertNotNull(runtimeExceptionChannel.receive(1000));
|
||||
@@ -99,10 +115,10 @@ public class ErrorMessageExceptionTypeRouterTests {
|
||||
MessageHandlingException error = new MessageHandlingException(failedMessage, "failed", middleCause);
|
||||
ErrorMessage message = new ErrorMessage(error);
|
||||
ErrorMessageExceptionTypeRouter router = new ErrorMessageExceptionTypeRouter();
|
||||
Map<Class<? extends Throwable>, MessageChannel> exceptionTypeChannelMap =
|
||||
new HashMap<Class<? extends Throwable>, MessageChannel>();
|
||||
exceptionTypeChannelMap.put(MessageHandlingException.class, messageHandlingExceptionChannel);
|
||||
router.setExceptionTypeChannelMap(exceptionTypeChannelMap);
|
||||
Map<String, String> exceptionTypeChannelMap = new HashMap<String, String>();
|
||||
exceptionTypeChannelMap.put(MessageHandlingException.class.getName(), "messageHandlingExceptionChannel");
|
||||
router.setChannelIdentifierMap(exceptionTypeChannelMap);
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
router.handleMessage(message);
|
||||
assertNotNull(messageHandlingExceptionChannel.receive(1000));
|
||||
@@ -135,10 +151,10 @@ public class ErrorMessageExceptionTypeRouterTests {
|
||||
MessageHandlingException error = new MessageHandlingException(failedMessage, "failed", middleCause);
|
||||
ErrorMessage message = new ErrorMessage(error);
|
||||
ErrorMessageExceptionTypeRouter router = new ErrorMessageExceptionTypeRouter();
|
||||
Map<Class<? extends Throwable>, MessageChannel> exceptionTypeChannelMap =
|
||||
new HashMap<Class<? extends Throwable>, MessageChannel>();
|
||||
exceptionTypeChannelMap.put(MessageDeliveryException.class, messageDeliveryExceptionChannel);
|
||||
router.setExceptionTypeChannelMap(exceptionTypeChannelMap);
|
||||
Map<String, String> exceptionTypeChannelMap = new HashMap<String, String>();
|
||||
exceptionTypeChannelMap.put(MessageDeliveryException.class.getName(), "messageDeliveryExceptionChannel");
|
||||
router.setChannelIdentifierMap(exceptionTypeChannelMap);
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setResolutionRequired(true);
|
||||
router.handleMessage(message);
|
||||
}
|
||||
@@ -151,12 +167,12 @@ public class ErrorMessageExceptionTypeRouterTests {
|
||||
MessageHandlingException error = new MessageHandlingException(failedMessage, "failed", middleCause);
|
||||
Message<?> message = new GenericMessage<Exception>(error);
|
||||
ErrorMessageExceptionTypeRouter router = new ErrorMessageExceptionTypeRouter();
|
||||
Map<Class<? extends Throwable>, MessageChannel> exceptionTypeChannelMap =
|
||||
new HashMap<Class<? extends Throwable>, MessageChannel>();
|
||||
exceptionTypeChannelMap.put(IllegalArgumentException.class, illegalArgumentChannel);
|
||||
exceptionTypeChannelMap.put(RuntimeException.class, runtimeExceptionChannel);
|
||||
exceptionTypeChannelMap.put(MessageHandlingException.class, messageHandlingExceptionChannel);
|
||||
router.setExceptionTypeChannelMap(exceptionTypeChannelMap);
|
||||
Map<String, String> exceptionTypeChannelMap = new HashMap<String, String>();
|
||||
exceptionTypeChannelMap.put(IllegalArgumentException.class.getName(), "illegalArgumentChannel");
|
||||
exceptionTypeChannelMap.put(RuntimeException.class.getName(), "runtimeExceptionChannel");
|
||||
exceptionTypeChannelMap.put(MessageHandlingException.class.getName(), "messageHandlingExceptionChannel");
|
||||
router.setChannelIdentifierMap(exceptionTypeChannelMap);
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
router.handleMessage(message);
|
||||
assertNotNull(illegalArgumentChannel.receive(1000));
|
||||
@@ -173,11 +189,11 @@ public class ErrorMessageExceptionTypeRouterTests {
|
||||
MessageHandlingException error = new MessageHandlingException(failedMessage, "failed", middleCause);
|
||||
ErrorMessage message = new ErrorMessage(error);
|
||||
ErrorMessageExceptionTypeRouter router = new ErrorMessageExceptionTypeRouter();
|
||||
Map<Class<? extends Throwable>, MessageChannel> exceptionTypeChannelMap =
|
||||
new HashMap<Class<? extends Throwable>, MessageChannel>();
|
||||
exceptionTypeChannelMap.put(IllegalArgumentException.class, illegalArgumentChannel);
|
||||
exceptionTypeChannelMap.put(MessageHandlingException.class, messageHandlingExceptionChannel);
|
||||
router.setExceptionTypeChannelMap(exceptionTypeChannelMap);
|
||||
Map<String, String> exceptionTypeChannelMap = new HashMap<String, String>();
|
||||
exceptionTypeChannelMap.put(IllegalArgumentException.class.getName(), "illegalArgumentChannel");
|
||||
exceptionTypeChannelMap.put(MessageHandlingException.class.getName(), "messageHandlingExceptionChannel");
|
||||
router.setChannelIdentifierMap(exceptionTypeChannelMap);
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
router.handleMessage(message);
|
||||
assertNotNull(illegalArgumentChannel.receive(1000));
|
||||
|
||||
@@ -16,23 +16,26 @@
|
||||
|
||||
package org.springframework.integration.router;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.support.ManagedMap;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.channel.MapBasedChannelResolver;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
|
||||
import org.springframework.integration.support.channel.ChannelResolver;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class HeaderValueRouterTests {
|
||||
|
||||
@@ -61,6 +64,7 @@ public class HeaderValueRouterTests {
|
||||
routerBeanDefinition.getPropertyValues().addPropertyValue("resolutionRequired", "true");
|
||||
context.registerBeanDefinition("router", routerBeanDefinition);
|
||||
context.registerBeanDefinition("testChannel", new RootBeanDefinition(QueueChannel.class));
|
||||
context.registerBeanDefinition("newChannel", new RootBeanDefinition(QueueChannel.class));
|
||||
context.refresh();
|
||||
MessageHandler handler = (MessageHandler) context.getBean("router");
|
||||
Message<?> message = MessageBuilder.withPayload("test").setHeader("testHeaderName", "testChannel").build();
|
||||
@@ -69,6 +73,20 @@ public class HeaderValueRouterTests {
|
||||
Message<?> result = channel.receive(1000);
|
||||
assertNotNull(result);
|
||||
assertSame(message, result);
|
||||
|
||||
// validate dynamics
|
||||
HeaderValueRouter router = (HeaderValueRouter) context.getBean("router");
|
||||
router.setChannelMapping("testChannel", "newChannel");
|
||||
router.handleMessage(message);
|
||||
QueueChannel newChannel = (QueueChannel) context.getBean("newChannel");
|
||||
result = newChannel.receive(10);
|
||||
assertNotNull(result);
|
||||
|
||||
router.removeChannelMapping("testChannel");
|
||||
router.handleMessage(message);
|
||||
result = channel.receive(1000);
|
||||
assertNotNull(result);
|
||||
assertSame(message, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -76,14 +94,12 @@ public class HeaderValueRouterTests {
|
||||
public void resolveChannelNameFromMap() {
|
||||
StaticApplicationContext context = new StaticApplicationContext();
|
||||
ManagedMap channelMap = new ManagedMap();
|
||||
channelMap.put("testKey", new RuntimeBeanReference("testChannel"));
|
||||
RootBeanDefinition channelResolverBeanDefinition = new RootBeanDefinition(MapBasedChannelResolver.class);
|
||||
channelResolverBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue(channelMap);
|
||||
channelMap.put("testKey", "testChannel");
|
||||
RootBeanDefinition routerBeanDefinition = new RootBeanDefinition(HeaderValueRouter.class);
|
||||
routerBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue("testHeaderName");
|
||||
routerBeanDefinition.getPropertyValues().addPropertyValue("resolutionRequired", "true");
|
||||
routerBeanDefinition.getPropertyValues().addPropertyValue("channelResolver", new RuntimeBeanReference("resolver"));
|
||||
context.registerBeanDefinition("resolver", channelResolverBeanDefinition);
|
||||
routerBeanDefinition.getPropertyValues().addPropertyValue("channelIdentifierMap", channelMap);
|
||||
routerBeanDefinition.getPropertyValues().addPropertyValue("beanFactory", context);
|
||||
context.registerBeanDefinition("router", routerBeanDefinition);
|
||||
context.registerBeanDefinition("testChannel", new RootBeanDefinition(QueueChannel.class));
|
||||
context.refresh();
|
||||
@@ -95,6 +111,34 @@ public class HeaderValueRouterTests {
|
||||
assertNotNull(result);
|
||||
assertSame(message, result);
|
||||
}
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void resolveChannelNameFromMapAndCustomeResolver() {
|
||||
final StaticApplicationContext context = new StaticApplicationContext();
|
||||
ManagedMap channelMap = new ManagedMap();
|
||||
channelMap.put("testKey", "testChannel");
|
||||
RootBeanDefinition routerBeanDefinition = new RootBeanDefinition(HeaderValueRouter.class);
|
||||
routerBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue("testHeaderName");
|
||||
routerBeanDefinition.getPropertyValues().addPropertyValue("resolutionRequired", "true");
|
||||
routerBeanDefinition.getPropertyValues().addPropertyValue("channelIdentifierMap", channelMap);
|
||||
routerBeanDefinition.getPropertyValues().addPropertyValue("beanFactory", context);
|
||||
routerBeanDefinition.getPropertyValues().addPropertyValue("channelResolver", new ChannelResolver() {
|
||||
public MessageChannel resolveChannelName(String channelName) {
|
||||
return context.getBean("anotherChannel", MessageChannel.class);
|
||||
}
|
||||
});
|
||||
context.registerBeanDefinition("router", routerBeanDefinition);
|
||||
context.registerBeanDefinition("testChannel", new RootBeanDefinition(QueueChannel.class));
|
||||
context.registerBeanDefinition("anotherChannel", new RootBeanDefinition(QueueChannel.class));
|
||||
context.refresh();
|
||||
MessageHandler handler = (MessageHandler) context.getBean("router");
|
||||
Message<?> message = MessageBuilder.withPayload("test").setHeader("testHeaderName", "testKey").build();
|
||||
handler.handleMessage(message);
|
||||
QueueChannel channel = (QueueChannel) context.getBean("anotherChannel");
|
||||
Message<?> result = channel.receive(1000);
|
||||
assertNotNull(result);
|
||||
assertSame(message, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveMultipleChannelsWithStringArray() {
|
||||
@@ -144,4 +188,5 @@ public class HeaderValueRouterTests {
|
||||
assertSame(message, result2);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,16 +18,19 @@ package org.springframework.integration.router;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.channel.TestChannelResolver;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
@@ -37,7 +40,7 @@ public class MultiChannelRouterTests {
|
||||
|
||||
@Test
|
||||
public void routeWithChannelMapping() {
|
||||
AbstractChannelNameResolvingMessageRouter router = new AbstractChannelNameResolvingMessageRouter() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] {"channel1", "channel2"});
|
||||
@@ -61,7 +64,7 @@ public class MultiChannelRouterTests {
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void channelNameLookupFailure() {
|
||||
AbstractChannelNameResolvingMessageRouter router = new AbstractChannelNameResolvingMessageRouter() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] {"noSuchChannel"} );
|
||||
@@ -75,12 +78,13 @@ public class MultiChannelRouterTests {
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void channelMappingNotAvailable() {
|
||||
AbstractChannelNameResolvingMessageRouter router = new AbstractChannelNameResolvingMessageRouter() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] {"noSuchChannel"});
|
||||
}
|
||||
};
|
||||
router.setBeanFactory(mock(BeanFactory.class));
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.router;
|
||||
|
||||
import static junit.framework.Assert.fail;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
@@ -25,7 +26,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
@@ -34,6 +35,7 @@ import org.springframework.integration.message.GenericMessage;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class PayloadTypeRouterTests {
|
||||
|
||||
@@ -41,17 +43,46 @@ public class PayloadTypeRouterTests {
|
||||
public void resolveExactMatch() {
|
||||
QueueChannel stringChannel = new QueueChannel();
|
||||
QueueChannel integerChannel = new QueueChannel();
|
||||
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
|
||||
payloadTypeChannelMap.put(String.class, stringChannel);
|
||||
payloadTypeChannelMap.put(Integer.class, integerChannel);
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("stringChannel", stringChannel);
|
||||
beanFactory.registerSingleton("integerChannel", integerChannel);
|
||||
|
||||
|
||||
Map<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
|
||||
payloadTypeChannelMap.put(String.class.getName(), "stringChannel");
|
||||
payloadTypeChannelMap.put(Integer.class.getName(), "integerChannel");
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
|
||||
router.setChannelIdentifierMap(payloadTypeChannelMap);
|
||||
router.setBeanFactory(beanFactory);
|
||||
|
||||
Message<String> message1 = new GenericMessage<String>("test");
|
||||
Message<Integer> message2 = new GenericMessage<Integer>(123);
|
||||
MessageChannel result1 = router.determineTargetChannel(message1);
|
||||
MessageChannel result2 = router.determineTargetChannel(message2);
|
||||
assertEquals(1, router.determineTargetChannels(message1).size());
|
||||
MessageChannel result1 = router.determineTargetChannels(message1).iterator().next();
|
||||
assertEquals(1, router.determineTargetChannels(message2).size());
|
||||
MessageChannel result2 = router.determineTargetChannels(message2).iterator().next();
|
||||
|
||||
assertEquals(stringChannel, result1);
|
||||
assertEquals(integerChannel, result2);
|
||||
// validate dynamics
|
||||
QueueChannel newChannel = new QueueChannel();
|
||||
beanFactory.registerSingleton("newChannel", newChannel);
|
||||
router.setChannelMapping(String.class.getName(), "newChannel");
|
||||
assertEquals(1, router.determineTargetChannels(message1).size());
|
||||
result1 = router.determineTargetChannels(message1).iterator().next();
|
||||
assertEquals(newChannel, result1);
|
||||
// validate nothing happens if mappings were removed and resolutionRequires = false
|
||||
router.removeChannelMapping(String.class.getName());
|
||||
router.removeChannelMapping(Integer.class.getName());
|
||||
router.handleMessage(message1);
|
||||
// validate exception is thrown if mappings were removed and resolutionRequires = true
|
||||
router.setResolutionRequired(true);
|
||||
try {
|
||||
router.handleMessage(message1);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -60,10 +91,15 @@ public class PayloadTypeRouterTests {
|
||||
defaultChannel.setBeanName("defaultChannel");
|
||||
QueueChannel numberChannel = new QueueChannel();
|
||||
numberChannel.setBeanName("numberChannel");
|
||||
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
|
||||
payloadTypeChannelMap.put(Number.class, numberChannel);
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("defaultChannel", defaultChannel);
|
||||
beanFactory.registerSingleton("numberChannel", numberChannel);
|
||||
|
||||
Map<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
|
||||
payloadTypeChannelMap.put(Number.class.getName(), "numberChannel");
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
|
||||
router.setChannelIdentifierMap(payloadTypeChannelMap);
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
Message<Integer> message = new GenericMessage<Integer>(99);
|
||||
router.handleMessage(message);
|
||||
@@ -71,6 +107,15 @@ public class PayloadTypeRouterTests {
|
||||
assertNotNull(result);
|
||||
assertEquals(99, result.getPayload());
|
||||
assertNull(defaultChannel.receive(0));
|
||||
|
||||
// validate dynamics
|
||||
QueueChannel newChannel = new QueueChannel();
|
||||
beanFactory.registerSingleton("newChannel", newChannel);
|
||||
router.setChannelMapping(Integer.class.getName(), "newChannel");
|
||||
assertEquals(1, router.determineTargetChannels(message).size());
|
||||
router.handleMessage(message);
|
||||
result = newChannel.receive(10);
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -81,11 +126,20 @@ public class PayloadTypeRouterTests {
|
||||
numberChannel.setBeanName("numberChannel");
|
||||
QueueChannel integerChannel = new QueueChannel();
|
||||
integerChannel.setBeanName("integerChannel");
|
||||
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
|
||||
payloadTypeChannelMap.put(Number.class, numberChannel);
|
||||
payloadTypeChannelMap.put(Integer.class, integerChannel);
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("defaultChannel", defaultChannel);
|
||||
beanFactory.registerSingleton("numberChannel", numberChannel);
|
||||
beanFactory.registerSingleton("integerChannel", integerChannel);
|
||||
|
||||
Map<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
|
||||
payloadTypeChannelMap.put(Number.class.getName(), "numberChannel");
|
||||
payloadTypeChannelMap.put(Integer.class.getName(), "integerChannel");
|
||||
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setChannelIdentifierMap(payloadTypeChannelMap);
|
||||
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
Message<Integer> message = new GenericMessage<Integer>(99);
|
||||
router.handleMessage(message);
|
||||
@@ -102,10 +156,18 @@ public class PayloadTypeRouterTests {
|
||||
defaultChannel.setBeanName("defaultChannel");
|
||||
QueueChannel comparableChannel = new QueueChannel();
|
||||
comparableChannel.setBeanName("comparableChannel");
|
||||
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
|
||||
payloadTypeChannelMap.put(Comparable.class, comparableChannel);
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("defaultChannel", defaultChannel);
|
||||
beanFactory.registerSingleton("comparableChannel", comparableChannel);
|
||||
|
||||
Map<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
|
||||
payloadTypeChannelMap.put(Comparable.class.getName(), "comparableChannel");
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
|
||||
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setChannelIdentifierMap(payloadTypeChannelMap);
|
||||
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
Message<Integer> message = new GenericMessage<Integer>(99);
|
||||
router.handleMessage(message);
|
||||
@@ -123,11 +185,20 @@ public class PayloadTypeRouterTests {
|
||||
numberChannel.setBeanName("numberChannel");
|
||||
QueueChannel comparableChannel = new QueueChannel();
|
||||
comparableChannel.setBeanName("comparableChannel");
|
||||
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
|
||||
payloadTypeChannelMap.put(Number.class, numberChannel);
|
||||
payloadTypeChannelMap.put(Comparable.class, comparableChannel);
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("defaultChannel", defaultChannel);
|
||||
beanFactory.registerSingleton("numberChannel", numberChannel);
|
||||
beanFactory.registerSingleton("comparableChannel", comparableChannel);
|
||||
|
||||
Map<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
|
||||
payloadTypeChannelMap.put(Number.class.getName(), "numberChannel");
|
||||
payloadTypeChannelMap.put(Comparable.class.getName(), "comparableChannel");
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
|
||||
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setChannelIdentifierMap(payloadTypeChannelMap);
|
||||
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
Message<Integer> message = new GenericMessage<Integer>(99);
|
||||
router.handleMessage(message);
|
||||
@@ -136,6 +207,15 @@ public class PayloadTypeRouterTests {
|
||||
assertEquals(99, result.getPayload());
|
||||
assertNull(numberChannel.receive(0));
|
||||
assertNull(defaultChannel.receive(0));
|
||||
|
||||
// validate dynamics
|
||||
QueueChannel newChannel = new QueueChannel();
|
||||
beanFactory.registerSingleton("newChannel", newChannel);
|
||||
router.setChannelMapping(Integer.class.getName(), "newChannel");
|
||||
assertEquals(1, router.determineTargetChannels(message).size());
|
||||
router.handleMessage(message);
|
||||
result = newChannel.receive(10);
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@@ -146,11 +226,20 @@ public class PayloadTypeRouterTests {
|
||||
serializableChannel.setBeanName("serializableChannel");
|
||||
QueueChannel comparableChannel = new QueueChannel();
|
||||
comparableChannel.setBeanName("comparableChannel");
|
||||
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
|
||||
payloadTypeChannelMap.put(Serializable.class, serializableChannel);
|
||||
payloadTypeChannelMap.put(Comparable.class, comparableChannel);
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("defaultChannel", defaultChannel);
|
||||
beanFactory.registerSingleton("serializableChannel", serializableChannel);
|
||||
beanFactory.registerSingleton("comparableChannel", comparableChannel);
|
||||
|
||||
Map<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
|
||||
payloadTypeChannelMap.put(Serializable.class.getName(), "serializableChannel");
|
||||
payloadTypeChannelMap.put(Comparable.class.getName(), "comparableChannel");
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
|
||||
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setChannelIdentifierMap(payloadTypeChannelMap);
|
||||
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
try {
|
||||
@@ -169,11 +258,22 @@ public class PayloadTypeRouterTests {
|
||||
numberChannel.setBeanName("numberChannel");
|
||||
QueueChannel serializableChannel = new QueueChannel();
|
||||
serializableChannel.setBeanName("serializableChannel");
|
||||
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
|
||||
payloadTypeChannelMap.put(Number.class, numberChannel);
|
||||
payloadTypeChannelMap.put(Serializable.class, serializableChannel);
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("defaultChannel", defaultChannel);
|
||||
beanFactory.registerSingleton("numberChannel", numberChannel);
|
||||
beanFactory.registerSingleton("serializableChannel", serializableChannel);
|
||||
|
||||
|
||||
Map<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
|
||||
|
||||
payloadTypeChannelMap.put(Number.class.getName(), "numberChannel");
|
||||
payloadTypeChannelMap.put(Serializable.class.getName(), "serializableChannel");
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
|
||||
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setChannelIdentifierMap(payloadTypeChannelMap);
|
||||
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
Message<Integer> message = new GenericMessage<Integer>(99);
|
||||
router.handleMessage(message);
|
||||
@@ -190,11 +290,19 @@ public class PayloadTypeRouterTests {
|
||||
QueueChannel integerChannel = new QueueChannel();
|
||||
stringChannel.setBeanName("stringChannel");
|
||||
integerChannel.setBeanName("integerChannel");
|
||||
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
|
||||
payloadTypeChannelMap.put(String.class, stringChannel);
|
||||
payloadTypeChannelMap.put(Integer.class, integerChannel);
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("stringChannel", stringChannel);
|
||||
beanFactory.registerSingleton("integerChannel", integerChannel);
|
||||
|
||||
Map<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
|
||||
payloadTypeChannelMap.put(String.class.getName(), "stringChannel");
|
||||
payloadTypeChannelMap.put(Integer.class.getName(), "integerChannel");
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
|
||||
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setChannelIdentifierMap(payloadTypeChannelMap);
|
||||
|
||||
Message<String> message1 = new GenericMessage<String>("test");
|
||||
Message<Integer> message2 = new GenericMessage<Integer>(123);
|
||||
router.handleMessage(message1);
|
||||
@@ -211,10 +319,19 @@ public class PayloadTypeRouterTests {
|
||||
stringChannel.setBeanName("stringChannel");
|
||||
QueueChannel defaultChannel = new QueueChannel();
|
||||
defaultChannel.setBeanName("defaultChannel");
|
||||
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
|
||||
payloadTypeChannelMap.put(String.class, stringChannel);
|
||||
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerSingleton("stringChannel", stringChannel);
|
||||
beanFactory.registerSingleton("defaultChannel", defaultChannel);
|
||||
|
||||
|
||||
Map<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
|
||||
payloadTypeChannelMap.put(String.class.getName(), "stringChannel");
|
||||
PayloadTypeRouter router = new PayloadTypeRouter();
|
||||
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
|
||||
|
||||
router.setBeanFactory(beanFactory);
|
||||
router.setChannelIdentifierMap(payloadTypeChannelMap);
|
||||
|
||||
router.setDefaultOutputChannel(defaultChannel);
|
||||
Message<String> message1 = new GenericMessage<String>("test");
|
||||
Message<Integer> message2 = new GenericMessage<Integer>(123);
|
||||
@@ -227,5 +344,4 @@ public class PayloadTypeRouterTests {
|
||||
assertNotNull(result2);
|
||||
assertEquals(123, result2.getPayload());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,16 +17,15 @@
|
||||
package org.springframework.integration.router;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
@@ -36,15 +35,17 @@ import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class RouterTests {
|
||||
|
||||
@Test
|
||||
public void nullChannelIgnoredByDefault() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
public List<MessageChannel> determineTargetChannels(Message<?> message) {
|
||||
@Override
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
@@ -53,7 +54,8 @@ public class RouterTests {
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void nullChannelThrowsExceptionWhenResolutionRequired() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
public List<MessageChannel> determineTargetChannels(Message<?> message) {
|
||||
@Override
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -65,8 +67,9 @@ public class RouterTests {
|
||||
@Test
|
||||
public void emptyChannelListIgnoredByDefault() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
public List<MessageChannel> determineTargetChannels(Message<?> message) {
|
||||
return Collections.emptyList();
|
||||
@Override
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
@@ -76,8 +79,9 @@ public class RouterTests {
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void emptyChannelListThrowsExceptionWhenResolutionRequired() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
public List<MessageChannel> determineTargetChannels(Message<?> message) {
|
||||
return Collections.emptyList();
|
||||
@Override
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
router.setResolutionRequired(true);
|
||||
@@ -87,8 +91,9 @@ public class RouterTests {
|
||||
|
||||
@Test
|
||||
public void nullChannelNameArrayIgnoredByDefault() {
|
||||
AbstractChannelNameResolvingMessageRouter router = new AbstractChannelNameResolvingMessageRouter() {
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@Override
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -100,7 +105,7 @@ public class RouterTests {
|
||||
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void nullChannelNameArrayThrowsExceptionWhenResolutionRequired() {
|
||||
AbstractChannelNameResolvingMessageRouter router = new AbstractChannelNameResolvingMessageRouter() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
@@ -115,7 +120,7 @@ public class RouterTests {
|
||||
|
||||
@Test
|
||||
public void emptyChannelNameArrayIgnoredByDefault() {
|
||||
AbstractChannelNameResolvingMessageRouter router = new AbstractChannelNameResolvingMessageRouter() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return new ArrayList<Object>();
|
||||
}
|
||||
@@ -128,7 +133,7 @@ public class RouterTests {
|
||||
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void emptyChannelNameArrayThrowsExceptionWhenResolutionRequired() {
|
||||
AbstractChannelNameResolvingMessageRouter router = new AbstractChannelNameResolvingMessageRouter() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] {});
|
||||
@@ -148,17 +153,19 @@ public class RouterTests {
|
||||
return "notImportant";
|
||||
}
|
||||
};
|
||||
router.setBeanFactory(mock(BeanFactory.class));
|
||||
router.handleMessage(new GenericMessage<String>("this should fail"));
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void channelMappingIsRequiredWhenResolvingChannelNamesWithMultiChannelRouter() {
|
||||
AbstractChannelNameResolvingMessageRouter router = new AbstractChannelNameResolvingMessageRouter() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message){
|
||||
return CollectionUtils.arrayToList(new String[] { "notImportant" });
|
||||
}
|
||||
};
|
||||
router.setBeanFactory(mock(BeanFactory.class));
|
||||
router.handleMessage(new GenericMessage<String>("this should fail"));
|
||||
}
|
||||
|
||||
@@ -180,7 +187,7 @@ public class RouterTests {
|
||||
|
||||
@Test
|
||||
public void beanFactoryWithMultiChannelRouter() {
|
||||
AbstractChannelNameResolvingMessageRouter router = new AbstractChannelNameResolvingMessageRouter() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] { "testChannel" });
|
||||
|
||||
@@ -1,93 +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.router;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.channel.TestChannelResolver;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class SingleChannelRouterTests {
|
||||
|
||||
@Test
|
||||
public void routeWithChannelResolver() {
|
||||
final QueueChannel channel = new QueueChannel();
|
||||
AbstractSingleChannelRouter router = new AbstractSingleChannelRouter() {
|
||||
public MessageChannel determineTargetChannel(Message<?> message) {
|
||||
return channel;
|
||||
}
|
||||
};
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
Message<?> result = channel.receive(25);
|
||||
assertNotNull(result);
|
||||
assertEquals("test", result.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void routeWithChannelNameResolver() {
|
||||
AbstractSingleChannelNameRouter router = new AbstractSingleChannelNameRouter() {
|
||||
public String determineTargetChannelName(Message<?> message) {
|
||||
return "testChannel";
|
||||
}
|
||||
};
|
||||
QueueChannel channel = new QueueChannel();
|
||||
TestChannelResolver channelResolver = new TestChannelResolver();
|
||||
channelResolver.addChannel("testChannel", channel);
|
||||
router.setChannelResolver(channelResolver);
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
Message<?> result = channel.receive(25);
|
||||
assertNotNull(result);
|
||||
assertEquals("test", result.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullChannelResultIgnored() {
|
||||
AbstractSingleChannelRouter router = new AbstractSingleChannelRouter() {
|
||||
public MessageChannel determineTargetChannel(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void channelNameResolutionFailure() {
|
||||
AbstractSingleChannelNameRouter router = new AbstractSingleChannelNameRouter() {
|
||||
public String determineTargetChannelName(Message<?> message) {
|
||||
return "noSuchChannel";
|
||||
}
|
||||
};
|
||||
TestChannelResolver channelResolver = new TestChannelResolver();
|
||||
router.setChannelResolver(channelResolver);
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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="even">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<channel id="odd">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<router input-channel="input">
|
||||
<expression key="router.oddeven" source="testExpressionSource"/>
|
||||
</router>
|
||||
|
||||
<beans:bean id="testExpressionSource" class="org.springframework.integration.expression.ReloadableResourceBundleExpressionSource">
|
||||
<beans:property name="basename" value="org/springframework/integration/router/config/expressions"/>
|
||||
</beans:bean>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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.router.config;
|
||||
|
||||
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.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class DynamicExpressionRouterIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel input;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel even;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel odd;
|
||||
|
||||
|
||||
@Test
|
||||
public void dynamicExpressionBasedRouter() {
|
||||
TestBean testBean1 = new TestBean(1);
|
||||
TestBean testBean2 = new TestBean(2);
|
||||
TestBean testBean3 = new TestBean(3);
|
||||
TestBean testBean4 = new TestBean(4);
|
||||
Message<?> message1 = MessageBuilder.withPayload(testBean1).build();
|
||||
Message<?> message2 = MessageBuilder.withPayload(testBean2).build();
|
||||
Message<?> message3 = MessageBuilder.withPayload(testBean3).build();
|
||||
Message<?> message4 = MessageBuilder.withPayload(testBean4).build();
|
||||
this.input.send(message1);
|
||||
this.input.send(message2);
|
||||
this.input.send(message3);
|
||||
this.input.send(message4);
|
||||
assertEquals(testBean1, odd.receive(0).getPayload());
|
||||
assertEquals(testBean2, even.receive(0).getPayload());
|
||||
assertEquals(testBean3, odd.receive(0).getPayload());
|
||||
assertEquals(testBean4, even.receive(0).getPayload());
|
||||
assertNull(odd.receive(0));
|
||||
assertNull(even.receive(0));
|
||||
}
|
||||
|
||||
|
||||
static class TestBean {
|
||||
|
||||
private final int number;
|
||||
|
||||
public TestBean(int number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public int getNumber() {
|
||||
return this.number;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -61,15 +61,6 @@ public class PayloadTypeRouterParserTests {
|
||||
assertTrue(chanel2.receive(0).getPayload() instanceof Integer);
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionStoreException.class)
|
||||
public void testFakeTypes(){
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(routerConfigFakeType.getBytes());
|
||||
GenericApplicationContext ac = new GenericApplicationContext();
|
||||
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(ac);
|
||||
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
|
||||
reader.loadBeanDefinitions(new InputStreamResource(stream));
|
||||
}
|
||||
|
||||
@Test(expected=BeanDefinitionStoreException.class)
|
||||
public void testNoMappingElement(){
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(routerConfigNoMaping.getBytes());
|
||||
|
||||
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
@@ -205,9 +206,10 @@ public class RouterParserTests {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
|
||||
return Collections.singletonList(this.channel);
|
||||
protected List<Object> getChannelIndicatorList(Message<?> message) {
|
||||
return Collections.singletonList((Object)this.channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<queue capacity="1" />
|
||||
</channel>
|
||||
|
||||
<router input-channel="expressionRouter" expression="payload.name"
|
||||
<router id="spelRouter" input-channel="expressionRouter" expression="payload.name"
|
||||
default-output-channel="defaultChannelForExpression"
|
||||
ignore-channel-name-resolution-failures="true">
|
||||
<mapping value="foo" channel="fooChannelForExpression"/>
|
||||
|
||||
@@ -23,10 +23,14 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.config.ConsumerEndpointFactoryBean;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.router.AbstractMessageRouter;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -39,6 +43,10 @@ public class RouterWithMappingTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel expressionRouter;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("spelRouter")
|
||||
private ConsumerEndpointFactoryBean spelRouter;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel pojoRouter;
|
||||
@@ -79,6 +87,13 @@ public class RouterWithMappingTests {
|
||||
assertNotNull(defaultChannelForExpression.receive(0));
|
||||
assertNull(fooChannelForExpression.receive(0));
|
||||
assertNull(barChannelForExpression.receive(0));
|
||||
// validate dynamics
|
||||
AbstractMessageRouter router = (AbstractMessageRouter) TestUtils.getPropertyValue(spelRouter, "handler");
|
||||
router.setChannelMapping("baz", "fooChannelForExpression");
|
||||
expressionRouter.send(message3);
|
||||
assertNull(defaultChannelForExpression.receive(10));
|
||||
assertNotNull(fooChannelForExpression.receive(10));
|
||||
assertNull(barChannelForExpression.receive(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
router.oddeven=payload.number % 2 == 0 ? 'even' : 'odd'
|
||||
@@ -0,0 +1,22 @@
|
||||
<?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="output">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<splitter input-channel="input" output-channel="output">
|
||||
<expression key="split.lessThan5" source="testExpressionSource"/>
|
||||
</splitter>
|
||||
|
||||
<beans:bean id="testExpressionSource" class="org.springframework.integration.expression.ReloadableResourceBundleExpressionSource">
|
||||
<beans:property name="basename" value="org/springframework/integration/splitter/expressions"/>
|
||||
</beans:bean>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.splitter;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class DynamicExpressionSplitterIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel input;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel output;
|
||||
|
||||
|
||||
@Test
|
||||
public void simple() {
|
||||
Message<?> message = MessageBuilder.withPayload(new TestBean()).setHeader("foo", "foo").build();
|
||||
this.input.send(message);
|
||||
Message<?> one = output.receive(0);
|
||||
Message<?> two = output.receive(0);
|
||||
Message<?> three = output.receive(0);
|
||||
Message<?> four = output.receive(0);
|
||||
assertEquals(new Integer(1), one.getPayload());
|
||||
assertEquals("foo", one.getHeaders().get("foo"));
|
||||
assertEquals(new Integer(2), two.getPayload());
|
||||
assertEquals("foo", two.getHeaders().get("foo"));
|
||||
assertEquals(new Integer(3), three.getPayload());
|
||||
assertEquals("foo", three.getHeaders().get("foo"));
|
||||
assertEquals(new Integer(4), four.getPayload());
|
||||
assertEquals("foo", four.getHeaders().get("foo"));
|
||||
assertNull(output.receive(0));
|
||||
}
|
||||
|
||||
|
||||
static class TestBean {
|
||||
|
||||
private final List<Integer> numbers = new ArrayList<Integer>();
|
||||
|
||||
public TestBean() {
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
this.numbers.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Integer> getNumbers() {
|
||||
return this.numbers;
|
||||
}
|
||||
|
||||
public String[] split(String s) {
|
||||
return s.split(",");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
split.lessThan5=payload.numbers.?[#this < 5]
|
||||
@@ -0,0 +1,24 @@
|
||||
<?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="output">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<header-enricher input-channel="input" output-channel="output">
|
||||
<header name="testHeader">
|
||||
<expression key="test.header"/>
|
||||
</header>
|
||||
</header-enricher>
|
||||
|
||||
<beans:bean id="expressionSource" class="org.springframework.integration.expression.ReloadableResourceBundleExpressionSource">
|
||||
<beans:property name="basename" value="org/springframework/integration/transformer/expressions"/>
|
||||
</beans:bean>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.transformer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class DynamicExpressionHeaderEnricherIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel input;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel output;
|
||||
|
||||
|
||||
@Test
|
||||
public void dynamicExpressionHeader() {
|
||||
Message<?> message = MessageBuilder.withPayload("test").build();
|
||||
this.input.send(message);
|
||||
Message<?> result = output.receive(0);
|
||||
assertEquals("foo", result.getHeaders().get("testHeader"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?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="output">
|
||||
<queue/>
|
||||
</channel>
|
||||
|
||||
<transformer input-channel="input" output-channel="output">
|
||||
<expression key="test.transform"/>
|
||||
</transformer>
|
||||
|
||||
<beans:bean id="expressionSource" class="org.springframework.integration.expression.ReloadableResourceBundleExpressionSource">
|
||||
<beans:property name="basename" value="org/springframework/integration/transformer/expressions"/>
|
||||
</beans:bean>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.transformer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class DynamicExpressionTransformerIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel input;
|
||||
|
||||
@Autowired
|
||||
private PollableChannel output;
|
||||
|
||||
|
||||
@Test
|
||||
public void transformWithDynamicExpression() {
|
||||
Message<?> message = MessageBuilder.withPayload(new TestBean()).setHeader("bar", 123).build();
|
||||
this.input.send(message);
|
||||
Message<?> result = output.receive(0);
|
||||
assertEquals("test123", result.getPayload());
|
||||
}
|
||||
|
||||
|
||||
static class TestBean {
|
||||
|
||||
public String getFoo() {
|
||||
return "test";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
test.transform=payload.foo + headers.bar
|
||||
test.header='foo'
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.springframework.integration.util;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
*
|
||||
*/
|
||||
public class BeanFactoryTypeConverterTests {
|
||||
|
||||
@Test
|
||||
public void testEmptyCollectionConversion(){
|
||||
BeanFactoryTypeConverter typeConverter = new BeanFactoryTypeConverter();
|
||||
List<String> sourceObject = new ArrayList<String>();
|
||||
// source type doesn't even matter
|
||||
ArrayList<BeanFactoryTypeConverterTests> convertedCollection =
|
||||
(ArrayList<BeanFactoryTypeConverterTests>) typeConverter.convertValue(sourceObject, null, TypeDescriptor.forObject(new ArrayList<BeanFactoryTypeConverterTests>()));
|
||||
assertEquals(sourceObject, convertedCollection);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
#Wed Sep 22 11:50:06 EDT 2010
|
||||
//com.springsource.sts.config.flow.coordinates\:http\://www.springframework.org/schema/integration\:/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventInboundChannelAdapterParserTests-context.xml=<?xml version\="1.0" encoding\="UTF-8"?>\n<graph>\n<element clazz\="ChannelModelElement" type\="channel">\n<structure end\="1040" endstart\="1026" start\="985" startend\="1009"/>\n<bounds height\="112" width\="116" x\="19" y\="17"/>\n</element>\n<element clazz\="ChannelModelElement" type\="channel">\n<structure end\="1508" endstart\="1494" start\="1445" startend\="1477"/>\n<bounds height\="112" width\="116" x\="19" y\="149"/>\n</element>\n<element clazz\="ChannelModelElement" type\="channel">\n<structure end\="1731" endstart\="1717" start\="1657" startend\="1700"/>\n<bounds height\="112" width\="116" x\="19" y\="281"/>\n</element>\n</graph>
|
||||
#Fri Oct 08 14:30:53 EDT 2010
|
||||
//com.springsource.sts.config.flow.coordinates\:http\://www.springframework.org/schema/integration\:/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventInboundChannelAdapterParserTests-context.xml=<?xml version\="1.0" encoding\="UTF-8"?>\n<graph>\n<element clazz\="InboundChannelAdapterModelElement" type\="inbound-channel-adapter">\n<structure end\="982" endstart\="982" start\="906" startend\="982"/>\n<bounds height\="112" width\="116" x\="19" y\="17"/>\n</element>\n<element clazz\="ChannelModelElement" type\="channel">\n<structure end\="1040" endstart\="1026" start\="985" startend\="1009"/>\n<bounds height\="112" width\="116" x\="155" y\="17"/>\n</element>\n<element clazz\="InboundChannelAdapterModelElement" type\="inbound-channel-adapter">\n<structure end\="1442" endstart\="1442" start\="1044" startend\="1442"/>\n<bounds height\="112" width\="116" x\="19" y\="149"/>\n</element>\n<element clazz\="ChannelModelElement" type\="channel">\n<structure end\="1508" endstart\="1494" start\="1445" startend\="1477"/>\n<bounds height\="112" width\="116" x\="155" y\="149"/>\n</element>\n<element clazz\="InboundChannelAdapterModelElement" type\="inbound-channel-adapter">\n<structure end\="1654" endstart\="1654" start\="1512" startend\="1654"/>\n<bounds height\="112" width\="116" x\="19" y\="281"/>\n</element>\n<element clazz\="ChannelModelElement" type\="channel">\n<structure end\="1731" endstart\="1717" start\="1657" startend\="1700"/>\n<bounds height\="112" width\="116" x\="155" y\="281"/>\n</element>\n<element clazz\="InboundChannelAdapterModelElement" type\="inbound-channel-adapter">\n<structure end\="1850" endstart\="1850" start\="1734" startend\="1850"/>\n<bounds height\="112" width\="116" x\="19" y\="413"/>\n</element>\n<element clazz\="ChannelModelElement" type\="channel">\n<structure end\="1912" endstart\="1898" start\="1853" startend\="1881"/>\n<bounds height\="112" width\="116" x\="155" y\="413"/>\n</element>\n</graph>
|
||||
eclipse.preferences.version=1
|
||||
|
||||
@@ -21,14 +21,17 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.integration.endpoint.MessageProducerSupport;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* An inbound Channel Adapter that passes Spring
|
||||
* {@link ApplicationEvent ApplicationEvents} within messages.
|
||||
* An inbound Channel Adapter that passes Spring {@link ApplicationEvent ApplicationEvents} within messages.
|
||||
* If a {@link #setPayloadExpression(String) payloadExpression} is provided, it will be evaluated against
|
||||
* the ApplicationEvent instance to create the Message payload.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@@ -36,6 +39,10 @@ public class ApplicationEventInboundChannelAdapter extends MessageProducerSuppor
|
||||
|
||||
private final Set<Class<? extends ApplicationEvent>> eventTypes = new CopyOnWriteArraySet<Class<? extends ApplicationEvent>>();
|
||||
|
||||
private volatile Expression payloadExpression;
|
||||
|
||||
private final SpelExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
|
||||
/**
|
||||
* Set the list of event types (classes that extend ApplicationEvent) that
|
||||
@@ -51,6 +58,24 @@ public class ApplicationEventInboundChannelAdapter extends MessageProducerSuppor
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide an expression to be evaluated against the received ApplicationEvent
|
||||
* instance (the "root object") in order to create the Message payload. If none
|
||||
* is provided, the ApplicationEvent itself will be used as the payload.
|
||||
*/
|
||||
public void setPayloadExpression(String payloadExpression) {
|
||||
if (payloadExpression == null) {
|
||||
this.payloadExpression = null;
|
||||
}
|
||||
else {
|
||||
this.payloadExpression = this.parser.parseExpression(payloadExpression);
|
||||
}
|
||||
}
|
||||
|
||||
public String getComponentType() {
|
||||
return "event:inbound-channel-adapter";
|
||||
}
|
||||
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (CollectionUtils.isEmpty(this.eventTypes)) {
|
||||
this.sendEventAsMessage(event);
|
||||
@@ -65,11 +90,8 @@ public class ApplicationEventInboundChannelAdapter extends MessageProducerSuppor
|
||||
}
|
||||
|
||||
private void sendEventAsMessage(ApplicationEvent event) {
|
||||
this.sendMessage(MessageBuilder.withPayload(event).build());
|
||||
}
|
||||
|
||||
public String getComponentType(){
|
||||
return "event:inbound-channel-adapter";
|
||||
Object payload = (this.payloadExpression != null) ? this.payloadExpression.getValue(event) : event;
|
||||
this.sendMessage(MessageBuilder.withPayload(payload).build());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.event.config;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
@@ -30,11 +31,11 @@ import org.w3c.dom.Element;
|
||||
public class EventInboundChannelAdapterParser extends AbstractChannelAdapterParser{
|
||||
|
||||
@Override
|
||||
protected AbstractBeanDefinition doParse(Element element,
|
||||
ParserContext parserContext, String channelName) {
|
||||
protected AbstractBeanDefinition doParse(Element element, ParserContext parserContext, String channelName) {
|
||||
BeanDefinitionBuilder adapterBuilder = BeanDefinitionBuilder.rootBeanDefinition(ApplicationEventInboundChannelAdapter.class);
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(adapterBuilder, element, "channel", "outputChannel");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(adapterBuilder, element, "event-types");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(adapterBuilder, element, "payload-expression");
|
||||
return adapterBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,15 @@
|
||||
types will be sent [OPTIONAL]
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="payload-expression">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
SpEL expression to be evaluated against the ApplicationEvent to create the payload instance.
|
||||
If not provided, the ApplicationEvent itself will be used as the payload.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.
|
||||
@@ -53,8 +53,8 @@ public class ApplicationEventInboundChannelAdapterTests {
|
||||
assertEquals("event2", ((ApplicationEvent) message3.getPayload()).getSource());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onlyConfiguredEventTypesAreSent() {
|
||||
QueueChannel channel = new QueueChannel();
|
||||
ApplicationEventInboundChannelAdapter adapter = new ApplicationEventInboundChannelAdapter();
|
||||
@@ -93,6 +93,24 @@ public class ApplicationEventInboundChannelAdapterTests {
|
||||
assertEquals(ContextClosedEvent.class, closedEventMessage.getPayload().getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void payloadExpressionEvaluatedAgainstApplicationEvent() {
|
||||
QueueChannel channel = new QueueChannel();
|
||||
ApplicationEventInboundChannelAdapter adapter = new ApplicationEventInboundChannelAdapter();
|
||||
adapter.setPayloadExpression("'received: ' + source");
|
||||
adapter.setOutputChannel(channel);
|
||||
Message<?> message1 = channel.receive(0);
|
||||
assertNull(message1);
|
||||
adapter.onApplicationEvent(new TestApplicationEvent1());
|
||||
adapter.onApplicationEvent(new TestApplicationEvent2());
|
||||
Message<?> message2 = channel.receive(20);
|
||||
assertNotNull(message2);
|
||||
assertEquals("received: event1", message2.getPayload());
|
||||
Message<?> message3 = channel.receive(20);
|
||||
assertNotNull(message3);
|
||||
assertEquals("received: event2", message3.getPayload());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private static class TestApplicationEvent1 extends ApplicationEvent {
|
||||
@@ -100,6 +118,8 @@ public class ApplicationEventInboundChannelAdapterTests {
|
||||
public TestApplicationEvent1() {
|
||||
super("event1");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,13 @@
|
||||
<int:channel id="inputFilteredPlaceHolder">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
|
||||
<int-event:inbound-channel-adapter id="eventAdapterSpel" channel="inputSpel" payload-expression="source + '-test'"/>
|
||||
|
||||
<int:channel id="inputSpel">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
<context:property-placeholder location="classpath:org/springframework/integration/event/config/inbound-adapter.properties"/>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.event.ApplicationEventInboundChannelAdapter;
|
||||
@@ -62,9 +63,9 @@ public class EventInboundChannelAdapterParserTests {
|
||||
DirectFieldAccessor adapterAccessor = new DirectFieldAccessor(adapter);
|
||||
Assert.assertEquals(context.getBean("input"), adapterAccessor.getPropertyValue("outputChannel"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void validateEventParserWithEventTypes() {
|
||||
Object adapter = context.getBean("eventAdapterFiltered");
|
||||
Assert.assertNotNull(adapter);
|
||||
@@ -77,9 +78,9 @@ public class EventInboundChannelAdapterParserTests {
|
||||
assertTrue(eventTypes.contains(SampleEvent.class));
|
||||
assertTrue(eventTypes.contains(AnotherSampleEvent.class));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void validateEventParserWithEventTypesAndPlaceholder() {
|
||||
Object adapter = context.getBean("eventAdapterFilteredPlaceHolder");
|
||||
Assert.assertNotNull(adapter);
|
||||
@@ -108,6 +109,16 @@ public class EventInboundChannelAdapterParserTests {
|
||||
assertEquals(SampleEvent.class, message.getPayload().getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validatePayloadExpression() {
|
||||
Object adapter = context.getBean("eventAdapterSpel");
|
||||
Assert.assertNotNull(adapter);
|
||||
Assert.assertTrue(adapter instanceof ApplicationEventInboundChannelAdapter);
|
||||
DirectFieldAccessor adapterAccessor = new DirectFieldAccessor(adapter);
|
||||
Expression expression = (Expression) adapterAccessor.getPropertyValue("payloadExpression");
|
||||
Assert.assertEquals("source + '-test'", expression.getExpressionString());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class SampleEvent extends ApplicationEvent {
|
||||
|
||||
@@ -4,8 +4,9 @@ Bundle-Vendor: SpringSource
|
||||
Bundle-ManifestVersion: 2
|
||||
Import-Template:
|
||||
org.springframework.integration.*;version="[2.0.0, 2.0.1)",
|
||||
org.springframework.context;version="[3.0.3, 4.0.0)",
|
||||
org.springframework.util;version="[3.0.3, 4.0.0)",
|
||||
org.springframework.beans.*;version="[3.0.3, 4.0.0)",
|
||||
org.springframework.context;version="[3.0.3, 4.0.0)",
|
||||
org.springframework.expression.*;version="[3.0.3, 4.0.0)",
|
||||
org.springframework.util;version="[3.0.3, 4.0.0)",
|
||||
org.apache.commons.logging;version="[1.1.1, 2.0.0)",
|
||||
org.w3c.dom.*;version="0"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-integration-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-ftp</artifactId>
|
||||
@@ -30,37 +31,31 @@
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib-nodep</artifactId>
|
||||
<version>${cglib.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymock</artifactId>
|
||||
<version>${org.easymock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymockclassextension</artifactId>
|
||||
<version>${org.easymock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.
|
||||
@@ -13,8 +13,18 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.ftp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.SocketException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.apache.commons.lang.SystemUtils;
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -22,18 +32,12 @@ import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.MessageRejectedException;
|
||||
import org.springframework.integration.core.MessageHandler;
|
||||
import org.springframework.integration.file.DefaultFileNameGenerator;
|
||||
import org.springframework.integration.file.FileNameGenerator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.SocketException;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.integration.core.MessageHandler} implementation that sends files to an FTP server.
|
||||
*
|
||||
@@ -41,14 +45,21 @@ import java.net.SocketException;
|
||||
* @author Mark Fisher
|
||||
* @author Josh Long
|
||||
*/
|
||||
public class FtpSendingMessageHandler implements MessageHandler,
|
||||
InitializingBean {
|
||||
public class FtpSendingMessageHandler implements MessageHandler, InitializingBean {
|
||||
|
||||
private static final String TEMPORARY_FILE_SUFFIX = ".writing";
|
||||
private FtpClientPool ftpClientPool;
|
||||
private FileNameGenerator fileNameGenerator = new DefaultFileNameGenerator();
|
||||
private File temporaryBufferFolderFile;
|
||||
private Resource temporaryBufferFolder = new FileSystemResource(SystemUtils.getJavaIoTmpDir());
|
||||
private String charset;
|
||||
|
||||
|
||||
private volatile FtpClientPool ftpClientPool;
|
||||
|
||||
private volatile FileNameGenerator fileNameGenerator = new DefaultFileNameGenerator();
|
||||
|
||||
private volatile File temporaryBufferFolderFile;
|
||||
|
||||
private volatile Resource temporaryBufferFolder = new FileSystemResource(SystemUtils.getJavaIoTmpDir());
|
||||
|
||||
private volatile String charset = Charset.defaultCharset().name();
|
||||
|
||||
|
||||
public FtpSendingMessageHandler() {
|
||||
}
|
||||
@@ -57,10 +68,23 @@ public class FtpSendingMessageHandler implements MessageHandler,
|
||||
this.ftpClientPool = ftpClientPool;
|
||||
}
|
||||
|
||||
|
||||
public void setFtpClientPool(FtpClientPool ftpClientPool) {
|
||||
this.ftpClientPool = ftpClientPool;
|
||||
}
|
||||
|
||||
public void setTemporaryBufferFolder(Resource temporaryBufferFolder) {
|
||||
this.temporaryBufferFolder = temporaryBufferFolder;
|
||||
}
|
||||
|
||||
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
|
||||
this.fileNameGenerator = fileNameGenerator;
|
||||
}
|
||||
|
||||
public void setCharset(String charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(ftpClientPool, "'ftpClientPool' must not be null");
|
||||
Assert.notNull(temporaryBufferFolder,
|
||||
@@ -70,95 +94,65 @@ public class FtpSendingMessageHandler implements MessageHandler,
|
||||
|
||||
/* Ugh this needs to be put in a convenient place accessible for all the file:, sftp:, and ftp:* adapters */
|
||||
|
||||
private File handleFileMessage(File sourceFile, File tempFile,
|
||||
File resultFile) throws IOException {
|
||||
private File handleFileMessage(File sourceFile, File tempFile, File resultFile) throws IOException {
|
||||
if (sourceFile.renameTo(resultFile)) {
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
FileCopyUtils.copy(sourceFile, tempFile);
|
||||
tempFile.renameTo(resultFile);
|
||||
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
private File handleByteArrayMessage(byte[] bytes, File tempFile,
|
||||
File resultFile) throws IOException {
|
||||
private File handleByteArrayMessage(byte[] bytes, File tempFile, File resultFile) throws IOException {
|
||||
FileCopyUtils.copy(bytes, tempFile);
|
||||
tempFile.renameTo(resultFile);
|
||||
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
private File handleStringMessage(String content, File tempFile,
|
||||
File resultFile, String charset) throws IOException {
|
||||
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(
|
||||
tempFile), charset);
|
||||
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(tempFile), charset);
|
||||
FileCopyUtils.copy(content, writer);
|
||||
tempFile.renameTo(resultFile);
|
||||
|
||||
return resultFile;
|
||||
}
|
||||
|
||||
public void setTemporaryBufferFolder(Resource temporaryBufferFolder) {
|
||||
this.temporaryBufferFolder = temporaryBufferFolder;
|
||||
}
|
||||
|
||||
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
|
||||
this.fileNameGenerator = fileNameGenerator;
|
||||
}
|
||||
|
||||
private File redeemForStorableFile(Message<?> msg)
|
||||
throws MessageDeliveryException {
|
||||
private File redeemForStorableFile(Message<?> message) throws MessageDeliveryException {
|
||||
try {
|
||||
Object payload = msg.getPayload();
|
||||
String generateFileName = this.fileNameGenerator.generateFileName(msg);
|
||||
File tempFile = new File(temporaryBufferFolderFile,
|
||||
generateFileName + TEMPORARY_FILE_SUFFIX);
|
||||
File resultFile = new File(temporaryBufferFolderFile,
|
||||
generateFileName);
|
||||
Object payload = message.getPayload();
|
||||
String generateFileName = this.fileNameGenerator.generateFileName(message);
|
||||
File tempFile = new File(temporaryBufferFolderFile, generateFileName + TEMPORARY_FILE_SUFFIX);
|
||||
File resultFile = new File(temporaryBufferFolderFile, generateFileName);
|
||||
File sendableFile;
|
||||
|
||||
if (payload instanceof String) {
|
||||
sendableFile = this.handleStringMessage((String) payload,
|
||||
tempFile, resultFile, this.charset);
|
||||
} else if (payload instanceof File) {
|
||||
sendableFile = this.handleFileMessage((File) payload, tempFile,
|
||||
resultFile);
|
||||
} else if (payload instanceof byte[]) {
|
||||
sendableFile = this.handleByteArrayMessage((byte[]) payload,
|
||||
tempFile, resultFile);
|
||||
} else {
|
||||
sendableFile = this.handleStringMessage((String) payload, tempFile, resultFile, this.charset);
|
||||
}
|
||||
else if (payload instanceof File) {
|
||||
sendableFile = this.handleFileMessage((File) payload, tempFile, resultFile);
|
||||
}
|
||||
else if (payload instanceof byte[]) {
|
||||
sendableFile = this.handleByteArrayMessage((byte[]) payload, tempFile, resultFile);
|
||||
}
|
||||
else {
|
||||
sendableFile = null;
|
||||
}
|
||||
|
||||
return sendableFile;
|
||||
} catch (Throwable th) {
|
||||
throw new MessageDeliveryException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCharset(String charset) {
|
||||
this.charset = charset;
|
||||
catch (Throwable th) {
|
||||
throw new MessageDeliveryException(message);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ugh this needs to be put in a convenient place accessible for all the file:, sftp:, and ftp:* adapters */
|
||||
|
||||
public void handleMessage(Message<?> message)
|
||||
throws MessageRejectedException, MessageHandlingException,
|
||||
MessageDeliveryException {
|
||||
public void handleMessage(Message<?> message) {
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
|
||||
Object payload = message.getPayload();
|
||||
|
||||
Assert.notNull(payload, "Message payload must not be null");
|
||||
|
||||
File file = this.redeemForStorableFile(message);
|
||||
|
||||
if ((file != null) && file.exists()) {
|
||||
FTPClient client = null;
|
||||
boolean sentSuccesfully;
|
||||
|
||||
try {
|
||||
client = getFtpClient();
|
||||
sentSuccesfully = sendFile(file, client);
|
||||
@@ -167,14 +161,17 @@ public class FtpSendingMessageHandler implements MessageHandler,
|
||||
"File [" + file +
|
||||
"] not found in local working directory; it was moved or deleted unexpectedly",
|
||||
e);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MessageDeliveryException(message,
|
||||
"Error transferring file [" + file +
|
||||
"] from local working directory to remote FTP directory", e);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MessageDeliveryException(message,
|
||||
"Error handling message for file [" + file + "]", e);
|
||||
} finally {
|
||||
}
|
||||
finally {
|
||||
if (file.exists()) {
|
||||
try {
|
||||
file.delete();
|
||||
@@ -182,12 +179,10 @@ public class FtpSendingMessageHandler implements MessageHandler,
|
||||
/// noop
|
||||
}
|
||||
}
|
||||
|
||||
if (client != null) {
|
||||
ftpClientPool.releaseClient(client);
|
||||
}
|
||||
}
|
||||
|
||||
if (!sentSuccesfully) {
|
||||
throw new MessageDeliveryException(message,
|
||||
"Failed to store file '" + file + "'");
|
||||
@@ -195,22 +190,19 @@ public class FtpSendingMessageHandler implements MessageHandler,
|
||||
}
|
||||
}
|
||||
|
||||
private boolean sendFile(File file, FTPClient client)
|
||||
throws FileNotFoundException, IOException {
|
||||
private boolean sendFile(File file, FTPClient client) throws FileNotFoundException, IOException {
|
||||
FileInputStream fileInputStream = new FileInputStream(file);
|
||||
boolean sent = client.storeFile(file.getName(), fileInputStream);
|
||||
fileInputStream.close();
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
private FTPClient getFtpClient() throws SocketException, IOException {
|
||||
FTPClient client;
|
||||
client = this.ftpClientPool.getClient();
|
||||
Assert.state(client != null,
|
||||
FtpClientPool.class.getSimpleName() +
|
||||
" returned 'null' client this most likely a bug in the pool implementation.");
|
||||
|
||||
Assert.state(client != null, FtpClientPool.class.getSimpleName() +
|
||||
" returned 'null' client this most likely a bug in the pool implementation.");
|
||||
return client;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -71,9 +71,10 @@ public class FtpSendingMessageHandlerFactoryBean extends AbstractFactoryBean<Ftp
|
||||
defaultFtpClientFactory);
|
||||
|
||||
FtpSendingMessageHandler ftpSendingMessageHandler = new FtpSendingMessageHandler(queuedFtpClientPool);
|
||||
ftpSendingMessageHandler.setCharset( this.charset);
|
||||
if (this.charset != null) {
|
||||
ftpSendingMessageHandler.setCharset(this.charset);
|
||||
}
|
||||
ftpSendingMessageHandler.afterPropertiesSet();
|
||||
|
||||
return ftpSendingMessageHandler;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-integration-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-groovy</artifactId>
|
||||
@@ -24,19 +25,16 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<!-- test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -69,6 +69,7 @@ public class HttpOutboundChannelAdapterParser extends AbstractOutboundChannelAda
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expected-response-type");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "request-factory");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "error-handler");
|
||||
List<Element> uriVariableElements = DomUtils.getChildElementsByTagName(element, "uri-variable");
|
||||
if (!CollectionUtils.isEmpty(uriVariableElements)) {
|
||||
Map<String, String> uriVariableExpressions = new HashMap<String, String>();
|
||||
|
||||
@@ -75,6 +75,7 @@ public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser {
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "expected-response-type");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-timeout", "sendTimeout");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "request-factory");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "error-handler");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel", "outputChannel");
|
||||
List<Element> uriVariableElements = DomUtils.getChildElementsByTagName(element, "uri-variable");
|
||||
if (!CollectionUtils.isEmpty(uriVariableElements)) {
|
||||
|
||||
@@ -245,6 +245,9 @@
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-factory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Reference to a ClientHttpRequestFactory to be used by the underlying RestTemplate.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.http.client.ClientHttpRequestFactory" />
|
||||
@@ -252,6 +255,18 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="error-handler" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Reference to a ResponseErrorHandler to be used by the underlying RestTemplate.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.web.client.ResponseErrorHandler" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="order" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -347,6 +362,9 @@
|
||||
<xsd:attribute name="charset" type="xsd:string" />
|
||||
<xsd:attribute name="request-factory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Reference to a ClientHttpRequestFactory to be used by the underlying RestTemplate.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.http.client.ClientHttpRequestFactory" />
|
||||
@@ -354,6 +372,18 @@
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="error-handler" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Reference to a ResponseErrorHandler to be used by the underlying RestTemplate.
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.web.client.ResponseErrorHandler" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="order" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
expected-response-type="java.lang.Boolean"
|
||||
mapped-request-headers="requestHeader1, requestHeader2"
|
||||
request-factory="testRequestFactory"
|
||||
error-handler="testErrorHandler"
|
||||
order="77"
|
||||
auto-startup="false">
|
||||
<uri-variable name="foo" expression="headers.bar"/>
|
||||
@@ -31,6 +32,8 @@
|
||||
|
||||
<beans:bean id="testRequestFactory" class="org.springframework.http.client.SimpleClientHttpRequestFactory"/>
|
||||
|
||||
<beans:bean id="testErrorHandler" class="org.springframework.integration.http.config.HttpOutboundChannelAdapterParserTests$StubErrorHandler"/>
|
||||
|
||||
<util:list id="converterList">
|
||||
<beans:bean class="org.springframework.integration.http.config.StubHttpMessageConverter"/>
|
||||
<beans:bean class="org.springframework.integration.http.config.StubHttpMessageConverter"/>
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -32,12 +33,14 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
import org.springframework.integration.http.HttpRequestExecutingMessageHandler;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.client.ResponseErrorHandler;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
@@ -94,6 +97,8 @@ public class HttpOutboundChannelAdapterParserTests {
|
||||
assertEquals(converterListBean, templateAccessor.getPropertyValue("messageConverters"));
|
||||
Object requestFactoryBean = this.applicationContext.getBean("testRequestFactory");
|
||||
assertEquals(requestFactoryBean, requestFactory);
|
||||
Object errorHandlerBean = this.applicationContext.getBean("testErrorHandler");
|
||||
assertEquals(errorHandlerBean, templateAccessor.getPropertyValue("errorHandler"));
|
||||
assertEquals("http://localhost/test2/{foo}", handlerAccessor.getPropertyValue("uri"));
|
||||
assertEquals(HttpMethod.GET, handlerAccessor.getPropertyValue("httpMethod"));
|
||||
assertEquals("UTF-8", handlerAccessor.getPropertyValue("charset"));
|
||||
@@ -111,4 +116,15 @@ public class HttpOutboundChannelAdapterParserTests {
|
||||
assertTrue(ObjectUtils.containsElement(mappedRequestHeaders, "requestHeader2"));
|
||||
}
|
||||
|
||||
|
||||
public static class StubErrorHandler implements ResponseErrorHandler {
|
||||
|
||||
public boolean hasError(ClientHttpResponse response) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void handleError(ClientHttpResponse response) throws IOException {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
expected-response-type="java.lang.String"
|
||||
mapped-request-headers="requestHeader1, requestHeader2"
|
||||
mapped-response-headers="responseHeader"
|
||||
error-handler="testErrorHandler"
|
||||
reply-channel="replies"
|
||||
charset="UTF-8"
|
||||
order="77"
|
||||
@@ -40,6 +41,8 @@
|
||||
|
||||
<beans:bean id="testRequestFactory" class="org.springframework.http.client.SimpleClientHttpRequestFactory"/>
|
||||
|
||||
<beans:bean id="testErrorHandler" class="org.springframework.integration.http.config.HttpOutboundGatewayParserTests$StubErrorHandler"/>
|
||||
|
||||
<util:list id="converterList">
|
||||
<beans:bean class="org.springframework.integration.http.config.StubHttpMessageConverter"/>
|
||||
<beans:bean class="org.springframework.integration.http.config.StubHttpMessageConverter"/>
|
||||
|
||||
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -33,6 +34,7 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.endpoint.AbstractEndpoint;
|
||||
@@ -40,6 +42,7 @@ import org.springframework.integration.http.HttpRequestExecutingMessageHandler;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.client.ResponseErrorHandler;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
@@ -105,6 +108,8 @@ public class HttpOutboundGatewayParserTests {
|
||||
assertEquals(false, handlerAccessor.getPropertyValue("extractPayload"));
|
||||
Object requestFactoryBean = this.applicationContext.getBean("testRequestFactory");
|
||||
assertEquals(requestFactoryBean, requestFactory);
|
||||
Object errorHandlerBean = this.applicationContext.getBean("testErrorHandler");
|
||||
assertEquals(errorHandlerBean, templateAccessor.getPropertyValue("errorHandler"));
|
||||
Object sendTimeout = new DirectFieldAccessor(
|
||||
handlerAccessor.getPropertyValue("messagingTemplate")).getPropertyValue("sendTimeout");
|
||||
assertEquals(new Long("1234"), sendTimeout);
|
||||
@@ -122,4 +127,15 @@ public class HttpOutboundGatewayParserTests {
|
||||
assertEquals("responseHeader", mappedResponseHeaders[0]);
|
||||
}
|
||||
|
||||
|
||||
public static class StubErrorHandler implements ResponseErrorHandler {
|
||||
|
||||
public boolean hasError(ClientHttpResponse response) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void handleError(ClientHttpResponse response) throws IOException {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user