|
|||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| Folder.java | 0% | 12.9% | 7.7% | 9.2% |
|
||||||||||||||
| 1 | /** | |
| 2 | * | |
| 3 | * Copyright 2003-2006 The Apache Software Foundation | |
| 4 | * | |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
| 6 | * you may not use this file except in compliance with the License. | |
| 7 | * You may obtain a copy of the License at | |
| 8 | * | |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | * | |
| 11 | * Unless required by applicable law or agreed to in writing, software | |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | * See the License for the specific language governing permissions and | |
| 15 | * limitations under the License. | |
| 16 | */ | |
| 17 | ||
| 18 | package javax.mail; | |
| 19 | ||
| 20 | import java.util.ArrayList; | |
| 21 | import java.util.List; | |
| 22 | import javax.mail.Flags.Flag; | |
| 23 | import javax.mail.event.ConnectionEvent; | |
| 24 | import javax.mail.event.ConnectionListener; | |
| 25 | import javax.mail.event.FolderEvent; | |
| 26 | import javax.mail.event.FolderListener; | |
| 27 | import javax.mail.event.MessageChangedEvent; | |
| 28 | import javax.mail.event.MessageChangedListener; | |
| 29 | import javax.mail.event.MessageCountEvent; | |
| 30 | import javax.mail.event.MessageCountListener; | |
| 31 | import javax.mail.search.SearchTerm; | |
| 32 | ||
| 33 | /** | |
| 34 | * An abstract representation of a folder in a mail system; subclasses would | |
| 35 | * implement Folders for each supported protocol. | |
| 36 | * <p/> | |
| 37 | * Depending on protocol and implementation, folders may contain other folders, messages, | |
| 38 | * or both as indicated by the {@link Folder#HOLDS_FOLDERS} and {@link Folder#HOLDS_MESSAGES} flags. | |
| 39 | * If the immplementation supports hierarchical folders, the format of folder names is | |
| 40 | * implementation dependent; however, components of the name are separated by the | |
| 41 | * delimiter character returned by {@link Folder#getSeparator()}. | |
| 42 | * <p/> | |
| 43 | * The case-insensitive folder name "INBOX" is reserved to refer to the primary folder | |
| 44 | * for the current user on the current server; not all stores will provide an INBOX | |
| 45 | * and it may not be available at all times. | |
| 46 | * | |
| 47 | * @version $Rev: 421852 $ $Date: 2006-07-14 03:02:19 -0700 (Fri, 14 Jul 2006) $ | |
| 48 | */ | |
| 49 | public abstract class Folder { | |
| 50 | /** | |
| 51 | * Flag that indicates that a folder can contain messages. | |
| 52 | */ | |
| 53 | public static final int HOLDS_MESSAGES = 1; | |
| 54 | /** | |
| 55 | * Flag that indicates that a folder can contain other folders. | |
| 56 | */ | |
| 57 | public static final int HOLDS_FOLDERS = 2; | |
| 58 | ||
| 59 | /** | |
| 60 | * Flag indicating that this folder cannot be modified. | |
| 61 | */ | |
| 62 | public static final int READ_ONLY = 1; | |
| 63 | /** | |
| 64 | * Flag indictaing that this folder can be modified. | |
| 65 | * Question: what does it mean if both are set? | |
| 66 | */ | |
| 67 | public static final int READ_WRITE = 2; | |
| 68 | ||
| 69 | /** | |
| 70 | * The store that this folder is part of. | |
| 71 | */ | |
| 72 | protected Store store; | |
| 73 | /** | |
| 74 | * The current mode of this folder. | |
| 75 | * When open, this can be {@link #READ_ONLY} or {@link #READ_WRITE}; | |
| 76 | * otherwise is set to -1. | |
| 77 | */ | |
| 78 | protected int mode = -1; | |
| 79 | ||
| 80 | private final List connectionListeners = new ArrayList(2); | |
| 81 | private final List folderListeners = new ArrayList(2); | |
| 82 | private final List messageChangedListeners = new ArrayList(2); | |
| 83 | private final List messageCountListeners = new ArrayList(2); | |
| 84 | private final EventQueue queue = new EventQueue(); | |
| 85 | ||
| 86 | /** | |
| 87 | * Constructor that initializes the Store. | |
| 88 | * | |
| 89 | * @param store the store that this folder is part of | |
| 90 | */ | |
| 91 | 9 | protected Folder(Store store) { |
| 92 | 9 | this.store = store; |
| 93 | } | |
| 94 | ||
| 95 | /** | |
| 96 | * Return the name of this folder. | |
| 97 | * This can be invoked when the folder is closed. | |
| 98 | * | |
| 99 | * @return this folder's name | |
| 100 | */ | |
| 101 | public abstract String getName(); | |
| 102 | ||
| 103 | /** | |
| 104 | * Return the full absolute name of this folder. | |
| 105 | * This can be invoked when the folder is closed. | |
| 106 | * | |
| 107 | * @return the full name of this folder | |
| 108 | */ | |
| 109 | public abstract String getFullName(); | |
| 110 | ||
| 111 | /** | |
| 112 | * Return the URLName for this folder, which includes the location of the store. | |
| 113 | * | |
| 114 | * @return the URLName for this folder | |
| 115 | * @throws MessagingException | |
| 116 | */ | |
| 117 | 0 | public URLName getURLName() throws MessagingException { |
| 118 | // todo shouldn't this include the full name of the folder? | |
| 119 | 0 | return store.getURLName(); |
| 120 | } | |
| 121 | ||
| 122 | /** | |
| 123 | * Return the store that this folder is part of. | |
| 124 | * | |
| 125 | * @return the store this folder is part of | |
| 126 | */ | |
| 127 | 3 | public Store getStore() { |
| 128 | 3 | return store; |
| 129 | } | |
| 130 | ||
| 131 | /** | |
| 132 | * Return the parent for this folder; if the folder is at the root of a heirarchy | |
| 133 | * this returns null. | |
| 134 | * This can be invoked when the folder is closed. | |
| 135 | * | |
| 136 | * @return this folder's parent | |
| 137 | * @throws MessagingException | |
| 138 | */ | |
| 139 | public abstract Folder getParent() throws MessagingException; | |
| 140 | ||
| 141 | /** | |
| 142 | * Check to see if this folder physically exists in the store. | |
| 143 | * This can be invoked when the folder is closed. | |
| 144 | * | |
| 145 | * @return true if the folder really exists | |
| 146 | * @throws MessagingException if there was a problem accessing the store | |
| 147 | */ | |
| 148 | public abstract boolean exists() throws MessagingException; | |
| 149 | ||
| 150 | /** | |
| 151 | * Return a list of folders from this Folder's namespace that match the supplied pattern. | |
| 152 | * Patterns may contain the following wildcards: | |
| 153 | * <ul><li>'%' which matches any characater except hierarchy delimiters</li> | |
| 154 | * <li>'*' which matches any character including hierarchy delimiters</li> | |
| 155 | * </ul> | |
| 156 | * This can be invoked when the folder is closed. | |
| 157 | * | |
| 158 | * @param pattern the pattern to search for | |
| 159 | * @return a, possibly empty, array containing Folders that matched the pattern | |
| 160 | * @throws MessagingException if there was a problem accessing the store | |
| 161 | */ | |
| 162 | public abstract Folder[] list(String pattern) throws MessagingException; | |
| 163 | ||
| 164 | /** | |
| 165 | * Return a list of folders to which the user is subscribed and which match the supplied pattern. | |
| 166 | * If the store does not support the concept of subscription then this should match against | |
| 167 | * all folders; the default implementation of this method achieves this by defaulting to the | |
| 168 | * {@link #list(String)} method. | |
| 169 | * | |
| 170 | * @param pattern the pattern to search for | |
| 171 | * @return a, possibly empty, array containing subscribed Folders that matched the pattern | |
| 172 | * @throws MessagingException if there was a problem accessing the store | |
| 173 | */ | |
| 174 | 0 | public Folder[] listSubscribed(String pattern) throws MessagingException { |
| 175 | 0 | return list(pattern); |
| 176 | } | |
| 177 | ||
| 178 | /** | |
| 179 | * Convenience method that invokes {@link #list(String)} with the pattern "%". | |
| 180 | * | |
| 181 | * @return a, possibly empty, array of subfolders | |
| 182 | * @throws MessagingException if there was a problem accessing the store | |
| 183 | */ | |
| 184 | 0 | public Folder[] list() throws MessagingException { |
| 185 | 0 | return list("%"); |
| 186 | } | |
| 187 | ||
| 188 | /** | |
| 189 | * Convenience method that invokes {@link #listSubscribed(String)} with the pattern "%". | |
| 190 | * | |
| 191 | * @return a, possibly empty, array of subscribed subfolders | |
| 192 | * @throws MessagingException if there was a problem accessing the store | |
| 193 | */ | |
| 194 | 0 | public Folder[] listSubscribed() throws MessagingException { |
| 195 | 0 | return listSubscribed("%"); |
| 196 | } | |
| 197 | ||
| 198 | /** | |
| 199 | * Return the character used by this folder's Store to separate path components. | |
| 200 | * | |
| 201 | * @return the name separater character | |
| 202 | * @throws MessagingException if there was a problem accessing the store | |
| 203 | */ | |
| 204 | public abstract char getSeparator() throws MessagingException; | |
| 205 | ||
| 206 | /** | |
| 207 | * Return the type of this folder, indicating whether it can contain subfolders, | |
| 208 | * messages, or both. The value returned is a bitmask with the appropriate bits set. | |
| 209 | * | |
| 210 | * @return the type of this folder | |
| 211 | * @throws MessagingException if there was a problem accessing the store | |
| 212 | * @see #HOLDS_FOLDERS | |
| 213 | * @see #HOLDS_MESSAGES | |
| 214 | */ | |
| 215 | public abstract int getType() throws MessagingException; | |
| 216 | ||
| 217 | /** | |
| 218 | * Create a new folder capable of containing subfoldera and/or messages as | |
| 219 | * determined by the type parameter. Any hierarchy defined by the folder | |
| 220 | * name will be recursively created. | |
| 221 | * If the folder was sucessfully created, a {@link FolderEvent#CREATED CREATED FolderEvent} | |
| 222 | * is sent to all FolderListeners registered with this Folder or with the Store. | |
| 223 | * | |
| 224 | * @param type the type, indicating if this folder should contain subfolders, messages or both | |
| 225 | * @return true if the folder was sucessfully created | |
| 226 | * @throws MessagingException if there was a problem accessing the store | |
| 227 | */ | |
| 228 | public abstract boolean create(int type) throws MessagingException; | |
| 229 | ||
| 230 | /** | |
| 231 | * Determine if the user is subscribed to this Folder. The default implementation in | |
| 232 | * this class always returns true. | |
| 233 | * | |
| 234 | * @return true is the user is subscribed to this Folder | |
| 235 | */ | |
| 236 | 0 | public boolean isSubscribed() { |
| 237 | 0 | return true; |
| 238 | } | |
| 239 | ||
| 240 | /** | |
| 241 | * Set the user's subscription to this folder. | |
| 242 | * Not all Stores support subscription; the default implementation in this class | |
| 243 | * always throws a MethodNotSupportedException | |
| 244 | * | |
| 245 | * @param subscribed whether to subscribe to this Folder | |
| 246 | * @throws MessagingException if there was a problem accessing the store | |
| 247 | * @throws MethodNotSupportedException if the Store does not support subscription | |
| 248 | */ | |
| 249 | 0 | public void setSubscribed(boolean subscribed) throws MessagingException { |
| 250 | 0 | throw new MethodNotSupportedException(); |
| 251 | } | |
| 252 | ||
| 253 | /** | |
| 254 | * Check to see if this Folder conatins messages with the {@link Flag.RECENT} flag set. | |
| 255 | * This can be used when the folder is closed to perform a light-weight check for new mail; | |
| 256 | * to perform an incremental check for new mail the folder must be opened. | |
| 257 | * | |
| 258 | * @return true if the Store has recent messages | |
| 259 | * @throws MessagingException if there was a problem accessing the store | |
| 260 | */ | |
| 261 | public abstract boolean hasNewMessages() throws MessagingException; | |
| 262 | ||
| 263 | /** | |
| 264 | * Get the Folder determined by the supplied name; if the name is relative | |
| 265 | * then it is interpreted relative to this folder. This does not check that | |
| 266 | * the named folder actually exists. | |
| 267 | * | |
| 268 | * @param name the name of the folder to return | |
| 269 | * @return the named folder | |
| 270 | * @throws MessagingException if there was a problem accessing the store | |
| 271 | */ | |
| 272 | public abstract Folder getFolder(String name) throws MessagingException; | |
| 273 | ||
| 274 | /** | |
| 275 | * Delete this folder and possibly any subfolders. This operation can only be | |
| 276 | * performed on a closed folder. | |
| 277 | * If recurse is true, then all subfolders are deleted first, then any messages in | |
| 278 | * this folder are removed and it is finally deleted; {@link FolderEvent#DELETED} | |
| 279 | * events are sent as appropriate. | |
| 280 | * If recurse is false, then the behaviour depends on the folder type and store | |
| 281 | * implementation as followd: | |
| 282 | * <ul> | |
| 283 | * <li>If the folder can only conrain messages, then all messages are removed and | |
| 284 | * then the folder is deleted; a {@link FolderEvent#DELETED} event is sent.</li> | |
| 285 | * <li>If the folder can onlu contain subfolders, then if it is empty it will be | |
| 286 | * deleted and a {@link FolderEvent#DELETED} event is sent; if the folder is not | |
| 287 | * empty then the delete fails and this method returns false.</li> | |
| 288 | * <li>If the folder can contain both subfolders and messages, then if the folder | |
| 289 | * does not contain any subfolders, any messages are deleted, the folder itself | |
| 290 | * is deleted and a {@link FolderEvent#DELETED} event is sent; if the folder does | |
| 291 | * contain subfolders then the implementation may choose from the following three | |
| 292 | * behaviors: | |
| 293 | * <ol> | |
| 294 | * <li>it may return false indicting the operation failed</li> | |
| 295 | * <li>it may remove all messages within the folder, send a {@link FolderEvent#DELETED} | |
| 296 | * event, and then return true to indicate the delete was performed. Note this does | |
| 297 | * not delete the folder itself and the {@link #exists()} operation for this folder | |
| 298 | * will return true</li> | |
| 299 | * <li>it may remove all messages within the folder as per the previous option; in | |
| 300 | * addition it may change the type of the Folder to only HOLDS_FOLDERS indictaing | |
| 301 | * that messages may no longer be added</li> | |
| 302 | * </li> | |
| 303 | * </ul> | |
| 304 | * FolderEvents are sent to all listeners registered with this folder or | |
| 305 | * with the Store. | |
| 306 | * | |
| 307 | * @param recurse whether subfolders should be recursively deleted as well | |
| 308 | * @return true if the delete operation succeeds | |
| 309 | * @throws MessagingException if there was a problem accessing the store | |
| 310 | */ | |
| 311 | public abstract boolean delete(boolean recurse) throws MessagingException; | |
| 312 | ||
| 313 | /** | |
| 314 | * Rename this folder; the folder must be closed. | |
| 315 | * If the rename is successfull, a {@link FolderEvent#RENAMED} event is sent to | |
| 316 | * all listeners registered with this folder or with the store. | |
| 317 | * | |
| 318 | * @param newName the new name for this folder | |
| 319 | * @return true if the rename succeeded | |
| 320 | * @throws MessagingException if there was a problem accessing the store | |
| 321 | */ | |
| 322 | public abstract boolean renameTo(Folder newName) throws MessagingException; | |
| 323 | ||
| 324 | /** | |
| 325 | * Open this folder; the folder must be able to contain messages and | |
| 326 | * must currently be closed. If the folder is opened successfully then | |
| 327 | * a {@link ConnectionEvent#OPENED} event is sent to listeners registered | |
| 328 | * with this Folder. | |
| 329 | * <p/> | |
| 330 | * Whether the Store allows multiple connections or if it allows multiple | |
| 331 | * writers is implementation defined. | |
| 332 | * | |
| 333 | * @param mode READ_ONLY or READ_WRITE | |
| 334 | * @throws MessagingException if there was a problem accessing the store | |
| 335 | */ | |
| 336 | public abstract void open(int mode) throws MessagingException; | |
| 337 | ||
| 338 | /** | |
| 339 | * Close this folder; it must already be open. | |
| 340 | * A {@link ConnectionEvent#CLOSED} event is sent to all listeners registered | |
| 341 | * with this folder. | |
| 342 | * | |
| 343 | * @param expunge whether to expunge all deleted messages | |
| 344 | * @throws MessagingException if there was a problem accessing the store; the folder is still closed | |
| 345 | */ | |
| 346 | public abstract void close(boolean expunge) throws MessagingException; | |
| 347 | ||
| 348 | /** | |
| 349 | * Indicates that the folder has been opened. | |
| 350 | * | |
| 351 | * @return true if the folder is open | |
| 352 | */ | |
| 353 | public abstract boolean isOpen(); | |
| 354 | ||
| 355 | /** | |
| 356 | * Return the mode of this folder ass passed to {@link #open(int)}, or -1 if | |
| 357 | * the folder is closed. | |
| 358 | * | |
| 359 | * @return the mode this folder was opened with | |
| 360 | */ | |
| 361 | 0 | public int getMode() { |
| 362 | 0 | return mode; |
| 363 | } | |
| 364 | ||
| 365 | /** | |
| 366 | * Get the flags supported by this folder. | |
| 367 | * | |
| 368 | * @return the flags supported by this folder, or null if unknown | |
| 369 | * @see Flags | |
| 370 | */ | |
| 371 | public abstract Flags getPermanentFlags(); | |
| 372 | ||
| 373 | /** | |
| 374 | * Return the number of messages this folder contains. | |
| 375 | * If this operation is invoked on a closed folder, the implementation | |
| 376 | * may choose to return -1 to avoid the expense of opening the folder. | |
| 377 | * | |
| 378 | * @return the number of messages, or -1 if unknown | |
| 379 | * @throws MessagingException if there was a problem accessing the store | |
| 380 | */ | |
| 381 | public abstract int getMessageCount() throws MessagingException; | |
| 382 | ||
| 383 | /** | |
| 384 | * Return the numbew of messages in this folder that have the {@link Flag.RECENT} flag set. | |
| 385 | * If this operation is invoked on a closed folder, the implementation | |
| 386 | * may choose to return -1 to avoid the expense of opening the folder. | |
| 387 | * The default implmentation of this method iterates over all messages | |
| 388 | * in the folder; subclasses should override if possible to provide a more | |
| 389 | * efficient implementation. | |
| 390 | * | |
| 391 | * @return the number of new messages, or -1 if unknown | |
| 392 | * @throws MessagingException if there was a problem accessing the store | |
| 393 | */ | |
| 394 | 0 | public int getNewMessageCount() throws MessagingException { |
| 395 | 0 | return getCount(Flags.Flag.RECENT, true); |
| 396 | } | |
| 397 | ||
| 398 | /** | |
| 399 | * Return the numbew of messages in this folder that do not have the {@link Flag.SEEN} flag set. | |
| 400 | * If this operation is invoked on a closed folder, the implementation | |
| 401 | * may choose to return -1 to avoid the expense of opening the folder. | |
| 402 | * The default implmentation of this method iterates over all messages | |
| 403 | * in the folder; subclasses should override if possible to provide a more | |
| 404 | * efficient implementation. | |
| 405 | * | |
| 406 | * @return the number of new messages, or -1 if unknown | |
| 407 | * @throws MessagingException if there was a problem accessing the store | |
| 408 | */ | |
| 409 | 0 | public int getUnreadMessageCount() throws MessagingException { |
| 410 | 0 | return getCount(Flags.Flag.SEEN, false); |
| 411 | } | |
| 412 | ||
| 413 | /** | |
| 414 | * Return the numbew of messages in this folder that have the {@link Flag.DELETED} flag set. | |
| 415 | * If this operation is invoked on a closed folder, the implementation | |
| 416 | * may choose to return -1 to avoid the expense of opening the folder. | |
| 417 | * The default implmentation of this method iterates over all messages | |
| 418 | * in the folder; subclasses should override if possible to provide a more | |
| 419 | * efficient implementation. | |
| 420 | * | |
| 421 | * @return the number of new messages, or -1 if unknown | |
| 422 | * @throws MessagingException if there was a problem accessing the store | |
| 423 | */ | |
| 424 | 0 | public int getDeletedMessageCount() throws MessagingException { |
| 425 | 0 | return getCount(Flags.Flag.DELETED, true); |
| 426 | } | |
| 427 | ||
| 428 | 0 | private int getCount(Flag flag, boolean value) throws MessagingException { |
| 429 | 0 | if (!isOpen()) { |
| 430 | 0 | return -1; |
| 431 | } | |
| 432 | 0 | Message[] messages = getMessages(); |
| 433 | 0 | int total = 0; |
| 434 | 0 | for (int i = 0; i < messages.length; i++) { |
| 435 | 0 | if (messages[i].getFlags().contains(flag) == value) { |
| 436 | 0 | total++; |
| 437 | } | |
| 438 | } | |
| 439 | 0 | return total; |
| 440 | } | |
| 441 | ||
| 442 | /** | |
| 443 | * Retrieve the message with the specified index in this Folder; | |
| 444 | * messages indices start at 1 not zero. | |
| 445 | * Clients should note that the index for a specific message may change | |
| 446 | * if the folder is expunged; {@link Message} objects should be used as | |
| 447 | * references instead. | |
| 448 | * | |
| 449 | * @param index the index of the message to fetch | |
| 450 | * @return the message | |
| 451 | * @throws MessagingException if there was a problem accessing the store | |
| 452 | */ | |
| 453 | public abstract Message getMessage(int index) throws MessagingException; | |
| 454 | ||
| 455 | /** | |
| 456 | * Retrieve messages with index between start and end inclusive | |
| 457 | * | |
| 458 | * @param start index of first message | |
| 459 | * @param end index of last message | |
| 460 | * @return an array of messages from start to end inclusive | |
| 461 | * @throws MessagingException if there was a problem accessing the store | |
| 462 | */ | |
| 463 | 0 | public Message[] getMessages(int start, int end) throws MessagingException { |
| 464 | 0 | Message[] result = new Message[end - start + 1]; |
| 465 | 0 | for (int i = 0; i < result.length; i++) { |
| 466 | 0 | result[i] = getMessage(start++); |
| 467 | } | |
| 468 | 0 | return result; |
| 469 | } | |
| 470 | ||
| 471 | /** | |
| 472 | * Retrieve messages with the specified indices. | |
| 473 | * | |
| 474 | * @param ids the indices of the messages to fetch | |
| 475 | * @return the specified messages | |
| 476 | * @throws MessagingException if there was a problem accessing the store | |
| 477 | */ | |
| 478 | 0 | public Message[] getMessages(int ids[]) throws MessagingException { |
| 479 | 0 | Message[] result = new Message[ids.length]; |
| 480 | 0 | for (int i = 0; i < ids.length; i++) { |
| 481 | 0 | result[i] = getMessage(ids[i]); |
| 482 | } | |
| 483 | 0 | return result; |
| 484 | } | |
| 485 | ||
| 486 | /** | |
| 487 | * Retrieve all messages. | |
| 488 | * | |
| 489 | * @return all messages in this folder | |
| 490 | * @throws MessagingException if there was a problem accessing the store | |
| 491 | */ | |
| 492 | 0 | public Message[] getMessages() throws MessagingException { |
| 493 | 0 | return getMessages(1, getMessageCount()); |
| 494 | } | |
| 495 | ||
| 496 | /** | |
| 497 | * Append the supplied messages to this folder. A {@link MessageCountEvent} is sent | |
| 498 | * to all listeners registered with this folder when all messages have been appended. | |
| 499 | * If the array contains a previously expunged message, it must be re-appended to the Store | |
| 500 | * and implementations must not abort this operation. | |
| 501 | * | |
| 502 | * @param messages the messages to append | |
| 503 | * @throws MessagingException if there was a problem accessing the store | |
| 504 | */ | |
| 505 | public abstract void appendMessages(Message[] messages) throws MessagingException; | |
| 506 | ||
| 507 | /** | |
| 508 | * Hint to the store to prefetch information on the supplied messaged. | |
| 509 | * Subclasses should override this method to provide an efficient implementation; | |
| 510 | * the default implementation in this class simply returns. | |
| 511 | * | |
| 512 | * @param messages messages for which information should be fetched | |
| 513 | * @param profile the information to fetch | |
| 514 | * @throws MessagingException if there was a problem accessing the store | |
| 515 | * @see FetchProfile | |
| 516 | */ | |
| 517 | 0 | public void fetch(Message[] messages, FetchProfile profile) throws MessagingException { |
| 518 | 0 | return; |
| 519 | } | |
| 520 | ||
| 521 | /** | |
| 522 | * Set flags on the messages to the supplied value; all messages must belong to this folder. | |
| 523 | * This method may be overridden by subclasses that can optimize the setting | |
| 524 | * of flags on multiple messages at once; the default implementation simply calls | |
| 525 | * {@link Message#setFlags(Flags, boolean)} for each supplied messages. | |
| 526 | * | |
| 527 | * @param messages whose flags should be set | |
| 528 | * @param flags the set of flags to modify | |
| 529 | * @param value the value the flags should be set to | |
| 530 | * @throws MessagingException if there was a problem accessing the store | |
| 531 | */ | |
| 532 | 0 | public void setFlags(Message[] messages, Flags flags, boolean value) throws MessagingException { |
| 533 | 0 | for (int i = 0; i < messages.length; i++) { |
| 534 | 0 | Message message = messages[i]; |
| 535 | 0 | message.setFlags(flags, value); |
| 536 | } | |
| 537 | } | |
| 538 | ||
| 539 | /** | |
| 540 | * Set flags on a range of messages to the supplied value. | |
| 541 | * This method may be overridden by subclasses that can optimize the setting | |
| 542 | * of flags on multiple messages at once; the default implementation simply | |
| 543 | * gets each message and then calls {@link Message#setFlags(Flags, boolean)}. | |
| 544 | * | |
| 545 | * @param start first message end set | |
| 546 | * @param end last message end set | |
| 547 | * @param flags the set of flags end modify | |
| 548 | * @param value the value the flags should be set end | |
| 549 | * @throws MessagingException if there was a problem accessing the store | |
| 550 | */ | |
| 551 | 0 | public void setFlags(int start, int end, Flags flags, boolean value) throws MessagingException { |
| 552 | 0 | for (int i = start; i <= end; i++) { |
| 553 | 0 | Message message = getMessage(i); |
| 554 | 0 | message.setFlags(flags, value); |
| 555 | } | |
| 556 | } | |
| 557 | ||
| 558 | /** | |
| 559 | * Set flags on a set of messages to the supplied value. | |
| 560 | * This method may be overridden by subclasses that can optimize the setting | |
| 561 | * of flags on multiple messages at once; the default implementation simply | |
| 562 | * gets each message and then calls {@link Message#setFlags(Flags, boolean)}. | |
| 563 | * | |
| 564 | * @param ids the indexes of the messages to set | |
| 565 | * @param flags the set of flags end modify | |
| 566 | * @param value the value the flags should be set end | |
| 567 | * @throws MessagingException if there was a problem accessing the store | |
| 568 | */ | |
| 569 | 0 | public void setFlags(int ids[], Flags flags, boolean value) throws MessagingException { |
| 570 | 0 | for (int i = 0; i < ids.length; i++) { |
| 571 | 0 | Message message = getMessage(ids[i]); |
| 572 | 0 | message.setFlags(flags, value); |
| 573 | } | |
| 574 | } | |
| 575 | ||
| 576 | /** | |
| 577 | * Copy the specified messages to another folder. | |
| 578 | * The default implementation simply appends the supplied messages to the | |
| 579 | * target folder using {@link #appendMessages(Message[])}. | |
| 580 | * @param messages the messages to copy | |
| 581 | * @param folder the folder to copy to | |
| 582 | * @throws MessagingException if there was a problem accessing the store | |
| 583 | */ | |
| 584 | 0 | public void copyMessages(Message[] messages, Folder folder) throws MessagingException { |
| 585 | 0 | folder.appendMessages(messages); |
| 586 | } | |
| 587 | ||
| 588 | /** | |
| 589 | * Permanently delete all supplied messages that have the DELETED flag set from the Store. | |
| 590 | * The original message indices of all messages actually deleted are returned and a | |
| 591 | * {@link MessageCountEvent} event is sent to all listeners with this folder. The expunge | |
| 592 | * may cause the indices of all messaged that remain in the folder to change. | |
| 593 | * | |
| 594 | * @return the original indices of messages that were actually deleted | |
| 595 | * @throws MessagingException if there was a problem accessing the store | |
| 596 | */ | |
| 597 | public abstract Message[] expunge() throws MessagingException; | |
| 598 | ||
| 599 | /** | |
| 600 | * Search this folder for messages matching the supplied search criteria. | |
| 601 | * The default implementation simply invoke <code>search(term, getMessages()) | |
| 602 | * applying the search over all messages in the folder; subclasses may provide | |
| 603 | * a more efficient mechanism. | |
| 604 | * | |
| 605 | * @param term the search criteria | |
| 606 | * @return an array containing messages that match the criteria | |
| 607 | * @throws MessagingException if there was a problem accessing the store | |
| 608 | */ | |
| 609 | 0 | public Message[] search(SearchTerm term) throws MessagingException { |
| 610 | 0 | return search(term, getMessages()); |
| 611 | } | |
| 612 | ||
| 613 | /** | |
| 614 | * Search the supplied messages for those that match the supplied criteria; | |
| 615 | * messages must belong to this folder. | |
| 616 | * The default implementation iterates through the messages, returning those | |
| 617 | * whose {@link Message#match(javax.mail.search.SearchTerm)} method returns true; | |
| 618 | * subclasses may provide a more efficient implementation. | |
| 619 | * | |
| 620 | * @param term the search criteria | |
| 621 | * @param messages the messages to search | |
| 622 | * @return an array containing messages that match the criteria | |
| 623 | * @throws MessagingException if there was a problem accessing the store | |
| 624 | */ | |
| 625 | 0 | public Message[] search(SearchTerm term, Message[] messages) throws MessagingException { |
| 626 | 0 | List result = new ArrayList(messages.length); |
| 627 | 0 | for (int i = 0; i < messages.length; i++) { |
| 628 | 0 | Message message = messages[i]; |
| 629 | 0 | if (message.match(term)) { |
| 630 | 0 | result.add(message); |
| 631 | } | |
| 632 | } | |
| 633 | 0 | return (Message[]) result.toArray(new Message[result.size()]); |
| 634 | } | |
| 635 | ||
| 636 | 0 | public void addConnectionListener(ConnectionListener listener) { |
| 637 | 0 | connectionListeners.add(listener); |
| 638 | } | |
| 639 | ||
| 640 | 0 | public void removeConnectionListener(ConnectionListener listener) { |
| 641 | 0 | connectionListeners.remove(listener); |
| 642 | } | |
| 643 | ||
| 644 | 0 | protected void notifyConnectionListeners(int type) { |
| 645 | 0 | queue.queueEvent(new ConnectionEvent(this, type), connectionListeners); |
| 646 | } | |
| 647 | ||
| 648 | 0 | public void addFolderListener(FolderListener listener) { |
| 649 | 0 | folderListeners.add(listener); |
| 650 | } | |
| 651 | ||
| 652 | 0 | public void removeFolderListener(FolderListener listener) { |
| 653 | 0 | folderListeners.remove(listener); |
| 654 | } | |
| 655 | ||
| 656 | 0 | protected void notifyFolderListeners(int type) { |
| 657 | 0 | queue.queueEvent(new FolderEvent(this, this, type), folderListeners); |
| 658 | } | |
| 659 | ||
| 660 | 0 | protected void notifyFolderRenamedListeners(Folder newFolder) { |
| 661 | 0 | queue.queueEvent(new FolderEvent(this, this, newFolder, FolderEvent.RENAMED), folderListeners); |
| 662 | } | |
| 663 | ||
| 664 | 0 | public void addMessageCountListener(MessageCountListener listener) { |
| 665 | 0 | messageCountListeners.add(listener); |
| 666 | } | |
| 667 | ||
| 668 | 0 | public void removeMessageCountListener(MessageCountListener listener) { |
| 669 | 0 | messageCountListeners.remove(listener); |
| 670 | } | |
| 671 | ||
| 672 | 0 | protected void notifyMessageAddedListeners(Message[] messages) { |
| 673 | 0 | queue.queueEvent(new MessageCountEvent(this, MessageCountEvent.ADDED, false, messages), messageChangedListeners); |
| 674 | } | |
| 675 | ||
| 676 | 0 | protected void notifyMessageRemovedListeners(boolean removed, Message[] messages) { |
| 677 | 0 | queue.queueEvent(new MessageCountEvent(this, MessageCountEvent.REMOVED, removed, messages), messageChangedListeners); |
| 678 | } | |
| 679 | ||
| 680 | 0 | public void addMessageChangedListener(MessageChangedListener listener) { |
| 681 | 0 | messageChangedListeners.add(listener); |
| 682 | } | |
| 683 | ||
| 684 | 0 | public void removeMessageChangedListener(MessageChangedListener listener) { |
| 685 | 0 | messageChangedListeners.remove(listener); |
| 686 | } | |
| 687 | ||
| 688 | 0 | protected void notifyMessageChangedListeners(int type, Message message) { |
| 689 | 0 | queue.queueEvent(new MessageChangedEvent(this, type, message), messageChangedListeners); |
| 690 | } | |
| 691 | ||
| 692 | /** | |
| 693 | * Unregisters all listeners. | |
| 694 | */ | |
| 695 | 8 | protected void finalize() throws Throwable { |
| 696 | 8 | queue.stop(); |
| 697 | 8 | connectionListeners.clear(); |
| 698 | 8 | folderListeners.clear(); |
| 699 | 8 | messageChangedListeners.clear(); |
| 700 | 8 | messageCountListeners.clear(); |
| 701 | 8 | store = null; |
| 702 | 8 | super.finalize(); |
| 703 | } | |
| 704 | ||
| 705 | /** | |
| 706 | * Returns the full name of this folder; if null, returns the value from the superclass. | |
| 707 | * @return a string form of this folder | |
| 708 | */ | |
| 709 | 0 | public String toString() { |
| 710 | 0 | String name = getFullName(); |
| 711 | 0 | return name == null ? super.toString() : name; |
| 712 | } | |
| 713 | } |
|
||||||||||