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.util.check;
21  
22  import java.io.IOException;
23  
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.Collections;
27  import java.util.Enumeration;
28  import java.util.List;
29  import java.util.ListIterator;
30  
31  import javax.mail.Header;
32  import javax.mail.Message;
33  import javax.mail.MessagingException;
34  
35  import org.apache.jsieve.exception.SieveException;
36  import org.apache.jsieve.mail.Action;
37  import org.apache.jsieve.mail.MailAdapter;
38  import org.apache.jsieve.mail.MailUtils;
39  import org.apache.jsieve.mail.SieveMailException;
40  import org.apache.jsieve.parser.address.SieveAddressBuilder;
41  import org.apache.jsieve.parser.generated.address.ParseException;
42  
43  /**
44   * Checks script execution for an email. The wrapped email is set by called
45   * {@link #setMail}. Actions are recorded on {@link #executedActions} and can
46   * be retrieved by {@link #getExecutedActions()}.
47   */
48  public class ScriptCheckMailAdapter implements MailAdapter {
49  
50      private final List actions;
51  
52      private final List executedActions;
53  
54      private Message mail = null;
55  
56      public ScriptCheckMailAdapter() {
57          actions = new ArrayList();
58          executedActions = new ArrayList();
59      }
60  
61      /**
62       * Gets the wrapped email.
63       * 
64       * @return <code>Message</code>, possibly null
65       */
66      public Message getMail() {
67          return mail;
68      }
69  
70      /**
71       * Sets the wrapped email and {@link #reset}s the adapter ready for another
72       * execution.
73       * 
74       * @param mail
75       *                <code>Message</code>, possibly null
76       */
77      public void setMail(Message mail) {
78          this.mail = mail;
79          reset();
80      }
81  
82      /**
83       * Method addAction adds an Action to the List of Actions to be performed by
84       * the receiver.
85       * 
86       * @param action
87       */
88      public void addAction(final Action action) {
89          actions.add(action);
90      }
91  
92      /**
93       * Method executeActions. Applies the Actions accumulated by the receiver.
94       */
95      public void executeActions() throws SieveException {
96          executedActions.clear();
97          executedActions.addAll(actions);
98      }
99  
100     /**
101      * Gets the actions accumulated when {@link #executedActions} was last
102      * called.
103      * 
104      * @return <code>List</code> of {@link Action}s, not null. This list is a
105      *         modifiable copy
106      */
107     public List getExecutedActions() {
108         final ArrayList result = new ArrayList(executedActions);
109         return result;
110     }
111 
112     /**
113      * Method getActions answers the List of Actions accumulated by the
114      * receiver. Implementations may elect to supply an unmodifiable collection.
115      * 
116      * @return <code>List</code> of {@link Action}'s, not null, possibly
117      *         unmodifiable
118      */
119     public List getActions() {
120         final List result = Collections.unmodifiableList(actions);
121         return result;
122     }
123 
124     /**
125      * Method getActionIteraror answers an Iterator over the List of Actions
126      * accumulated by the receiver. Implementations may elect to supply an
127      * unmodifiable iterator.
128      * 
129      * @return <code>ListIterator</code>, not null, possibly unmodifiable
130      */
131     public ListIterator getActionsIterator() {
132         final List unmodifiableActions = getActions();
133         final ListIterator result = unmodifiableActions.listIterator();
134         return result;
135     }
136 
137     /**
138      * Resets executed and accumlated actions. An instance may be safely reused
139      * to check a script once this method has been called.
140      */
141     public void reset() {
142         executedActions.clear();
143         actions.clear();
144     }
145 
146     /**
147      * Method getHeader answers a List of all of the headers in the receiver
148      * whose name is equal to the passed name. If no headers are found an empty
149      * List is returned.
150      * 
151      * @param name
152      * @return <code>List</code> not null, possibly empty
153      * @throws SieveMailException
154      */
155     public List getHeader(String name) throws SieveMailException {
156         List result = Collections.EMPTY_LIST;
157         if (mail != null) {
158             try {
159                 String[] values = mail.getHeader(name);
160                 if (values != null) {
161                     result = Arrays.asList(values);
162                 }
163             } catch (MessagingException e) {
164                 throw new SieveMailException(e);
165             }
166         }
167         return result;
168     }
169 
170     /**
171      * Method getHeaderNames answers a List of all of the headers in the
172      * receiver. No duplicates are allowed.
173      * 
174      * @return <code>List</code>, not null possible empty, possible
175      *         unmodifiable
176      * @throws SieveMailException
177      */
178     public List getHeaderNames() throws SieveMailException {
179         List results = Collections.EMPTY_LIST;
180         if (mail != null) {
181             try {
182                 results = new ArrayList();
183                 for (final Enumeration en = mail.getAllHeaders(); en
184                         .hasMoreElements();) {
185                     final Header header = (Header) en.nextElement();
186                     final String name = header.getName();
187                     if (!results.contains(name)) {
188                         results.add(name);
189                     }
190                 }
191             } catch (MessagingException e) {
192                 throw new SieveMailException(e);
193             }
194         }
195         return results;
196     }
197 
198     /**
199      * <p>
200      * Method getMatchingHeader answers a List of all of the headers in the
201      * receiver with the passed name. If no headers are found an empty List is
202      * returned.
203      * </p>
204      * 
205      * <p>
206      * This method differs from getHeader(String) in that it ignores case and
207      * the whitespace prefixes and suffixes of a header name when performing the
208      * match, as required by RFC 3028. Thus "From", "from ", " From" and " from "
209      * are considered equal.
210      * </p>
211      * 
212      * @param name
213      * @return <code>List</code>, not null possibly empty
214      * @throws SieveMailException
215      */
216     public List getMatchingHeader(String name) throws SieveMailException {
217         List result = Collections.EMPTY_LIST;
218         if (mail != null) {
219             result = MailUtils.getMatchingHeader(this, name);
220         }
221         return result;
222     }
223 
224     /**
225      * Method getSize answers the receiver's message size in octets.
226      * 
227      * @return int
228      * @throws SieveMailException
229      */
230     public int getSize() throws SieveMailException {
231         int result = 0;
232         if (mail != null) {
233             try {
234                 result = mail.getSize();
235             } catch (MessagingException e) {
236                 throw new SieveMailException(e);
237             }
238         }
239         return result;
240     }
241 
242     /**
243      * Method getContentType returns string/mime representation of the message
244      * type.
245      * 
246      * @return String
247      * @throws SieveMailException
248      */
249     public String getContentType() throws SieveMailException {
250         String result = null;
251         if (mail != null) {
252             try {
253                 result = mail.getContentType();
254             } catch (MessagingException e) {
255                 throw new SieveMailException(e);
256             }
257         }
258         return result;
259     }
260 
261     /**
262      * Method getContent returns object containing the message content.
263      * 
264      * @return Object
265      * @throws SieveMailException
266      */
267     public Object getContent() throws SieveMailException {
268         Object result = null;
269         if (mail != null) {
270             try {
271                 result = mail.getContent();
272             } catch (MessagingException e) {
273                 throw new SieveMailException(e);
274             } catch (IOException e) {
275                 throw new SieveMailException(e);
276             }
277         }
278         return result;
279     }
280 
281     public Address[] parseAddresses(String headerName)
282             throws SieveMailException {
283         return parseAddresses(headerName, mail);
284     }
285 
286     /**
287      * Parses the value from the given message into addresses.
288      * 
289      * @param headerName
290      *                header name, to be matched case insensitively
291      * @param message
292      *                <code>Message</code>, not null
293      * @return <code>Address</code> array, not null possibly empty
294      * @throws SieveMailException
295      */
296     public Address[] parseAddresses(final String headerName,
297             final Message message) throws SieveMailException {
298         try {
299            final SieveAddressBuilder builder = new SieveAddressBuilder();
300 
301             for (Enumeration en = message.getAllHeaders(); en.hasMoreElements();) {
302                 final Header header = (Header) en.nextElement();
303                 final String name = header.getName();
304                 if (name.trim().equalsIgnoreCase(headerName)) {
305                     builder.addAddresses(header.getValue());
306                 }
307             }
308 
309             final Address[] results = builder.getAddresses();
310             return results;
311 
312         } catch (MessagingException ex) {
313            throw new SieveMailException(ex);
314         } catch (ParseException ex) {
315             throw new SieveMailException(ex);
316         }
317     }
318 
319 }