📄 imapstore.java
字号:
/* * 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 + -