View Javadoc

1   /*
2    * Copyright (c) 2004-2007 Creative Sphere Limited.
3    * All rights reserved. This program and the accompanying materials
4    * are made available under the terms of the Eclipse Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/epl-v10.html
7    *
8    * Contributors:
9    *
10   *   Creative Sphere - initial API and implementation
11   *
12   */
13  package org.abstracthorizon.mercury.imap.util;
14  
15  import java.io.IOException;
16  import java.text.SimpleDateFormat;
17  import java.util.Date;
18  import java.util.Enumeration;
19  import java.util.Iterator;
20  import java.util.List;
21  import javax.mail.Folder;
22  import javax.mail.Message;
23  import javax.mail.MessagingException;
24  import javax.mail.UIDFolder;
25  import javax.mail.internet.MimeMessage;
26  import javax.mail.internet.MimePart;
27  
28  import org.abstracthorizon.mercury.common.util.RFCDate;
29  import org.abstracthorizon.mercury.imap.IMAPSession;
30  
31  /**
32   * Utility methods for working with messages
33   *
34   * @author Daniel Sendula
35   */
36  public class MessageUtilities {
37  
38      /** Date format */
39      public static SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
40  
41      /** CR/LF */
42      public static final String CRLF = "\r\n";
43  
44      /**
45       * Find message by UID
46       * @param f folder
47       * @param uid uid
48       * @return message
49       * @throws MessagingException if folder is not of {@link UIDFolder} type
50       */
51      public static Message findMessageByUID(Folder f, long uid) throws MessagingException {
52          if (f instanceof UIDFolder) {
53              return ((UIDFolder) f).getMessageByUID(uid);
54          } else {
55              throw new MessagingException("Not Implemented");
56          }
57      }
58  
59      /**
60       * Returns messages's UID
61       * @param m message
62       * @return UID
63       * @throws MessagingException if folder is not of {@link UIDFolder} type
64       */
65      public static long findUID(Message m) throws MessagingException {
66          Folder f = m.getFolder();
67          if (f instanceof UIDFolder) {
68              return ((UIDFolder) f).getUID(m);
69          } else {
70              throw new MessagingException("Not Implemented");
71          }
72      }
73  
74      /**
75       * Creates string representation of headers for mime part
76       * @param m mime part
77       * @return string representation of headers
78       * @throws MessagingException
79       */
80      public static String createHeaders(MimePart m) throws MessagingException {
81          Enumeration<?> en = m.getAllHeaderLines();
82          // StringBuffer buf = new StringBuffer(512);
83          return createHeaders(m, en);
84          // while (en.hasMoreElements()) {
85          // buf.append(en.nextElement().toString()).append(MessageUtilities.CRLF);
86          // }
87          // if (m.getSize() > 0) {
88          // buf.append(MessageUtilities.CRLF);
89          // }
90          // return buf.toString();
91      }
92  
93      /**
94       * Creates string representation of headers for mime part
95       * @param m mime part
96       * @param headers headers
97       * @param not should headers form the list be included or excluded
98       * @return string representation of headers
99       * @throws MessagingException
100      */
101     public static String createHeaders(MimePart m, List<String> headers, boolean not)
102             throws MessagingException {
103         String[] list = new String[headers.size()];
104         list = headers.toArray(list);
105         Enumeration<?> en = null;
106         if (not) {
107             en = m.getNonMatchingHeaderLines(list);
108         } else {
109             en = m.getMatchingHeaderLines(list);
110         }
111         return createHeaders(m, en);
112     }
113 
114     /**
115      * Creates string representation of headers for mime part
116      * @param m mime part
117      * @param headers headers
118      * @return stirng representation of headers
119      * @throws MessagingException
120      */
121     public static String createHeaders(MimePart m, Enumeration<?> headers)
122             throws MessagingException {
123         StringBuffer buf = new StringBuffer(512);
124         while (headers.hasMoreElements()) {
125             String headerLine = headers.nextElement().toString();
126             if (headerLine.startsWith("Date: ")) {
127                 String date = headerLine.substring(6).trim();
128                 if (RFCDate.validate(date)) {
129                     buf.append(headerLine).append(CRLF);
130                 } else {
131                     Date d;
132                     if (m instanceof MimeMessage) {
133                         d = ((MimeMessage) m).getReceivedDate();
134                     } else {
135                         d = new Date(); // !!!
136                     }
137                     String newHeaderLine = "Date: "
138                             + RFCDate.DATE_FORMAT.format(d);
139                     buf.append(newHeaderLine).append(CRLF);
140                 }
141             } else {
142                 buf.append(headerLine).append(CRLF);
143             }
144         }
145         if (m.getSize() > 0) {
146             buf.append(CRLF);
147         }
148         return buf.toString();
149     }
150 
151     /**
152      * Iterates over sequence for given folder's messages
153      * @param session imap session
154      * @param processor message processor
155      * @param f folder
156      * @param sequenceSet sequence
157      * @param asuid does sequence represent UIDs or positions of messages
158      * @throws IOException
159      * @throws MessagingException
160      */
161     public static void sequenceIterator(IMAPSession session, MessageProcessor processor, Folder f,
162             Sequence sequenceSet, boolean asuid) throws IOException,
163             MessagingException {
164         if (!asuid) {
165             int msgCount = f.getMessageCount();
166             sequenceSet.setLowerLimit(1);
167             sequenceSet.setUpperLimit(msgCount);
168         }
169         if (sequenceSet instanceof ComposedSequence) {
170             composedSequenceIterator(session, processor, f,
171                     (ComposedSequence) sequenceSet, asuid);
172         } else if (sequenceSet instanceof SimpleSequence) {
173             simpleSequenceIterator(session, processor, f, (SimpleSequence) sequenceSet,
174                     asuid);
175         }
176     }
177 
178     /**
179      * Iterates over sequence for given folder's messages
180      * @param session imap session
181      * @param processor message processor
182      * @param f folder
183      * @param sequenceSet sequence
184      * @param asuid does sequence represent UIDs or positions of messages
185      * @throws IOException
186      * @throws MessagingException
187      */
188     public static void composedSequenceIterator(IMAPSession session, MessageProcessor processor,
189             Folder f, ComposedSequence sequenceSet, boolean asuid)
190             throws IOException, MessagingException {
191         Iterator<Sequence> iterator = sequenceSet.getSequencesAsIterator();
192         while (iterator.hasNext()) {
193             Sequence set = (Sequence) iterator.next();
194             if (set instanceof ComposedSequence) {
195                 composedSequenceIterator(session, processor, f, (ComposedSequence) set,
196                         asuid);
197             } else if (set instanceof SimpleSequence) {
198                 simpleSequenceIterator(session, processor, f, (SimpleSequence) set,
199                         asuid);
200             }
201         }
202     }
203 
204     /**
205      * Iterates over sequence for given folder's messages
206      * @param session imap session
207      * @param processor message processor
208      * @param f folder
209      * @param sequenceSet sequence
210      * @param asuid does sequence represent UIDs or positions of messages
211      * @throws IOException
212      * @throws MessagingException
213      */
214     public static void simpleSequenceIterator(IMAPSession session, MessageProcessor processor,
215             Folder f, SimpleSequence sequenceSet, boolean asuid)
216             throws IOException, MessagingException {
217         int min = sequenceSet.getMin();
218         int max = sequenceSet.getMax();
219         if (min < 1) {
220             min = 1;
221         }
222 
223         if (min == max) {
224             MimeMessage msg;
225             if (asuid) {
226                 msg = (MimeMessage) ((UIDFolder) f).getMessageByUID(min);
227             } else {
228                 msg = (MimeMessage) f.getMessage(min);
229             }
230             if (msg != null) {
231                 processor.process(session, msg);
232             }
233         } else {
234             Message[] msgs;
235             if (asuid) {
236                 msgs = ((UIDFolder) f).getMessagesByUID(min, max);
237             } else {
238                 int msgCount = f.getMessageCount();
239                 if (max > msgCount) {
240                     max = msgCount;
241                 }
242                 msgs = f.getMessages(min, max);
243             }
244             for (int i = 0; i < msgs.length; i++) {
245                 MimeMessage msg = (MimeMessage) msgs[i];
246                 if (msg != null) {
247                     processor.process(session, msg);
248                 }
249             }
250         }
251     }
252 
253     /**
254      * Iterates over sequence for given folder's messages
255      * @param session imap session
256      * @param processor message processor
257      * @param f folder
258      * @param sequenceSet sequence
259      * @param asuid does sequence represent UIDs or positions of messages
260      * @throws IOException
261      * @throws MessagingException
262      */
263     public static void sequenceIteratorOld(IMAPSession session, MessageProcessor processor,
264             Folder f, Sequence sequenceSet, boolean asuid) throws IOException,
265             MessagingException {
266         int msgs = f.getMessageCount();
267         // logger.debug("1) min="+sequenceSet.getMin()+"
268         // max="+sequenceSet.getMax());
269         sequenceSet.setLowerLimit(1);
270         // logger.debug("2) min="+sequenceSet.getMin()+"
271         // max="+sequenceSet.getMax());
272         if (asuid) {
273             int max = (int) MessageUtilities.maxUID(f);
274             // logger.debug("max="+max);
275             sequenceSet.setUpperLimit(max);
276         } else {
277             // logger.debug("max="+msgs);
278             sequenceSet.setUpperLimit(msgs);
279         }
280         // logger.debug("3) min="+sequenceSet.getMin()+"
281         // max="+sequenceSet.getMax());
282 
283         sequenceSet.first();
284         // logger.debug("4) min="+sequenceSet.getMin()+"
285         // max="+sequenceSet.getMax());
286         if (asuid) {
287             // logger.debug("as uid!");
288             int msgNo = -1;
289             while (sequenceSet.more()) {
290                 int uid = sequenceSet.next();
291                 // if (uid > 573) {
292                 // logger.debug(": "+uid);
293                 // }
294                 MimeMessage m = null;
295                 if (msgNo < 0) {
296                     if (uid == 2764) {
297                         uid = uid * 2 / 2;
298                     }
299                     m = (MimeMessage) MessageUtilities.findMessageByUID(f, uid);
300                     if (m != null) {
301                         msgNo = m.getMessageNumber();
302                         // logger.debug(":(1) #="+msgNo);
303                     } else {
304                         // logger.debug(":(1) = null!");
305                         msgNo = -1;
306                     }
307                 } else {
308                     m = (MimeMessage) f.getMessage(msgNo + 1);
309                     if (m != null) {
310                         // logger.debug(":(2) #="+m.getMessageNumber());
311                         int u = (int) MessageUtilities.findUID(m);
312                         if (u > uid) {
313                             // logger.debug(":(3) = u="+u);
314                             sequenceSet.setLowerLimit(u);
315                             sequenceSet.first();
316                             m = null;
317                         } else if (u < uid) {
318                             // logger.debug(":(4) = u="+u);
319                             m = (MimeMessage) MessageUtilities
320                                     .findMessageByUID(f, uid);
321                             if (m != null) {
322                                 msgNo = m.getMessageNumber();
323                                 // logger.debug(":(4) = #="+msgNo);
324                             } else {
325                                 // logger.debug(":(4) = null");
326                                 msgNo = -1;
327                             }
328                         } else {
329                             msgNo = msgNo + 1;
330                             // logger.debug(":(4) = msgNo = msgNo+1 u="+u+"
331                             // uid="+uid);
332                         }
333                     } else {
334                         // logger.debug(":(2) = null!");
335                         sequenceSet.setLowerLimit(sequenceSet.getMax() + 1);
336                     }
337                 }
338 
339                 if (m != null) {
340                     processor.process(session, m);
341                 }
342             }
343         } else {
344             while (sequenceSet.more()) {
345                 int msgNo = sequenceSet.next();
346                 MimeMessage m = (MimeMessage) f.getMessage(msgNo);
347                 if (m != null) {
348                     processor.process(session, m);
349                 }
350 
351             } // while
352         }
353     }
354 
355     /**
356      * Returns maximum UID form the folder
357      * @param f folder
358      * @return maxumum UID
359      * @throws MessagingException if folder is not of {@link UIDFolder} type
360      */
361     public static long maxUID(Folder f) throws MessagingException {
362         // logger.debug("count="+f.getMessageCount()+"
363         // #="+f.getMessage(f.getMessageCount()).getMessageNumber());
364         return findUID(f.getMessage(f.getMessageCount()));
365     }
366 }