KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > mail > Folder


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21
22 /*
23  * @(#)Folder.java 1.57 05/08/29
24  *
25  * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
26  */

27
28 package javax.mail;
29
30 import java.io.*;
31 import java.lang.*;
32 import java.util.Vector JavaDoc;
33 import java.util.StringTokenizer JavaDoc;
34 import javax.mail.search.SearchTerm JavaDoc;
35 import javax.mail.event.*;
36
37 /**
38  * Folder is an abstract class that represents a folder for mail
39  * messages. Subclasses implement protocol specific Folders.<p>
40  *
41  * Folders can contain Messages, other Folders or both, thus providing
42  * a tree-like hierarchy rooted at the Store's default folder. (Note
43  * that some Folder implementations may not allow both Messages and
44  * other Folders in the same Folder).<p>
45  *
46  * The interpretation of folder names is implementation dependent.
47  * The different levels of hierarchy in a folder's full name
48  * are separated from each other by the hierarchy delimiter
49  * character.<p>
50  *
51  * The case-insensitive full folder name (that is, the full name
52  * relative to the default folder for a Store) <strong>INBOX</strong>
53  * is reserved to mean the "primary folder for this user on this
54  * server". Not all Stores will provide an INBOX folder, and not
55  * all users will have an INBOX folder at all times. The name
56  * <strong>INBOX</strong> is reserved to refer to this folder,
57  * when it exists, in Stores that provide it. <p>
58  *
59  * A Folder object obtained from a Store need not actually exist
60  * in the backend store. The <code>exists</code> method tests whether
61  * the folder exists or not. The <code>create</code> method
62  * creates a Folder. <p>
63  *
64  * A Folder is initially in the closed state. Certain methods are valid
65  * in this state; the documentation for those methods note this. A
66  * Folder is opened by calling its 'open' method. All Folder methods,
67  * except <code>open</code>, <code>delete</code> and
68  * <code>renameTo</code>, are valid in this state. <p>
69  *
70  * The only way to get a Folder is by invoking the
71  * <code>getFolder</code> method on Store, Folder, or Session, or by invoking
72  * the <code>list</code> or <code>listSubscribed</code> methods
73  * on Folder. Folder objects returned by the above methods are not
74  * cached by the Store. Thus, invoking the <code>getFolder</code> method
75  * with the same folder name multiple times will return distinct Folder
76  * objects. Likewise for the <code>list</code> and <code>listSubscribed</code>
77  * methods. <p>
78  *
79  * The Message objects within the Folder are cached by the Folder.
80  * Thus, invoking <code>getMessage(msgno)</code> on the same message number
81  * multiple times will return the same Message object, until an
82  * expunge is done on this Folder. <p>
83  *
84  * Note that a Message's message number can change within a
85  * session if the containing Folder is expunged using the expunge
86  * method. Clients that use message numbers as references to messages
87  * should be aware of this and should be prepared to deal with
88  * situation (probably by flushing out existing message number references
89  * and reloading them). Because of this complexity, it is better for
90  * clients to use Message objects as references to messages, rather than
91  * message numbers. Expunged Message objects still have to be
92  * pruned, but other Message objects in that folder are not affected by the
93  * expunge.
94  *
95  * @author John Mani
96  * @author Bill Shannon
97  */

98
99 public abstract class Folder {
100
101     /**
102      * The parent store.
103      */

104     protected Store JavaDoc store;
105
106     /**
107      * The open mode of this folder. The open mode is
108      * <code>Folder.READ_ONLY</code>, <code>Folder.READ_WRITE</code>,
109      * or -1 if not known.
110      * @since JavaMail 1.1
111      */

112     protected int mode = -1;
113
114     /**
115      * Constructor that takes a Store object.
116      *
117      * @param store the Store that holds this folder
118      */

119     protected Folder(Store JavaDoc store) {
120     this.store = store;
121     }
122
123     /**
124      * Returns the name of this Folder. <p>
125      *
126      * This method can be invoked on a closed Folder.
127      *
128      * @return name of the Folder
129      */

130     public abstract String JavaDoc getName();
131
132     /**
133      * Returns the full name of this Folder. If the folder resides under
134      * the root hierarchy of this Store, the returned name is relative
135      * to the root. Otherwise an absolute name, starting with the
136      * hierarchy delimiter, is returned. <p>
137      *
138      * This method can be invoked on a closed Folder.
139      *
140      * @return full name of the Folder
141      */

142     public abstract String JavaDoc getFullName();
143
144     /**
145      * Return a URLName representing this folder. The returned URLName
146      * does <em>not</em> include the password used to access the store.
147      *
148      * @return the URLName representing this folder
149      * @see URLName
150      * @since JavaMail 1.1
151      */

152     public URLName JavaDoc getURLName() throws MessagingException JavaDoc {
153     URLName JavaDoc storeURL = getStore().getURLName();
154     String JavaDoc fullname = getFullName();
155     StringBuffer JavaDoc encodedName = new StringBuffer JavaDoc();
156     char separator = getSeparator();
157
158     if (fullname != null) {
159         /*
160         // We need to encode each of the folder's names.
161         StringTokenizer tok = new StringTokenizer(
162         fullname, new Character(separator).toString(), true);
163
164         while (tok.hasMoreTokens()) {
165         String s = tok.nextToken();
166         if (s.charAt(0) == separator)
167             encodedName.append(separator);
168         else
169             // XXX - should encode, but since there's no decoder...
170             //encodedName.append(java.net.URLEncoder.encode(s));
171             encodedName.append(s);
172         }
173         */

174         // append the whole thing, until we can encode
175
encodedName.append(fullname);
176     }
177
178     /*
179      * Sure would be convenient if URLName had a
180      * constructor that took a base URLName.
181      */

182     return new URLName JavaDoc(storeURL.getProtocol(), storeURL.getHost(),
183                 storeURL.getPort(), encodedName.toString(),
184                 storeURL.getUsername(),
185                 null /* no password */);
186     }
187
188     /**
189      * Returns the Store that owns this Folder object.
190      * This method can be invoked on a closed Folder.
191      * @return the Store
192      */

193     public Store JavaDoc getStore() {
194     return store;
195     }
196
197     /**
198      * Returns the parent folder of this folder.
199      * This method can be invoked on a closed Folder. If this folder
200      * is the top of a folder hierarchy, this method returns null. <p>
201      *
202      * Note that since Folder objects are not cached, invoking this method
203      * returns a new distinct Folder object.
204      *
205      * @return Parent folder
206      */

207     public abstract Folder JavaDoc getParent() throws MessagingException JavaDoc;
208
209     /**
210      * Tests if this folder physically exists on the Store.
211      * This method can be invoked on a closed Folder.
212      *
213      * @return true if the folder exists, otherwise false
214      * @see #create
215      * @exception MessagingException typically if the connection
216      * to the server is lost.
217      */

218     public abstract boolean exists() throws MessagingException JavaDoc;
219
220     /**
221      * Returns a list of Folders belonging to this Folder's namespace
222      * that match the specified pattern. Patterns may contain the wildcard
223      * characters <code>"%"</code>, which matches any character except hierarchy
224      * delimiters, and <code>"*"</code>, which matches any character. <p>
225      *
226      * As an example, given the folder hierarchy: <pre>
227      * Personal/
228      * Finance/
229      * Stocks
230      * Bonus
231      * StockOptions
232      * Jokes
233      * </pre>
234      * <code>list("*")</code> on "Personal" will return the whole
235      * hierarchy. <br>
236      * <code>list("%")</code> on "Personal" will return "Finance" and
237      * "Jokes". <br>
238      * <code>list("Jokes")</code> on "Personal" will return "Jokes".<br>
239      * <code>list("Stock*")</code> on "Finance" will return "Stocks"
240      * and "StockOptions". <p>
241      *
242      * Folder objects are not cached by the Store, so invoking this
243      * method on the same pattern multiple times will return that many
244      * distinct Folder objects. <p>
245      *
246      * This method can be invoked on a closed Folder.
247      *
248      * @param pattern the match pattern
249      * @return array of matching Folder objects. An empty
250      * array is returned if no matching Folders exist.
251      * @see #listSubscribed
252      * @exception FolderNotFoundException if this folder does
253      * not exist.
254      * @exception MessagingException
255      */

256     public abstract Folder JavaDoc[] list(String JavaDoc pattern) throws MessagingException JavaDoc;
257
258     /**
259      * Returns a list of subscribed Folders belonging to this Folder's
260      * namespace that match the specified pattern. If the folder does
261      * not support subscription, this method should resolve to
262      * <code>list</code>.
263      * (The default implementation provided here, does just this).
264      * The pattern can contain wildcards as for <code>list</code>. <p>
265      *
266      * Note that, at a given level of the folder hierarchy, a particular
267      * folder may not be subscribed, but folders underneath that folder
268      * in the folder hierarchy may be subscribed. In order to allow
269      * walking the folder hierarchy, such unsubscribed folders may be
270      * returned, indicating that a folder lower in the hierarchy is
271      * subscribed. The <code>isSubscribed</code> method on a folder will
272      * tell whether any particular folder is actually subscribed. <p>
273      *
274      * Folder objects are not cached by the Store, so invoking this
275      * method on the same pattern multiple times will return that many
276      * distinct Folder objects. <p>
277      *
278      * This method can be invoked on a closed Folder.
279      *
280      * @param pattern the match pattern
281      * @return array of matching subscribed Folder objects. An
282      * empty array is returned if no matching
283      * subscribed folders exist.
284      * @see #list
285      * @exception FolderNotFoundException if this folder does
286      * not exist.
287      * @exception MessagingException
288      */

289     public Folder JavaDoc[] listSubscribed(String JavaDoc pattern) throws MessagingException JavaDoc {
290     return list(pattern);
291     }
292
293     /**
294      * Convenience method that returns the list of folders under this
295      * Folder. This method just calls the <code>list(String pattern)</code>
296      * method with <code>"%"</code> as the match pattern. This method can
297      * be invoked on a closed Folder.
298      *
299      * @return array of Folder objects under this Folder. An
300      * empty array is returned if no subfolders exist.
301      * @see #list
302      * @exception FolderNotFoundException if this folder does
303      * not exist.
304      * @exception MessagingException
305      */

306
307     public Folder JavaDoc[] list() throws MessagingException JavaDoc {
308     return list("%");
309     }
310
311     /**
312      * Convenience method that returns the list of subscribed folders
313      * under this Folder. This method just calls the
314      * <code>listSubscribed(String pattern)</code> method with <code>"%"</code>
315      * as the match pattern. This method can be invoked on a closed Folder.
316      *
317      * @return array of subscribed Folder objects under this
318      * Folder. An empty array is returned if no subscribed
319      * subfolders exist.
320      * @see #listSubscribed
321      * @exception FolderNotFoundException if this folder does
322      * not exist.
323      * @exception MessagingException
324      */

325     public Folder JavaDoc[] listSubscribed() throws MessagingException JavaDoc {
326     return listSubscribed("%");
327     }
328
329     /**
330      * Return the delimiter character that separates this Folder's pathname
331      * from the names of immediate subfolders. This method can be invoked
332      * on a closed Folder.
333      *
334      * @exception FolderNotFoundException if the implementation
335      * requires the folder to exist, but it does not
336      * @return Hierarchy separator character
337      */

338     public abstract char getSeparator() throws MessagingException JavaDoc;
339
340     /**
341      * This folder can contain messages
342      */

343     public final static int HOLDS_MESSAGES = 0x01;
344
345     /**
346      * This folder can contain other folders
347      */

348     public final static int HOLDS_FOLDERS = 0x02;
349
350     /**
351      * Returns the type of this Folder, that is, whether this folder can hold
352      * messages or subfolders or both. The returned value is an integer
353      * bitfield with the appropriate bits set. This method can be invoked
354      * on a closed folder.
355      *
356      * @return integer with appropriate bits set
357      * @exception FolderNotFoundException if this folder does
358      * not exist.
359      * @see #HOLDS_FOLDERS
360      * @see #HOLDS_MESSAGES
361      */

362     public abstract int getType() throws MessagingException JavaDoc;
363
364     /**
365      * Create this folder on the Store. When this folder is created, any
366      * folders in its path that do not exist are also created. <p>
367      *
368      * If the creation is successful, a CREATED FolderEvent is delivered
369      * to any FolderListeners registered on this Folder and this Store.
370      *
371      * @param type The type of this folder.
372      *
373      * @return true if the creation succeeds, else false.
374      * @exception MessagingException
375      * @see #HOLDS_FOLDERS
376      * @see #HOLDS_MESSAGES
377      * @see javax.mail.event.FolderEvent
378      */

379     public abstract boolean create(int type) throws MessagingException JavaDoc;
380
381     /**
382      * Returns true if this Folder is subscribed. <p>
383      *
384      * This method can be invoked on a closed Folder. <p>
385      *
386      * The default implementation provided here just returns true.
387      *
388      * @return true if this Folder is subscribed
389      */

390     public boolean isSubscribed() {
391     return true;
392     }
393
394     /**
395      * Subscribe or unsubscribe this Folder. Not all Stores support
396      * subscription. <p>
397      *
398      * This method can be invoked on a closed Folder. <p>
399      *
400      * The implementation provided here just throws the
401      * MethodNotSupportedException.
402      *
403      * @param subscribe true to subscribe, false to unsubscribe
404      * @exception FolderNotFoundException if this folder does
405      * not exist.
406      * @exception MethodNotSupportedException if this store
407      * does not support subscription
408      * @exception MessagingException
409      */

410     public void setSubscribed(boolean subscribe)
411             throws MessagingException JavaDoc {
412     throw new MethodNotSupportedException JavaDoc();
413     }
414
415     /**
416      * Returns true if this Folder has new messages since the last time
417      * this indication was reset. When this indication is set or reset
418      * depends on the Folder implementation (and in the case of IMAP,
419      * depends on the server). This method can be used to implement
420      * a lightweight "check for new mail" operation on a Folder without
421      * opening it. (For example, a thread that monitors a mailbox and
422      * flags when it has new mail.) This method should indicate whether
423      * any messages in the Folder have the <code>RECENT</code> flag set. <p>
424      *
425      * Note that this is not an incremental check for new mail, i.e.,
426      * it cannot be used to determine whether any new messages have
427      * arrived since the last time this method was invoked. To
428      * implement incremental checks, the Folder needs to be opened. <p>
429      *
430      * This method can be invoked on a closed Folder that can contain
431      * Messages.
432      *
433      * @return true if the Store has new Messages
434      * @exception FolderNotFoundException if this folder does
435      * not exist.
436      * @exception MessagingException
437      */

438     public abstract boolean hasNewMessages() throws MessagingException JavaDoc;
439
440     /**
441      * Return the Folder object corresponding to the given name. Note that
442      * this folder does not physically have to exist in the Store. The
443      * <code>exists()</code> method on a Folder indicates whether it really
444      * exists on the Store. <p>
445      *
446      * In some Stores, name can be an absolute path if it starts with the
447      * hierarchy delimiter. Otherwise, it is interpreted relative to
448      * this Folder. <p>
449      *
450      * Folder objects are not cached by the Store, so invoking this
451      * method on the same name multiple times will return that many
452      * distinct Folder objects. <p>
453      *
454      * This method can be invoked on a closed Folder.
455      *
456      * @param name name of the Folder
457      * @return Folder object
458      * @exception MessagingException
459      */

460     public abstract Folder JavaDoc getFolder(String JavaDoc name)
461                 throws MessagingException JavaDoc;
462
463     /**
464      * Delete this Folder. This method will succeed only on a closed
465      * Folder. <p>
466      *
467      * The <code>recurse</code> flag controls whether the deletion affects
468      * subfolders or not. If true, all subfolders are deleted, then this
469      * folder itself is deleted. If false, the behaviour is dependent on
470      * the folder type and is elaborated below: <p>
471      *
472      * <ul>
473      * <li>
474      * The folder can contain only messages: (type == HOLDS_MESSAGES).
475      * <br>
476      * All messages within the folder are removed. The folder
477      * itself is then removed. An appropriate FolderEvent is generated by
478      * the Store and this folder. <p>
479      *
480      * <li>
481      * The folder can contain only subfolders: (type == HOLDS_FOLDERS).
482      * <br>
483      * If this folder is empty (does not contain any
484      * subfolders at all), it is removed. An appropriate FolderEvent is
485      * generated by the Store and this folder.<br>
486      * If this folder contains any subfolders, the delete fails
487      * and returns false. <p>
488      *
489      * <li>
490      * The folder can contain subfolders as well as messages: <br>
491      * If the folder is empty (no messages or subfolders), it
492      * is removed. If the folder contains no subfolders, but only messages,
493      * then all messages are removed. The folder itself is then removed.
494      * In both the above cases, an appropriate FolderEvent is
495      * generated by the Store and this folder. <p>
496      *
497      * If the folder contains subfolders there are 3 possible
498      * choices an implementation is free to do: <p>
499      *
500      * <ol>
501      * <li> The operation fails, irrespective of whether this folder
502      * contains messages or not. Some implementations might elect to go
503      * with this simple approach. The delete() method returns false.
504      *
505      * <li> Any messages within the folder are removed. Subfolders
506      * are not removed. The folder itself is not removed or affected
507      * in any manner. The delete() method returns true. And the
508      * exists() method on this folder will return true indicating that
509      * this folder still exists. <br>
510      * An appropriate FolderEvent is generated by the Store and this folder.
511      *
512      * <li> Any messages within the folder are removed. Subfolders are
513      * not removed. The folder itself changes its type from
514      * HOLDS_FOLDERS | HOLDS_MESSAGES to HOLDS_FOLDERS. Thus new
515      * messages cannot be added to this folder, but new subfolders can
516      * be created underneath. The delete() method returns true indicating
517      * success. The exists() method on this folder will return true
518      * indicating that this folder still exists. <br>
519      * An appropriate FolderEvent is generated by the Store and this folder.
520      * </ol>
521      * </ul>
522      *
523      * @return true if the Folder is deleted successfully
524      * @exception FolderNotFoundException if this folder does
525      * not exist
526      * @exception IllegalStateException if this folder is not in
527      * the closed state.
528      * @exception MessagingException
529      * @see javax.mail.event.FolderEvent
530      */

531     public abstract boolean delete(boolean recurse)
532                 throws MessagingException JavaDoc;
533
534     /**
535      * Rename this Folder. This method will succeed only on a closed
536      * Folder. <p>
537      *
538      * If the rename is successful, a RENAMED FolderEvent is delivered
539      * to FolderListeners registered on this folder and its containing
540      * Store.
541      *
542      * @param f a folder representing the new name for this Folder
543      * @return true if the Folder is renamed successfully
544      * @exception FolderNotFoundException if this folder does
545      * not exist
546      * @exception IllegalStateException if this folder is not in
547      * the closed state.
548      * @exception MessagingException
549      * @see javax.mail.event.FolderEvent
550      */

551     public abstract boolean renameTo(Folder JavaDoc f) throws MessagingException JavaDoc;
552
553     /**
554      * The Folder is read only. The state and contents of this
555      * folder cannot be modified.
556      */

557     public static final int READ_ONLY = 1;
558
559     /**
560      * The state and contents of this folder can be modified.
561      */

562     public static final int READ_WRITE = 2;
563
564     /**
565      * Open this Folder. This method is valid only on Folders that
566      * can contain Messages and that are closed. <p>
567      *
568      * If this folder is opened successfully, an OPENED ConnectionEvent
569      * is delivered to any ConnectionListeners registered on this
570      * Folder. <p>
571      *
572      * The effect of opening multiple connections to the same folder
573      * on a specifc Store is implementation dependent. Some implementations
574      * allow multiple readers, but only one writer. Others allow
575      * multiple writers as well as readers.
576      *
577      * @param mode open the Folder READ_ONLY or READ_WRITE
578      * @exception FolderNotFoundException if this folder does
579      * not exist.
580      * @exception IllegalStateException if this folder is not in
581      * the closed state.
582      * @exception MessagingException
583      * @see #READ_ONLY
584      * @see #READ_WRITE
585      * @see #getType()
586      * @see javax.mail.event.ConnectionEvent
587      */

588     public abstract void open(int mode) throws MessagingException JavaDoc;
589
590     /**
591      * Close this Folder. This method is valid only on open Folders. <p>
592      *
593      * A CLOSED ConnectionEvent is delivered to any ConnectionListeners
594      * registered on this Folder. Note that the folder is closed even
595      * if this method terminates abnormally by throwing a
596      * MessagingException.
597      *
598      * @param expunge expunges all deleted messages if this flag is true
599      * @exception IllegalStateException if this folder is not opened
600      * @exception MessagingException
601      * @see javax.mail.event.ConnectionEvent
602      */

603     public abstract void close(boolean expunge) throws MessagingException JavaDoc;
604
605     /**
606      * Indicates whether this Folder is in the 'open' state.
607      * @return true if this Folder is in the 'open' state.
608      */

609     public abstract boolean isOpen();
610
611     /**
612      * Return the open mode of this folder. Returns
613      * <code>Folder.READ_ONLY</code>, <code>Folder.READ_WRITE</code>,
614      * or -1 if the open mode is not known (usually only because an older
615      * <code>Folder</code> provider has not been updated to use this new
616      * method).
617      *
618      * @exception IllegalStateException if this folder is not opened
619      * @return the open mode of this folder
620      * @since JavaMail 1.1
621      */

622     public int getMode() {
623     if (!isOpen())
624         throw new IllegalStateException JavaDoc("Folder not open");
625     return mode;
626     }
627  
628     /**
629      * Get the permanent flags supported by this Folder. Returns a Flags
630      * object that contains all the flags supported. <p>
631      *
632      * The special flag <code>Flags.USER </code> indicates that this Folder
633      * supports arbitrary user-defined flags. <p>
634      *
635      * The supported permanent flags for a folder may not be available
636      * until the folder is opened.
637      *
638      * @return permanent flags, or null if not known
639      */

640     public abstract Flags JavaDoc getPermanentFlags();
641
642     /**
643      * Get total number of messages in this Folder. <p>
644      *
645      * This method can be invoked on a closed folder. However, note
646      * that for some folder implementations, getting the total message
647      * count can be an expensive operation involving actually opening
648      * the folder. In such cases, a provider can choose not to support
649      * this functionality in the closed state, in which case this method
650      * must return -1. <p>
651      *
652      * Clients invoking this method on a closed folder must be aware
653      * that this is a potentially expensive operation. Clients must
654      * also be prepared to handle a return value of -1 in this case.
655      *
656      * @return total number of messages. -1 may be returned
657      * by certain implementations if this method is
658      * invoked on a closed folder.
659      * @exception FolderNotFoundException if this folder does
660      * not exist.
661      * @exception MessagingException
662      */

663     public abstract int getMessageCount() throws MessagingException JavaDoc;
664
665     /**
666      * Get the number of new messages in this Folder. <p>
667      *
668      * This method can be invoked on a closed folder. However, note
669      * that for some folder implementations, getting the new message
670      * count can be an expensive operation involving actually opening
671      * the folder. In such cases, a provider can choose not to support
672      * this functionality in the closed state, in which case this method
673      * must return -1. <p>
674      *
675      * Clients invoking this method on a closed folder must be aware
676      * that this is a potentially expensive operation. Clients must
677      * also be prepared to handle a return value of -1 in this case. <p>
678      *
679      * This implementation returns -1 if this folder is closed. Else
680      * this implementation gets each Message in the folder using
681      * <code>getMessage(int)</code> and checks whether its
682      * <code>RECENT</code> flag is set. The total number of messages
683      * that have this flag set is returned.
684      *
685      * @return number of new messages. -1 may be returned
686      * by certain implementations if this method is
687      * invoked on a closed folder.
688      * @exception FolderNotFoundException if this folder does
689      * not exist.
690      * @exception MessagingException
691      */

692     public synchronized int getNewMessageCount()
693             throws MessagingException JavaDoc {
694     if (!isOpen())
695         return -1;
696
697     int newmsgs = 0;
698     int total = getMessageCount();
699     for (int i = 1; i <= total; i++) {
700         try {
701         if (getMessage(i).isSet(Flags.Flag.RECENT))
702             newmsgs++;
703         } catch (MessageRemovedException JavaDoc me) {
704         // This is an expunged message, ignore it.
705
continue;
706         }
707     }
708     return newmsgs;
709     }
710
711     /**
712      * Get the total number of unread messages in this Folder. <p>
713      *
714      * This method can be invoked on a closed folder. However, note
715      * that for some folder implementations, getting the unread message
716      * count can be an expensive operation involving actually opening
717      * the folder. In such cases, a provider can choose not to support
718      * this functionality in the closed state, in which case this method
719      * must return -1. <p>
720      *
721      * Clients invoking this method on a closed folder must be aware
722      * that this is a potentially expensive operation. Clients must
723      * also be prepared to handle a return value of -1 in this case. <p>
724      *
725      * This implementation returns -1 if this folder is closed. Else
726      * this implementation gets each Message in the folder using
727      * <code>getMessage(int)</code> and checks whether its
728      * <code>SEEN</code> flag is set. The total number of messages
729      * that do not have this flag set is returned.
730      *
731      * @return total number of unread messages. -1 may be returned
732      * by certain implementations if this method is
733      * invoked on a closed folder.
734      * @exception FolderNotFoundException if this folder does
735      * not exist.
736      * @exception MessagingException
737      */

738     public synchronized int getUnreadMessageCount()
739             throws MessagingException JavaDoc {
740     if (!isOpen())
741         return -1;
742
743     int unread = 0;
744     int total = getMessageCount();
745     for (int i = 1; i <= total; i++) {
746         try {
747         if (!getMessage(i).isSet(Flags.Flag.SEEN))
748             unread++;
749         } catch (MessageRemovedException JavaDoc me) {
750         // This is an expunged message, ignore it.
751
continue;
752         }
753     }
754     return unread;
755     }
756
757     /**
758      * Get the number of deleted messages in this Folder. <p>
759      *
760      * This method can be invoked on a closed folder. However, note
761      * that for some folder implementations, getting the deleted message
762      * count can be an expensive operation involving actually opening
763      * the folder. In such cases, a provider can choose not to support
764      * this functionality in the closed state, in which case this method
765      * must return -1. <p>
766      *
767      * Clients invoking this method on a closed folder must be aware
768      * that this is a potentially expensive operation. Clients must
769      * also be prepared to handle a return value of -1 in this case. <p>
770      *
771      * This implementation returns -1 if this folder is closed. Else
772      * this implementation gets each Message in the folder using
773      * <code>getMessage(int)</code> and checks whether its
774      * <code>DELETED</code> flag is set. The total number of messages
775      * that have this flag set is returned.
776      *
777      * @return number of deleted messages. -1 may be returned
778      * by certain implementations if this method is
779      * invoked on a closed folder.
780      * @exception FolderNotFoundException if this folder does
781      * not exist.
782      * @exception MessagingException
783      * @since JavaMail 1.3
784      */

785     public synchronized int getDeletedMessageCount() throws MessagingException JavaDoc {
786     if (!isOpen())
787         return -1;
788
789     int deleted = 0;
790     int total = getMessageCount();
791     for (int i = 1; i <= total; i++) {
792         try {
793         if (getMessage(i).isSet(Flags.Flag.DELETED))
794             deleted++;
795         } catch (MessageRemovedException JavaDoc me) {
796         // This is an expunged message, ignore it.
797
continue;
798         }
799     }
800     return deleted;
801     }
802
803     /**
804      * Get the Message object corresponding to the given message
805      * number. A Message object's message number is the relative
806      * position of this Message in its Folder. Messages are numbered
807      * starting at 1 through the total number of message in the folder.
808      * Note that the message number for a particular Message can change
809      * during a session if other messages in the Folder are deleted and
810      * the Folder is expunged. <p>
811      *
812      * Message objects are light-weight references to the actual message
813      * that get filled up on demand. Hence Folder implementations are
814      * expected to provide light-weight Message objects. <p>
815      *
816      * Unlike Folder objects, repeated calls to getMessage with the
817      * same message number will return the same Message object, as
818      * long as no messages in this folder have been expunged. <p>
819      *
820      * Since message numbers can change within a session if the folder
821      * is expunged , clients are advised not to use message numbers as
822      * references to messages. Use Message objects instead.
823      *
824      * @param msgnum the message number
825      * @return the Message object
826      * @see #getMessageCount
827      * @see #fetch
828      * @exception FolderNotFoundException if this folder does
829      * not exist.
830      * @exception IllegalStateException if this folder is not opened
831      * @exception IndexOutOfBoundsException if the message number
832      * is out of range.
833      * @exception MessagingException
834      */

835     public abstract Message JavaDoc getMessage(int msgnum)
836                 throws MessagingException JavaDoc;
837
838     /**
839      * Get the Message objects for message numbers ranging from start
840      * through end, both start and end inclusive. Note that message
841      * numbers start at 1, not 0. <p>
842      *
843      * Message objects are light-weight references to the actual message
844      * that get filled up on demand. Hence Folder implementations are
845      * expected to provide light-weight Message objects. <p>
846      *
847      * This implementation uses getMessage(index) to obtain the required
848      * Message objects. Note that the returned array must contain
849      * <code>(end-start+1)</code> Message objects.
850      *
851      * @param start the number of the first message
852      * @param end the number of the last message
853      * @return the Message objects
854      * @see #fetch
855      * @exception FolderNotFoundException if this folder does
856      * not exist.
857      * @exception IllegalStateException if this folder is not opened.
858      * @exception IndexOutOfBoundsException if the start or end
859      * message numbers are out of range.
860      * @exception MessagingException
861      */

862     public synchronized Message JavaDoc[] getMessages(int start, int end)
863             throws MessagingException JavaDoc {
864     Message JavaDoc[] msgs = new Message JavaDoc[end - start +1];
865     for (int i = start; i <= end; i++)
866         msgs[i - start] = getMessage(i);
867     return msgs;
868     }
869
870     /**
871      * Get the Message objects for message numbers specified in
872      * the array. <p>
873      *
874      * Message objects are light-weight references to the actual message
875      * that get filled up on demand. Hence Folder implementations are
876      * expected to provide light-weight Message objects. <p>
877      *
878      * This implementation uses getMessage(index) to obtain the required
879      * Message objects. Note that the returned array must contain
880      * <code>msgnums.length</code> Message objects
881      *
882      * @param msgnums the array of message numbers
883      * @return the array of Message objects.
884      * @see #fetch
885      * @exception FolderNotFoundException if this folder does
886      * not exist.
887      * @exception IllegalStateException if this folder is not opened.
888      * @exception IndexOutOfBoundsException if any message number
889      * in the given array is out of range.
890      * @exception MessagingException
891      */

892     public synchronized Message JavaDoc[] getMessages(int[] msgnums)
893             throws MessagingException JavaDoc {
894     int len = msgnums.length;
895     Message JavaDoc[] msgs = new Message JavaDoc[len];
896     for (int i = 0; i < len; i++)
897         msgs[i] = getMessage(msgnums[i]);
898     return msgs;
899     }
900
901     /**
902      * Get all Message objects from this Folder. Returns an empty array
903      * if the folder is empty.
904      *
905      * Clients can use Message objects (instead of sequence numbers)
906      * as references to the messages within a folder; this method supplies
907      * the Message objects to the client. Folder implementations are
908      * expected to provide light-weight Message objects, which get
909      * filled on demand. <p>
910      *
911      * This implementation invokes <code>getMessageCount()</code> to get
912      * the current message count and then uses <code>getMessage()</code>
913      * to get Message objects from 1 till the message count.
914      *
915      * @return array of Message objects, empty array if folder
916      * is empty.
917      * @see #fetch
918      * @exception FolderNotFoundException if this folder does
919      * not exist.
920      * @exception IllegalStateException if this folder is not opened.
921      * @exception MessagingException
922      */

923     public synchronized Message JavaDoc[] getMessages() throws MessagingException JavaDoc {
924     if (!isOpen()) // otherwise getMessageCount might return -1
925
throw new IllegalStateException JavaDoc("Folder not open");
926     int total = getMessageCount();
927     Message JavaDoc[] msgs = new Message JavaDoc[total];
928     for (int i = 1; i <= total; i++)
929         msgs[i-1] = getMessage(i);
930     return msgs;
931     }
932
933     /**
934      * Append given Messages to this folder. This method can be
935      * invoked on a closed Folder. An appropriate MessageCountEvent
936      * is delivered to any MessageCountListener registered on this
937      * folder when the messages arrive in the folder. <p>
938      *
939      * Folder implementations must not abort this operation if a
940      * Message in the given message array turns out to be an
941      * expunged Message.
942      *
943      * @param msgs array of Messages to be appended
944      * @exception FolderNotFoundException if this folder does
945      * not exist.
946      * @exception MessagingException if the append failed.
947      */

948     public abstract void appendMessages(Message JavaDoc[] msgs)
949                 throws MessagingException JavaDoc;
950
951     /**
952      * Prefetch the items specified in the FetchProfile for the
953      * given Messages. <p>
954      *
955      * Clients use this method to indicate that the specified items are
956      * needed en-masse for the given message range. Implementations are
957      * expected to retrieve these items for the given message range in
958      * a efficient manner. Note that this method is just a hint to the
959      * implementation to prefetch the desired items. <p>
960      *
961      * An example is a client filling its header-view window with
962      * the Subject, From and X-mailer headers for all messages in the
963      * folder.<p>
964      * <blockquote><pre>
965      *
966      * Message[] msgs = folder.getMessages();
967      *
968      * FetchProfile fp = new FetchProfile();
969      * fp.add(FetchProfile.Item.ENVELOPE);
970      * fp.add("X-mailer");
971      * folder.fetch(msgs, fp);
972      *
973      * for (int i = 0; i < folder.getMessageCount(); i++) {
974      * display(msg[i].getFrom());
975      * display(msg[i].getSubject());
976      * display(msg[i].getHeader("X-mailer"));
977      * }
978      *
979      * </pre></blockquote><p>
980      *
981      * The implementation provided here just returns without
982      * doing anything useful. Providers wanting to provide a real
983      * implementation for this method should override this method.
984      *
985      * @param msgs fetch items for these messages
986      * @param fp the FetchProfile
987      * @exception IllegalStateException if this folder is not opened
988      * @exception MessagingException.
989      */

990     public void fetch(Message JavaDoc[] msgs, FetchProfile JavaDoc fp)
991             throws MessagingException JavaDoc {
992     return;
993     }
994
995     /**
996      * Set the specified flags on the messages specified in the array.
997      * This will result in appropriate MessageChangedEvents being
998      * delivered to any MessageChangedListener registered on this
999      * Message's containing folder. <p>
1000     *
1001     * Note that the specified Message objects <strong>must</strong>
1002