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

📄 imapstore.java

📁 此源码是在sun站点上提供的javamail基础上改进。用来解决中文邮件或很多国际间邮件乱码问题。版权属于sun公司。不过当你开发webmail程序时做邮件展示时
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 *
 * Contributor(s):
 *
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

/*
 * @(#)IMAPStore.java	1.72 07/05/04
 */

package com.sun.mail.imap;

import java.util.Vector;
import java.util.StringTokenizer;
import java.io.PrintStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.mail.*;
import javax.mail.event.*;

import com.sun.mail.iap.*;
import com.sun.mail.imap.protocol.*;

/**
 * This class provides access to an IMAP message store. <p>
 *
 * Applications that need to make use of IMAP-specific features may cast
 * a <code>Store</code> object to an <code>IMAPStore</code> object and
 * use the methods on this class. The {@link #getQuota getQuota} and
 * {@link #setQuota setQuota} methods support the IMAP QUOTA extension.
 * Refer to <A HREF="http://www.ietf.org/rfc/rfc2087.txt">RFC 2087</A>
 * for more information. <p>
 *
 * See the <a href="package-summary.html">com.sun.mail.imap</a> package
 * documentation for further information on the IMAP protocol provider. <p>
 *
 * <strong>WARNING:</strong> The APIs unique to this class should be
 * considered <strong>EXPERIMENTAL</strong>.  They may be changed in the
 * future in ways that are incompatible with applications using the
 * current APIs.
 *
 * @version 1.72, 07/05/04
 * @author  John Mani
 * @author  Bill Shannon
 * @author  Jim Glennon
 */
/*
 * This package is implemented over the "imap.protocol" package, which
 * implements the protocol-level commands. <p>
 *
 * A connected IMAPStore maintains a pool of IMAP protocol objects for
 * use in communicating with the IMAP server. The IMAPStore will create
 * the initial AUTHENTICATED connection and seed the pool with this
 * connection. As folders are opened and new IMAP protocol objects are
 * needed, the IMAPStore will provide them from the connection pool,
 * or create them if none are available. When a folder is closed,
 * its IMAP protocol object is returned to the connection pool if the
 * pool is not over capacity. The pool size can be configured by setting
 * the mail.imap.connectionpoolsize property. <p>
 *
 * A mechanism is provided for timing out idle connection pool IMAP
 * protocol objects. Timed out connections are closed and removed (pruned)
 * from the connection pool. The time out interval can be configured via
 * the mail.imap.connectionpooltimeout property. <p>
 *
 * The connected IMAPStore object may or may not maintain a separate IMAP
 * protocol object that provides the store a dedicated connection to the
 * IMAP server. This is provided mainly for compatibility with previous
 * implementations of JavaMail and is determined by the value of the 
 * mail.imap.separatestoreconnection property. <p>
 *
 * An IMAPStore object provides closed IMAPFolder objects thru its list()
 * and listSubscribed() methods. A closed IMAPFolder object acquires an
 * IMAP protocol object from the store to communicate with the server. When
 * the folder is opened, it gets its own protocol object and thus its own,
 * separate connection to the server. The store maintains references to
 * all 'open' folders. When a folder is/gets closed, the store removes
 * it from its list. When the store is/gets closed, it closes all open 
 * folders in its list, thus cleaning up all open connections to the
 * server. <p>
 *
 * A mutex is used to control access to the connection pool resources.
 * Any time any of these resources need to be accessed, the following
 * convention should be followed:
 *
 *     synchronized (pool) { // ACQUIRE LOCK
 *         // access connection pool resources
 *     } // RELEASE LOCK <p>
 *
 * The locking relationship between the store and folders is that the
 * store lock must be acquired before a folder lock. This is currently only
 * applicable in the store's cleanup method. It's important that the
 * connection pool lock is not held when calling into folder objects.
 * The locking hierarchy is that a folder lock must be acquired before
 * any connection pool operations are performed. <p>
 *
 * The IMAPStore implements the ResponseHandler interface and listens to
 * BYE or untagged OK-notification events from the server. <p>
 */

public class IMAPStore extends Store 
	     implements QuotaAwareStore, ResponseHandler {
    
    /**
     * A special event type for a StoreEvent to indicate an IMAP
     * response, if the mail.imap.enableimapevents property is set.
     */
    public static final int RESPONSE = 1000;

    // XXX - most of these should be final, initialized only in constructor
    private String name = "imap";	// name of this protocol
    private int defaultPort = 143;	// default IMAP port
    private boolean isSSL = false;	// use SSL?

    private int port = -1;		// port to use
    private int blksize = 1024 * 16;	// Block size for data requested
					// in FETCH requests. Defaults to
					// 16K

    private int statusCacheTimeout = 1000;	// cache Status for 1 second

    private int appendBufferSize = -1;	// max size of msg buffered for append

    private int minIdleTime = 10;	// minimum idle time

    // Auth info
    private String host;
    private String user;
    private String password;
    private String proxyAuthUser;
    private String authorizationID;
    private String saslRealm;

    private Namespaces namespaces;

    private boolean disableAuthLogin = false;	// disable AUTH=LOGIN
    private boolean disableAuthPlain = false;	// disable AUTH=PLAIN
    private boolean enableStartTLS = false;	// enable STARTTLS
    private boolean enableSASL = false;		// enable SASL authentication
    private String[] saslMechanisms;
    private boolean forcePasswordRefresh = false;
    // enable notification of IMAP responses
    private boolean enableImapEvents = false;

    /*
     * Track our connected state.  Set on successful return from
     * protocolConnect and reset in cleanup.  Field is volatile
     * so that it can be tested in handleResponse without holding
     * any locks.
     */
    private volatile boolean connected = false;

    private PrintStream out;		// debug output stream

    // Connection pool info

    static class ConnectionPool {

        // container for the pool's IMAP protocol objects
        private Vector authenticatedConnections = new Vector();

        // vectore of open folders
        private Vector folders;

        // flag to indicate whether there is a dedicated connection for
        // store commands
        private boolean separateStoreConnection = false;

        // is the store connection being used?
        private boolean storeConnectionInUse = false; 

        //default client timeout interval
        private long clientTimeoutInterval = 45 * 1000;		// 45 seconds

        //default server timeout interval
        private long serverTimeoutInterval = 30 *60 * 1000;	// 30 minutes

        // the last time (in millis) the pool was checked for timed out
        // connections
        private long lastTimePruned;

        // default size of the connection pool
        private int poolSize = 1;

        // default interval for checking for timed out connections
        private long pruningInterval = 60000;
    
        // connection pool debug flag
        private boolean debug = false;

	/*
	 * The idleState field supports the IDLE command.
	 * Normally when executing an IMAP command we hold the
	 * store's lock.
	 * While executing the IDLE command we can't hold the
	 * lock or it would prevent other threads from
	 * entering Store methods even far enough to check whether
	 * an IDLE command is in progress.  We need to check before
	 * issuing another command so that we can abort the IDLE
	 * command.
	 *
	 * The idleState field is protected by the store's lock.
	 * The RUNNING state is the normal state and means no IDLE
	 * command is in progress.  The IDLE state means we've issued
	 * an IDLE command and are reading responses.  The ABORTING
	 * state means we've sent the DONE continuation command and
	 * are waiting for the thread running the IDLE command to
	 * break out of its read loop.
	 *
	 * When an IDLE command is in progress, the thread calling
	 * the idle method will be reading from the IMAP connection
	 * while not holding the sotre's lock.
	 * It's obviously critical that no other thread try to send a
	 * command or read from the connection while in this state.
	 * However, other threads can send the DONE continuation
	 * command that will cause the server to break out of the IDLE
	 * loop and send the ending tag response to the IDLE command.
	 * The thread in the idle method that's reading the responses
	 * from the IDLE command will see this ending response and
	 * complete the idle method, setting the idleState field back
	 * to RUNNING, and notifying any threads waiting to use the
	 * connection.
	 *
	 * All uses of the IMAP connection (IMAPProtocol object) must
	 * be preceeded by a check to make sure an IDLE command is not
	 * running, and abort the IDLE command if necessary.  This check
	 * is made while holding the connection pool lock.  While
	 * waiting for the IDLE command to complete, these other threads
	 * will give up the connection pool lock.  This check is done by
	 * the getStoreProtocol() method.
	 */
	private static final int RUNNING = 0;	// not doing IDLE command
	private static final int IDLE = 1;	// IDLE command in effect
	private static final int ABORTING = 2;	// IDLE command aborting
	private int idleState = RUNNING;
	private IMAPProtocol idleProtocol;	// protocol object when IDLE
    }
 
    private ConnectionPool pool = new ConnectionPool();

 
    /**
     * Constructor that takes a Session object and a URLName that
     * represents a specific IMAP server.
     */
    public IMAPStore(Session session, URLName url) {
	this(session, url, "imap", 143, false);
    }

    /**
     * Constructor used by this class and by IMAPSSLStore subclass.
     */
    protected IMAPStore(Session session, URLName url,
				String name, int defaultPort, boolean isSSL) {
	super(session, url); // call super constructor
	if (url != null)
	    name = url.getProtocol();
	this.name = name;
	this.defaultPort = defaultPort;
	this.isSSL = isSSL;

        pool.lastTimePruned = System.currentTimeMillis();

        debug = session.getDebug();
	out = session.getDebugOut();
	if (out == null)	// should never happen
	    out = System.out;

        String s = session.getProperty(
	    "mail." + name + ".connectionpool.debug");        

        if (s != null && s.equalsIgnoreCase("true"))
            pool.debug = true;

	s = session.getProperty("mail." + name + ".partialfetch");

	if (s != null && s.equalsIgnoreCase("false")) {
	    // property exits and is set to false
	    blksize = -1; // turn off partial-fetch
	    if (debug)
		out.println("DEBUG: mail.imap.partialfetch: false");
	} else { // either property doesn't exist, or its set to true
	    if ((s = session.getProperty("mail." + name +".fetchsize"))
		     != null)
		// Set the block size to be used in FETCH requests
		blksize = Integer.parseInt(s);
                if (debug)
                    out.println("DEBUG: mail.imap.fetchsize: " + blksize);
	}

	s = session.getProperty("mail." + name + ".statuscachetimeout");
	if (s != null) {
	    statusCacheTimeout = Integer.parseInt(s);
	    if (debug)
		out.println("DEBUG: mail.imap.statuscachetimeout: " +
						statusCacheTimeout);
	}
	s = session.getProperty("mail." + name + ".appendbuffersize");
	if (s != null) {
	    appendBufferSize = Integer.parseInt(s);
	    if (debug)
		out.println("DEBUG: mail.imap.appendbuffersize: " +
						appendBufferSize);
	}
	s = session.getProperty("mail." + name + ".minidletime");
	if (s != null) {
	    minIdleTime = Integer.parseInt(s);
	    if (debug)
		out.println("DEBUG: mail.imap.minidletime: " + minIdleTime);
	}

        // check if the default connection pool size is overridden
        s = session.getProperty("mail." + name + ".connectionpoolsize");
        if (s != null) {
            try {
                int size = Integer.parseInt(s);
                if (size > 0)
                    pool.poolSize = size;
            } catch (NumberFormatException nfe) {
            }
            if (pool.debug)
                out.println("DEBUG: mail.imap.connectionpoolsize: " +
                    pool.poolSize);
        }


        // check if the default client-side timeout value is overridden
        s = session.getProperty("mail." + name + ".connectionpooltimeout");
        if (s != null) {
            try {
                int connectionPoolTimeout = Integer.parseInt(s);
                if (connectionPoolTimeout > 0)
                    pool.clientTimeoutInterval = connectionPoolTimeout;
            } catch (NumberFormatException nfe) {
            }
            if (pool.debug)
                out.println("DEBUG: mail.imap.connectionpooltimeout: " +
                    pool.clientTimeoutInterval);
        } 

        // check if the default server-side timeout value is overridden
        s = session.getProperty("mail." + name + ".servertimeout");
        if (s != null) {
            try {
                int serverTimeout = Integer.parseInt(s);
                if (serverTimeout > 0)
                    pool.serverTimeoutInterval = serverTimeout;
            } catch (NumberFormatException nfe) {
            }
            if (pool.debug)
                out.println("DEBUG: mail.imap.servertimeout: " +
                    pool.serverTimeoutInterval);
        } 
 
        // check to see if we should use a separate (i.e. dedicated)
        // store connection
        s = session.getProperty("mail." + name + ".separatestoreconnection");
        if (s != null && s.equalsIgnoreCase("true")) {
            if (pool.debug)
                out.println("DEBUG: dedicate a store connection");
            pool.separateStoreConnection = true;
        }

	// check if we should do a PROXYAUTH login
	s = session.getProperty("mail." + name + ".proxyauth.user");
	if (s != null) {
	    proxyAuthUser = s;
	    if (debug)
		out.println("DEBUG: mail.imap.proxyauth.user: " +
						proxyAuthUser);
	}

	// check if AUTH=LOGIN is disabled
	s = session.getProperty("mail." + name + ".auth.login.disable");
	if (s != null && s.equalsIgnoreCase("true")) {
	    if (debug)
		out.println("DEBUG: disable AUTH=LOGIN");
	    disableAuthLogin = true;
	}

	// check if AUTH=PLAIN is disabled
	s = session.getProperty("mail." + name + ".auth.plain.disable");
	if (s != null && s.equalsIgnoreCase("true")) {
	    if (debug)
		out.println("DEBUG: disable AUTH=PLAIN");
	    disableAuthPlain = true;
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -