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.utils;
21  
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.Enumeration;
26  import java.util.HashSet;
27  import java.util.List;
28  import java.util.Set;
29  
30  import javax.mail.Header;
31  import javax.mail.Message;
32  import javax.mail.MessagingException;
33  import javax.mail.internet.MimeMessage;
34  
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  import org.apache.jsieve.SieveContext;
38  import org.apache.jsieve.exception.SieveException;
39  import org.apache.jsieve.mail.Action;
40  import org.apache.jsieve.mail.MailAdapter;
41  import org.apache.jsieve.mail.MailUtils;
42  import org.apache.jsieve.mail.SieveMailException;
43  import org.apache.jsieve.parser.address.SieveAddressBuilder;
44  
45  /**
46   * <p>
47   * Class SieveMailAdapter implements a mock MailAdapter for testing purposes.
48   * </p>
49   * 
50   * <p>
51   * Being a mock object, Actions are not performed against a mail server, but in
52   * most other respects it behaves as would expect a MailAdapter wrapping a
53   * JavaMail message should. To this extent, it is a useful demonstration of how
54   * to create an implementation of a MailAdapter.
55   */
56  public class SieveMailAdapter implements MailAdapter {
57      private Log log = LogFactory.getLog(SieveMailAdapter.class);
58  
59      /**
60       * The message being adapted.
61       */
62      private MimeMessage fieldMessage;
63  
64      /**
65       * List of Actions to perform.
66       */
67      private List<Action> fieldActions;
68  
69      private String contentAsLowerCaseString;
70  
71      /**
72       * Constructor for SieveMailAdapter.
73       */
74      private SieveMailAdapter() {
75          super();
76      }
77  
78      /**
79       * Constructor for SieveMailAdapter.
80       * 
81       * @param message
82       */
83      public SieveMailAdapter(MimeMessage message) {
84          this();
85          setMessage(message);
86      }
87  
88      /**
89       * Returns the message.
90       * 
91       * @return MimeMessage
92       */
93      public MimeMessage getMessage() {
94          return fieldMessage;
95      }
96  
97      /**
98       * Sets the message.
99       * 
100      * @param message
101      *            The message to set
102      */
103     protected void setMessage(MimeMessage message) {
104         fieldMessage = message;
105     }
106 
107     /**
108      * Returns the List of actions.
109      * 
110      * @return List
111      */
112     public List<Action> getActions() {
113         List<Action> actions = null;
114         if (null == (actions = getActionsBasic())) {
115             updateActions();
116             return getActions();
117         }
118         return actions;
119     }
120 
121     /**
122      * Returns a new List of actions.
123      * 
124      * @return List
125      */
126     protected List<Action> computeActions() {
127         return new ArrayList<Action>();
128     }
129 
130     /**
131      * Returns the List of actions.
132      * 
133      * @return List
134      */
135     private List<Action> getActionsBasic() {
136         return fieldActions;
137     }
138 
139     /**
140      * Adds an Action.
141      * 
142      * @param action
143      *            The action to set
144      */
145     public void addAction(Action action) {
146         getActions().add(action);
147     }
148 
149     /**
150      * @see org.apache.jsieve.mail.MailAdapter#executeActions()
151      */
152     public void executeActions() throws SieveException {
153         boolean isDebugEnabled = log.isDebugEnabled();
154         final List<Action> actions = getActions();
155         for (final Action action:actions) {
156             if (isDebugEnabled)
157                 log.debug("Executing " + action.toString());
158         }
159 
160     }
161 
162     /**
163      * Sets the actions.
164      * 
165      * @param actions
166      *            The actions to set
167      */
168     protected void setActions(List<Action> actions) {
169         fieldActions = actions;
170     }
171 
172     /**
173      * Updates the actions.
174      */
175     protected void updateActions() {
176         setActions(computeActions());
177     }
178 
179     /**
180      * @see org.apache.jsieve.mail.MailAdapter#getHeader(String)
181      */
182     public List<String> getHeader(String name) throws SieveMailException {
183         try {
184             String[] headers = getMessage().getHeader(name);
185             return (headers == null ? new ArrayList<String>(0) : Arrays.asList(headers));
186         } catch (MessagingException ex) {
187             throw new SieveMailException(ex);
188         }
189     }
190 
191     /**
192      * @see org.apache.jsieve.mail.MailAdapter#getHeaderNames()
193      */
194     public List<String> getHeaderNames() throws SieveMailException {
195         Set<String> headerNames = new HashSet<String>();
196         try {
197             Enumeration allHeaders = getMessage().getAllHeaders();
198             while (allHeaders.hasMoreElements()) {
199                 headerNames.add(((Header) allHeaders.nextElement()).getName());
200             }
201             return new ArrayList<String>(headerNames);
202         } catch (MessagingException ex) {
203             throw new SieveMailException(ex);
204         }
205     }
206 
207     /**
208      * @see org.apache.jsieve.mail.MailAdapter#getMatchingHeader(String)
209      */
210     public List<String> getMatchingHeader(String name) throws SieveMailException {
211         return MailUtils.getMatchingHeader(this, name);
212     }
213 
214     /**
215      * @see org.apache.jsieve.mail.MailAdapter#getSize()
216      */
217     public int getSize() throws SieveMailException {
218         try {
219             return getMessage().getSize();
220         } catch (MessagingException ex) {
221             throw new SieveMailException(ex);
222         }
223     }
224 
225     /**
226      * @see org.apache.jsieve.mail.MailAdapter#getContentType()
227      */
228     public String getContentType() throws SieveMailException {
229         try {
230             return getMessage().getContentType();
231         } catch (MessagingException ex) {
232             throw new SieveMailException(ex);
233         }
234     }
235 
236     public Address[] parseAddresses(final String headerName)
237             throws SieveMailException {
238         return parseAddresses(headerName, getMessage());
239     }
240 
241     /**
242      * Parses the value from the given message into addresses.
243      * 
244      * @param headerName
245      *            header name, to be matched case insensitively
246      * @param message
247      *            <code>Message</code>, not null
248      * @return <code>Address</code> array, not null possibly empty
249      * @throws SieveMailException
250      */
251     public Address[] parseAddresses(final String headerName,
252             final Message message) throws SieveMailException {
253         try {
254             final SieveAddressBuilder builder = new SieveAddressBuilder();
255 
256             for (Enumeration en = message.getAllHeaders(); en.hasMoreElements();) {
257                 final Header header = (Header) en.nextElement();
258                 final String name = header.getName();
259                 if (name.trim().equalsIgnoreCase(headerName)) {
260                     builder.addAddresses(header.getValue());
261                 }
262             }
263 
264             final Address[] results = builder.getAddresses();
265             return results;
266 
267         } catch (MessagingException ex) {
268             throw new SieveMailException(ex);
269         } catch (org.apache.jsieve.parser.generated.address.ParseException ex) {
270             throw new SieveMailException(ex);
271         }
272     }
273 
274     public boolean isInBodyText(String phraseCaseInsensitive) throws SieveMailException {
275         try {
276             return contentAsText().indexOf(phraseCaseInsensitive.toLowerCase()) != -1;
277         } catch (MessagingException ex) {
278             throw new SieveMailException(ex);
279         } catch (IOException ex) {
280             throw new SieveMailException(ex);
281         }
282     }
283 
284     private String contentAsText() throws IOException, MessagingException {
285         if (contentAsLowerCaseString == null) {
286             contentAsLowerCaseString = getMessage().getContent().toString().toLowerCase();
287         }
288         return contentAsLowerCaseString;
289     }
290 
291     public void setContext(SieveContext context) {}
292 }