⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imapstore.java

📁 此源码是在sun站点上提供的javamail基础上改进。用来解决中文邮件或很多国际间邮件乱码问题。版权属于sun公司。不过当你开发webmail程序时做邮件展示时
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
                    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 + -