📄 imapfolder.java
字号:
* Get the named subfolder. <p> */ public Folder getFolder(String name) throws MessagingException { // If we know that this folder is *not* a directory, don't // send the request to the server at all ... if (attributes != null && !isDirectory()) throw new MessagingException("Cannot contain subfolders"); char c = getSeparator(); return new IMAPFolder(fullName + c + name, c, (IMAPStore)store); } /** * Delete this folder. */ public synchronized boolean delete(boolean recurse) throws MessagingException { checkClosed(); // insure that this folder is closed. if (recurse) { // Delete all subfolders. Folder[] f = list(); for (int i = 0; i < f.length; i++) f[i].delete(recurse); // ignore intermediate failures } // Attempt to delete this folder Object ret = doCommandIgnoreFailure(new ProtocolCommand() { public Object doCommand(IMAPProtocol p) throws ProtocolException { p.delete(fullName); return Boolean.TRUE; } }); if (ret == null) // Non-existent folder/No permission ?? return false; // DELETE succeeded. exists = false; attributes = null; // Notify listeners on self and our Store notifyFolderListeners(FolderEvent.DELETED); return true; } /** * Rename this folder. <p> */ public synchronized boolean renameTo(final Folder f) throws MessagingException { checkClosed(); // insure that we are closed. checkExists(); if (f.getStore() != store) throw new MessagingException("Can't rename across Stores"); Object ret = doCommandIgnoreFailure(new ProtocolCommand() { public Object doCommand(IMAPProtocol p) throws ProtocolException { p.rename(fullName, f.getFullName()); return Boolean.TRUE; } }); if (ret == null) return false; exists = false; attributes = null; notifyFolderRenamedListeners(f); return true; } /** * Open this folder in the given mode. */ public synchronized void open(int mode) throws MessagingException { checkClosed(); // insure that we are not already open MailboxInfo mi = null; // Request store for our own protocol connection. protocol = ((IMAPStore)store).getProtocol(this); CommandFailedException exc = null; lock: synchronized(messageCacheLock) { // Acquire messageCacheLock /* * Add response handler right away so we get any alerts or * notifications that occur during the SELECT or EXAMINE. * Have to be sure to remove it if we fail to open the * folder. */ protocol.addResponseHandler(this); try { if (mode == READ_ONLY) mi = protocol.examine(fullName); else mi = protocol.select(fullName); } catch (CommandFailedException cex) { // got a NO; connection still good, return it releaseProtocol(true); protocol = null; exc = cex; break lock; } catch (ProtocolException pex) { // got a BAD or a BYE; connection may be bad, close it try { protocol.logout(); } catch (ProtocolException pex2) { // ignore } finally { releaseProtocol(false); protocol = null; throw new MessagingException(pex.getMessage(), pex); } } if (mi.mode != mode) { if (mode == READ_WRITE && mi.mode == READ_ONLY && ((IMAPStore)store).allowReadOnlySelect()) { ; // all ok, allow it } else { // otherwise, it's an error try { // close mailbox and return connection protocol.close(); releaseProtocol(true); } catch (ProtocolException pex) { // something went wrong, close connection try { protocol.logout(); } catch (ProtocolException pex2) { // ignore } finally { releaseProtocol(false); } } finally { protocol = null; throw new ReadOnlyFolderException(this, "Cannot open in desired mode"); } } } // Initialize stuff. opened = true; reallyClosed = false; this.mode = mi.mode; availableFlags = mi.availableFlags; permanentFlags = mi.permanentFlags; total = realTotal = mi.total; recent = mi.recent; uidvalidity = mi.uidvalidity; uidnext = mi.uidnext; // Create the message cache vector of appropriate size messageCache = new Vector(total); // Fill up the cache with light-weight IMAPMessage objects for (int i = 0; i < total; i++) messageCache.addElement(new IMAPMessage(this, i+1, i+1)); } // Release lock /* * Handle SELECT or EXAMINE failure after lock is released. * Try to figure out why the operation failed so we can * report a more reasonable exception. */ if (exc != null) { checkExists(); // throw exception if folder doesn't exist if ((type & HOLDS_MESSAGES) == 0) throw new MessagingException("folder cannot contain messages"); throw new MessagingException(exc.getMessage(), exc); } exists = true; // if we opened it, it must exist attributes = null; // but we don't yet know its attributes type = HOLDS_MESSAGES; // lacking more info, we know at least this much // notify listeners notifyConnectionListeners(ConnectionEvent.OPENED); } /** * Prefetch attributes, based on the given FetchProfile. */ public synchronized void fetch(Message[] msgs, FetchProfile fp) throws MessagingException { checkOpened(); IMAPMessage.fetch(this, msgs, fp); } /** * Set the specified flags for the given array of messages. */ public synchronized void setFlags(Message[] msgs, Flags flag, boolean value) throws MessagingException { checkOpened(); checkFlags(flag); // validate flags if (msgs.length == 0) // boundary condition return; synchronized(messageCacheLock) { try { IMAPProtocol p = getProtocol(); MessageSet[] ms = Utility.toMessageSet(msgs, null); if (ms == null) throw new MessageRemovedException( "Messages have been removed"); p.storeFlags(ms, flag, value); } catch (ConnectionException cex) { throw new FolderClosedException(this, cex.getMessage()); } catch (ProtocolException pex) { throw new MessagingException(pex.getMessage(), pex); } } } /** * Close this folder. */ public synchronized void close(boolean expunge) throws MessagingException { close(expunge, false); } /** * Close this folder without waiting for the server. */ public synchronized void forceClose() throws MessagingException { close(false, true); } /* * Common close method. */ private void close(boolean expunge, boolean force) throws MessagingException { assert Thread.holdsLock(this); synchronized(messageCacheLock) { /* * If we already know we're closed, this is illegal. * Can't use checkOpened() because if we were forcibly * closed asynchronously we just want to complete the * closing here. */ if (!opened && reallyClosed) throw new IllegalStateException( "This operation is not allowed on a closed folder" ); reallyClosed = true; // Ok, lets reset // Maybe this folder is already closed, or maybe another // thread which had the messageCacheLock earlier, found // that our server connection is dead and cleaned up // everything .. if (!opened) return; try { waitIfIdle(); if (force) { if (debug) out.println("DEBUG: forcing folder " + fullName + " to close"); if (protocol != null) protocol.disconnect(); } else if (((IMAPStore)store).isConnectionPoolFull()) { // If the connection pool is full, logout the connection if (debug) out.println("DEBUG: pool is full, not adding " + "an Authenticated connection"); // If the expunge flag is set, close the folder first. if (expunge) protocol.close(); if (protocol != null) protocol.logout(); } else { // If the expunge flag is set or we're open read-only we // can just close the folder, otherwise open it read-only // before closing. if (!expunge && mode == READ_WRITE) { try { MailboxInfo mi = protocol.examine(fullName); } catch (ProtocolException pex2) { if (protocol != null) protocol.disconnect(); } } if (protocol != null) protocol.close(); } } catch (ProtocolException pex) { throw new MessagingException(pex.getMessage(), pex); } finally { // cleanup if we haven't already if (opened) cleanup(true); } } } // NOTE: this method can currently be invoked from close() or // from handleResponses(). Both invocations are conditional, // based on the "opened" flag, so we are sure that multiple // Connection.CLOSED events are not generated. Also both // invocations are from within messageCacheLock-ed areas. private void cleanup(boolean returnToPool) { releaseProtocol(returnToPool); protocol = null; messageCache = null; uidTable = null; exists = false; // to force a recheck in exists(). attributes = null; opened = false; idleState = RUNNING; // just in case notifyConnectionListeners(ConnectionEvent.CLOSED); } /** * Check whether this connection is really open. */ public synchronized boolean isOpen() { synchronized(messageCacheLock) { // Probe the connection to make sure its really open. if (opened) { try { keepConnectionAlive(false); } catch (ProtocolException pex) { } } } return opened; } /** * Return the permanent flags supported by the server. */ public synchronized Flags getPermanentFlags() { return (Flags)(permanentFlags.clone()); } /** * Get the total message count. */ public synchronized int getMessageCount() throws MessagingException { if (!opened) { checkExists(); // If this folder is not yet open, we use STATUS to // get the total message count try { Status status = getStatus(); return status.total; } catch (BadCommandException bex) { // doesn't support STATUS, probably vanilla IMAP4 .. // lets try EXAMINE IMAPProtocol p = null; try { p = getStoreProtocol(); // XXX MailboxInfo minfo = p.examine(fullName); p.close(); return minfo.total; } catch (ProtocolException pex) { // Give up. throw new MessagingException(pex.getMessage(), pex); } finally { releaseStoreProtocol(p); } } catch (ConnectionException cex) { throw new StoreClosedException(store, cex.getMessage()); } catch (ProtocolException pex) { throw new MessagingException(pex.getMessage(), pex); } } // Folder is open, we know what the total message count is .. synchronized(messageCacheLock) { // tickle the folder and store connections. try { keepConnectionAlive(true); return total; } catch (ConnectionException cex) { throw new FolderClosedException(this, cex.getMessage()); } catch (ProtocolException pex) { throw new MessagingException(pex.getMessage(), pex); } } } /** * Get the new message count. */ public synchronized int getNewMessageCount() throws MessagingException { if (!opened) { checkExists(); // If this folder is not yet open, we use STATUS to // get the new message count try { Status status = getStatus(); return status.recent; } catch (BadCommandException bex) { // doesn't support STATUS, probably vanilla IMAP4 .. // lets try EXAMINE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -