/*
* Copyright 2002-2016 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;
import org.springframework.expression.Expression;
import org.springframework.integration.core.MessageSelector;
import org.springframework.integration.filter.ExpressionEvaluatingSelector;
import org.springframework.integration.filter.MessageFilter;
import org.springframework.integration.filter.MethodInvokingSelector;
import org.springframework.integration.handler.AbstractMessageProducingHandler;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Factory bean for creating a Message Filter.
*
* @author Mark Fisher
* @author Gary Russell
* @author David Liu
* @since 2.0
*/
public class FilterFactoryBean extends AbstractStandardMessageHandlerFactoryBean {
private volatile MessageChannel discardChannel;
private volatile Boolean throwExceptionOnRejection;
private volatile Long sendTimeout;
private volatile Boolean discardWithinAdvice;
public void setDiscardChannel(MessageChannel discardChannel) {
this.discardChannel = discardChannel;
}
public void setThrowExceptionOnRejection(Boolean throwExceptionOnRejection) {
this.throwExceptionOnRejection = throwExceptionOnRejection;
}
public void setSendTimeout(Long sendTimeout) {
this.sendTimeout = sendTimeout;
}
public void setDiscardWithinAdvice(boolean discardWithinAdvice) {
this.discardWithinAdvice = discardWithinAdvice;
}
@Override
protected MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName) {
MessageSelector selector = null;
if (targetObject instanceof MessageSelector) {
selector = (MessageSelector) targetObject;
}
else if (StringUtils.hasText(targetMethodName)) {
this.checkForIllegalTarget(targetObject, targetMethodName);
selector = new MethodInvokingSelector(targetObject, targetMethodName);
}
else {
selector = new MethodInvokingSelector(targetObject);
}
return this.createFilter(selector);
}
@Override
protected void checkForIllegalTarget(Object targetObject, String targetMethodName) {
if (targetObject instanceof AbstractReplyProducingMessageHandler
&& this.methodIsHandleMessageOrEmpty(targetMethodName)) {
throw new IllegalArgumentException("You cannot use 'AbstractReplyProducingMessageHandler.handleMessage()' "
+ "as a filter - it does not return a result");
}
}
@Override
protected MessageHandler createExpressionEvaluatingHandler(Expression expression) {
return this.createFilter(new ExpressionEvaluatingSelector(expression));
}
protected MessageFilter createFilter(MessageSelector selector) {
MessageFilter filter = new MessageFilter(selector);
postProcessReplyProducer(filter);
return filter;
}
protected void postProcessFilter(MessageFilter filter) {
if (this.throwExceptionOnRejection != null) {
filter.setThrowExceptionOnRejection(this.throwExceptionOnRejection);
}
if (this.discardChannel != null) {
filter.setDiscardChannel(this.discardChannel);
}
if (this.discardWithinAdvice != null) {
filter.setDiscardWithinAdvice(this.discardWithinAdvice);
}
}
@Override
protected void postProcessReplyProducer(AbstractMessageProducingHandler handler) {
if (this.sendTimeout != null) {
handler.setSendTimeout(this.sendTimeout);
}
if (!(handler instanceof MessageFilter)) {
Assert.isNull(this.throwExceptionOnRejection, "Cannot set throwExceptionOnRejection if the referenced bean is "
+ "an AbstractReplyProducingMessageHandler, but not a MessageFilter");
Assert.isNull(this.discardChannel, "Cannot set discardChannel if the referenced bean is "
+ "an AbstractReplyProducingMessageHandler, but not a MessageFilter");
Assert.isNull(this.discardWithinAdvice, "Cannot set discardWithinAdvice if the referenced bean is "
+ "an AbstractReplyProducingMessageHandler, but not a MessageFilter");
}
else {
postProcessFilter((MessageFilter) handler);
}
}
/**
* MessageFilter is an ARPMH. If a non-MessageFilter ARPMH is also a
* MessageSelector, MesageSelector wins and gets wrapped in a MessageFilter.
*/
@Override
protected boolean canBeUsedDirect(AbstractMessageProducingHandler handler) {
return handler instanceof MessageFilter
|| (!(handler instanceof MessageSelector)
&& this.discardChannel == null && this.throwExceptionOnRejection == null
&& this.discardWithinAdvice == null);
}
@Override
protected Class<? extends MessageHandler> getPreCreationHandlerType() {
return MessageFilter.class;
}
}