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.james.mailboxmanager;
21  
22  import java.io.IOException;
23  import java.nio.channels.WritableByteChannel;
24  import java.util.Date;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import javax.mail.Flags;
31  import javax.mail.MessagingException;
32  
33  import org.apache.james.mailboxmanager.util.MessageResultUtils;
34  
35  /**
36   * <p>
37   * Used to get specific informations about a Message without dealing with a
38   * MimeMessage instance. Demanded information can be requested by binary
39   * combining the constants.
40   * </p>
41   * 
42   * <p>
43   * I came to the Idea of the MessageResult because there are many possible
44   * combinations of different requests (uid, msn, MimeMessage, Flags).
45   * </p>
46   * <p>
47   * e.g. I want to have all uids, msns and flags of all messages. (a common IMAP
48   * operation) Javamail would do it that way:
49   * <ol>
50   * <li>get all Message objects (Message[])</li>
51   * <li>call Message.getMessageNumber() </li>
52   * <li>call Message.getFlags() </li>
53   * <li>call Folder.getUid(Message)</li>
54   * </ol>
55   * <p>
56   * This means creating a lazy-loading MimeMessage instance. </br> So why don't
57   * call getMessages(MessageResult.UID | MessageResult.MSN |
58   * MessageResult.FLAGS)? This would leave a lot of room for the implementation
59   * to optimize
60   * </p>
61   * 
62   * 
63   */
64  
65  public interface MessageResult extends Comparable, Headers {
66  
67      /**
68       * Indicates the results fetched.
69       */
70      public interface FetchGroup {
71  
72          /**
73           * For example: could have best performance when doing store and then
74           * forget. UIDs are always returned
75           */
76          public static final int MINIMAL = 0x00;
77  
78          /**
79           * 
80           */
81          public static final int MIME_DESCRIPTOR = 0x01;
82  
83          public static final int SIZE = 0x20;
84  
85          public static final int INTERNAL_DATE = 0x40;
86  
87          public static final int FLAGS = 0x80;
88  
89          public static final int HEADERS = 0x100;
90  
91          public static final int FULL_CONTENT = 0x200;
92  
93          public static final int BODY_CONTENT = 0x400;
94  
95          public static final int MIME_HEADERS = 0x800;
96  
97          public static final int MIME_CONTENT = 0x1000;
98  
99          /**
100          * Contents to be fetched. Composed bitwise.
101          * 
102          * @return bitwise descripion
103          * @see #MINIMAL
104          * @see #MIME_MESSAGE
105          * @see #KEY
106          * @see #SIZE
107          * @see #INTERNAL_DATE
108          * @see #FLAGS
109          * @see #HEADERS
110          * @see #FULL_CONTENT
111          * @see #BODY_CONTENT
112          * @see #MIME_CONTENT
113          */
114         public int content();
115 
116         /**
117          * Gets contents to be fetched for contained parts. For each part to be
118          * contained, only one descriptor should be contained.
119          * 
120          * @return <code>Set</code> of {@link PartContentDescriptor}, or null
121          *         if there is no part content to be fetched
122          */
123         public Set getPartContentDescriptors();
124 
125         /**
126          * Describes the contents to be fetched for a mail part. All
127          * implementations MUST implement equals. Two implementations are equal
128          * if and only if their paths are equal.
129          */
130         public interface PartContentDescriptor {
131             /**
132              * Contents to be fetched. Composed bitwise.
133              * 
134              * @return bitwise descripion
135              * @see #MINIMAL
136              * @see #MIME_MESSAGE
137              * @see #KEY
138              * @see #SIZE
139              * @see #INTERNAL_DATE
140              * @see #FLAGS
141              * @see #HEADERS
142              * @see #FULL_CONTENT
143              * @see #BODY_CONTENT
144              */
145             public int content();
146 
147             /**
148              * Path describing the part to be fetched.
149              * 
150              * @return path describing the part, not null
151              */
152             public MimePath path();
153         }
154     }
155 
156     /**
157      * Gets the results set.
158      * 
159      * @return bitwise indication of result set
160      * @see MessageResultUtils#isIncluded(MessageResult, int)
161      */
162     FetchGroup getIncludedResults();
163 
164     MimeDescriptor getMimeDescriptor() throws MailboxManagerException;
165 
166     long getUid();
167 
168     long getUidValidity();
169 
170     /**
171      * 
172      * <p>
173      * IMAP defines this as the time when the message has arrived to the server
174      * (by smtp). Clients are also allowed to set the internalDate on apppend.
175      * </p>
176      * <p>
177      * Is this Mail.getLastUpdates() for James delivery? Should we use
178      * MimeMessage.getReceivedDate()?
179      * </p>
180      * 
181      */
182 
183     Date getInternalDate();
184 
185     /**
186      * TODO optional, to be decided <br />
187      * maybe this is a good thing because IMAP often requests only the Flags and
188      * this way we don't need to create a lazy-loading MimeMessage instance just
189      * for the Flags.
190      * 
191      */
192     Flags getFlags() throws MailboxManagerException;
193 
194     int getSize();
195 
196     /**
197      * Gets headers for the message.
198      * 
199      * @return <code>Header</code> <code>Iterator</code>, or null if
200      *         {@link FetchGroup#HEADERS} was not fetched
201      */
202     Iterator headers() throws MailboxManagerException;
203 
204     /**
205      * Iterates the message headers for the given part in a multipart message.
206      * 
207      * @param path
208      *            describing the part's position within a multipart message
209      * @return <code>Header</code> <code>Iterator</code>, or null when
210      *         {@link FetchGroup#mimeHeaders()} does not include the index and
211      *         when the mime part cannot be found
212      * @throws MailboxManagerException
213      */
214     Iterator iterateHeaders(MimePath path) throws MailboxManagerException;
215 
216     /**
217      * Iterates the MIME headers for the given part in a multipart message.
218      * 
219      * @param path
220      *            describing the part's position within a multipart message
221      * @return <code>Header</code> <code>Iterator</code>, or null when
222      *         {@link FetchGroup#mimeHeaders()} does not include the index and
223      *         when the mime part cannot be found
224      * @throws MailboxManagerException
225      */
226     Iterator iterateMimeHeaders(MimePath path) throws MailboxManagerException;
227 
228     /**
229      * A header.
230      */
231     public interface Header extends Content {
232 
233         /**
234          * Gets the name of this header.
235          * 
236          * @return name of this header
237          * @throws MessagingException
238          */
239         public String getName() throws MailboxManagerException;
240 
241         /**
242          * Gets the (unparsed) value of this header.
243          * 
244          * @return value of this header
245          * @throws MessagingException
246          */
247         public String getValue() throws MailboxManagerException;
248     }
249 
250     /**
251      * Gets the full message including headers and body. The message data should
252      * have normalised line endings (CRLF).
253      * 
254      * @return <code>Content</code>, or or null if
255      *         {@link FetchGroup#FULL_CONTENT} has not been included in the
256      *         results
257      */
258     Content getFullContent() throws MailboxManagerException;
259 
260     /**
261      * Gets the full content of the given mime part.
262      * 
263      * @param path
264      *            describes the part
265      * @return <code>Content</code>, or null when
266      *         {@link FetchGroup#mimeBodies()} did not been include the given
267      *         index and when the mime part cannot be found
268      * @throws MailboxManagerException
269      */
270     Content getFullContent(MimePath path) throws MailboxManagerException;
271 
272     /**
273      * Gets the body of the message excluding headers. The message data should
274      * have normalised line endings (CRLF).
275      * 
276      * @return <code>Content</code>, or or null if
277      *         {@link FetchGroup#FULL_CONTENT} has not been included in the
278      *         results
279      */
280     Content getBody() throws MailboxManagerException;
281 
282     /**
283      * Gets the body of the given mime part.
284      * 
285      * @param path
286      *            describes the part
287      * @return <code>Content</code>, or null when
288      *         {@link FetchGroup#mimeBodies()} did not been include the given
289      *         index and when the mime part cannot be found
290      * @throws MailboxManagerException
291      */
292     Content getBody(MimePath path) throws MailboxManagerException;
293 
294     /**
295      * Gets the body of the given mime part.
296      * 
297      * @param path
298      *            describes the part
299      * @return <code>Content</code>, or null when
300      *         {@link FetchGroup#mimeBodies()} did not been include the given
301      *         index and when the mime part cannot be found
302      * @throws MailboxManagerException
303      */
304     Content getMimeBody(MimePath path) throws MailboxManagerException;
305 
306     /**
307      * IMAP needs to know the size of the content before it starts to write it
308      * out. This interface allows direct writing whilst exposing total size.
309      */
310     public interface Content {
311         /**
312          * Writes content into the given buffer.
313          * 
314          * @param buffer
315          *            <code>StringBuffer</code>, not null
316          * @throws MessagingException
317          */
318         public void writeTo(StringBuffer buffer);
319 
320         /**
321          * Writes content to the given channel.
322          * 
323          * @param channel
324          *            <code>Channel</code> open, not null
325          * @throws MailboxManagerException
326          * @throws IOException
327          *             when channel IO fails
328          */
329         public void writeTo(WritableByteChannel channel) throws IOException;
330 
331         /**
332          * Size (in octets) of the content.
333          * 
334          * @return number of octets to be written
335          * @throws MessagingException
336          */
337         public long size();
338     }
339 
340     /**
341      * Describes a path within a multipart MIME message. All implementations
342      * must implement equals. Two paths are equal if and only if each position
343      * is identical.
344      */
345     public interface MimePath {
346 
347         /**
348          * Gets the positions of each part in the path.
349          * 
350          * @return part positions describing the path
351          */
352         public int[] getPositions();
353     }
354 
355     public interface MimeDescriptor extends Headers {
356 
357         /**
358          * Gets the top level MIME content media type.
359          * 
360          * @return top level MIME content media type, or null if default
361          */
362         public String getMimeType();
363 
364         /**
365          * Gets the MIME content subtype.
366          * 
367          * @return the MIME content subtype, or null if default
368          */
369         public String getMimeSubType();
370 
371         /**
372          * Gets the MIME <code>Content-ID</code> header value.
373          * 
374          * @return MIME <code>Content-ID</code>, possibly null
375          */
376         public String getContentID();
377 
378         /**
379          * Gets MIME <code>Content-Description</code> header value.
380          * 
381          * @return MIME <code>Content-Description</code>, possibly null
382          */
383         public String getContentDescription();
384 
385         /**
386          * Gets MIME <code>Content-Location</code> header value.
387          * 
388          * @return parsed MIME <code>Content-Location</code>, possibly null
389          */
390         public String getContentLocation();
391 
392         /**
393          * Gets MIME <code>Content-MD5</code> header value.
394          * 
395          * @return parsed MIME <code>Content-MD5</code>, possibly null
396          */
397         public String getContentMD5();
398 
399         /**
400          * Gets the MIME content transfer encoding.
401          * 
402          * @return MIME <code>Content-Transfer-Encoding</code>, possibly null
403          */
404         public String getTransferContentEncoding();
405 
406         /**
407          * Gets the languages, From the MIME <code>Content-Language</code>
408          * header value.
409          * 
410          * @return <code>List</code> of <code>String</code> names
411          */
412         public List getLanguages();
413 
414         /**
415          * Gets MIME <code>Content-Disposition</code>.
416          * 
417          * @return <code>Content-Disposition</code>, or null if no
418          *         disposition header exists
419          */
420         public String getDisposition();
421 
422         /**
423          * Gets MIME <code>Content-Disposition</code> parameters.
424          * 
425          * @return <code>Content-Disposition</code> values indexed by names
426          */
427         public Map getDispositionParams();
428 
429         /**
430          * Gets the number of lines of text in a part of type <code>TEXT</code>
431          * when transfer encoded.
432          * 
433          * @return <code>CRLF</code> count when a <code>TEXT</code> type,
434          *         otherwise -1
435          */
436         public long getLines();
437 
438         /**
439          * The number of octets contained in the body of this part.
440          * 
441          * @return number of octets
442          */
443         public long getBodyOctets();
444 
445         /**
446          * Gets parts.
447          * 
448          * @return <code>MimeDescriptor</code> <code>Iterator</code> when a
449          *         composite top level MIME media type, null otherwise
450          */
451         public Iterator parts();
452 
453         /**
454          * Gets embedded message.
455          * 
456          * @return <code>MimeDescriptor</code> when top level MIME type is
457          *         <code>message</code>, null otherwise
458          */
459         public MimeDescriptor embeddedMessage();
460 
461         /**
462          * Gets headers.
463          * 
464          * @return <code>Header</code> <code>Iterator</code>, not null
465          */
466         public Iterator headers();
467 
468         /**
469          * Gets MIME body parameters parsed from <code>Content-Type</code>.
470          * 
471          * @return <code>Header</code> <code>Iterator</code>, not null
472          */
473         public Iterator contentTypeParameters();
474     }
475 }