📄 imapstore.java
字号:
p = null; } if (p == null) throw new ConnectionException( "failed to create new store connection"); p.addResponseHandler(this); pool.authenticatedConnections.addElement(p); } else { // Always use the first element in the Authenticated queue. if (pool.debug) out.println("DEBUG: getStoreProtocol() - " + "connection available -- size: " + pool.authenticatedConnections.size()); p = (IMAPProtocol)pool.authenticatedConnections.firstElement(); } if (pool.storeConnectionInUse) { try { // someone else is using the connection, give up // and wait until they're done p = null; pool.wait(); } catch (InterruptedException ex) { } } else { pool.storeConnectionInUse = true; if (pool.debug) out.println("DEBUG: getStoreProtocol() -- " + "storeConnectionInUse"); } timeoutConnections(); } } return p; } /** * If a SELECT succeeds, but indicates that the folder is * READ-ONLY, and the user asked to open the folder READ_WRITE, * do we allow the open to succeed? */ boolean allowReadOnlySelect() { String s = session.getProperty("mail." + name + ".allowreadonlyselect"); return s != null && s.equalsIgnoreCase("true"); } /** * Report whether the separateStoreConnection is set. */ boolean hasSeparateStoreConnection() { return pool.separateStoreConnection; } /** * Report whether connection pool debugging is enabled. */ boolean getConnectionPoolDebug() { return pool.debug; } /** * Report whether the connection pool is full. */ boolean isConnectionPoolFull() { synchronized (pool) { if (pool.debug) out.println("DEBUG: current size: " + pool.authenticatedConnections.size() + " pool size: " + pool.poolSize); return (pool.authenticatedConnections.size() >= pool.poolSize); } } /** * Release the protocol object back to the connection pool. */ void releaseProtocol(IMAPFolder folder, IMAPProtocol protocol) { synchronized (pool) { if (protocol != null) { // If the pool is not full, add the store as a response handler // and return the protocol object to the connection pool. if (!isConnectionPoolFull()) { protocol.addResponseHandler(this); pool.authenticatedConnections.addElement(protocol); if (debug) out.println("DEBUG: added an " + "Authenticated connection -- size: " + pool.authenticatedConnections.size()); } else { if (debug) out.println("DEBUG: pool is full, not adding " + "an Authenticated connection"); try { protocol.logout(); } catch (ProtocolException pex) {}; } } if (pool.folders != null) pool.folders.removeElement(folder); timeoutConnections(); } } /** * Release the store connection. */ void releaseStoreProtocol(IMAPProtocol protocol) { if (protocol == null) return; // nothing to release synchronized (pool) { pool.storeConnectionInUse = false; pool.notifyAll(); // in case anyone waiting if (pool.debug) out.println("DEBUG: releaseStoreProtocol()"); timeoutConnections(); } } /** * Empty the connection pool. */ private void emptyConnectionPool(boolean force) { synchronized (pool) { for (int index = pool.authenticatedConnections.size() - 1; index >= 0; --index) { try { IMAPProtocol p = (IMAPProtocol) pool.authenticatedConnections.elementAt(index); p.removeResponseHandler(this); if (force) p.disconnect(); else p.logout(); } catch (ProtocolException pex) {}; } pool.authenticatedConnections.removeAllElements(); } if (pool.debug) out.println("DEBUG: removed all authenticated connections"); } /** * Check to see if it's time to shrink the connection pool. */ private void timeoutConnections() { synchronized (pool) { // If we've exceeded the pruning interval, look for stale // connections to logout. if (System.currentTimeMillis() - pool.lastTimePruned > pool.pruningInterval && pool.authenticatedConnections.size() > 1) { if (pool.debug) { out.println("DEBUG: checking for connections " + "to prune: " + (System.currentTimeMillis() - pool.lastTimePruned)); out.println("DEBUG: clientTimeoutInterval: " + pool.clientTimeoutInterval); } IMAPProtocol p; // Check the timestamp of the protocol objects in the pool and // logout if the interval exceeds the client timeout value // (leave the first connection). for (int index = pool.authenticatedConnections.size() - 1; index > 0; index--) { p = (IMAPProtocol)pool.authenticatedConnections. elementAt(index); if (pool.debug) { out.println("DEBUG: protocol last used: " + (System.currentTimeMillis() - p.getTimestamp())); } if (System.currentTimeMillis() - p.getTimestamp() > pool.clientTimeoutInterval) { if (pool.debug) { out.println("DEBUG: authenticated " + "connection timed out"); out.println("DEBUG: logging out " + "the connection"); } p.removeResponseHandler(this); pool.authenticatedConnections.removeElementAt(index); try { p.logout(); } catch (ProtocolException pex) {} } } pool.lastTimePruned = System.currentTimeMillis(); } } } /** * Get the block size to use for fetch requests on this Store. */ int getFetchBlockSize() { return blksize; } /** * Get a reference to the session. */ Session getSession() { return session; } /** * Get the number of milliseconds to cache STATUS response. */ int getStatusCacheTimeout() { return statusCacheTimeout; } /** * Get the maximum size of a message to buffer for append. */ int getAppendBufferSize() { return appendBufferSize; } /** * Get the minimum amount of time to delay when returning from idle. */ int getMinIdleTime() { return minIdleTime; } /** * Return true if the specified capability string is in the list * of capabilities the server announced. * * @since JavaMail 1.3.3 */ public synchronized boolean hasCapability(String capability) throws MessagingException { IMAPProtocol p = null; try { p = getStoreProtocol(); return p.hasCapability(capability); } catch (ProtocolException pex) { if (p == null) { // failed to get a Store connection // have to force Store to be closed cleanup(); } throw new MessagingException(pex.getMessage(), pex); } finally { releaseStoreProtocol(p); } } /** * Check whether this store is connected. Override superclass * method, to actually ping our server connection. */ public synchronized boolean isConnected() { if (!connected) { // if we haven't been connected at all, don't bother with // the NOOP. super.setConnected(false); // just in case return false; } /* * The below noop() request can: * (1) succeed - in which case all is fine. * * (2) fail because the server returns NO or BAD, in which * case we ignore it since we can't really do anything. * (2) fail because a BYE response is obtained from the * server * (3) fail because the socket.write() to the server fails, * in which case the iap.protocol() code converts the * IOException into a BYE response. * * Thus, our BYE handler will take care of closing the Store * in case our connection is really gone. */ IMAPProtocol p = null; try { p = getStoreProtocol(); p.noop(); } catch (ProtocolException pex) { if (p == null) { // failed to get a Store connection // have to force Store to be closed cleanup(); } // will return false below } finally { releaseStoreProtocol(p); } return super.isConnected(); } /** * Close this Store. */ public synchronized void close() throws MessagingException { if (!super.isConnected()) // Already closed. return; IMAPProtocol protocol = null; try { boolean isEmpty; synchronized (pool) { // If there's no authenticated connections available // don't create a new one isEmpty = pool.authenticatedConnections.isEmpty(); } /* * Have to drop the lock before calling cleanup. * Yes, there's a potential race here. The pool could * become empty after we check, in which case we'll just * waste time getting a new connection and closing it. * Or, the pool could be empty now and not empty by the * time we get into cleanup, but that's ok because cleanup * will just close the connection. */ if (isEmpty) { if (pool.debug) out.println("DEBUG: close() - no connections "); cleanup(); return; } protocol = getStoreProtocol(); /* * We have to remove the protocol from the pool so that, * when our response handler processes the BYE response * and calls cleanup, which calls emptyConnection, that * we don't try to log out this connection twice. */ synchronized (pool) { pool.authenticatedConnections.removeElement(protocol); } /* * LOGOUT. * * Note that protocol.logout() closes the server socket * connection, regardless of what happens .. * * Also note that protocol.logout() results in a BYE * response (As per rfc 2060, BYE is a *required* response * to LOGOUT). In fact, even if protocol.logout() fails * with an IOException (if the server connection is dead), * iap.Protocol.command() converts that exception into a * BYE response. So, I depend on my BYE handler to do the * Store cleanup. */ protocol.logout(); } catch (ProtocolException pex) { // Hmm .. will this ever happen ? cleanup(); throw new MessagingException(pex.getMessage(), pex); } finally { releaseStoreProtocol(protocol); } } protected void finalize() throws Throwable { super.finalize(); close(); } // Cleanup before dying. private void cleanup() { cleanup(false); } /** * Cleanup before dying. * If force is true, we force the folders to close * abruptly without waiting for the server. Used when * the store connection times out. * * Not synchronized so that it can be safely called from handleResponse. */ private void cleanup(boolean force) { if (debug) out.println("DEBUG: IMAPStore cleanup, force " + force); Vector foldersCopy = null; boolean done = true; // To avoid violating the locking hierarchy, there's no lock we // can hold that prevents another thread from trying to open a // folder at the same time we're trying to close all the folders. // Thus, there's an inherent race condition here. We close all // the folders we know about and then check whether any new folders // have been opened in the mean time. We keep trying until we're // successful in closing all the folders. for (;;) { // Make a copy of the folders list so we do not violate the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -