View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.routing.filters;
8   
9   import org.mule.api.MuleMessage;
10  import org.mule.api.routing.filter.Filter;
11  import org.mule.api.transport.PropertyScope;
12  import org.mule.util.StringUtils;
13  
14  import org.apache.commons.logging.Log;
15  import org.apache.commons.logging.LogFactory;
16  
17  import static org.mule.util.ClassUtils.equal;
18  import static org.mule.util.ClassUtils.hash;
19  
20  /**
21   * <code>MessagePropertyFilter</code> can be used to filter against properties on
22   * an event. This can be very useful as the event properties represent all the meta
23   * information about the event from the underlying transport, so for an event
24   * received over HTTP you can check for HTTP headers etc. The pattern should be
25   * expressed as a key/value pair, i.e. "propertyName=value". If you want to compare
26   * more than one property you can use the logic filters for And, Or and Not
27   * expressions. By default the comparison is case sensitive; you can set the
28   * <i>caseSensitive</i> property to override this.
29   * <p/>
30   * Since 3.0.0 its possible to set the property value as a wildcard expression i.e.
31   * <p/>
32   * <pre>fooHeader = *foo*</pre>
33   */
34  public class MessagePropertyFilter implements Filter
35  {
36      /**
37       * logger used by this class
38       */
39      protected transient final Log logger = LogFactory.getLog(MessagePropertyFilter.class);
40      private boolean caseSensitive = true;
41      private boolean not = false;
42  
43      private String propertyName;
44      private String propertyValue;
45      private PropertyScope scope = PropertyScope.OUTBOUND;
46  
47      private WildcardFilter wildcardFilter;
48  
49      public MessagePropertyFilter()
50      {
51          super();
52      }
53  
54      public MessagePropertyFilter(String expression)
55      {
56          setPattern(expression);
57      }
58  
59      public boolean accept(MuleMessage message)
60      {
61          if (message == null)
62          {
63              return false;
64          }
65          Object value = message.getProperty(propertyName, scope);
66          boolean match;
67          if (value == null)
68          {
69              match = compare(null, propertyValue);
70          }
71          else
72          {
73              match = compare(value.toString(), propertyValue);
74          }
75          if (!match && logger.isDebugEnabled())
76          {
77              logger.debug(String.format("Property: '%s' not found in scope '%s'. Message %n%s", propertyName, scope, message));
78          }
79          return match;
80      }
81  
82      protected boolean compare(String value1, String value2)
83      {
84          if (value1 == null && value2 != null && !"null".equals(value2) && not)
85          {
86              return true;
87          }
88  
89          if (value1 == null)
90          {
91              value1 = "null";
92          }
93  
94  
95          boolean result;
96  
97          result = wildcardFilter.accept(value1);
98  
99          return (not ? !result : result);
100     }
101 
102     public String getPattern()
103     {
104         return propertyName + '=' + propertyValue;
105     }
106 
107     public void setPattern(String expression)
108     {
109         int x = expression.indexOf(":");
110         int i = expression.indexOf('=');
111 
112         if (i == -1)
113         {
114             throw new IllegalArgumentException(
115                     "Pattern is malformed - it should be a key value pair, i.e. property=value: " + expression);
116         }
117 
118         if (x > -1 && x < i)
119         {
120             setScope(expression.substring(0, x));
121             expression = expression.substring(x + 1);
122             i = expression.indexOf('=');
123         }
124 
125 
126         if (expression.charAt(i - 1) == '!')
127         {
128             not = true;
129             propertyName = expression.substring(0, i - 1).trim();
130         }
131         else
132         {
133             propertyName = expression.substring(0, i).trim();
134         }
135         propertyValue = expression.substring(i + 1).trim();
136 
137         wildcardFilter = new WildcardFilter(propertyValue);
138         wildcardFilter.setCaseSensitive(isCaseSensitive());
139     }
140 
141     public boolean isCaseSensitive()
142     {
143         return caseSensitive;
144     }
145 
146     public void setCaseSensitive(boolean caseSensitive)
147     {
148         this.caseSensitive = caseSensitive;
149         if (wildcardFilter != null)
150         {
151             wildcardFilter.setCaseSensitive(caseSensitive);
152         }
153     }
154 
155     public String getScope()
156     {
157         return scope.getScopeName();
158     }
159 
160     public void setScope(String scope)
161     {
162         if (StringUtils.isBlank(scope))
163         {
164             // ignore and use defaults
165             return;
166         }
167 
168         PropertyScope ps = PropertyScope.get(scope.toLowerCase().trim());
169         if (ps == null)
170         {
171             throw new IllegalArgumentException(String.format("'%s' is not a valid property scope.", scope));
172         }
173         this.scope = ps;
174     }
175 
176     public boolean equals(Object obj)
177     {
178         if (this == obj)
179         {
180             return true;
181         }
182         if (obj == null || getClass() != obj.getClass())
183         {
184             return false;
185         }
186 
187         final MessagePropertyFilter other = (MessagePropertyFilter) obj;
188         return equal(propertyName, other.propertyName)
189                 && equal(propertyValue, other.propertyValue)
190                 && equal(scope, other.scope)
191                 && caseSensitive == other.caseSensitive;
192     }
193 
194     public int hashCode()
195     {
196         return hash(new Object[]{this.getClass(), propertyName, propertyValue, scope, caseSensitive});
197     }
198 }