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.tests;
21  
22  import static org.apache.jsieve.comparators.ComparatorNames.ASCII_CASEMAP_COMPARATOR;
23  import static org.apache.jsieve.comparators.MatchTypeTags.CONTAINS_TAG;
24  import static org.apache.jsieve.comparators.MatchTypeTags.IS_TAG;
25  import static org.apache.jsieve.comparators.MatchTypeTags.MATCHES_TAG;
26  import static org.apache.jsieve.tests.AddressPartTags.ALL_TAG;
27  import static org.apache.jsieve.tests.AddressPartTags.DOMAIN_TAG;
28  import static org.apache.jsieve.tests.AddressPartTags.LOCALPART_TAG;
29  import static org.apache.jsieve.tests.ComparatorTags.COMPARATOR_TAG;
30  
31  import java.util.List;
32  import java.util.ListIterator;
33  
34  import org.apache.jsieve.Argument;
35  import org.apache.jsieve.Arguments;
36  import org.apache.jsieve.SieveContext;
37  import org.apache.jsieve.StringListArgument;
38  import org.apache.jsieve.TagArgument;
39  import org.apache.jsieve.exception.SieveException;
40  import org.apache.jsieve.exception.SyntaxException;
41  import org.apache.jsieve.mail.MailAdapter;
42  import org.apache.jsieve.mail.SieveMailException;
43  
44  
45  public abstract class AbstractCompatatorTest extends AbstractTest {
46  
47      public AbstractCompatatorTest() {
48          super();
49      }
50  
51      /**
52       * <p>
53       * From RFC 3028, Section 5.1...
54       * </p>
55       * <code>  
56       * Syntax: address [ADDRESS-PART] [COMPARATOR] [MATCH-TYPE]
57       *         &lt;header-list: string-list&gt; &lt;key-list: string-list&gt;
58       * </code>
59       * <p>
60       * Note that the spec. then goes on to give an example where the order of
61       * the optional parts is different, so I am assuming that the order of the
62       * optional parts is optional too!
63       * </p>
64       * 
65       * @see org.apache.jsieve.tests.AbstractTest#executeBasic(MailAdapter,
66       *      Arguments, SieveContext)
67       */
68      protected boolean executeBasic(MailAdapter mail, Arguments arguments,
69              SieveContext context) throws SieveException {
70          String addressPart = null;
71          String comparator = null;
72          String matchType = null;
73          List<String> headerNames = null;
74          List<String> keys = null;
75  
76          ListIterator<Argument> argumentsIter = arguments.getArgumentList().listIterator();
77          boolean stop = false;
78  
79          // Tag processing
80          while (!stop && argumentsIter.hasNext()) {
81              Argument argument = argumentsIter.next();
82              if (argument instanceof TagArgument) {
83                  String tag = ((TagArgument) argument).getTag();
84  
85                  // [ADDRESS-PART]?
86                  if (null == addressPart
87                          && (tag.equals(LOCALPART_TAG) || tag.equals(DOMAIN_TAG) || tag
88                                  .equals(ALL_TAG)))
89                      addressPart = tag;
90                  // [COMPARATOR]?
91                  else if (null == comparator && tag.equals(COMPARATOR_TAG)) {
92                      // The next argument must be a stringlist
93                      if (argumentsIter.hasNext()) {
94                          argument = argumentsIter.next();
95                          if (argument instanceof StringListArgument) {
96                              List stringList = ((StringListArgument) argument)
97                                      .getList();
98                              if (stringList.size() != 1)
99                                  throw new SyntaxException(
100                                         "Expecting exactly one String");
101                             comparator = (String) stringList.get(0);
102                         } else
103                             throw new SyntaxException("Expecting a StringList");
104                     }
105                 }
106                 // [MATCH-TYPE]?
107                 else if (null == matchType
108                         && (tag.equals(IS_TAG) || tag.equals(CONTAINS_TAG) || tag
109                                 .equals(MATCHES_TAG)))
110                     matchType = tag;
111                 else
112                     throw context.getCoordinate().syntaxException(
113                             "Found unexpected TagArgument");
114             } else {
115                 // Stop when a non-tag argument is encountered
116                 argumentsIter.previous();
117                 stop = true;
118             }
119         }
120 
121         // The next argument MUST be a string-list of header names
122         if (argumentsIter.hasNext()) {
123             Argument argument = argumentsIter.next();
124             if (argument instanceof StringListArgument)
125                 headerNames = ((StringListArgument) argument).getList();
126         }
127         if (null == headerNames)
128             throw context.getCoordinate().syntaxException(
129                     "Expecting a StringList of header names");
130 
131         // The next argument MUST be a string-list of keys
132         if (argumentsIter.hasNext()) {
133             Argument argument = argumentsIter.next();
134             if (argument instanceof StringListArgument)
135                 keys = ((StringListArgument) argument).getList();
136         } else if (null == keys)
137             throw context.getCoordinate().syntaxException(
138                     "Expecting a StringList of keys");
139 
140         if (argumentsIter.hasNext())
141             throw context.getCoordinate().syntaxException(
142                     "Found unexpected arguments");
143 
144         return match(mail, (addressPart == null ? ALL_TAG : addressPart),
145                 (comparator == null ? ASCII_CASEMAP_COMPARATOR : comparator),
146                 (matchType == null ? IS_TAG : matchType), headerNames, keys,
147                 context);
148     }
149 
150     /**
151      * Method match.
152      * 
153      * @param mail
154      * @param addressPart
155      * @param comparator
156      * @param matchType
157      * @param headerNames
158      * @param keys
159      * @param context not null
160      * @return boolean
161      * @throws SieveMailException
162      */
163     protected boolean match(MailAdapter mail, String addressPart,
164             String comparator, String matchType, List<String> headerNames, List<String> keys,
165             SieveContext context) throws SieveException {
166         // Iterate over the header names looking for a match
167         boolean isMatched = false;
168         for (final String headerName: headerNames) {
169             isMatched = match(mail, addressPart, comparator, matchType,
170                     headerName, keys, context); 
171             if (isMatched) {
172                 break;
173             }
174         }
175         return isMatched;
176     }
177 
178     /**
179      * Method match.
180      * 
181      * @param mail
182      * @param addressPart
183      * @param comparator
184      * @param matchType
185      * @param headerName
186      * @param keys
187      * @param context not null
188      * @return boolean
189      * @throws SieveMailException
190      */
191     protected boolean match(MailAdapter mail, String addressPart,
192             String comparator, String matchType, String headerName, List<String> keys,
193             SieveContext context) throws SieveException {
194         // Iterate over the keys looking for a match
195         boolean isMatched = false;
196         for (final String key:keys) {
197             isMatched = match(mail, addressPart, comparator, matchType,
198                     headerName, key, context);
199             if (isMatched) {
200                 break;
201             }
202         }
203         return isMatched;
204     }
205 
206     /**
207      * Method match.
208      * 
209      * @param mail
210      * @param addressPart
211      * @param comparator
212      * @param matchType
213      * @param headerName
214      * @param key
215      * @param context not null
216      * @return boolean
217      * @throws SieveMailException
218      */
219     protected abstract boolean match(MailAdapter mail, String addressPart,
220             String comparator, String matchType, String headerName, String key,
221             SieveContext context) throws SieveException;
222 
223     /**
224      * @see org.apache.jsieve.tests.AbstractTest#validateArguments(Arguments,
225      *      SieveContext)
226      */
227     protected void validateArguments(Arguments arguments, SieveContext context)
228             throws SieveException {
229         if (arguments.hasTests())
230             throw context.getCoordinate().syntaxException(
231                     "Found unexpected tests");
232     }
233 
234 }