View Javadoc

1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.jsieve.comparators;
21  
22  import java.util.regex.Matcher;
23  import java.util.regex.Pattern;
24  import java.util.regex.PatternSyntaxException;
25  
26  import org.apache.jsieve.SieveContext;
27  import org.apache.jsieve.exception.LookupException;
28  import org.apache.jsieve.exception.SieveException;
29  import org.apache.jsieve.exception.SievePatternException;
30  
31  import static  org.apache.jsieve.comparators.MatchTypeTags.*;
32  
33  /**
34   * Class ComparatorUtils implements utility methods used by Comparators.
35   */
36  public class ComparatorUtils {
37  
38      /**
39       * Constructor for ComparatorUtils.
40       */
41      private ComparatorUtils() {
42          super();
43      }
44  
45      /**
46       * Method <code>match</code> answers a boolean indicating if the parameter
47       * <code>matchTarget</code> compares to parameter
48       * <code>matchArgument</code> is a match of <code>matchType</code> using
49       * the comparator <code>comparatorName</code>.
50       * 
51       * @param comparatorName not null
52       * @param matchType not null
53       * @param matchTarget not null
54       * @param matchArgument not null
55       * @param context not null
56       * @return boolean
57       */
58      public static boolean match(String comparatorName, String matchType,
59              String matchTarget, String matchArgument, SieveContext context)
60              throws SieveException {
61          boolean isMatched = false;
62          if (matchType.equals(IS_TAG))
63              isMatched = is(comparatorName, matchTarget, matchArgument, context);
64          else if (matchType.equals(CONTAINS_TAG))
65              isMatched = contains(comparatorName, matchTarget, matchArgument,
66                      context);
67          else if (matchType.equals(MATCHES_TAG))
68              isMatched = matches(comparatorName, matchTarget, matchArgument,
69                      context);
70          return isMatched;
71      }
72  
73      /**
74       * <p>
75       * Method <code>matches</code> answers a boolean indicating if the
76       * parameter <code>string</code> matches the glob pattern described by
77       * parameter <code>glob</code>.
78       * 
79       * @param string
80       * @param glob
81       * @return boolean
82       * @throws SievePatternException
83       */
84      static public boolean matches(String string, String glob)
85              throws SievePatternException {
86          try {
87              String regex = sieveToJavaRegex(glob);
88              final Matcher matcher = Pattern.compile(regex).matcher(string);
89              return matcher.matches();
90          } catch (PatternSyntaxException e) {
91              throw new SievePatternException(e.getMessage());
92          }
93      }
94  
95      /**
96       * <p>
97       * Method <code>contains</code> answers a boolean indicating if the
98       * parameter <code>container</code> contains the parameter
99       * <code>contents</code>.
100      * </p>
101      * 
102      * @param container
103      * @param contents
104      * @return boolean
105      */
106     static public boolean contains(String container, String contents) {
107         return container.indexOf(contents) > -1;
108     }
109 
110     /**
111      * <p>
112      * Method <code>equals</code> answers a boolean indicating if the
113      * parameter <code>string1</code> is equal to the parameter
114      * <code>string2</code>.
115      * </p>
116      * 
117      * @param string1
118      * @param string2
119      * @return boolean
120      */
121     static public boolean equals(String string1, String string2) {
122         return string1.equals(string2);
123     }
124 
125     /**
126      * Returns true if the char is a special char for regex
127      */
128     private static boolean isRegexSpecialChar(char ch) {
129         return (ch == '*' || ch == '?' || ch == '+' || ch == '[' || ch == ']'
130                 || ch == '(' || ch == ')' || ch == '|' || ch == '^'
131                 || ch == '$' || ch == '.' || ch == '{' || ch == '}' || ch == '\\');
132     }
133 
134     /**
135      * Returns true if the char is a special char for sieve matching
136      */
137     private static boolean isSieveMatcherSpecialChar(char ch) {
138         return (ch == '*' || ch == '?' || ch == '\\');
139     }
140 
141     /**
142      * Converts a Sieve pattern in a java regex pattern
143      */
144     public static String sieveToJavaRegex(String pattern) {
145         int ch;
146         StringBuffer buffer = new StringBuffer(2 * pattern.length());
147         boolean lastCharWasStar = false;
148         for (ch = 0; ch < pattern.length(); ch++) {
149             final char nextChar = pattern.charAt(ch);
150             switch (nextChar) {
151             case '*':
152                 //
153                 // Java Matcher has issues with repeated stars
154                 //
155                 if (!lastCharWasStar) {
156                     buffer.append(".*");
157                 }
158                 break;
159             case '?':
160                 buffer.append('.');
161                 break;
162             case '\\':
163                 buffer.append('\\');
164                 if (ch == pattern.length() - 1)
165                     buffer.append('\\');
166                 else if (isSieveMatcherSpecialChar(pattern.charAt(ch + 1)))
167                     buffer.append(pattern.charAt(++ch));
168                 else
169                     buffer.append('\\');
170                 break;
171             default:
172                 if (isRegexSpecialChar(nextChar))
173                     buffer.append('\\');
174                 buffer.append(nextChar);
175                 break;
176             }
177             // Workaround for issue with Java Matcher
178             lastCharWasStar = '*' == nextChar;
179         }
180         return buffer.toString();
181     }
182 
183     /**
184      * Method <code>contains<code> answers a boolean indicating if the parameter 
185      * <code>container</code> contains the parameter <code>contents</code> using an
186      * instance of <code>comparatorName</code>.
187      * @param comparatorName not null
188      * @param container not null
189      * @param contents not null
190      * @param context not null
191      * @return boolean
192      */
193     public static boolean contains(String comparatorName, String container,
194             String contents, SieveContext context) throws SieveException {
195         Contains comparatorObj = context.getComparatorManager().getComparator(comparatorName);
196         return comparatorObj.contains(container, contents);
197     }
198 
199     /**
200      * Method <code>is<code> answers a boolean indicating if the parameter 
201      * <code>container</code> is equal to the parameter <code>contents</code> using 
202      * an instance of <code>comparatorName</code>.
203      * @param comparatorName
204      * @param string1 not null
205      * @param string2 not null
206      * @param context not null
207      * @return boolean
208      */
209     public static boolean is(String comparatorName, String string1,
210             String string2, SieveContext context) throws LookupException {
211         Equals comparatorObj = context.getComparatorManager().getComparator(comparatorName);
212         return comparatorObj.equals(string1, string2);
213     }
214 
215     /**
216      * Method <code>matches</code> answers a boolean indicating if the
217      * parameter
218      * <code>string/code> is matched by the patterm <code>glob</code> using an
219      * instance of <code>comparatorName</code>.
220      * @param comparatorName not null
221      * @param string not null
222      * @param glob not null
223      * @param context not null
224      * @return boolean
225      */
226     public static boolean matches(String comparatorName, String string,
227             String glob, SieveContext context) throws SieveException {
228         Matches comparatorObj = context.getComparatorManager().getComparator(comparatorName);
229         return comparatorObj.matches(string, glob);
230     }
231 
232 }