/* * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package org.mule.runtime.core.routing.filters; import static org.mule.runtime.core.util.ClassUtils.equal; import static org.mule.runtime.core.util.ClassUtils.hash; import static org.mule.runtime.core.util.ClassUtils.withContextClassLoader; import org.mule.runtime.api.message.Message; import org.mule.runtime.core.api.Event; import org.mule.runtime.core.api.MuleContext; import org.mule.runtime.core.api.context.MuleContextAware; import org.mule.runtime.core.api.routing.filter.Filter; import org.mule.runtime.core.expression.ExpressionConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Allows boolean expressions to be executed on a message. Note that when using this filter you must be able to either specify a * boolean expression when using an expression filter or use one of the standard Mule filters. Otherwise you can use eny * expression filter providing you can define a boolean expression i.e. <code> * #[mel:xpath:count(/Foo/Bar) == 0] * </code> Note that it if the expression is not a boolean expression this filter will return true if the expression returns a * result */ public class ExpressionFilter implements Filter, MuleContextAware { /** * logger used by this class */ protected transient final Logger logger = LoggerFactory.getLogger(ExpressionFilter.class); private ExpressionConfig config; private boolean nullReturnsTrue = false; private MuleContext muleContext; /** * For evaluators that are not expression languages we can delegate the execution to another filter */ private Filter delegateFilter; public ExpressionFilter(String expression) { this.config = new ExpressionConfig(); this.config.parse(expression); } public ExpressionFilter() { super(); this.config = new ExpressionConfig(); } @Override public void setMuleContext(MuleContext context) { this.muleContext = context; } /** * Check a given message against this filter. * * @param message a non null message to filter. * @return <code>true</code> if the message matches the filter */ @Override public boolean accept(Message message, Event.Builder builder) { // TODO MULE-9341 Remove Filters. Expression filter will be replaced by something that uses MuleEvent. return accept(builder.message(message).build(), builder); } /** * Check a given event against this filter. * * @param event a non null event to filter. * @return <code>true</code> if the event matches the filter */ @Override public boolean accept(Event event, Event.Builder builder) { return withContextClassLoader(muleContext.getExecutionClassLoader(), () -> muleContext.getExpressionManager() .evaluateBoolean(getFullExpression(), event, null, nullReturnsTrue, !nullReturnsTrue)); } protected String getFullExpression() { return config.getExpression(); } public String getExpression() { return config.getExpression(); } public void setExpression(String expression) { this.config.setExpression(expression); } public boolean isNullReturnsTrue() { return nullReturnsTrue; } public void setNullReturnsTrue(boolean nullReturnsTrue) { this.nullReturnsTrue = nullReturnsTrue; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } final ExpressionFilter other = (ExpressionFilter) obj; return equal(config, other.config) && equal(delegateFilter, other.delegateFilter) && nullReturnsTrue == other.nullReturnsTrue; } @Override public int hashCode() { return hash(new Object[] {this.getClass(), config, delegateFilter, nullReturnsTrue}); } }