commits@javamail.java.net

[javamail~mercurial:473] MailHandler add auto-submitted header from RFC 3834 section 5

From: <shannon_at_kenai.com>
Date: Tue, 6 Nov 2012 21:32:51 +0000

Project: javamail
Repository: mercurial
Revision: 473
Author: shannon
Date: 2012-11-06 00:28:24 UTC
Link:

Log Message:
------------
Add support for logging debug messages using java.util.logging.
Sigh, can't use StackTraceElement yet because no public constructor in 1.4.
Avoid NullPointerException when encountering a bad Content-Type.
MailHandler add auto-submitted header from RFC 3834 section 5
MailHandler support passwords saved in the LogManager properties.
MailHandler better documentation on LogManager and subclasses (bug 7159567).
MailHandlerTest test for auto-submitted header.
MailHandlerTest added test for literal password.
MailHandlerTest add casts for null method arguments.
MailHandlerTest add tracing of suppressed java.security.debug messages.

(Updates from Jason)


Revisions:
----------
470
471
472
473


Modified Paths:
---------------
doc/release/CHANGES.txt
dsn/src/main/java/com/sun/mail/dsn/DeliveryStatus.java
dsn/src/main/java/com/sun/mail/dsn/DispositionNotification.java
dsn/src/main/java/com/sun/mail/dsn/package.html
gimap/src/main/java/com/sun/mail/gimap/GmailStore.java
gimap/src/main/java/com/sun/mail/gimap/protocol/GmailProtocol.java
mail/src/main/java/com/sun/mail/auth/Ntlm.java
mail/src/main/java/com/sun/mail/iap/Protocol.java
mail/src/main/java/com/sun/mail/imap/IMAPFolder.java
mail/src/main/java/com/sun/mail/imap/IMAPStore.java
mail/src/main/java/com/sun/mail/imap/MessageCache.java
mail/src/main/java/com/sun/mail/imap/package.html
mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java
mail/src/main/java/com/sun/mail/imap/protocol/IMAPSaslAuthenticator.java
mail/src/main/java/com/sun/mail/pop3/POP3Folder.java
mail/src/main/java/com/sun/mail/pop3/POP3Message.java
mail/src/main/java/com/sun/mail/pop3/POP3Store.java
mail/src/main/java/com/sun/mail/pop3/Protocol.java
mail/src/main/java/com/sun/mail/pop3/package.html
mail/src/main/java/com/sun/mail/smtp/DigestMD5.java
mail/src/main/java/com/sun/mail/smtp/SMTPSaslAuthenticator.java
mail/src/main/java/com/sun/mail/smtp/SMTPTransport.java
mail/src/main/java/com/sun/mail/smtp/package.html
mail/src/main/java/com/sun/mail/util/SocketFetcher.java
mail/src/main/java/com/sun/mail/util/TraceInputStream.java
mail/src/main/java/com/sun/mail/util/TraceOutputStream.java
mail/src/main/java/com/sun/mail/util/package.html
mail/src/main/java/javax/mail/Session.java
mail/src/main/java/javax/mail/internet/MailDateFormat.java
mail/src/main/java/javax/mail/internet/package.html
mail/src/main/java/javax/mail/package.html
mail/src/test/java/com/sun/mail/imap/MessageCacheTest.java
mail/src/main/java/com/sun/mail/util/MailLogger.java
mail/src/main/java/javax/mail/internet/MimeUtility.java
mail/src/test/java/javax/mail/internet/MimeUtilityTest.java
mail/src/main/java/com/sun/mail/util/logging/MailHandler.java
mail/src/test/java/com/sun/mail/util/logging/MailHandlerTest.java


Added Paths:
------------
mail/src/main/java/com/sun/mail/util/LogOutputStream.java
mail/src/main/java/com/sun/mail/util/MailLogger.java


Diffs:
------
diff -r b9c0981a9ce2 -r a48ce25328db doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Fri Sep 21 13:25:28 2012 -0700
+++ b/doc/release/CHANGES.txt Wed Oct 31 16:45:03 2012 -0700
@@ -25,6 +25,7 @@
 <no id> add mail.imap.ignorebodystructuresize to work around server bugs
 <no id> add "gimap" EXPERIMENTAL Gmail IMAP provider
 <no id> add isSSL() method to all protocol providers
+<no id> add support for debug output using java.util.logging
 
 
                   CHANGES IN THE 1.4.5 RELEASE

diff -r b9c0981a9ce2 -r a48ce25328db dsn/src/main/java/com/sun/mail/dsn/DeliveryStatus.java
--- a/dsn/src/main/java/com/sun/mail/dsn/DeliveryStatus.java Fri Sep 21 13:25:28 2012 -0700
+++ b/dsn/src/main/java/com/sun/mail/dsn/DeliveryStatus.java Wed Oct 31 16:45:03 2012 -0700
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997-2012 Oracle and/or its affiliates. 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
@@ -42,6 +42,7 @@
 
 import java.io.*;
 import java.util.*;
+import java.util.logging.Level;
 
 import javax.activation.*;
 import javax.mail.*;
@@ -49,6 +50,7 @@
 
 import com.sun.mail.util.LineOutputStream; // XXX
 import com.sun.mail.util.PropUtil;
+import com.sun.mail.util.MailLogger;
 
 /**
  * A message/delivery-status message content, as defined in
@@ -58,8 +60,11 @@
  */
 public class DeliveryStatus extends Report {
 
- private static boolean debug =
- PropUtil.getBooleanSystemProperty("mail.dsn.debug", false);
+ private static MailLogger logger = new MailLogger(
+ DeliveryStatus.class,
+ "DEBUG DSN",
+ PropUtil.getBooleanSystemProperty("mail.dsn.debug", false),
+ System.out);
 
     /**
      * The DSN fields for the message.
@@ -88,22 +93,19 @@
                                 throws MessagingException, IOException {
         super("delivery-status");
         messageDSN = new InternetHeaders(is);
- if (debug)
- System.out.println("DSN: got messageDSN");
+ logger.fine("got messageDSN");
         Vector v = new Vector();
         try {
             while (is.available() > 0) {
                 InternetHeaders h = new InternetHeaders(is);
- if (debug)
- System.out.println("DSN: got recipientDSN");
+ logger.fine("got recipientDSN");
                 v.addElement(h);
             }
         } catch (EOFException ex) {
- if (debug)
- System.out.println("DSN: got EOFException");
+ logger.log(Level.FINE, "got EOFException", ex);
         }
- if (debug)
- System.out.println("DSN: recipientDSN size " + v.size());
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("recipientDSN size " + v.size());
         recipientDSN = new InternetHeaders[v.size()];
         v.copyInto(recipientDSN);
     }

diff -r b9c0981a9ce2 -r a48ce25328db dsn/src/main/java/com/sun/mail/dsn/DispositionNotification.java
--- a/dsn/src/main/java/com/sun/mail/dsn/DispositionNotification.java Fri Sep 21 13:25:28 2012 -0700
+++ b/dsn/src/main/java/com/sun/mail/dsn/DispositionNotification.java Wed Oct 31 16:45:03 2012 -0700
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997-2012 Oracle and/or its affiliates. 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
@@ -48,6 +48,7 @@
 
 import com.sun.mail.util.LineOutputStream; // XXX
 import com.sun.mail.util.PropUtil;
+import com.sun.mail.util.MailLogger;
 
 /**
  * A message/disposition-notification message content, as defined in
@@ -57,8 +58,11 @@
  */
 public class DispositionNotification extends Report {
 
- private static boolean debug =
- PropUtil.getBooleanSystemProperty("mail.dsn.debug", false);
+ private static MailLogger logger = new MailLogger(
+ DeliveryStatus.class,
+ "DEBUG DSN",
+ PropUtil.getBooleanSystemProperty("mail.dsn.debug", false),
+ System.out);
 
     /**
      * The disposition notification content fields.
@@ -81,8 +85,7 @@
                                 throws MessagingException, IOException {
         super("disposition-notification");
         notifications = new InternetHeaders(is);
- if (debug)
- System.out.println("MDN: got notification content");
+ logger.fine("got MDN notification content");
     }
 
     /**

diff -r b9c0981a9ce2 -r a48ce25328db dsn/src/main/java/com/sun/mail/dsn/package.html
--- a/dsn/src/main/java/com/sun/mail/dsn/package.html Fri Sep 21 13:25:28 2012 -0700
+++ b/dsn/src/main/java/com/sun/mail/dsn/package.html Wed Oct 31 16:45:03 2012 -0700
@@ -5,7 +5,7 @@
 
     DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
- Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 1997-2012 Oracle and/or its affiliates. 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
@@ -72,6 +72,23 @@
 <P>
 To use the classes in this package, include <code>dsn.jar</code>
 in your class path.
+<P>
+Classes in this package log debugging information using
+{_at_link java.util.logging} as described in the following table:
+<P>
+<TABLE BORDER>
+<TR>
+<TH>Logger Name</TH>
+<TH>Logging Level</TH>
+<TH>Purpose</TH>
+</TR>
+
+<TR>
+<TD>com.sun.mail.dsn</TD>
+<TD>FINER</TD>
+<TD>General debugging output</TD>
+</TR>
+</TABLE>
 
 <P>
 <strong>WARNING:</strong> The APIs unique to this package should be

diff -r b9c0981a9ce2 -r a48ce25328db gimap/src/main/java/com/sun/mail/gimap/GmailStore.java
--- a/gimap/src/main/java/com/sun/mail/gimap/GmailStore.java Fri Sep 21 13:25:28 2012 -0700
+++ b/gimap/src/main/java/com/sun/mail/gimap/GmailStore.java Wed Oct 31 16:45:03 2012 -0700
@@ -87,10 +87,9 @@
     protected IMAPProtocol newIMAPProtocol(String host, int port)
                                 throws IOException, ProtocolException {
         return new GmailProtocol(name, host, port,
- session.getDebug(),
- session.getDebugOut(),
                                             session.getProperties(),
- isSSL
+ isSSL,
+ logger
                                            );
     }
 

diff -r b9c0981a9ce2 -r a48ce25328db gimap/src/main/java/com/sun/mail/gimap/protocol/GmailProtocol.java
--- a/gimap/src/main/java/com/sun/mail/gimap/protocol/GmailProtocol.java Fri Sep 21 13:25:28 2012 -0700
+++ b/gimap/src/main/java/com/sun/mail/gimap/protocol/GmailProtocol.java Wed Oct 31 16:45:03 2012 -0700
@@ -47,6 +47,8 @@
 import com.sun.mail.imap.protocol.*;
 import com.sun.mail.gimap.GmailFolder.FetchProfileItem;
 
+import com.sun.mail.util.MailLogger;
+
 /**
  * Extend IMAP support to handle Gmail-specific protocol extensions.
  *
@@ -92,22 +94,21 @@
      *
      * @param host host to connect to
      * @param port portnumber to connect to
- * @param debug debug mode
- * @param props Properties object used by this protocol
+ * @param props Properties object used by this protocol
+ * @param isSSL use SSL?
+ * @param logger for log messages
      */
     public GmailProtocol(String name, String host, int port,
- boolean debug, PrintStream out, Properties props,
- boolean isSSL) throws IOException, ProtocolException {
- super(name, host, port, debug, out, props, isSSL);
+ Properties props, boolean isSSL, MailLogger logger)
+ throws IOException, ProtocolException {
+ super(name, host, port, props, isSSL, logger);
 
         // check to see if this is really Gmail
         if (!hasCapability("X-GM-EXT-1")) {
- if (debug)
- out.println("DEBUG GIMAP: WARNING! Not connected to Gmail!");
+ logger.fine("WARNING! Not connected to Gmail!");
             // XXX - could call "disconnect()" here and make this a fatal error
         } else {
- if (debug)
- out.println("DEBUG GIMAP: connected to Gmail");
+ logger.fine("connected to Gmail");
         }
         supportsXlist = hasCapability("XLIST");
     }

diff -r b9c0981a9ce2 -r a48ce25328db mail/src/main/java/com/sun/mail/auth/Ntlm.java
--- a/mail/src/main/java/com/sun/mail/auth/Ntlm.java Fri Sep 21 13:25:28 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/auth/Ntlm.java Wed Oct 31 16:45:03 2012 -0700
@@ -50,6 +50,7 @@
 import java.security.GeneralSecurityException;
 import java.security.NoSuchAlgorithmException;
 import java.util.Locale;
+import java.util.logging.Level;
 import javax.crypto.Cipher;
 import javax.crypto.NoSuchPaddingException;
 import javax.crypto.SecretKey;
@@ -58,6 +59,7 @@
 
 import com.sun.mail.util.BASE64DecoderStream;
 import com.sun.mail.util.BASE64EncoderStream;
+import com.sun.mail.util.MailLogger;
 
 
 /**
@@ -79,7 +81,7 @@
     private String username;
     private String password;
 
- private PrintStream debugout; // if not null, debug output stream
+ private MailLogger logger;
 
     private void init0() {
         type1 = new byte[256];
@@ -117,7 +119,7 @@
      * from the ntdomain parameter.
      */
     public Ntlm(String ntdomain, String hostname, String username,
- String password, PrintStream debugout) {
+ String password, MailLogger logger) {
         int i = hostname.indexOf('.');
         if (i != -1) {
             hostname = hostname.substring(0, i);
@@ -133,7 +135,7 @@
         this.hostname = hostname;
         this.username = username;
         this.password = password;
- this.debugout = debugout;
+ this.logger = logger.getLogger(this.getClass(), "DEBUG NTLM");
         init0();
     }
 
@@ -169,8 +171,8 @@
 
         byte[] msg = new byte[32 + hlen + dlen];
         System.arraycopy(type1, 0, msg, 0, 32 + hlen + dlen);
- if (debugout != null)
- debugout.println("DEBUG NTLM: type 1 message: " + toHex(msg));
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("type 1 message: " + toHex(msg));
 
         String result = null;
         try {
@@ -329,8 +331,8 @@
 
         byte[] msg = new byte[l];
         System.arraycopy(type3, 0, msg, 0, l);
- if (debugout != null)
- debugout.println("DEBUG NTLM: type 3 message: " + toHex(msg));
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("type 3 message: " + toHex(msg));
 
         String result = null;
         try {
@@ -342,8 +344,7 @@
 
         } catch (GeneralSecurityException ex) {
             // should never happen
- if (debugout != null)
- debugout.println("DEBUG NTLM: " + ex);
+ logger.log(Level.FINE, "GeneralSecurityException", ex);
             return ""; // will fail later
         }
     }

diff -r b9c0981a9ce2 -r a48ce25328db mail/src/main/java/com/sun/mail/iap/Protocol.java
--- a/mail/src/main/java/com/sun/mail/iap/Protocol.java Fri Sep 21 13:25:28 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/iap/Protocol.java Wed Oct 31 16:45:03 2012 -0700
@@ -44,6 +44,7 @@
 import java.util.Properties;
 import java.io.*;
 import java.net.*;
+import java.util.logging.Level;
 import javax.net.ssl.SSLSocket;
 import com.sun.mail.util.*;
 
@@ -61,9 +62,9 @@
     protected String host;
     private Socket socket;
     // in case we turn on TLS, we'll need these later
- protected boolean debug;
     protected boolean quote;
- protected PrintStream out;
+ protected MailLogger logger;
+ protected MailLogger traceLogger;
     protected Properties props;
     protected String prefix;
 
@@ -96,26 +97,27 @@
      *
      * @param host host to connect to
      * @param port portnumber to connect to
- * @param debug debug mode
- * @param out debug output stream
      * @param props Properties object used by this protocol
      * @param prefix Prefix to prepend to property keys
+ * @param isSSL use SSL?
+ * @param logger log messages here
      */
- public Protocol(String host, int port, boolean debug,
- PrintStream out, Properties props, String prefix,
- boolean isSSL) throws IOException, ProtocolException {
+ public Protocol(String host, int port,
+ Properties props, String prefix,
+ boolean isSSL, MailLogger logger)
+ throws IOException, ProtocolException {
         try {
             this.host = host;
- this.debug = debug;
- this.out = out;
             this.props = props;
             this.prefix = prefix;
+ this.logger = logger;
+ traceLogger = logger.getSubLogger("protocol", null);
 
             socket = SocketFetcher.getSocket(host, port, props, prefix, isSSL);
             quote = PropUtil.getBooleanProperty(props,
                                         "mail.debug.quote", false);
 
- initStreams(out);
+ initStreams();
 
             // Read server greeting
             processGreeting(readResponse());
@@ -135,14 +137,13 @@
         }
     }
 
- private void initStreams(PrintStream out) throws IOException {
- traceInput = new TraceInputStream(socket.getInputStream(), out);
- traceInput.setTrace(debug);
+ private void initStreams() throws IOException {
+ traceInput = new TraceInputStream(socket.getInputStream(), traceLogger);
         traceInput.setQuote(quote);
         input = new ResponseInputStream(traceInput);
 
- traceOutput = new TraceOutputStream(socket.getOutputStream(), out);
- traceOutput.setTrace(debug);
+ traceOutput =
+ new TraceOutputStream(socket.getOutputStream(), traceLogger);
         traceOutput.setQuote(quote);
         output = new DataOutputStream(new BufferedOutputStream(traceOutput));
     }
@@ -150,21 +151,19 @@
     /**
      * Constructor for debugging.
      */
- public Protocol(InputStream in, OutputStream out, boolean debug)
+ public Protocol(InputStream in, PrintStream out, boolean debug)
                                 throws IOException {
         this.host = "localhost";
- this.debug = debug;
         this.quote = false;
- this.out = System.out;
+ logger = new MailLogger(this.getClass(), "DEBUG", debug, out);
+ traceLogger = logger.getSubLogger("protocol", null);
 
         // XXX - inlined initStreams, won't allow later startTLS
- traceInput = new TraceInputStream(in, System.out);
- traceInput.setTrace(debug);
+ traceInput = new TraceInputStream(in, traceLogger);
         traceInput.setQuote(quote);
         input = new ResponseInputStream(traceInput);
 
- traceOutput = new TraceOutputStream(out, System.out);
- traceOutput.setTrace(debug);
+ traceOutput = new TraceOutputStream(out, traceLogger);
         traceOutput.setQuote(quote);
         output = new DataOutputStream(new BufferedOutputStream(traceOutput));
 
@@ -387,7 +386,7 @@
             return; // nothing to do
         simpleCommand(cmd, null);
         socket = SocketFetcher.startTLS(socket, host, props, prefix);
- initStreams(out);
+ initStreams();
     }
 
     /**
@@ -454,11 +453,18 @@
     }
 
     /**
+ * Is protocol tracing enabled?
+ */
+ protected boolean isTracing() {
+ return traceLogger.isLoggable(Level.FINEST);
+ }
+
+ /**
      * Temporarily turn off protocol tracing, e.g., to prevent
      * tracing the authentication sequence, including the password.
      */
     protected void suspendTracing() {
- if (debug) {
+ if (traceLogger.isLoggable(Level.FINEST)) {
             traceInput.setTrace(false);
             traceOutput.setTrace(false);
         }
@@ -468,7 +474,7 @@
      * Resume protocol tracing, if it was enabled to begin with.
      */
     protected void resumeTracing() {
- if (debug) {
+ if (traceLogger.isLoggable(Level.FINEST)) {
             traceInput.setTrace(true);
             traceOutput.setTrace(true);
         }

diff -r b9c0981a9ce2 -r a48ce25328db mail/src/main/java/com/sun/mail/imap/IMAPFolder.java
--- a/mail/src/main/java/com/sun/mail/imap/IMAPFolder.java Fri Sep 21 13:25:28 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/IMAPFolder.java Wed Oct 31 16:45:03 2012 -0700
@@ -44,6 +44,7 @@
 import java.util.Vector;
 import java.util.Hashtable;
 import java.util.NoSuchElementException;
+import java.util.logging.Level;
 import java.io.*;
 
 import javax.mail.*;
@@ -266,10 +267,8 @@
 
     private boolean hasMessageCountListener = false; // optimize notification
 
- protected boolean debug = false;
- protected PrintStream out; // debug output stream
-
- private boolean connectionPoolDebug;
+ protected MailLogger logger;
+ private MailLogger connectionPoolLogger;
 
     /**
      * A fetch profile item for fetching headers.
@@ -328,11 +327,9 @@
             throw new NullPointerException("Folder name is null");
         this.fullName = fullName;
         this.separator = separator;
- debug = store.getSession().getDebug();
- connectionPoolDebug = ((IMAPStore)store).getConnectionPoolDebug();
- out = store.getSession().getDebugOut();
- if (out == null) // should never happen
- out = System.out;
+ logger = new MailLogger(this.getClass(),
+ "DEBUG IMAP", store.getSession());
+ connectionPoolLogger = ((IMAPStore)store).getConnectionPoolLogger();
 
         /*
          * Work around apparent bug in Exchange. Exchange
@@ -1273,16 +1270,14 @@
             try {
                 waitIfIdle();
                 if (force) {
- if (debug)
- out.println("DEBUG: forcing folder " + fullName +
- " to close");
+ logger.log(Level.FINE, "forcing folder {0} to close",
+ fullName);
                     if (protocol != null)
                         protocol.disconnect();
                 } else if (((IMAPStore)store).isConnectionPoolFull()) {
                     // If the connection pool is full, logout the connection
- if (debug)
- out.println("DEBUG: pool is full, not adding " +
- "an Authenticated connection");
+ logger.fine(
+ "pool is full, not adding an Authenticated connection");
 
                     // If the expunge flag is set, close the folder first.
                     if (expunge && protocol != null)
@@ -2605,8 +2600,7 @@
         if (!(r instanceof IMAPResponse)) {
             // Probably a bug in our code !
             // XXX - should be an assert
- out.println("UNEXPECTED RESPONSE : " + r.toString());
- out.println("CONTACT javamail_at_sun.com");
+ logger.fine("UNEXPECTED RESPONSE : " + r.toString());
             return;
         }
 
@@ -2709,10 +2703,7 @@
      */
     protected synchronized IMAPProtocol getStoreProtocol()
             throws ProtocolException {
- if (connectionPoolDebug) {
- out.println("DEBUG: getStoreProtocol() - " +
- "borrowing a connection");
- }
+ connectionPoolLogger.fine("getStoreProtocol() borrowing a connection");
         return ((IMAPStore)store).getFolderStoreProtocol();
     }
 
@@ -2925,8 +2916,7 @@
             ((IMAPStore)store).releaseFolderStoreProtocol(p);
         else {
             // XXX - should never happen
- if (debug)
- out.println("DEBUG: releasing our protocol as store protocol?");
+ logger.fine("releasing our protocol as store protocol?");
         }
     }
 

diff -r b9c0981a9ce2 -r a48ce25328db mail/src/main/java/com/sun/mail/imap/IMAPStore.java
--- a/mail/src/main/java/com/sun/mail/imap/IMAPStore.java Fri Sep 21 13:25:28 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/IMAPStore.java Wed Oct 31 16:45:03 2012 -0700
@@ -47,6 +47,7 @@
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.util.logging.Level;
 
 import javax.mail.*;
 import javax.mail.event.*;
@@ -54,6 +55,7 @@
 import com.sun.mail.iap.*;
 import com.sun.mail.imap.protocol.*;
 import com.sun.mail.util.PropUtil;
+import com.sun.mail.util.MailLogger;
 
 /**
  * This class provides access to an IMAP message store. <p>
@@ -212,7 +214,7 @@
 
     private boolean debugusername; // include username in debug output?
     private boolean debugpassword; // include password in debug output?
- protected PrintStream out; // debug output stream
+ protected MailLogger logger; // for debug output
 
     private boolean messageCacheDebug;
 
@@ -253,8 +255,8 @@
         // interval for checking for timed out connections
         private final long pruningInterval;
     
- // connection pool debug flag
- private final boolean debug;
+ // connection pool logger
+ private final MailLogger logger;
 
         /*
          * The idleState field supports the IDLE command.
@@ -303,24 +305,21 @@
         private int idleState = RUNNING;
         private IMAPProtocol idleProtocol; // protocol object when IDLE
 
- ConnectionPool(String name, Session session) {
+ ConnectionPool(String name, MailLogger plogger, Session session) {
             lastTimePruned = System.currentTimeMillis();
 
- PrintStream out = session.getDebugOut();
- if (out == null) // should never happen
- out = System.out;
-
- debug = PropUtil.getBooleanSessionProperty(session,
+ boolean debug = PropUtil.getBooleanSessionProperty(session,
                 "mail." + name + ".connectionpool.debug", false);
+ logger = plogger.getSubLogger("connectionpool",
+ "DEBUG IMAP CP", debug);
 
             // check if the default connection pool size is overridden
             int size = PropUtil.getIntSessionProperty(session,
                 "mail." + name + ".connectionpoolsize", -1);
             if (size > 0) {
                 poolSize = size;
- if (debug)
- out.println("DEBUG: mail.imap.connectionpoolsize: " +
- poolSize);
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("mail.imap.connectionpoolsize: " + poolSize);
             } else
                 poolSize = 1;
 
@@ -329,8 +328,8 @@
                 "mail." + name + ".connectionpooltimeout", -1);
             if (connectionPoolTimeout > 0) {
                 clientTimeoutInterval = connectionPoolTimeout;
- if (debug)
- out.println("DEBUG: mail.imap.connectionpooltimeout: " +
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("mail.imap.connectionpooltimeout: " +
                         clientTimeoutInterval);
             } else
                 clientTimeoutInterval = 45 * 1000; // 45 seconds
@@ -340,8 +339,8 @@
                 "mail." + name + ".servertimeout", -1);
             if (serverTimeout > 0) {
                 serverTimeoutInterval = serverTimeout;
- if (debug)
- out.println("DEBUG: mail.imap.servertimeout: " +
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("mail.imap.servertimeout: " +
                         serverTimeoutInterval);
             } else
                 serverTimeoutInterval = 30 * 60 * 1000; // 30 minutes
@@ -351,8 +350,8 @@
                 "mail." + name + ".pruninginterval", -1);
             if (pruning > 0) {
                 pruningInterval = pruning;
- if (debug)
- out.println("DEBUG: mail.imap.pruninginterval: " +
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("mail.imap.pruninginterval: " +
                         pruningInterval);
             } else
                 pruningInterval = 60 * 1000; // 1 minute
@@ -362,8 +361,8 @@
             separateStoreConnection =
                 PropUtil.getBooleanSessionProperty(session,
                     "mail." + name + ".separatestoreconnection", false);
- if (debug && separateStoreConnection)
- out.println("DEBUG: dedicate a store connection");
+ if (separateStoreConnection)
+ logger.config("dedicate a store connection");
 
         }
     }
@@ -382,8 +381,8 @@
             // Any of these responses may have a response code.
             if (r.isOK() || r.isNO() || r.isBAD() || r.isBYE())
                 handleResponseCode(r);
- if (debug && r.isBYE())
- out.println("DEBUG: IMAPStore non-store connection dead");
+ if (r.isBYE())
+ logger.fine("IMAPStore non-store connection dead");
         }
     };
  
@@ -418,97 +417,92 @@
                         "mail.debug.auth.username", true);
         debugpassword = PropUtil.getBooleanSessionProperty(session,
                         "mail.debug.auth.password", false);
- out = session.getDebugOut();
- if (out == null) // should never happen
- out = System.out;
+ logger = new MailLogger(this.getClass(),
+ "DEBUG " + name.toUpperCase(), session);
 
         boolean partialFetch = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".partialfetch", true);
         if (!partialFetch) {
             blksize = -1;
- if (debug)
- out.println("DEBUG: mail.imap.partialfetch: false");
+ logger.config("mail.imap.partialfetch: false");
         } else {
             blksize = PropUtil.getIntSessionProperty(session,
                 "mail." + name +".fetchsize", 1024 * 16);
- if (debug)
- out.println("DEBUG: mail.imap.fetchsize: " + blksize);
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("mail.imap.fetchsize: " + blksize);
         }
 
         ignoreSize = PropUtil.getBooleanSessionProperty(session,
             "mail." + name +".ignorebodystructuresize", false);
- if (debug)
- out.println("DEBUG: mail.imap.ignorebodystructuresize: " +
- ignoreSize);
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("mail.imap.ignorebodystructuresize: " + ignoreSize);
 
         statusCacheTimeout = PropUtil.getIntSessionProperty(session,
             "mail." + name + ".statuscachetimeout", 1000);
- if (debug)
- out.println("DEBUG: mail.imap.statuscachetimeout: " +
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("mail.imap.statuscachetimeout: " +
                                                 statusCacheTimeout);
 
         appendBufferSize = PropUtil.getIntSessionProperty(session,
             "mail." + name + ".appendbuffersize", -1);
- if (debug)
- out.println("DEBUG: mail.imap.appendbuffersize: " +
- appendBufferSize);
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("mail.imap.appendbuffersize: " + appendBufferSize);
 
         minIdleTime = PropUtil.getIntSessionProperty(session,
             "mail." + name + ".minidletime", 10);
- if (debug)
- out.println("DEBUG: mail.imap.minidletime: " + minIdleTime);
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("mail.imap.minidletime: " + minIdleTime);
 
         // check if we should do a PROXYAUTH login
         String s = session.getProperty("mail." + name + ".proxyauth.user");
         if (s != null) {
             proxyAuthUser = s;
- if (debug)
- out.println("DEBUG: mail.imap.proxyauth.user: " +
- proxyAuthUser);
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("mail.imap.proxyauth.user: " + proxyAuthUser);
         }
 
         // check if AUTH=LOGIN is disabled
         disableAuthLogin = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".auth.login.disable", false);
- if (debug && disableAuthLogin)
- out.println("DEBUG: disable AUTH=LOGIN");
+ if (disableAuthLogin)
+ logger.config("disable AUTH=LOGIN");
 
         // check if AUTH=PLAIN is disabled
         disableAuthPlain = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".auth.plain.disable", false);
- if (debug && disableAuthPlain)
- out.println("DEBUG: disable AUTH=PLAIN");
+ if (disableAuthPlain)
+ logger.config("disable AUTH=PLAIN");
 
         // check if AUTH=NTLM is disabled
         disableAuthNtlm = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".auth.ntlm.disable", false);
- if (debug && disableAuthNtlm)
- out.println("DEBUG: disable AUTH=NTLM");
+ if (disableAuthNtlm)
+ logger.config("disable AUTH=NTLM");
 
         // check if STARTTLS is enabled
         enableStartTLS = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".starttls.enable", false);
- if (debug && enableStartTLS)
- out.println("DEBUG: enable STARTTLS");
+ if (enableStartTLS)
+ logger.config("enable STARTTLS");
 
         // check if STARTTLS is required
         requireStartTLS = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".starttls.required", false);
- if (debug && requireStartTLS)
- out.println("DEBUG: require STARTTLS");
+ if (requireStartTLS)
+ logger.config("require STARTTLS");
 
         // check if SASL is enabled
         enableSASL = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".sasl.enable", false);
- if (debug && enableSASL)
- out.println("DEBUG: enable SASL");
+ if (enableSASL)
+ logger.config("enable SASL");
 
         // check if SASL mechanisms are specified
         if (enableSASL) {
             s = session.getProperty("mail." + name + ".sasl.mechanisms");
             if (s != null && s.length() > 0) {
- if (debug)
- out.println("DEBUG: SASL mechanisms allowed: " + s);
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("SASL mechanisms allowed: " + s);
                 Vector v = new Vector(5);
                 StringTokenizer st = new StringTokenizer(s, " ,");
                 while (st.hasMoreTokens()) {
@@ -525,8 +519,7 @@
         s = session.getProperty("mail." + name + ".sasl.authorizationid");
         if (s != null) {
             authorizationID = s;
- if (debug)
- out.println("DEBUG: mail.imap.sasl.authorizationid: " +
+ logger.log(Level.CONFIG, "mail.imap.sasl.authorizationid: {0}",
                                                 authorizationID);
         }
 
@@ -534,34 +527,32 @@
         s = session.getProperty("mail." + name + ".sasl.realm");
         if (s != null) {
             saslRealm = s;
- if (debug)
- out.println("DEBUG: mail.imap.sasl.realm: " + saslRealm);
+ logger.log(Level.CONFIG, "mail.imap.sasl.realm: {0}", saslRealm);
         }
 
         // check if forcePasswordRefresh is enabled
         forcePasswordRefresh = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".forcepasswordrefresh", false);
- if (debug && forcePasswordRefresh)
- out.println("DEBUG: enable forcePasswordRefresh");
+ if (forcePasswordRefresh)
+ logger.config("enable forcePasswordRefresh");
 
         // check if enableimapevents is enabled
         enableImapEvents = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".enableimapevents", false);
- if (debug && enableImapEvents)
- out.println("DEBUG: enable IMAP events");
+ if (enableImapEvents)
+ logger.config("enable IMAP events");
 
         // check if message cache debugging set
         messageCacheDebug = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".messagecache.debug", false);
 
         guid = session.getProperty("mail." + name + ".yahoo.guid");
- if (debug && guid != null)
- out.println("DEBUG: mail.imap.yahoo.guid: " + guid);
+ if (guid != null)
+ logger.log(Level.CONFIG, "mail.imap.yahoo.guid: {0}", guid);
 
         s = session.getProperty("mail." + name + ".folder.class");
         if (s != null) {
- if (debug)
- out.println("DEBUG IMAP: folder class: " + s);
+ logger.log(Level.CONFIG, "IMAP: folder class: {0}", s);
             try {
                 ClassLoader cl = this.getClass().getClassLoader();
 
@@ -585,13 +576,12 @@
                 Class[] c2 = { ListInfo.class, IMAPStore.class };
                 folderConstructorLI = folderClass.getConstructor(c2);
             } catch (Exception ex) {
- if (debug)
- out.println(
- "DEBUG IMAP: failed to load folder class: " + ex);
+ logger.log(Level.CONFIG,
+ "IMAP: failed to load folder class", ex);
             }
         }
 
- pool = new ConnectionPool(name, session);
+ pool = new ConnectionPool(name, logger, session);
     }
 
     /**
@@ -612,8 +602,8 @@
 
         // check for non-null values of host, password, user
         if (host == null || password == null || user == null) {
- if (debug)
- out.println("DEBUG: protocolConnect returning false" +
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("protocolConnect returning false" +
                                 ", host=" + host +
                                 ", user=" + traceUser(user) +
                                 ", password=" + tracePassword(password));
@@ -640,12 +630,12 @@
             }
 
             if (poolEmpty) {
- if (debug)
- out.println("DEBUG: trying to connect to host \"" + host +
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("trying to connect to host \"" + host +
                                 "\", port " + port + ", isSSL " + isSSL);
                 protocol = newIMAPProtocol(host, port);
- if (debug)
- out.println("DEBUG: protocolConnect login" +
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("protocolConnect login" +
                                 ", host=" + host +
                                 ", user=" + traceUser(user) +
                                 ", password=" + tracePassword(password));
@@ -693,10 +683,9 @@
     protected IMAPProtocol newIMAPProtocol(String host, int port)
                                 throws IOException, ProtocolException {
         return new IMAPProtocol(name, host, port,
- session.getDebug(),
- session.getDebugOut(),
                                             session.getProperties(),
- isSSL
+ isSSL,
+ logger
                                            );
     }
 
@@ -709,8 +698,7 @@
                 // if startTLS succeeds, refresh capabilities
                 p.capability();
             } else if (requireStartTLS) {
- if (debug)
- out.println("DEBUG: STARTTLS required but not supported");
+ logger.fine("STARTTLS required but not supported by server");
                 throw new ProtocolException(
                     "STARTTLS required but not supported by server");
             }
@@ -859,9 +847,7 @@
                 (pool.authenticatedConnections.size() == 1 &&
                 (pool.separateStoreConnection || pool.storeConnectionInUse))) {
 
- if (debug)
- out.println("DEBUG: no connections in the pool, " +
- "creating a new one");
+ logger.fine("no connections in the pool, creating a new one");
                 try {
                     if (forcePasswordRefresh)
                         refreshPassword();
@@ -880,8 +866,8 @@
                 if (p == null)
                     throw new MessagingException("connection failure");
             } else {
- if (debug)
- out.println("DEBUG: connection available -- size: " +
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("connection available -- size: " +
                         pool.authenticatedConnections.size());
 
                 // remove the available connection from the Authenticated queue
@@ -962,8 +948,7 @@
             // If there's no authenticated connections available create a
             // new one and place it in the authenticated queue.
             if (pool.authenticatedConnections.isEmpty()) {
- if (pool.debug)
- out.println("DEBUG: getStoreProtocol() - no connections " +
+ pool.logger.fine("getStoreProtocol() - no connections " +
                         "in the pool, creating a new one");
                 try {
                     if (forcePasswordRefresh)
@@ -989,8 +974,8 @@
  
             } else {
                 // Always use the first element in the Authenticated queue.
- if (pool.debug)
- out.println("DEBUG: getStoreProtocol() - " +
+ if (pool.logger.isLoggable(Level.FINE))
+ pool.logger.fine("getStoreProtocol() - " +
                         "connection available -- size: " +
                         pool.authenticatedConnections.size());
                 p = (IMAPProtocol)pool.authenticatedConnections.firstElement();
@@ -1006,9 +991,7 @@
             } else {
                 pool.storeConnectionInUse = true;
 
- if (pool.debug)
- out.println("DEBUG: getStoreProtocol() -- " +
- "storeConnectionInUse");
+ pool.logger.fine("getStoreProtocol() -- storeConnectionInUse");
             }
  
             timeoutConnections();
@@ -1036,8 +1019,8 @@
      * XXX - remove this when SASL support is added
      */
     private void refreshPassword() {
- if (debug)
- out.println("DEBUG: refresh password, user: " + traceUser(user));
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("refresh password, user: " + traceUser(user));
         InetAddress addr;
         try {
             addr = InetAddress.getByName(host);
@@ -1071,10 +1054,10 @@
     }
 
     /**
- * Report whether connection pool debugging is enabled.
+ * Return the connection pool logger.
      */
- boolean getConnectionPoolDebug() {
- return pool.debug;
+ MailLogger getConnectionPoolLogger() {
+ return pool.logger;
     }
  
     /**
@@ -1090,8 +1073,8 @@
     boolean isConnectionPoolFull() {
 
         synchronized (pool) {
- if (pool.debug)
- out.println("DEBUG: current size: " +
+ if (pool.logger.isLoggable(Level.FINE))
+ pool.logger.fine("connection pool current size: " +
                     pool.authenticatedConnections.size() +
                     " pool size: " + pool.poolSize);
 
@@ -1113,14 +1096,13 @@
                     protocol.addResponseHandler(this);
                     pool.authenticatedConnections.addElement(protocol);
 
- if (debug)
- out.println("DEBUG: added an " +
- "Authenticated connection -- size: " +
+ if (logger.isLoggable(Level.FINE))
+ logger.fine(
+ "added an Authenticated connection -- size: " +
                             pool.authenticatedConnections.size());
                 } else {
- if (debug)
- out.println("DEBUG: pool is full, not adding " +
- "an Authenticated connection");
+ logger.fine(
+ "pool is full, not adding an Authenticated connection");
                     try {
                         protocol.logout();
                     } catch (ProtocolException pex) {};
@@ -1162,8 +1144,7 @@
             pool.storeConnectionInUse = false;
             pool.notifyAll(); // in case anyone waiting
 
- if (pool.debug)
- out.println("DEBUG: releaseStoreProtocol()");
+ pool.logger.fine("releaseStoreProtocol()");
 
             timeoutConnections();
         }
@@ -1190,8 +1171,7 @@
             pool.storeConnectionInUse = false;
             pool.notifyAll(); // in case anyone waiting
 
- if (pool.debug)
- out.println("DEBUG: releaseFolderStoreProtocol()");
+ pool.logger.fine("releaseFolderStoreProtocol()");
 
             timeoutConnections();
         }
@@ -1219,8 +1199,7 @@
             pool.authenticatedConnections.removeAllElements();
         }
         
- if (pool.debug)
- out.println("DEBUG: removed all authenticated connections");
+ pool.logger.fine("removed all authenticated connections from pool");
     }
 
     /**
@@ -1236,11 +1215,10 @@
                 pool.pruningInterval &&
                 pool.authenticatedConnections.size() > 1) {
 
- if (pool.debug) {
- out.println("DEBUG: checking for connections " +
- "to prune: " +
+ if (pool.logger.isLoggable(Level.FINE)) {
+ pool.logger.fine("checking for connections to prune: " +
                         (System.currentTimeMillis() - pool.lastTimePruned));
- out.println("DEBUG: clientTimeoutInterval: " +
+ pool.logger.fine("clientTimeoutInterval: " +
                         pool.clientTimeoutInterval);
                 }
  
@@ -1253,19 +1231,15 @@
                      index > 0; index--) {
                     p = (IMAPProtocol)pool.authenticatedConnections.
                         elementAt(index);
- if (pool.debug) {
- out.println("DEBUG: protocol last used: " +
+ if (pool.logger.isLoggable(Level.FINE))
+ pool.logger.fine("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");
- }
+ pool.logger.fine(
+ "authenticated connection timed out, " +
+ "logging out the connection");
  
                         p.removeResponseHandler(this);
                         pool.authenticatedConnections.removeElementAt(index);
@@ -1407,8 +1381,7 @@
              * will just close the connection.
              */
             if (isEmpty) {
- if (pool.debug)
- out.println("DEBUG: close() - no connections ");
+ pool.logger.fine("close() - no connections ");
                 cleanup();
                 return;
             }
@@ -1459,8 +1432,7 @@
     private synchronized void cleanup() {
         // if we're not connected, someone beat us to it
         if (!super.isConnected()) {
- if (debug)
- out.println("DEBUG: IMAPStore cleanup, not connected");
+ logger.fine("IMAPStore cleanup, not connected");
             return;
         }
 
@@ -1476,8 +1448,8 @@
             forceClose = false;
             connectionFailed = false;
         }
- if (debug)
- out.println("DEBUG: IMAPStore cleanup, force " + force);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("IMAPStore cleanup, force " + force);
 
         Vector foldersCopy = null;
         boolean done = true;
@@ -1510,15 +1482,13 @@
 
                 try {
                     if (force) {
- if (debug)
- out.println("DEBUG: force folder to close");
+ logger.fine("force folder to close");
                         // Don't want to wait for folder connection to timeout
                         // (if, for example, the server is down) so we close
                         // folders abruptly.
                         f.forceClose();
                     } else {
- if (debug)
- out.println("DEBUG: close folder");
+ logger.fine("close folder");
                         f.close(false);
                     }
                 } catch (MessagingException mex) {
@@ -1538,8 +1508,7 @@
         try {
             super.close();
         } catch (MessagingException mex) { }
- if (debug)
- out.println("DEBUG: IMAPStore cleanup done");
+ logger.fine("IMAPStore cleanup done");
     }
 
     /**
@@ -1582,10 +1551,8 @@
                     { fullName, new Character(separator), this, isNamespace };
                 f = (IMAPFolder)folderConstructor.newInstance(o);
             } catch (Exception ex) {
- if (debug)
- out.println(
- "DEBUG IMAP: exception creating IMAPFolder class: " +
- ex.toString());
+ logger.log(Level.FINE,
+ "exception creating IMAPFolder class", ex);
             }
         }
         if (f == null)
@@ -1612,10 +1579,8 @@
                 Object[] o = { li, this };
                 f = (IMAPFolder)folderConstructorLI.newInstance(o);
             } catch (Exception ex) {
- if (debug)
- out.println(
- "DEBUG IMAP: exception creating IMAPFolder class LI: " +
- ex.toString());
+ logger.log(Level.FINE,
+ "exception creating IMAPFolder class LI", ex);
             }
         }
         if (f == null)
@@ -1776,8 +1741,7 @@
         if (r.isOK() || r.isNO() || r.isBAD() || r.isBYE())
             handleResponseCode(r);
         if (r.isBYE()) {
- if (debug)
- out.println("DEBUG: IMAPStore connection dead");
+ logger.fine("IMAPStore connection dead");
             // Store's IMAP connection is dead, save the response so that
             // releaseStoreProtocol will cleanup later.
             synchronized (connectionFailedLock) {

diff -r b9c0981a9ce2 -r a48ce25328db mail/src/main/java/com/sun/mail/imap/MessageCache.java
--- a/mail/src/main/java/com/sun/mail/imap/MessageCache.java Fri Sep 21 13:25:28 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/MessageCache.java Wed Oct 31 16:45:03 2012 -0700
@@ -42,9 +42,11 @@
 
 import java.io.PrintStream;
 import java.util.*;
+import java.util.logging.Level;
 
 import javax.mail.*;
 import com.sun.mail.util.PropUtil;
+import com.sun.mail.util.MailLogger;
 
 /**
  * A cache of IMAPMessage objects along with the
@@ -82,9 +84,8 @@
      */
     private IMAPFolder folder;
 
- // debugging flag and stream
- private boolean debug;
- private PrintStream out;
+ // debugging logger
+ private MailLogger logger;
 
     /**
      * Grow the array by at least this much, to avoid constantly
@@ -97,12 +98,10 @@
      */
     MessageCache(IMAPFolder folder, IMAPStore store, int size) {
         this.folder = folder;
- if (store != null) { // allow null store, for testing
- this.debug = store.getMessageCacheDebug();
- this.out = store.getSession().getDebugOut();
- }
- if (debug)
- out.println("DEBUG IMAP MC: create cache of size " + size);
+ logger = folder.logger.getSubLogger("messagecache", "DEBUG IMAP MC",
+ store.getMessageCacheDebug());
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("create cache of size " + size);
         ensureCapacity(size, 1);
     }
 
@@ -110,9 +109,13 @@
      * Constructor for debugging and testing.
      */
     MessageCache(int size, boolean debug) {
- this(null, null, size);
- this.debug = debug;
- this.out = System.out;
+ this.folder = null;
+ logger = new MailLogger(
+ this.getClass(), "messagecache",
+ "DEBUG IMAP MC", debug, System.out);
+ if (logger.isLoggable(Level.CONFIG))
+ logger.config("create DEBUG cache of size " + size);
+ ensureCapacity(size, 1);
     }
 
     /**
@@ -133,14 +136,13 @@
                 "message number (" + msgnum + ") out of bounds (" + size + ")");
         IMAPMessage msg = messages[msgnum-1];
         if (msg == null) {
- if (debug)
- out.println("DEBUG IMAP MC: create message number " + msgnum);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("create message number " + msgnum);
             msg = folder.newIMAPMessage(msgnum);
             messages[msgnum-1] = msg;
             // mark message expunged if no seqnum
             if (seqnumOf(msgnum) <= 0) {
- if (debug)
- out.println("DEBUG IMAP MC: it's expunged!");
+ logger.fine("it's expunged!");
                 msg.setExpunged(true);
             }
         }
@@ -155,8 +157,8 @@
     public IMAPMessage getMessageBySeqnum(int seqnum) {
         int msgnum = msgnumOf(seqnum);
         if (msgnum < 0) { // XXX - < 1 ?
- if (debug)
- out.println("DEBUG IMAP MC: no message seqnum " + seqnum);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("no message seqnum " + seqnum);
             return null;
         } else
             return getMessage(msgnum);
@@ -168,19 +170,18 @@
     public void expungeMessage(int seqnum) {
         int msgnum = msgnumOf(seqnum);
         if (msgnum < 0) {
- if (debug)
- out.println("DEBUG IMAP MC: expunge no seqnum " + seqnum);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("expunge no seqnum " + seqnum);
             return; // XXX - should never happen
         }
         IMAPMessage msg = messages[msgnum-1];
         if (msg != null) {
- if (debug)
- out.println("DEBUG IMAP MC: expunge existing " + msgnum);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("expunge existing " + msgnum);
             msg.setExpunged(true);
         }
         if (seqnums == null) { // time to fill it in
- if (debug)
- out.println("DEBUG IMAP MC: create seqnums array");
+ logger.fine("create seqnums array");
             seqnums = new int[messages.length];
             for (int i = 1; i < msgnum; i++)
                 seqnums[i-1] = i;
@@ -202,8 +203,7 @@
      * returning a list of removed message objects.
      */
     public IMAPMessage[] removeExpungedMessages() {
- if (debug)
- out.println("DEBUG IMAP MC: remove expunged messages");
+ logger.fine("remove expunged messages");
         List mlist = new ArrayList(); // list of expunged messages
 
         /*
@@ -237,8 +237,8 @@
         shrink(newnum, oldnum);
 
         IMAPMessage[] rmsgs = new IMAPMessage[mlist.size()];
- if (debug)
- out.println("DEBUG IMAP MC: return " + rmsgs.length);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("return " + rmsgs.length);
         mlist.toArray(rmsgs);
         return rmsgs;
     }
@@ -250,8 +250,7 @@
      * from this folder.
      */
     public IMAPMessage[] removeExpungedMessages(Message[] msgs) {
- if (debug)
- out.println("DEBUG IMAP MC: remove expunged messages");
+ logger.fine("remove expunged messages");
         List mlist = new ArrayList(); // list of expunged messages
 
         /*
@@ -322,8 +321,8 @@
         shrink(newnum, oldnum);
 
         IMAPMessage[] rmsgs = new IMAPMessage[mlist.size()];
- if (debug)
- out.println("DEBUG IMAP MC: return " + rmsgs.length);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("return " + rmsgs.length);
         mlist.toArray(rmsgs);
         return rmsgs;
     }
@@ -334,15 +333,14 @@
      */
     private void shrink(int newend, int oldend) {
         size = newend - 1;
- if (debug)
- out.println("DEBUG IMAP MC: size now " + size);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("size now " + size);
         if (size == 0) { // no messages left
             messages = null;
             seqnums = null;
         } else if (size > SLOP && size < messages.length / 2) {
             // if array shrinks by too much, reallocate it
- if (debug)
- out.println("DEBUG IMAP MC: reallocate array");
+ logger.fine("reallocate array");
             IMAPMessage[] newm = new IMAPMessage[size + SLOP];
             System.arraycopy(messages, 0, newm, 0, size);
             messages = newm;
@@ -352,8 +350,8 @@
                 seqnums = news;
             }
         } else {
- if (debug)
- out.println("DEBUG IMAP MC: clean " + newend + " to " + oldend);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("clean " + newend + " to " + oldend);
             // clear out unused entries in array
             for (int msgnum = newend; msgnum < oldend; msgnum++) {
                 messages[msgnum-1] = null;
@@ -368,8 +366,8 @@
      * newSeqNum is the sequence number of the first message added.
      */
     public void addMessages(int count, int newSeqNum) {
- if (debug)
- out.println("DEBUG IMAP MC: add " + count + " messages");
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("add " + count + " messages");
         // don't have to do anything other than making sure there's space
         ensureCapacity(size + count, newSeqNum);
     }
@@ -382,8 +380,8 @@
         if (messages == null)
             messages = new IMAPMessage[newsize + SLOP];
         else if (messages.length < newsize) {
- if (debug)
- out.println("DEBUG IMAP MC: expand capacity to " + newsize);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("expand capacity to " + newsize);
             IMAPMessage[] newm = new IMAPMessage[newsize + SLOP];
             System.arraycopy(messages, 0, newm, 0, messages.length);
             messages = newm;
@@ -393,14 +391,14 @@
                 for (int i = size; i < news.length; i++)
                     news[i] = newSeqNum++;
                 seqnums = news;
- if (debug)
- out.println("DEBUG IMAP MC: message " + newsize +
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("message " + newsize +
                         " has sequence number " + seqnums[newsize-1]);
             }
         } else if (newsize < size) { // shrinking?
             // this should never happen
- if (debug)
- out.println("DEBUG IMAP MC: shrink capacity to " + newsize);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("shrink capacity to " + newsize);
             for (int msgnum = newsize + 1; msgnum <= size; msgnum++) {
                 messages[msgnum-1] = null;
                 if (seqnums != null)
@@ -417,8 +415,8 @@
         if (seqnums == null)
             return msgnum;
         else {
- if (debug)
- out.println("DEBUG IMAP MC: msgnum " + msgnum + " is seqnum " +
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("msgnum " + msgnum + " is seqnum " +
                             seqnums[msgnum-1]);
             return seqnums[msgnum-1];
         }
@@ -431,8 +429,8 @@
         if (seqnums == null)
             return seqnum;
         if (seqnum < 1) { // should never happen
- if (debug)
- out.println("DEBUG IMAP MC: bad seqnum " + seqnum);
+ if (logger.isLoggable(Level.FINE))
+ logger.fine("bad seqnum " + seqnum);
             return -1;
         }
         for (int msgnum = seqnum; msgnum <= size; msgnum++) {

diff -r b9c0981a9ce2 -r a48ce25328db mail/src/main/java/com/sun/mail/imap/package.html
--- a/mail/src/main/java/com/sun/mail/imap/package.html Fri Sep 21 13:25:28 2012 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/package.html Wed Oct 31 16:45:03 2012 -0700
@@ -558,6 +558,62 @@
 appropriate <code>Store</code> object, and from that acquire
 <code>Folder</code> objects.
 <P>
+In addition to printing debugging output as controlled by the
+{_at_link javax.mail.Session Session} configuration,
+the com.sun.mail.imap provider logs the same information using
+{_at_link java.util.logging.Logger} as described in the following table:
+<P>
+<TABLE BORDER>
+<TR>
+<TH>Logger Name</TH>
+<TH>Logging Level</TH>
+<TH>Purpose</TH>
+</TR>
+
+<TR>
+<TD>com.sun.mail.imap</TD>
+<TD>CONFIG</TD>
+<TD>Configuration of the IMAPStore</TD>
+</TR>
+
+<TR>
+<TD>com.sun.mail.imap</TD>
+<TD>FINE</TD>
+<TD>General debugging output</TD>
+</TR>
+
+<TR>
+<TD>com.sun.mail.imap.connectionpool</TD>
+<TD>CONFIG</TD>
+<TD>Configuration of the IMAP connection pool</TD>
+</TR>
+
+<TR>
+<TD>com.sun.mail.imap.connectionpool</TD>
+<TD>FINE</TD>
+<TD>Debugging output related to the IMAP connection pool</TD>
+</TR>
+
+<TR>
+<TD>com.sun.mail.imap.messagecache</TD>
+<TD>CONFIG</TD>
+<TD>Configuration of the IMAP message cache</TD>
+</TR>
+
+<TR>
+<TD>com.sun.mail.imap.messagecache</TD>
+<TD>FINE</TD>
+<TD>Debugging output related to the IMAP message cache</TD>
+</TR>
+
+<TR>
+<TD>com.sun.mail.imap.protocol</TD>
+<TD>FINEST</TD>
+<T
[truncated due to length]