Skip to content

Package: Folder

Folder

nameinstructionbranchcomplexitylinemethod
Folder(Store)
M: 69 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 20 C: 0
0%
M: 1 C: 0
0%
addConnectionListener(ConnectionListener)
M: 13 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
addFolderListener(FolderListener)
M: 13 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
addMessageChangedListener(MessageChangedListener)
M: 13 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
addMessageCountListener(MessageCountListener)
M: 13 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
close()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
copyMessages(Message[], Folder)
M: 21 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
fetch(Message[], FetchProfile)
M: 1 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
finalize()
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
getDeletedMessageCount()
M: 29 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 11 C: 0
0%
M: 1 C: 0
0%
getMessages()
M: 31 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
getMessages(int, int)
M: 24 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
getMessages(int[])
M: 23 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
getMode()
M: 11 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
getNewMessageCount()
M: 29 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 11 C: 0
0%
M: 1 C: 0
0%
getStore()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getURLName()
M: 32 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
getUnreadMessageCount()
M: 29 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 11 C: 0
0%
M: 1 C: 0
0%
isSubscribed()
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
list()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
listSubscribed()
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
listSubscribed(String)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
notifyConnectionListeners(int)
M: 21 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
notifyFolderListeners(int)
M: 21 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
notifyFolderRenamedListeners(Folder)
M: 22 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
notifyMessageAddedListeners(Message[])
M: 18 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
notifyMessageChangedListeners(int, Message)
M: 17 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
notifyMessageRemovedListeners(boolean, Message[])
M: 18 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
queueEvent(MailEvent, Vector)
M: 10 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
removeConnectionListener(ConnectionListener)
M: 9 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
removeFolderListener(FolderListener)
M: 9 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
removeMessageChangedListener(MessageChangedListener)
M: 9 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
removeMessageCountListener(MessageCountListener)
M: 9 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
search(SearchTerm)
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
search(SearchTerm, Message[])
M: 37 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
setFlags(Message[], Flags, boolean)
M: 17 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 5 C: 0
0%
M: 1 C: 0
0%
setFlags(int, int, Flags, boolean)
M: 18 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
setFlags(int[], Flags, boolean)
M: 21 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
setSubscribed(boolean)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
toString()
M: 10 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package jakarta.mail;
18:
19: import java.lang.*;
20: import java.util.ArrayList;
21: import java.util.EventListener;
22: import java.util.List;
23: import java.util.Vector;
24: import java.util.concurrent.Executor;
25: import jakarta.mail.search.SearchTerm;
26: import jakarta.mail.event.*;
27:
28: /**
29: * Folder is an abstract class that represents a folder for mail
30: * messages. Subclasses implement protocol specific Folders.<p>
31: *
32: * Folders can contain Messages, other Folders or both, thus providing
33: * a tree-like hierarchy rooted at the Store's default folder. (Note
34: * that some Folder implementations may not allow both Messages and
35: * other Folders in the same Folder).<p>
36: *
37: * The interpretation of folder names is implementation dependent.
38: * The different levels of hierarchy in a folder's full name
39: * are separated from each other by the hierarchy delimiter
40: * character.<p>
41: *
42: * The case-insensitive full folder name (that is, the full name
43: * relative to the default folder for a Store) <strong>INBOX</strong>
44: * is reserved to mean the "primary folder for this user on this
45: * server". Not all Stores will provide an INBOX folder, and not
46: * all users will have an INBOX folder at all times. The name
47: * <strong>INBOX</strong> is reserved to refer to this folder,
48: * when it exists, in Stores that provide it. <p>
49: *
50: * A Folder object obtained from a Store need not actually exist
51: * in the backend store. The <code>exists</code> method tests whether
52: * the folder exists or not. The <code>create</code> method
53: * creates a Folder. <p>
54: *
55: * A Folder is initially in the closed state. Certain methods are valid
56: * in this state; the documentation for those methods note this. A
57: * Folder is opened by calling its 'open' method. All Folder methods,
58: * except <code>open</code>, <code>delete</code> and
59: * <code>renameTo</code>, are valid in this state. <p>
60: *
61: * The only way to get a Folder is by invoking the
62: * <code>getFolder</code> method on Store, Folder, or Session, or by invoking
63: * the <code>list</code> or <code>listSubscribed</code> methods
64: * on Folder. Folder objects returned by the above methods are not
65: * cached by the Store. Thus, invoking the <code>getFolder</code> method
66: * with the same folder name multiple times will return distinct Folder
67: * objects. Likewise for the <code>list</code> and <code>listSubscribed</code>
68: * methods. <p>
69: *
70: * The Message objects within the Folder are cached by the Folder.
71: * Thus, invoking <code>getMessage(msgno)</code> on the same message number
72: * multiple times will return the same Message object, until an
73: * expunge is done on this Folder. <p>
74: *
75: * Message objects from a Folder are only valid while a Folder is open
76: * and should not be accessed after the Folder is closed, even if the
77: * Folder is subsequently reopened. Instead, new Message objects must
78: * be fetched from the Folder after the Folder is reopened. <p>
79: *
80: * Note that a Message's message number can change within a
81: * session if the containing Folder is expunged using the expunge
82: * method. Clients that use message numbers as references to messages
83: * should be aware of this and should be prepared to deal with this
84: * situation (probably by flushing out existing message number references
85: * and reloading them). Because of this complexity, it is better for
86: * clients to use Message objects as references to messages, rather than
87: * message numbers. Expunged Message objects still have to be
88: * pruned, but other Message objects in that folder are not affected by the
89: * expunge.
90: *
91: * @author John Mani
92: * @author Bill Shannon
93: */
94:
95: public abstract class Folder implements AutoCloseable {
96:
97: /**
98: * The parent store.
99: */
100: protected Store store;
101:
102: /**
103: * The open mode of this folder. The open mode is
104: * <code>Folder.READ_ONLY</code>, <code>Folder.READ_WRITE</code>,
105: * or -1 if not known.
106: * @since        JavaMail 1.1
107: */
108: protected int mode = -1;
109:
110: /*
111: * The queue of events to be delivered.
112: */
113: private final EventQueue q;
114:
115: /**
116: * Constructor that takes a Store object.
117: *
118: * @param store the Store that holds this folder
119: */
120: protected Folder(Store store) {
121:         this.store = store;
122:
123:         // create or choose the appropriate event queue
124:         Session session = store.getSession();
125:         String scope =
126:          session.getProperties().getProperty("mail.event.scope", "folder");
127:         Executor executor =
128:                 (Executor)session.getProperties().get("mail.event.executor");
129:•        if (scope.equalsIgnoreCase("application"))
130:          q = EventQueue.getApplicationEventQueue(executor);
131:•        else if (scope.equalsIgnoreCase("session"))
132:          q = session.getEventQueue();
133:•        else if (scope.equalsIgnoreCase("store"))
134:          q = store.getEventQueue();
135:         else // if (scope.equalsIgnoreCase("folder"))
136:          q = new EventQueue(executor);
137: }
138:
139: /**
140: * Returns the name of this Folder. <p>
141: *
142: * This method can be invoked on a closed Folder.
143: *
144: * @return                name of the Folder
145: */
146: public abstract String getName();
147:
148: /**
149: * Returns the full name of this Folder. If the folder resides under
150: * the root hierarchy of this Store, the returned name is relative
151: * to the root. Otherwise an absolute name, starting with the
152: * hierarchy delimiter, is returned. <p>
153: *
154: * This method can be invoked on a closed Folder.
155: *
156: * @return                full name of the Folder
157: */
158: public abstract String getFullName();
159:
160: /**
161: * Return a URLName representing this folder. The returned URLName
162: * does <em>not</em> include the password used to access the store.
163: *
164: * @return        the URLName representing this folder
165: * @exception        MessagingException for failures
166: * @see        URLName
167: * @since        JavaMail 1.1
168: */
169: public URLName getURLName() throws MessagingException {
170:         URLName storeURL = getStore().getURLName();
171:         String fullname = getFullName();
172:         StringBuilder encodedName = new StringBuilder();
173:
174:•        if (fullname != null) {
175:          /*
176:          // We need to encode each of the folder's names.
177:          char separator = getSeparator();
178:          StringTokenizer tok = new StringTokenizer(
179:                 fullname, new Character(separator).toString(), true);
180:
181:          while (tok.hasMoreTokens()) {
182:                 String s = tok.nextToken();
183:                 if (s.charAt(0) == separator)
184:                  encodedName.append(separator);
185:                 else
186:                  // XXX - should encode, but since there's no decoder...
187:                  //encodedName.append(java.net.URLEncoder.encode(s));
188:                  encodedName.append(s);
189:          }
190:          */
191:          // append the whole thing, until we can encode
192:          encodedName.append(fullname);
193:         }
194:
195:         /*
196:          * Sure would be convenient if URLName had a
197:          * constructor that took a base URLName.
198:          */
199:         return new URLName(storeURL.getProtocol(), storeURL.getHost(),
200:                          storeURL.getPort(), encodedName.toString(),
201:                          storeURL.getUsername(),
202:                          null /* no password */);
203: }
204:
205: /**
206: * Returns the Store that owns this Folder object.
207: * This method can be invoked on a closed Folder.
208: *
209: * @return                 the Store
210: */
211: public Store getStore() {
212:         return store;
213: }
214:
215: /**
216: * Returns the parent folder of this folder.
217: * This method can be invoked on a closed Folder. If this folder
218: * is the top of a folder hierarchy, this method returns null. <p>
219: *
220: * Note that since Folder objects are not cached, invoking this method
221: * returns a new distinct Folder object.
222: *
223: * @return                Parent folder
224: * @exception        MessagingException for failures
225: */
226: public abstract Folder getParent() throws MessagingException;
227:
228: /**
229: * Tests if this folder physically exists on the Store.
230: * This method can be invoked on a closed Folder.
231: *
232: * @return true if the folder exists, otherwise false
233: * @see #create
234: * @exception        MessagingException typically if the connection
235: *                        to the server is lost.
236: */
237: public abstract boolean exists() throws MessagingException;
238:
239: /**
240: * Returns a list of Folders belonging to this Folder's namespace
241: * that match the specified pattern. Patterns may contain the wildcard
242: * characters <code>"%"</code>, which matches any character except hierarchy
243: * delimiters, and <code>"*"</code>, which matches any character. <p>
244: *
245: * As an example, given the folder hierarchy: <pre>
246: * Personal/
247: * Finance/
248: * Stocks
249: * Bonus
250: * StockOptions
251: * Jokes
252: * </pre>
253: * <code>list("*")</code> on "Personal" will return the whole
254: * hierarchy. <br>
255: * <code>list("%")</code> on "Personal" will return "Finance" and
256: * "Jokes". <br>
257: * <code>list("Jokes")</code> on "Personal" will return "Jokes".<br>
258: * <code>list("Stock*")</code> on "Finance" will return "Stocks"
259: * and "StockOptions". <p>
260: *
261: * Folder objects are not cached by the Store, so invoking this
262: * method on the same pattern multiple times will return that many
263: * distinct Folder objects. <p>
264: *
265: * This method can be invoked on a closed Folder.
266: *
267: * @param pattern        the match pattern
268: * @return                array of matching Folder objects. An empty
269: *                        array is returned if no matching Folders exist.
270: * @see                 #listSubscribed
271: * @exception         FolderNotFoundException if this folder does
272: *                        not exist.
273: * @exception         MessagingException for other failures
274: */
275: public abstract Folder[] list(String pattern) throws MessagingException;
276:
277: /**
278: * Returns a list of subscribed Folders belonging to this Folder's
279: * namespace that match the specified pattern. If the folder does
280: * not support subscription, this method should resolve to
281: * <code>list</code>.
282: * (The default implementation provided here, does just this).
283: * The pattern can contain wildcards as for <code>list</code>. <p>
284: *
285: * Note that, at a given level of the folder hierarchy, a particular
286: * folder may not be subscribed, but folders underneath that folder
287: * in the folder hierarchy may be subscribed. In order to allow
288: * walking the folder hierarchy, such unsubscribed folders may be
289: * returned, indicating that a folder lower in the hierarchy is
290: * subscribed. The <code>isSubscribed</code> method on a folder will
291: * tell whether any particular folder is actually subscribed. <p>
292: *
293: * Folder objects are not cached by the Store, so invoking this
294: * method on the same pattern multiple times will return that many
295: * distinct Folder objects. <p>
296: *
297: * This method can be invoked on a closed Folder.
298: *
299: * @param pattern        the match pattern
300: * @return                array of matching subscribed Folder objects. An
301: *                        empty array is returned if no matching
302: *                        subscribed folders exist.
303: * @see                 #list
304: * @exception         FolderNotFoundException if this folder does
305: *                        not exist.
306: * @exception         MessagingException for other failures
307: */
308: public Folder[] listSubscribed(String pattern) throws MessagingException {
309:         return list(pattern);
310: }
311:
312: /**
313: * Convenience method that returns the list of folders under this
314: * Folder. This method just calls the <code>list(String pattern)</code>
315: * method with <code>"%"</code> as the match pattern. This method can
316: * be invoked on a closed Folder.
317: *
318: * @return                array of Folder objects under this Folder. An
319: *                        empty array is returned if no subfolders exist.
320: * @see                #list
321: * @exception         FolderNotFoundException if this folder does
322: *                        not exist.
323: * @exception         MessagingException for other failures
324: */
325:
326: public Folder[] list() throws MessagingException {
327:         return list("%");
328: }
329:
330: /**
331: * Convenience method that returns the list of subscribed folders
332: * under this Folder. This method just calls the
333: * <code>listSubscribed(String pattern)</code> method with <code>"%"</code>
334: * as the match pattern. This method can be invoked on a closed Folder.
335: *
336: * @return                array of subscribed Folder objects under this
337: *                        Folder. An empty array is returned if no subscribed
338: *                        subfolders exist.
339: * @see                #listSubscribed
340: * @exception         FolderNotFoundException if this folder does
341: *                        not exist.
342: * @exception         MessagingException for other failures
343: */
344: public Folder[] listSubscribed() throws MessagingException {
345:         return listSubscribed("%");
346: }
347:
348: /**
349: * Return the delimiter character that separates this Folder's pathname
350: * from the names of immediate subfolders. This method can be invoked
351: * on a closed Folder.
352: *
353: * @exception         FolderNotFoundException if the implementation
354: *                        requires the folder to exist, but it does not
355: * @return Hierarchy separator character
356: */
357: public abstract char getSeparator() throws MessagingException;
358:
359: /**
360: * This folder can contain messages
361: */
362: public final static int HOLDS_MESSAGES = 0x01;
363:
364: /**
365: * This folder can contain other folders
366: */
367: public final static int HOLDS_FOLDERS = 0x02;
368:
369: /**
370: * Returns the type of this Folder, that is, whether this folder can hold
371: * messages or subfolders or both. The returned value is an integer
372: * bitfield with the appropriate bits set. This method can be invoked
373: * on a closed folder.
374: *
375: * @return                 integer with appropriate bits set
376: * @exception         FolderNotFoundException if this folder does
377: *                        not exist.
378: * @see                 #HOLDS_FOLDERS
379: * @see                #HOLDS_MESSAGES
380: */
381: public abstract int getType() throws MessagingException;
382:
383: /**
384: * Create this folder on the Store. When this folder is created, any
385: * folders in its path that do not exist are also created. <p>
386: *
387: * If the creation is successful, a CREATED FolderEvent is delivered
388: * to any FolderListeners registered on this Folder and this Store.
389: *
390: * @param type        The type of this folder.
391: *
392: * @return                true if the creation succeeds, else false.
393: * @exception         MessagingException for failures
394: * @see                 #HOLDS_FOLDERS
395: * @see                #HOLDS_MESSAGES
396: * @see                jakarta.mail.event.FolderEvent
397: */
398: public abstract boolean create(int type) throws MessagingException;
399:
400: /**
401: * Returns true if this Folder is subscribed. <p>
402: *
403: * This method can be invoked on a closed Folder. <p>
404: *
405: * The default implementation provided here just returns true.
406: *
407: * @return                true if this Folder is subscribed
408: */
409: public boolean isSubscribed() {
410:         return true;
411: }
412:
413: /**
414: * Subscribe or unsubscribe this Folder. Not all Stores support
415: * subscription. <p>
416: *
417: * This method can be invoked on a closed Folder. <p>
418: *
419: * The implementation provided here just throws the
420: * MethodNotSupportedException.
421: *
422: * @param subscribe        true to subscribe, false to unsubscribe
423: * @exception         FolderNotFoundException if this folder does
424: *                        not exist.
425: * @exception         MethodNotSupportedException if this store
426: *                        does not support subscription
427: * @exception         MessagingException for other failures
428: */
429: public void setSubscribed(boolean subscribe)
430:                         throws MessagingException {
431:         throw new MethodNotSupportedException();
432: }
433:
434: /**
435: * Returns true if this Folder has new messages since the last time
436: * this indication was reset. When this indication is set or reset
437: * depends on the Folder implementation (and in the case of IMAP,
438: * depends on the server). This method can be used to implement
439: * a lightweight "check for new mail" operation on a Folder without
440: * opening it. (For example, a thread that monitors a mailbox and
441: * flags when it has new mail.) This method should indicate whether
442: * any messages in the Folder have the <code>RECENT</code> flag set. <p>
443: *
444: * Note that this is not an incremental check for new mail, i.e.,
445: * it cannot be used to determine whether any new messages have
446: * arrived since the last time this method was invoked. To
447: * implement incremental checks, the Folder needs to be opened. <p>
448: *
449: * This method can be invoked on a closed Folder that can contain
450: * Messages.
451: *
452: * @return                true if the Store has new Messages
453: * @exception        FolderNotFoundException if this folder does
454: *                        not exist.
455: * @exception         MessagingException for other failures
456: */
457: public abstract boolean hasNewMessages() throws MessagingException;
458:
459: /**
460: * Return the Folder object corresponding to the given name. Note that
461: * this folder does not physically have to exist in the Store. The
462: * <code>exists()</code> method on a Folder indicates whether it really
463: * exists on the Store. <p>
464: *
465: * In some Stores, name can be an absolute path if it starts with the
466: * hierarchy delimiter. Otherwise, it is interpreted relative to
467: * this Folder. <p>
468: *
469: * Folder objects are not cached by the Store, so invoking this
470: * method on the same name multiple times will return that many
471: * distinct Folder objects. <p>
472: *
473: * This method can be invoked on a closed Folder.
474: *
475: * @param name         name of the Folder
476: * @return                Folder object
477: * @exception         MessagingException for failures
478: */
479: public abstract Folder getFolder(String name)
480:                                 throws MessagingException;
481:
482: /**
483: * Delete this Folder. This method will succeed only on a closed
484: * Folder. <p>
485: *
486: * The <code>recurse</code> flag controls whether the deletion affects
487: * subfolders or not. If true, all subfolders are deleted, then this
488: * folder itself is deleted. If false, the behaviour is dependent on
489: * the folder type and is elaborated below:
490: *
491: * <ul>
492: * <li>
493: * The folder can contain only messages: (type == HOLDS_MESSAGES).
494: * <br>
495: * All messages within the folder are removed. The folder
496: * itself is then removed. An appropriate FolderEvent is generated by
497: * the Store and this folder.
498: *
499: * <li>
500: * The folder can contain only subfolders: (type == HOLDS_FOLDERS).
501: * <br>
502: * If this folder is empty (does not contain any
503: * subfolders at all), it is removed. An appropriate FolderEvent is
504: * generated by the Store and this folder.<br>
505: * If this folder contains any subfolders, the delete fails
506: * and returns false.
507: *
508: * <li>
509: * The folder can contain subfolders as well as messages: <br>
510: * If the folder is empty (no messages or subfolders), it
511: * is removed. If the folder contains no subfolders, but only messages,
512: * then all messages are removed. The folder itself is then removed.
513: * In both the above cases, an appropriate FolderEvent is
514: * generated by the Store and this folder. <p>
515: *
516: * If the folder contains subfolders there are 3 possible
517: * choices an implementation is free to do:
518: *
519: * <ol>
520: * <li> The operation fails, irrespective of whether this folder
521: * contains messages or not. Some implementations might elect to go
522: * with this simple approach. The delete() method returns false.
523: *
524: * <li> Any messages within the folder are removed. Subfolders
525: * are not removed. The folder itself is not removed or affected
526: * in any manner. The delete() method returns true. And the
527: * exists() method on this folder will return true indicating that
528: * this folder still exists. <br>
529: * An appropriate FolderEvent is generated by the Store and this folder.
530: *
531: * <li> Any messages within the folder are removed. Subfolders are
532: * not removed. The folder itself changes its type from
533: * HOLDS_FOLDERS | HOLDS_MESSAGES to HOLDS_FOLDERS. Thus new
534: * messages cannot be added to this folder, but new subfolders can
535: * be created underneath. The delete() method returns true indicating
536: * success. The exists() method on this folder will return true
537: * indicating that this folder still exists. <br>
538: * An appropriate FolderEvent is generated by the Store and this folder.
539: * </ol>
540: * </ul>
541: *
542: * @param        recurse        also delete subfolders?
543: * @return                true if the Folder is deleted 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 for other failures
549: * @see                jakarta.mail.event.FolderEvent
550: */
551: public abstract boolean delete(boolean recurse)
552:                                 throws MessagingException;
553:
554: /**
555: * Rename this Folder. This method will succeed only on a closed
556: * Folder. <p>
557: *
558: * If the rename is successful, a RENAMED FolderEvent is delivered
559: * to FolderListeners registered on this folder and its containing
560: * Store.
561: *
562: * @param f                a folder representing the new name for this Folder
563: * @return                true if the Folder is renamed successfully
564: * @exception        FolderNotFoundException if this folder does
565: *                        not exist
566: * @exception        IllegalStateException if this folder is not in
567: *                        the closed state.
568: * @exception MessagingException for other failures
569: * @see                jakarta.mail.event.FolderEvent
570: */
571: public abstract boolean renameTo(Folder f) throws MessagingException;
572:
573: /**
574: * The Folder is read only. The state and contents of this
575: * folder cannot be modified.
576: */
577: public static final int READ_ONLY         = 1;
578:
579: /**
580: * The state and contents of this folder can be modified.
581: */
582: public static final int READ_WRITE         = 2;
583:
584: /**
585: * Open this Folder. This method is valid only on Folders that
586: * can contain Messages and that are closed. <p>
587: *
588: * If this folder is opened successfully, an OPENED ConnectionEvent
589: * is delivered to any ConnectionListeners registered on this
590: * Folder. <p>
591: *
592: * The effect of opening multiple connections to the same folder
593: * on a specifc Store is implementation dependent. Some implementations
594: * allow multiple readers, but only one writer. Others allow
595: * multiple writers as well as readers.
596: *
597: * @param mode        open the Folder READ_ONLY or READ_WRITE
598: * @exception        FolderNotFoundException if this folder does
599: *                        not exist.
600: * @exception        IllegalStateException if this folder is not in
601: *                        the closed state.
602: * @exception MessagingException for other failures
603: * @see                 #READ_ONLY
604: * @see                 #READ_WRITE
605: * @see                 #getType()
606: * @see                 jakarta.mail.event.ConnectionEvent
607: */
608: public abstract void open(int mode) throws MessagingException;
609:
610: /**
611: * Close this Folder. This method is valid only on open Folders. <p>
612: *
613: * A CLOSED ConnectionEvent is delivered to any ConnectionListeners
614: * registered on this Folder. Note that the folder is closed even
615: * if this method terminates abnormally by throwing a
616: * MessagingException.
617: *
618: * @param expunge        expunges all deleted messages if this flag is true
619: * @exception        IllegalStateException if this folder is not opened
620: * @exception MessagingException for other failures
621: * @see                 jakarta.mail.event.ConnectionEvent
622: */
623: public abstract void close(boolean expunge) throws MessagingException;
624:
625: /**
626: * Close this Folder and expunge deleted messages. <p>
627: *
628: * A CLOSED ConnectionEvent is delivered to any ConnectionListeners
629: * registered on this Folder. Note that the folder is closed even
630: * if this method terminates abnormally by throwing a
631: * MessagingException. <p>
632: *
633: * This method supports the {@link java.lang.AutoCloseable AutoCloseable}
634: * interface. <p>
635: *
636: * This implementation calls <code>close(true)</code>.
637: *
638: * @exception        IllegalStateException if this folder is not opened
639: * @exception MessagingException for other failures
640: * @see                 jakarta.mail.event.ConnectionEvent
641: * @since                JavaMail 1.6
642: */
643: @Override
644: public void close() throws MessagingException {
645:         close(true);
646: }
647:
648: /**
649: * Indicates whether this Folder is in the 'open' state.
650: * @return true if this Folder is in the 'open' state.
651: */
652: public abstract boolean isOpen();
653:
654: /**
655: * Return the open mode of this folder. Returns
656: * <code>Folder.READ_ONLY</code>, <code>Folder.READ_WRITE</code>,
657: * or -1 if the open mode is not known (usually only because an older
658: * <code>Folder</code> provider has not been updated to use this new
659: * method).
660: *
661: * @exception        IllegalStateException if this folder is not opened
662: * @return         the open mode of this folder
663: * @since                JavaMail 1.1
664: */
665: public synchronized int getMode() {
666:•        if (!isOpen())
667:          throw new IllegalStateException("Folder not open");
668:         return mode;
669: }
670:
671: /**
672: * Get the permanent flags supported by this Folder. Returns a Flags
673: * object that contains all the flags supported. <p>
674: *
675: * The special flag <code>Flags.Flag.USER </code> indicates that this Folder
676: * supports arbitrary user-defined flags. <p>
677: *
678: * The supported permanent flags for a folder may not be available
679: * until the folder is opened.
680: *
681: * @return                 permanent flags, or null if not known
682: */
683: public abstract Flags getPermanentFlags();
684:
685: /**
686: * Get total number of messages in this Folder. <p>
687: *
688: * This method can be invoked on a closed folder. However, note
689: * that for some folder implementations, getting the total message
690: * count can be an expensive operation involving actually opening
691: * the folder. In such cases, a provider can choose not to support
692: * this functionality in the closed state, in which case this method
693: * must return -1. <p>
694: *
695: * Clients invoking this method on a closed folder must be aware
696: * that this is a potentially expensive operation. Clients must
697: * also be prepared to handle a return value of -1 in this case.
698: *
699: * @return                 total number of messages. -1 may be returned
700: *                        by certain implementations if this method is
701: *                        invoked on a closed folder.
702: * @exception        FolderNotFoundException if this folder does
703: *                        not exist.
704: * @exception MessagingException for other failures
705: */
706: public abstract int getMessageCount() throws MessagingException;
707:
708: /**
709: * Get the number of new messages in this Folder. <p>
710: *
711: * This method can be invoked on a closed folder. However, note
712: * that for some folder implementations, getting the new message
713: * count can be an expensive operation involving actually opening
714: * the folder. In such cases, a provider can choose not to support
715: * this functionality in the closed state, in which case this method
716: * must return -1. <p>
717: *
718: * Clients invoking this method on a closed folder must be aware
719: * that this is a potentially expensive operation. Clients must
720: * also be prepared to handle a return value of -1 in this case. <p>
721: *
722: * This implementation returns -1 if this folder is closed. Else
723: * this implementation gets each Message in the folder using
724: * <code>getMessage(int)</code> and checks whether its
725: * <code>RECENT</code> flag is set. The total number of messages
726: * that have this flag set is returned.
727: *
728: * @return                 number of new messages. -1 may be returned
729: *                        by certain implementations if this method is
730: *                        invoked on a closed folder.
731: * @exception        FolderNotFoundException if this folder does
732: *                        not exist.
733: * @exception MessagingException for other failures
734: */
735: public synchronized int getNewMessageCount()
736:                         throws MessagingException {
737:•        if (!isOpen())
738:          return -1;
739:
740:         int newmsgs = 0;
741:         int total = getMessageCount();
742:•        for (int i = 1; i <= total; i++) {
743:          try {
744:•                if (getMessage(i).isSet(Flags.Flag.RECENT))
745:                  newmsgs++;
746:          } catch (MessageRemovedException me) {
747:                 // This is an expunged message, ignore it.
748:                 continue;
749:          }
750:         }
751:         return newmsgs;
752: }
753:
754: /**
755: * Get the total number of unread messages in this Folder. <p>
756: *
757: * This method can be invoked on a closed folder. However, note
758: * that for some folder implementations, getting the unread message
759: * count can be an expensive operation involving actually opening
760: * the folder. In such cases, a provider can choose not to support
761: * this functionality in the closed state, in which case this method
762: * must return -1. <p>
763: *
764: * Clients invoking this method on a closed folder must be aware
765: * that this is a potentially expensive operation. Clients must
766: * also be prepared to handle a return value of -1 in this case. <p>
767: *
768: * This implementation returns -1 if this folder is closed. Else
769: * this implementation gets each Message in the folder using
770: * <code>getMessage(int)</code> and checks whether its
771: * <code>SEEN</code> flag is set. The total number of messages
772: * that do not have this flag set is returned.
773: *
774: * @return                 total number of unread messages. -1 may be returned
775: *                        by certain implementations if this method is
776: *                        invoked on a closed folder.
777: * @exception        FolderNotFoundException if this folder does
778: *                        not exist.
779: * @exception MessagingException for other failures
780: */
781: public synchronized int getUnreadMessageCount()
782:                         throws MessagingException {
783:•        if (!isOpen())
784:          return -1;
785:
786:         int unread = 0;
787:         int total = getMessageCount();
788:•        for (int i = 1; i <= total; i++) {
789:          try {
790:•                if (!getMessage(i).isSet(Flags.Flag.SEEN))
791:                  unread++;
792:          } catch (MessageRemovedException me) {
793:                 // This is an expunged message, ignore it.
794:                 continue;
795:          }
796:         }
797:         return unread;
798: }
799:
800: /**
801: * Get the number of deleted messages in this Folder. <p>
802: *
803: * This method can be invoked on a closed folder. However, note
804: * that for some folder implementations, getting the deleted message
805: * count can be an expensive operation involving actually opening
806: * the folder. In such cases, a provider can choose not to support
807: * this functionality in the closed state, in which case this method
808: * must return -1. <p>
809: *
810: * Clients invoking this method on a closed folder must be aware
811: * that this is a potentially expensive operation. Clients must
812: * also be prepared to handle a return value of -1 in this case. <p>
813: *
814: * This implementation returns -1 if this folder is closed. Else
815: * this implementation gets each Message in the folder using
816: * <code>getMessage(int)</code> and checks whether its
817: * <code>DELETED</code> flag is set. The total number of messages
818: * that have this flag set is returned.
819: *
820: * @return                 number of deleted messages. -1 may be returned
821: *                        by certain implementations if this method is
822: *                        invoked on a closed folder.
823: * @exception        FolderNotFoundException if this folder does
824: *                        not exist.
825: * @exception MessagingException for other failures
826: * @since                JavaMail 1.3
827: */
828: public synchronized int getDeletedMessageCount() throws MessagingException {
829:•        if (!isOpen())
830:          return -1;
831:
832:         int deleted = 0;
833:         int total = getMessageCount();
834:•        for (int i = 1; i <= total; i++) {
835:          try {
836:•                if (getMessage(i).isSet(Flags.Flag.DELETED))
837:                  deleted++;
838:          } catch (MessageRemovedException me) {
839:                 // This is an expunged message, ignore it.
840:                 continue;
841:          }
842:         }
843:         return deleted;
844: }
845:
846: /**
847: * Get the Message object corresponding to the given message
848: * number. A Message object's message number is the relative
849: * position of this Message in its Folder. Messages are numbered
850: * starting at 1 through the total number of message in the folder.
851: * Note that the message number for a particular Message can change
852: * during a session if other messages in the Folder are deleted and
853: * the Folder is expunged. <p>
854: *
855: * Message objects are light-weight references to the actual message
856: * that get filled up on demand. Hence Folder implementations are
857: * expected to provide light-weight Message objects. <p>
858: *
859: * Unlike Folder objects, repeated calls to getMessage with the
860: * same message number will return the same Message object, as
861: * long as no messages in this folder have been expunged. <p>
862: *
863: * Since message numbers can change within a session if the folder
864: * is expunged , clients are advised not to use message numbers as
865: * references to messages. Use Message objects instead.
866: *
867: * @param msgnum        the message number
868: * @return                 the Message object
869: * @see                #getMessageCount
870: * @see                #fetch
871: * @exception        FolderNotFoundException if this folder does
872: *                        not exist.
873: * @exception        IllegalStateException if this folder is not opened
874: * @exception        IndexOutOfBoundsException if the message number
875: *                        is out of range.
876: * @exception         MessagingException for other failures
877: */
878: public abstract Message getMessage(int msgnum)
879:                                 throws MessagingException;
880:
881: /**
882: * Get the Message objects for message numbers ranging from start
883: * through end, both start and end inclusive. Note that message
884: * numbers start at 1, not 0. <p>
885: *
886: * Message objects are light-weight references to the actual message
887: * that get filled up on demand. Hence Folder implementations are
888: * expected to provide light-weight Message objects. <p>
889: *
890: * This implementation uses getMessage(index) to obtain the required
891: * Message objects. Note that the returned array must contain
892: * <code>(end-start+1)</code> Message objects.
893: *
894: * @param start        the number of the first message
895: * @param end        the number of the last message
896: * @return                 the Message objects
897: * @see                #fetch
898: * @exception        FolderNotFoundException if this folder does
899: *                        not exist.
900: * @exception        IllegalStateException if this folder is not opened.
901: * @exception        IndexOutOfBoundsException if the start or end
902: *                        message numbers are out of range.
903: * @exception         MessagingException for other failures
904: */
905: public synchronized Message[] getMessages(int start, int end)
906:                         throws MessagingException {
907:         Message[] msgs = new Message[end - start +1];
908:•        for (int i = start; i <= end; i++)
909:          msgs[i - start] = getMessage(i);
910:         return msgs;
911: }
912:
913: /**
914: * Get the Message objects for message numbers specified in
915: * the array. <p>
916: *
917: * Message objects are light-weight references to the actual message
918: * that get filled up on demand. Hence Folder implementations are
919: * expected to provide light-weight Message objects. <p>
920: *
921: * This implementation uses getMessage(index) to obtain the required
922: * Message objects. Note that the returned array must contain
923: * <code>msgnums.length</code> Message objects
924: *
925: * @param msgnums        the array of message numbers
926: * @return                 the array of Message objects.
927: * @see                #fetch
928: * @exception        FolderNotFoundException if this folder does
929: *                        not exist.
930: * @exception        IllegalStateException if this folder is not opened.
931: * @exception        IndexOutOfBoundsException if any message number
932: *                        in the given array is out of range.
933: * @exception         MessagingException for other failures
934: */
935: public synchronized Message[] getMessages(int[] msgnums)
936:                         throws MessagingException {
937:         int len = msgnums.length;
938:         Message[] msgs = new Message[len];
939:•        for (int i = 0; i < len; i++)
940:          msgs[i] = getMessage(msgnums[i]);
941:         return msgs;
942: }
943:
944: /**
945: * Get all Message objects from this Folder. Returns an empty array
946: * if the folder is empty.
947: *
948: * Clients can use Message objects (instead of sequence numbers)
949: * as references to the messages within a folder; this method supplies
950: * the Message objects to the client. Folder implementations are
951: * expected to provide light-weight Message objects, which get
952: * filled on demand. <p>
953: *
954: * This implementation invokes <code>getMessageCount()</code> to get
955: * the current message count and then uses <code>getMessage()</code>
956: * to get Message objects from 1 till the message count.
957: *
958: * @return                 array of Message objects, empty array if folder
959: *                        is empty.
960: * @see                #fetch
961: * @exception        FolderNotFoundException if this folder does
962: *                        not exist.
963: * @exception        IllegalStateException if this folder is not opened.
964: * @exception         MessagingException for other failures
965: */
966: public synchronized Message[] getMessages() throws MessagingException {
967:•        if (!isOpen())        // otherwise getMessageCount might return -1
968:          throw new IllegalStateException("Folder not open");
969:         int total = getMessageCount();
970:         Message[] msgs = new Message[total];
971:•        for (int i = 1; i <= total; i++)
972:          msgs[i-1] = getMessage(i);        
973:         return msgs;
974: }
975:
976: /**
977: * Append given Messages to this folder. This method can be
978: * invoked on a closed Folder. An appropriate MessageCountEvent
979: * is delivered to any MessageCountListener registered on this
980: * folder when the messages arrive in the folder. <p>
981: *
982: * Folder implementations must not abort this operation if a
983: * Message in the given message array turns out to be an
984: * expunged Message.
985: *
986: * @param msgs        array of Messages to be appended
987: * @exception        FolderNotFoundException if this folder does
988: *                        not exist.
989: * @exception         MessagingException if the append failed.
990: */
991: public abstract void appendMessages(Message[] msgs)
992:                                 throws MessagingException;
993:
994: /**
995: * Prefetch the items specified in the FetchProfile for the
996: * given Messages. <p>
997: *
998: * Clients use this method to indicate that the specified items are
999: * needed en-masse for the given message range. Implementations are
1000: * expected to retrieve these items for the given message range in
1001: * a efficient manner. Note that this method is just a hint to the
1002: * implementation to prefetch the desired items. <p>
1003: *
1004: * An example is a client filling its header-view window with
1005: * the Subject, From and X-mailer headers for all messages in the
1006: * folder.
1007: * <blockquote><pre>
1008: *
1009: * Message[] msgs = folder.getMessages();
1010: *
1011: * FetchProfile fp = new FetchProfile();
1012: * fp.add(FetchProfile.Item.ENVELOPE);
1013: * fp.add("X-mailer");
1014: * folder.fetch(msgs, fp);
1015: *
1016: * for (int i = 0; i < folder.getMessageCount(); i++) {
1017: * display(msg[i].getFrom());
1018: * display(msg[i].getSubject());
1019: * display(msg[i].getHeader("X-mailer"));
1020: * }
1021: *
1022: * </pre></blockquote><p>
1023: *
1024: * The implementation provided here just returns without
1025: * doing anything useful. Providers wanting to provide a real
1026: * implementation for this method should override this method.
1027: *
1028: * @param msgs        fetch items for these messages
1029: * @param fp        the FetchProfile
1030: * @exception        IllegalStateException if this folder is not opened
1031: * @exception        MessagingException for other failures
1032: */
1033: public void fetch(Message[] msgs, FetchProfile fp)
1034:                         throws MessagingException {
1035:         return;
1036: }
1037:
1038: /**
1039: * Set the specified flags on the messages specified in the array.
1040: * This will result in appropriate MessageChangedEvents being
1041: * delivered to any MessageChangedListener registered on this
1042: * Message's containing folder. <p>
1043: *
1044: * Note that the specified Message objects <strong>must</strong>
1045: * belong to this folder. Certain Folder implementations can
1046: * optimize the operation of setting Flags for a group of messages,
1047: * so clients might want to use this method, rather than invoking
1048: * <code>Message.setFlags</code> for each Message. <p>
1049: *
1050: * This implementation degenerates to invoking <code>setFlags()</code>
1051: * on each Message object. Specific Folder implementations that can
1052: * optimize this case should do so.
1053: * Also, an implementation must not abort the operation if a Message
1054: * in the array turns out to be an expunged Message.
1055: *
1056: * @param msgs        the array of message objects
1057: * @param flag        Flags object containing the flags to be set
1058: * @param value        set the flags to this boolean value
1059: * @exception        IllegalStateException if this folder is not opened
1060: *                        or if it has been opened READ_ONLY.
1061: * @exception         MessagingException for other failures
1062: * @see                Message#setFlags
1063: * @see                jakarta.mail.event.MessageChangedEvent
1064: */
1065: public synchronized void setFlags(Message[] msgs,
1066:                         Flags flag, boolean value) throws MessagingException {
1067:•        for (int i = 0; i < msgs.length; i++) {
1068:          try {
1069:                 msgs[i].setFlags(flag, value);
1070:          } catch (MessageRemovedException me) {
1071:                 // This message is expunged, skip
1072:          }
1073:         }
1074: }
1075:
1076: /**
1077: * Set the specified flags on the messages numbered from start
1078: * through end, both start and end inclusive. Note that message
1079: * numbers start at 1, not 0.
1080: * This will result in appropriate MessageChangedEvents being
1081: * delivered to any MessageChangedListener registered on this
1082: * Message's containing folder. <p>
1083: *
1084: * Certain Folder implementations can
1085: * optimize the operation of setting Flags for a group of messages,
1086: * so clients might want to use this method, rather than invoking
1087: * <code>Message.setFlags</code> for each Message. <p>
1088: *
1089: * The default implementation uses <code>getMessage(int)</code> to
1090: * get each <code>Message</code> object and then invokes
1091: * <code>setFlags</code> on that object to set the flags.
1092: * Specific Folder implementations that can optimize this case should do so.
1093: * Also, an implementation must not abort the operation if a message
1094: * number refers to an expunged message.
1095: *
1096: * @param start        the number of the first message
1097: * @param end        the number of the last message
1098: * @param flag        Flags object containing the flags to be set
1099: * @param value        set the flags to this boolean value
1100: * @exception        IllegalStateException if this folder is not opened
1101: *                        or if it has been opened READ_ONLY.
1102: * @exception        IndexOutOfBoundsException if the start or end
1103: *                        message numbers are out of range.
1104: * @exception         MessagingException for other failures
1105: * @see                Message#setFlags
1106: * @see                jakarta.mail.event.MessageChangedEvent
1107: */
1108: public synchronized void setFlags(int start, int end,
1109:                         Flags flag, boolean value) throws MessagingException {
1110:•        for (int i = start; i <= end; i++) {
1111:          try {
1112:                 Message msg = getMessage(i);
1113:                 msg.setFlags(flag, value);
1114:          } catch (MessageRemovedException me) {
1115:                 // This message is expunged, skip
1116:          }
1117:         }
1118: }
1119:
1120: /**
1121: * Set the specified flags on the messages whose message numbers
1122: * are in the array.
1123: * This will result in appropriate MessageChangedEvents being
1124: * delivered to any MessageChangedListener registered on this
1125: * Message's containing folder. <p>
1126: *
1127: * Certain Folder implementations can
1128: * optimize the operation of setting Flags for a group of messages,
1129: * so clients might want to use this method, rather than invoking
1130: * <code>Message.setFlags</code> for each Message. <p>
1131: *
1132: * The default implementation uses <code>getMessage(int)</code> to
1133: * get each <code>Message</code> object and then invokes
1134: * <code>setFlags</code> on that object to set the flags.
1135: * Specific Folder implementations that can optimize this case should do so.
1136: * Also, an implementation must not abort the operation if a message
1137: * number refers to an expunged message.
1138: *
1139: * @param msgnums        the array of message numbers
1140: * @param flag        Flags object containing the flags to be set
1141: * @param value        set the flags to this boolean value
1142: * @exception        IllegalStateException if this folder is not opened
1143: *                        or if it has been opened READ_ONLY.
1144: * @exception        IndexOutOfBoundsException if any message number
1145: *                        in the given array is out of range.
1146: * @exception         MessagingException for other failures
1147: * @see                Message#setFlags
1148: * @see                jakarta.mail.event.MessageChangedEvent
1149: */
1150: public synchronized void setFlags(int[] msgnums,
1151:                         Flags flag, boolean value) throws MessagingException {
1152:•        for (int i = 0; i < msgnums.length; i++) {
1153:          try {
1154:                 Message msg = getMessage(msgnums[i]);
1155:                 msg.setFlags(flag, value);
1156:          } catch (MessageRemovedException me) {
1157:                 // This message is expunged, skip
1158:          }
1159:         }
1160: }
1161:
1162: /**
1163: * Copy the specified Messages from this Folder into another
1164: * Folder. This operation appends these Messages to the
1165: * destination Folder. The destination Folder does not have to
1166: * be opened. An appropriate MessageCountEvent
1167: * is delivered to any MessageCountListener registered on the
1168: * destination folder when the messages arrive in the folder. <p>
1169: *
1170: * Note that the specified Message objects <strong>must</strong>
1171: * belong to this folder. Folder implementations might be able
1172: * to optimize this method by doing server-side copies. <p>
1173: *
1174: * This implementation just invokes <code>appendMessages()</code>
1175: * on the destination folder to append the given Messages. Specific
1176: * folder implementations that support server-side copies should
1177: * do so, if the destination folder's Store is the same as this
1178: * folder's Store.
1179: * Also, an implementation must not abort the operation if a
1180: * Message in the array turns out to be an expunged Message.
1181: *
1182: * @param msgs        the array of message objects
1183: * @param folder        the folder to copy the messages to
1184: * @exception        FolderNotFoundException if the destination
1185: *                        folder does not exist.
1186: * @exception        IllegalStateException if this folder is not opened.
1187: * @exception        MessagingException for other failures
1188: * @see                #appendMessages
1189: */
1190: public void copyMessages(Message[] msgs, Folder folder)
1191:                                 throws MessagingException {
1192:•        if (!folder.exists())
1193:          throw new FolderNotFoundException(
1194:                         folder.getFullName() + " does not exist",
1195:                         folder);
1196:
1197:         folder.appendMessages(msgs);
1198: }
1199:
1200: /**
1201: * Expunge (permanently remove) messages marked DELETED. Returns an
1202: * array containing the expunged message objects. The
1203: * <code>getMessageNumber</code> method
1204: * on each of these message objects returns that Message's original
1205: * (that is, prior to the expunge) sequence number. A MessageCountEvent
1206: * containing the expunged messages is delivered to any
1207: * MessageCountListeners registered on the folder. <p>
1208: *
1209: * Expunge causes the renumbering of Message objects subsequent to
1210: * the expunged messages. Clients that use message numbers as
1211: * references to messages should be aware of this and should be
1212: * prepared to deal with the situation (probably by flushing out
1213: * existing message number caches and reloading them). Because of
1214: * this complexity, it is better for clients to use Message objects
1215: * as references to messages, rather than message numbers. Any
1216: * expunged Messages objects still have to be pruned, but other
1217: * Messages in that folder are not affected by the expunge. <p>
1218: *
1219: * After a message is expunged, only the <code>isExpunged</code> and
1220: * <code>getMessageNumber</code> methods are still valid on the
1221: * corresponding Message object; other methods may throw
1222: * <code>MessageRemovedException</code>
1223: *
1224: * @return                array of expunged Message objects
1225: * @exception        FolderNotFoundException if this folder does not
1226: *                        exist
1227: * @exception        IllegalStateException if this folder is not opened.
1228: * @exception MessagingException for other failures
1229: * @see                Message#isExpunged
1230: * @see                jakarta.mail.event.MessageCountEvent
1231: */
1232: public abstract Message[] expunge() throws MessagingException;
1233:
1234: /**
1235: * Search this Folder for messages matching the specified
1236: * search criterion. Returns an array containing the matching
1237: * messages . Returns an empty array if no matches were found. <p>
1238: *
1239: * This implementation invokes
1240: * <code>search(term, getMessages())</code>, to apply the search
1241: * over all the messages in this folder. Providers that can implement
1242: * server-side searching might want to override this method to provide
1243: * a more efficient implementation.
1244: *
1245: * @param term        the search criterion
1246: * @return                 array of matching messages
1247: * @exception jakarta.mail.search.SearchException if the search
1248: *                        term is too complex for the implementation to handle.
1249: * @exception        FolderNotFoundException if this folder does
1250: *                        not exist.
1251: * @exception        IllegalStateException if this folder is not opened.
1252: * @exception MessagingException for other failures
1253: * @see                jakarta.mail.search.SearchTerm
1254: */
1255: public Message[] search(SearchTerm term) throws MessagingException {
1256:         return search(term, getMessages());
1257: }
1258:
1259: /**
1260: * Search the given array of messages for those that match the
1261: * specified search criterion. Returns an array containing the
1262: * matching messages. Returns an empty array if no matches were
1263: * found. <p>
1264: *
1265: * Note that the specified Message objects <strong>must</strong>
1266: * belong to this folder. <p>
1267: *
1268: * This implementation iterates through the given array of messages,
1269: * and applies the search criterion on each message by calling
1270: * its <code>match()</code> method with the given term. The
1271: * messages that succeed in the match are returned. Providers
1272: * that can implement server-side searching might want to override
1273: * this method to provide a more efficient implementation. If the
1274: * search term is too complex or contains user-defined terms that
1275: * cannot be executed on the server, providers may elect to either
1276: * throw a SearchException or degenerate to client-side searching by
1277: * calling <code>super.search()</code> to invoke this implementation.
1278: *
1279: * @param term        the search criterion
1280: * @param msgs         the messages to be searched
1281: * @return                 array of matching messages
1282: * @exception jakarta.mail.search.SearchException if the search
1283: *                        term is too complex for the implementation to handle.
1284: * @exception        IllegalStateException if this folder is not opened
1285: * @exception MessagingException for other failures
1286: * @see                jakarta.mail.search.SearchTerm
1287: */
1288: public Message[] search(SearchTerm term, Message[] msgs)
1289:                                 throws MessagingException {
1290:         List<Message> matchedMsgs = new ArrayList<>();
1291:
1292:         // Run thru the given messages
1293:•        for (Message msg : msgs) {
1294:          try {
1295:•                if (msg.match(term)) // matched
1296:                  matchedMsgs.add(msg); // add it
1297:          } catch(MessageRemovedException mrex) { }
1298:         }
1299:
1300:         return matchedMsgs.toArray(new Message[matchedMsgs.size()]);
1301: }
1302:
1303: /*
1304: * The set of listeners are stored in Vectors appropriate to their
1305: * type. We mark all listener Vectors as "volatile" because, while
1306: * we initialize them inside this folder's synchronization lock,
1307: * they are accessed (checked for null) in the "notify" methods,
1308: * which can't be synchronized due to lock ordering constraints.
1309: * Since the listener fields (the handles on the Vector objects)
1310: * are only ever set, and are never cleared, we believe this is
1311: * safe. The code that dispatches the notifications will either
1312: * see the null and assume there are no listeners or will see the
1313: * Vector and will process the listeners. There's an inherent race
1314: * between adding a listener and notifying the listeners; the lack
1315: * of synchronization during notification does not make the race
1316: * condition significantly worse. If one thread is setting a
1317: * listener at the "same" time an event is being dispatched, the
1318: * dispatch code might not see the listener right away. The
1319: * dispatch code doesn't have to worry about the Vector handle
1320: * being set to null, and thus using an out-of-date set of
1321: * listeners, because we never set the field to null.
1322: */
1323:
1324: // Vector of connection listeners.
1325: private volatile Vector<ConnectionListener> connectionListeners = null;
1326:
1327: /**
1328: * Add a listener for Connection events on this Folder. <p>
1329: *
1330: * The implementation provided here adds this listener
1331: * to an internal list of ConnectionListeners.
1332: *
1333: * @param l         the Listener for Connection events
1334: * @see                jakarta.mail.event.ConnectionEvent
1335: */
1336: public synchronized void
1337: addConnectionListener(ConnectionListener l) {
1338:•         if (connectionListeners == null)
1339:          connectionListeners = new Vector<>();
1340:         connectionListeners.addElement(l);
1341: }
1342:
1343: /**
1344: * Remove a Connection event listener. <p>
1345: *
1346: * The implementation provided here removes this listener
1347: * from the internal list of ConnectionListeners.
1348: *
1349: * @param l         the listener
1350: * @see                #addConnectionListener
1351: */
1352: public synchronized void
1353: removeConnectionListener(ConnectionListener l) {
1354:•         if (connectionListeners != null)
1355:          connectionListeners.removeElement(l);
1356: }
1357:
1358: /**
1359: * Notify all ConnectionListeners. Folder implementations are
1360: * expected to use this method to broadcast connection events. <p>
1361: *
1362: * The provided implementation queues the event into
1363: * an internal event queue. An event dispatcher thread dequeues
1364: * events from the queue and dispatches them to the registered
1365: * ConnectionListeners. Note that the event dispatching occurs
1366: * in a separate thread, thus avoiding potential deadlock problems.
1367: *
1368: * @param type        the ConnectionEvent type
1369: * @see                jakarta.mail.event.ConnectionEvent
1370: */
1371: protected void notifyConnectionListeners(int type) {
1372:•         if (connectionListeners != null) {
1373:          ConnectionEvent e = new ConnectionEvent(this, type);
1374:          queueEvent(e, connectionListeners);
1375:         }
1376:
1377:         /* Fix for broken JDK1.1.x Garbage collector :
1378:          * The 'conservative' GC in JDK1.1.x occasionally fails to
1379:          * garbage-collect Threads which are in the wait state.
1380:          * This would result in thread (and consequently memory) leaks.
1381:          *
1382:          * We attempt to fix this by sending a 'terminator' event
1383:          * to the queue, after we've sent the CLOSED event. The
1384:          * terminator event causes the event-dispatching thread to
1385:          * self destruct.
1386:          */
1387:•        if (type == ConnectionEvent.CLOSED)
1388:          q.terminateQueue();
1389: }
1390:
1391: // Vector of folder listeners
1392: private volatile Vector<FolderListener> folderListeners = null;
1393:
1394: /**
1395: * Add a listener for Folder events on this Folder. <p>
1396: *
1397: * The implementation provided here adds this listener
1398: * to an internal list of FolderListeners.
1399: *
1400: * @param l         the Listener for Folder events
1401: * @see                jakarta.mail.event.FolderEvent
1402: */
1403: public synchronized void addFolderListener(FolderListener l) {
1404:•         if (folderListeners == null)
1405:          folderListeners = new Vector<>();
1406:         folderListeners.addElement(l);
1407: }
1408:
1409: /**
1410: * Remove a Folder event listener. <p>
1411: *
1412: * The implementation provided here removes this listener
1413: * from the internal list of FolderListeners.
1414: *
1415: * @param l         the listener
1416: * @see                #addFolderListener
1417: */
1418: public synchronized void removeFolderListener(FolderListener l) {
1419:•        if (folderListeners != null)
1420:          folderListeners.removeElement(l);
1421: }
1422:
1423: /**
1424: * Notify all FolderListeners registered on this Folder and
1425: * this folder's Store. Folder implementations are expected
1426: * to use this method to broadcast Folder events. <p>
1427: *
1428: * The implementation provided here queues the event into
1429: * an internal event queue. An event dispatcher thread dequeues
1430: * events from the queue and dispatches them to the
1431: * FolderListeners registered on this folder. The implementation
1432: * also invokes <code>notifyFolderListeners</code> on this folder's
1433: * Store to notify any FolderListeners registered on the store.
1434: *
1435: * @param type        type of FolderEvent
1436: * @see                #notifyFolderRenamedListeners
1437: */
1438: protected void notifyFolderListeners(int type) {
1439:•         if (folderListeners != null) {
1440:          FolderEvent e = new FolderEvent(this, this, type);
1441:          queueEvent(e, folderListeners);
1442:         }
1443:         store.notifyFolderListeners(type, this);
1444: }
1445:
1446: /**
1447: * Notify all FolderListeners registered on this Folder and
1448: * this folder's Store about the renaming of this folder.
1449: * Folder implementations are expected to use this method to
1450: * broadcast Folder events indicating the renaming of folders. <p>
1451: *
1452: * The implementation provided here queues the event into
1453: * an internal event queue. An event dispatcher thread dequeues
1454: * events from the queue and dispatches them to the
1455: * FolderListeners registered on this folder. The implementation
1456: * also invokes <code>notifyFolderRenamedListeners</code> on this
1457: * folder's Store to notify any FolderListeners registered on the store.
1458: *
1459: * @param        folder        Folder representing the new name.
1460: * @see                #notifyFolderListeners
1461: * @since                JavaMail 1.1
1462: */
1463: protected void notifyFolderRenamedListeners(Folder folder) {
1464:•         if (folderListeners != null) {
1465:          FolderEvent e = new FolderEvent(this, this, folder,
1466:                                          FolderEvent.RENAMED);
1467:          queueEvent(e, folderListeners);
1468:         }
1469:         store.notifyFolderRenamedListeners(this, folder);
1470: }
1471:
1472: // Vector of MessageCount listeners
1473: private volatile Vector<MessageCountListener> messageCountListeners = null;
1474:
1475: /**
1476: * Add a listener for MessageCount events on this Folder. <p>
1477: *
1478: * The implementation provided here adds this listener
1479: * to an internal list of MessageCountListeners.
1480: *
1481: * @param l         the Listener for MessageCount events
1482: * @see                jakarta.mail.event.MessageCountEvent
1483: */
1484: public synchronized void addMessageCountListener(MessageCountListener l) {
1485:•         if (messageCountListeners == null)
1486:          messageCountListeners = new Vector<>();
1487:         messageCountListeners.addElement(l);
1488: }
1489:
1490: /**
1491: * Remove a MessageCount listener. <p>
1492: *
1493: * The implementation provided here removes this listener
1494: * from the internal list of MessageCountListeners.
1495: *
1496: * @param l         the listener
1497: * @see                #addMessageCountListener
1498: */
1499: public synchronized void
1500:                         removeMessageCountListener(MessageCountListener l) {
1501:•         if (messageCountListeners != null)
1502:          messageCountListeners.removeElement(l);
1503: }
1504:
1505: /**
1506: * Notify all MessageCountListeners about the addition of messages
1507: * into this folder. Folder implementations are expected to use this
1508: * method to broadcast MessageCount events for indicating arrival of
1509: * new messages. <p>
1510: *
1511: * The provided implementation queues the event into
1512: * an internal event queue. An event dispatcher thread dequeues
1513: * events from the queue and dispatches them to the registered
1514: * MessageCountListeners. Note that the event dispatching occurs
1515: * in a separate thread, thus avoiding potential deadlock problems.
1516: *
1517: * @param        msgs        the messages that were added
1518: */
1519: protected void notifyMessageAddedListeners(Message[] msgs) {
1520:•         if (messageCountListeners == null)
1521:          return;
1522:
1523:         MessageCountEvent e = new MessageCountEvent(
1524:                                         this,
1525:                                         MessageCountEvent.ADDED,
1526:                                         false,
1527:                                         msgs);
1528:
1529:         queueEvent(e, messageCountListeners);
1530: }
1531:
1532: /**
1533: * Notify all MessageCountListeners about the removal of messages
1534: * from this Folder. Folder implementations are expected to use this
1535: * method to broadcast MessageCount events indicating removal of
1536: * messages. <p>
1537: *
1538: * The provided implementation queues the event into
1539: * an internal event queue. An event dispatcher thread dequeues
1540: * events from the queue and dispatches them to the registered
1541: * MessageCountListeners. Note that the event dispatching occurs
1542: * in a separate thread, thus avoiding potential deadlock problems.
1543: *
1544: * @param        removed        was the message removed by this client?
1545: * @param        msgs        the messages that were removed
1546: */
1547: protected void notifyMessageRemovedListeners(boolean removed,
1548:                                                  Message[] msgs) {
1549:•         if (messageCountListeners == null)
1550:          return;
1551:
1552:         MessageCountEvent e = new MessageCountEvent(
1553:                                         this,
1554:                                         MessageCountEvent.REMOVED,
1555:                                         removed,
1556:                                         msgs);
1557:         queueEvent(e, messageCountListeners);
1558: }
1559:
1560: // Vector of MessageChanged listeners.
1561: private volatile Vector<MessageChangedListener> messageChangedListeners
1562:          = null;
1563:
1564: /**
1565: * Add a listener for MessageChanged events on this Folder. <p>
1566: *
1567: * The implementation provided here adds this listener
1568: * to an internal list of MessageChangedListeners.
1569: *
1570: * @param l         the Listener for MessageChanged events
1571: * @see                jakarta.mail.event.MessageChangedEvent
1572: */
1573: public synchronized void
1574:                         addMessageChangedListener(MessageChangedListener l) {
1575:•         if (messageChangedListeners == null)
1576:          messageChangedListeners = new Vector<>();
1577:         messageChangedListeners.addElement(l);
1578: }
1579:
1580: /**
1581: * Remove a MessageChanged listener. <p>
1582: *
1583: * The implementation provided here removes this listener
1584: * from the internal list of MessageChangedListeners.
1585: *
1586: * @param l         the listener
1587: * @see                #addMessageChangedListener
1588: */
1589: public synchronized void
1590:                 removeMessageChangedListener(MessageChangedListener l) {
1591:•         if (messageChangedListeners != null)
1592:          messageChangedListeners.removeElement(l);
1593: }
1594:
1595: /**
1596: * Notify all MessageChangedListeners. Folder implementations are
1597: * expected to use this method to broadcast MessageChanged events. <p>
1598: *
1599: * The provided implementation queues the event into
1600: * an internal event queue. An event dispatcher thread dequeues
1601: * events from the queue and dispatches them to registered
1602: * MessageChangedListeners. Note that the event dispatching occurs
1603: * in a separate thread, thus avoiding potential deadlock problems.
1604: *
1605: * @param        type        the MessageChangedEvent type
1606: * @param        msg        the message that changed
1607: */
1608: protected void notifyMessageChangedListeners(int type, Message msg) {
1609:•        if (messageChangedListeners == null)
1610:          return;
1611:         
1612:         MessageChangedEvent e = new MessageChangedEvent(this, type, msg);
1613:         queueEvent(e, messageChangedListeners);
1614: }
1615:
1616: /*
1617: * Add the event and vector of listeners to the queue to be delivered.
1618: */
1619: @SuppressWarnings("unchecked")
1620: private void queueEvent(MailEvent event,
1621:          Vector<? extends EventListener> vector) {
1622:         /*
1623: * Copy the vector in order to freeze the state of the set
1624: * of EventListeners the event should be delivered to prior
1625: * to delivery. This ensures that any changes made to the
1626: * Vector from a target listener's method during the delivery
1627: * of this event will not take effect until after the event is
1628: * delivered.
1629: */
1630:         Vector<? extends EventListener> v = (Vector)vector.clone();
1631:         q.enqueue(event, v);
1632: }
1633:
1634: @Override
1635: protected void finalize() throws Throwable {
1636:         try {
1637:          q.terminateQueue();
1638:         } finally {
1639:          super.finalize();
1640:         }
1641: }
1642:
1643: /**
1644: * override the default toString(), it will return the String
1645: * from Folder.getFullName() or if that is null, it will use
1646: * the default toString() behavior.
1647: */
1648:
1649: @Override
1650: public String toString() {
1651:         String s = getFullName();
1652:•        if (s != null)
1653:          return s;
1654:         else
1655:          return super.toString();
1656: }
1657: }