📄 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 + -