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