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.javaxmail;
21  
22  import java.io.ByteArrayInputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  import java.io.UnsupportedEncodingException;
27  import java.util.ArrayList;
28  import java.util.Arrays;
29  import java.util.Collection;
30  import java.util.Collections;
31  import java.util.Date;
32  import java.util.Enumeration;
33  import java.util.HashMap;
34  import java.util.Iterator;
35  import java.util.List;
36  import java.util.Map;
37  
38  import javax.activation.DataHandler;
39  import javax.mail.Address;
40  import javax.mail.Flags;
41  import javax.mail.Folder;
42  import javax.mail.Header;
43  import javax.mail.Message;
44  import javax.mail.MessagingException;
45  import javax.mail.Multipart;
46  import javax.mail.Session;
47  import javax.mail.internet.InternetAddress;
48  import javax.mail.internet.InternetHeaders;
49  import javax.mail.internet.MimeMessage;
50  import javax.mail.search.SearchTerm;
51  
52  /**
53   * Forked from JAMES server.
54   */
55  public class MockMimeMessage extends MimeMessage {
56  
57      private final List m_fromAddresses = new ArrayList();
58  
59      private Address m_senderAddress;
60  
61      private final List m_toRecepients = new ArrayList();
62  
63      private final List m_ccRecepients = new ArrayList();
64  
65      private final List m_bccRecepients = new ArrayList();
66  
67      private final List m_replyToAddresses = new ArrayList();
68  
69      private String m_subject;
70  
71      private int m_iMessageNumber;
72  
73      private boolean m_bIsExpunged;
74  
75      private Object m_content;
76  
77      private Date m_sentDate;
78  
79      private String[] m_contentLanguage;
80  
81      private String m_fileName;
82  
83      private DataHandler m_dataHandler;
84  
85      private HashMap m_contentHeaders = new HashMap();
86  
87      private Flags m_setFlags = new Flags();
88  
89      private boolean m_doMatch;
90  
91      private int m_size = -1;
92  
93      public MockMimeMessage() throws MessagingException {
94          super((Session) null);
95      }
96  
97      public MockMimeMessage(int messageNumber) throws MessagingException {
98          super((Session) null);
99          m_iMessageNumber = messageNumber;
100     }
101 
102     public MockMimeMessage(MimeMessage mimeMessage) throws MessagingException {
103         super(mimeMessage); // trivial implementation
104     }
105 
106     public Address[] getFrom() throws MessagingException {
107         return (Address[]) m_fromAddresses.toArray();
108     }
109 
110     public void setFrom(Address address) throws MessagingException {
111         m_fromAddresses.clear();
112         m_fromAddresses.add(address);
113     }
114 
115     public void setFrom() throws MessagingException {
116         m_fromAddresses.clear();
117         m_fromAddresses.add(InternetAddress.getLocalAddress(null));
118     }
119 
120     public void addFrom(Address[] addresses) throws MessagingException {
121         m_fromAddresses.add(addresses);
122     }
123 
124     public Address getSender() throws MessagingException {
125         return m_senderAddress;
126     }
127 
128     public void setSender(Address address) throws MessagingException {
129         m_senderAddress = address;
130     }
131 
132     public Address[] getRecipients(Message.RecipientType recipientType)
133             throws MessagingException {
134         List recipientsList = getRecipientsList(recipientType);
135         List recipientAddresses = new ArrayList();
136         for (Iterator iterator = recipientsList.iterator(); iterator.hasNext();) {
137             String recipient = (String) iterator.next();
138             recipientAddresses.add(new InternetAddress(recipient));
139         }
140         return (Address[]) (recipientAddresses.toArray(new Address[] {}));
141     }
142 
143     private List getRecipientsList(Message.RecipientType recipientType) {
144         if (Message.RecipientType.TO.equals(recipientType))
145             return m_toRecepients;
146         if (Message.RecipientType.CC.equals(recipientType))
147             return m_ccRecepients;
148         if (Message.RecipientType.BCC.equals(recipientType))
149             return m_bccRecepients;
150         return null;
151     }
152 
153     public Address[] getAllRecipients() throws MessagingException {
154         List allRecipients = new ArrayList();
155         allRecipients.addAll(m_toRecepients);
156         allRecipients.addAll(m_ccRecepients);
157         allRecipients.addAll(m_bccRecepients);
158         return (Address[]) allRecipients.toArray();
159     }
160 
161     public void setRecipients(Message.RecipientType recipientType,
162             Address[] addresses) throws MessagingException {
163         getRecipientsList(recipientType).addAll(Arrays.asList(addresses));
164     }
165 
166     public void setRecipients(Message.RecipientType recipientType,
167             String recipient) throws MessagingException {
168         getRecipientsList(recipientType).add(recipient);
169     }
170 
171     public void addRecipients(Message.RecipientType recipientType,
172             Address[] addresses) throws MessagingException {
173         getRecipientsList(recipientType).addAll(Arrays.asList(addresses));
174     }
175 
176     public void addRecipients(Message.RecipientType recipientType,
177             String recipient) throws MessagingException {
178         getRecipientsList(recipientType).add(recipient);
179     }
180 
181     public Address[] getReplyTo() throws MessagingException {
182         return (Address[]) m_replyToAddresses.toArray();
183     }
184 
185     public void setReplyTo(Address[] addresses) throws MessagingException {
186         m_replyToAddresses.addAll(Arrays.asList(addresses));
187     }
188 
189     public String getSubject() throws MessagingException {
190         return m_subject;
191     }
192 
193     public void setSubject(String subject) throws MessagingException {
194         m_subject = subject;
195     }
196 
197     public void setSubject(String subject, String charset)
198             throws MessagingException {
199         if (subject == null) {
200             m_subject = null;
201             return;
202         }
203         try {
204             m_subject = new String(subject.getBytes(charset));
205         } catch (UnsupportedEncodingException e) {
206             throw new MessagingException("setting subject failed", e);
207         }
208     }
209 
210     public Date getSentDate() throws MessagingException {
211         return m_sentDate;
212     }
213 
214     public void setSentDate(Date date) throws MessagingException {
215         m_sentDate = date;
216     }
217 
218     public Date getReceivedDate() throws MessagingException {
219         return null; // trivial implementation
220     }
221 
222     public int getSize() throws MessagingException {
223         return m_size; // trivial implementation
224     }
225 
226     public int getLineCount() throws MessagingException {
227         return -1; // trivial implementation
228     }
229 
230     public String getContentType() throws MessagingException {
231         return getHeader("Content-Type", null);
232     }
233 
234     public boolean isMimeType(String mimeType) throws MessagingException {
235         return mimeType.startsWith(getContentType());
236     }
237 
238     public String getDisposition() throws MessagingException {
239         return getHeader("Content-Disposition", null);
240     }
241 
242     public void setDisposition(String disposition) throws MessagingException {
243         setHeader("Content-Disposition", disposition);
244     }
245 
246     public String getEncoding() throws MessagingException {
247         return getHeader("Content-Transfer-Encoding", null);
248     }
249 
250     public String getContentID() throws MessagingException {
251         return getHeader("Content-ID", null);
252     }
253 
254     public void setContentID(String contentID) throws MessagingException {
255         setHeader("Content-ID", contentID);
256     }
257 
258     public String getContentMD5() throws MessagingException {
259         return getHeader("Content-MD5", null);
260     }
261 
262     public void setContentMD5(String value) throws MessagingException {
263         setHeader("Content-MD5", value);
264     }
265 
266     public String getDescription() throws MessagingException {
267         return getHeader("Content-Description", null);
268     }
269 
270     public void setDescription(String description) throws MessagingException {
271         setHeader("Content-Description", description);
272     }
273 
274     public void setDescription(String description, String charset)
275             throws MessagingException {
276         try {
277             setDescription(new String(description.getBytes(charset)));
278         } catch (UnsupportedEncodingException e) {
279             throw new MessagingException("setting description failed", e);
280         }
281     }
282 
283     public String[] getContentLanguage() throws MessagingException {
284         return m_contentLanguage;
285     }
286 
287     public void setContentLanguage(String[] contentLanguage)
288             throws MessagingException {
289         m_contentLanguage = contentLanguage;
290     }
291 
292     public String getMessageID() throws MessagingException {
293         return "ID-" + m_iMessageNumber; // trivial implementation
294     }
295 
296     public String getFileName() throws MessagingException {
297         return m_fileName;
298     }
299 
300     public void setFileName(String fileName) throws MessagingException {
301         m_fileName = fileName;
302     }
303 
304     public InputStream getInputStream() throws IOException, MessagingException {
305         return null; // trivial implementation
306     }
307 
308     protected InputStream getContentStream() throws MessagingException {
309         return null; // trivial implementation
310     }
311 
312     public InputStream getRawInputStream() throws MessagingException {
313         if (m_content instanceof String) {
314             return new ByteArrayInputStream(m_content.toString().getBytes());
315         }
316         throw new UnsupportedOperationException("Unimplementated method");
317     }
318 
319     public synchronized DataHandler getDataHandler() throws MessagingException {
320         return m_dataHandler;
321     }
322 
323     public synchronized void setDataHandler(DataHandler dataHandler)
324             throws MessagingException {
325         m_dataHandler = dataHandler;
326     }
327 
328     public Object getContent() throws IOException, MessagingException {
329         return m_content;
330     }
331 
332     public void setContent(Object object, String mimeType)
333             throws MessagingException {
334         m_content = object; // trivial implementation
335     }
336 
337     public void setText(String string) throws MessagingException {
338         setContent(string, "text/plain");
339     }
340 
341     public void setText(String string, String charset)
342             throws MessagingException {
343         try {
344             setContent(new String(string.getBytes(charset)), "text/plain");
345         } catch (UnsupportedEncodingException e) {
346             throw new MessagingException("setting text content failed", e);
347         }
348     }
349 
350     public void setContent(Multipart multipart) throws MessagingException {
351         m_content = multipart;
352     }
353 
354     public Message reply(boolean b) throws MessagingException {
355         return new MockMimeMessage(this); // trivial implementation
356     }
357 
358     public void writeTo(OutputStream outputStream) throws IOException,
359             MessagingException {
360         ; // trivial implementation
361     }
362 
363     public void writeTo(OutputStream outputStream, String[] strings)
364             throws IOException, MessagingException {
365         ; // trivial implementation
366     }
367 
368     public String[] getHeader(String name) throws MessagingException {
369         Object value = m_contentHeaders.get(name);
370         if (value == null)
371             return null;
372         if (value instanceof String) {
373             String stringValue = (String) value;
374             return new String[] { stringValue };
375         } else {
376             Collection values = (Collection) value;
377             return (String[]) values.toArray(new String[values.size()]);
378         }
379     }
380 
381     public String getHeader(String name, String delimiter)
382             throws MessagingException {
383         String[] header = getHeader(name);
384         if (header == null || header.length == 0)
385             return null;
386         return header[0];
387     }
388 
389     public void setHeader(String name, String value) throws MessagingException {
390         addHeader(name, value);
391     }
392 
393     public void addHeader(String name, String value) throws MessagingException {
394         Object newValue;
395         Object existingValue = m_contentHeaders.get(name);
396         if (existingValue == null) {
397             newValue = value;
398         } else if (existingValue instanceof String) {
399             List values = new ArrayList();
400             values.add(existingValue);
401             values.add(value);
402             newValue = values;
403         } else {
404             List values = (List) existingValue;
405             values.add(value);
406             newValue = values;
407         }
408         m_contentHeaders.put(name, newValue);
409     }
410 
411     public void removeHeader(String name) throws MessagingException {
412         m_contentHeaders.remove(name);
413     }
414 
415     public Enumeration getAllHeaders() throws MessagingException {
416         final Collection results = new ArrayList();
417         final Collection entries = m_contentHeaders.entrySet();
418         for (Iterator it = entries.iterator(); it.hasNext();) {
419             Map.Entry entry = (Map.Entry) it.next();
420             String name = entry.getKey().toString();
421             Object value = entry.getValue();
422             if (value == null) {
423                 // ignore
424             } else if (value instanceof Collection) {
425                 Collection values = (Collection) value;
426                 for (Iterator iterValues = values.iterator(); iterValues
427                         .hasNext();) {
428                     String stringValue = (String) iterValues.next();
429                     results.add(new Header(name, stringValue));
430                 }
431             } else {
432                 results.add(new Header(name, value.toString()));
433             }
434         }
435         return Collections.enumeration(results);
436     }
437 
438     public Enumeration getMatchingHeaders(String[] names)
439             throws MessagingException {
440         ArrayList matchingHeaders = new ArrayList();
441         for (int i = 0; i < names.length; i++) {
442             String name = names[i];
443             String value = getHeader(name, null);
444             if (value == null)
445                 continue;
446             matchingHeaders.add(value);
447         }
448         return Collections.enumeration(matchingHeaders);
449     }
450 
451     public Enumeration getNonMatchingHeaders(String[] names)
452             throws MessagingException {
453         List existingHeaders = Arrays.asList(names);
454 
455         ArrayList nonMatchingHeaders = new ArrayList();
456 
457         Iterator iterator = m_contentHeaders.keySet().iterator();
458         while (iterator.hasNext()) {
459             String name = (String) iterator.next();
460             if (existingHeaders.contains(name))
461                 continue;
462             String value = getHeader(name, null);
463             if (value == null)
464                 continue;
465             nonMatchingHeaders.add(value);
466         }
467         return Collections.enumeration(nonMatchingHeaders);
468     }
469 
470     public void addHeaderLine(String headerLine) throws MessagingException {
471         int separatorIndex = headerLine.indexOf(":");
472         if (separatorIndex < 0)
473             throw new MessagingException(
474                     "header line does not conform to standard");
475 
476         addHeader(headerLine.substring(0, separatorIndex), headerLine
477                 .substring(separatorIndex, headerLine.length()));
478     }
479 
480     public Enumeration getAllHeaderLines() throws MessagingException {
481         return Collections.enumeration(getHeadersAsStrings(m_contentHeaders));
482     }
483 
484     private ArrayList getHeadersAsStrings(HashMap contentHeaders) {
485         ArrayList headerLines = new ArrayList();
486         Iterator iterator = contentHeaders.keySet().iterator();
487         while (iterator.hasNext()) {
488             String key = (String) iterator.next();
489             String value = (String) contentHeaders.get(key);
490             headerLines.add(key + ":" + value);
491         }
492         return headerLines;
493     }
494 
495     public Enumeration getMatchingHeaderLines(String[] names)
496             throws MessagingException {
497         ArrayList matchingHeaders = new ArrayList();
498         for (int i = 0; i < names.length; i++) {
499             String name = names[i];
500             String value = getHeader(name, null);
501             if (value == null)
502                 continue;
503             matchingHeaders.add(name + ":" + value);
504         }
505         return Collections.enumeration(matchingHeaders);
506     }
507 
508     public Enumeration getNonMatchingHeaderLines(String[] names)
509             throws MessagingException {
510         List existingHeaders = names != null ? Arrays.asList(names) : null;
511 
512         ArrayList nonMatchingHeaders = new ArrayList();
513 
514         Iterator iterator = m_contentHeaders.keySet().iterator();
515         while (iterator.hasNext()) {
516             String name = (String) iterator.next();
517             if (existingHeaders != null && existingHeaders.contains(name))
518                 continue;
519             String value = getHeader(name, null);
520             if (value == null)
521                 continue;
522             nonMatchingHeaders.add(name + ":" + value);
523         }
524         return Collections.enumeration(nonMatchingHeaders);
525     }
526 
527     public synchronized Flags getFlags() throws MessagingException {
528         return new Flags(m_setFlags);
529     }
530 
531     public synchronized boolean isSet(Flags.Flag flag)
532             throws MessagingException {
533         return m_setFlags.contains(flag);
534     }
535 
536     public synchronized void setFlags(Flags flags, boolean set)
537             throws MessagingException {
538         if (set)
539             m_setFlags.add(flags);
540         else
541             m_setFlags.remove(flags);
542     }
543 
544     public void saveChanges() throws MessagingException {
545         ; // trivial implementation
546     }
547 
548     protected void updateHeaders() throws MessagingException {
549         ; // trivial implementation
550     }
551 
552     protected InternetHeaders createInternetHeaders(InputStream inputStream)
553             throws MessagingException {
554         return new InternetHeaders();
555     }
556 
557     public void setRecipient(Message.RecipientType recipientType,
558             Address address) throws MessagingException {
559         setRecipients(recipientType, new Address[] { address });
560     }
561 
562     public void addRecipient(Message.RecipientType recipientType,
563             Address address) throws MessagingException {
564         setRecipients(recipientType, new Address[] { address });
565     }
566 
567     public void setFlag(Flags.Flag flag, boolean set) throws MessagingException {
568         if (set)
569             m_setFlags.add(flag);
570         else
571             m_setFlags.remove(flag);
572     }
573 
574     public int getMessageNumber() {
575         return m_iMessageNumber;
576     }
577 
578     protected void setMessageNumber(int i) {
579         m_iMessageNumber = i;
580     }
581 
582     public Folder getFolder() {
583         return null;
584     }
585 
586     public boolean isExpunged() {
587         return m_bIsExpunged;
588     }
589 
590     protected void setExpunged(boolean b) {
591         m_bIsExpunged = b;
592     }
593 
594     public void setShouldMatch(boolean doMatch) {
595         m_doMatch = doMatch;
596     }
597 
598     public boolean match(SearchTerm searchTerm) throws MessagingException {
599         return m_doMatch;
600     }
601 
602     public void setSize(int size) {
603         this.m_size = size;
604     }
605 }