commits@javamail.java.net

[javamail~mercurial:630] send IMAP responses as events to Store's ConnectionListener - bug 6261

From: <shannon_at_java.net>
Date: Fri, 31 Jan 2014 21:12:15 +0000

Project: javamail
Repository: mercurial
Revision: 630
Author: shannon
Date: 2014-01-25 00:33:06 UTC
Link:

Log Message:
------------
Update link and fix javadocs.
Catch more exceptions while in IDLE and log if we get one.
handle IMAP failures during close properly - bug 6260
send IMAP responses as events to Store's ConnectionListener - bug 6261


Revisions:
----------
627
628
629
630


Modified Paths:
---------------
mail/src/main/java/javax/mail/event/MessageCountEvent.java
mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java
doc/release/CHANGES.txt
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/package.html


Added Paths:
------------
mail/src/test/java/com/sun/mail/imap/IMAPCloseFailureTest.java


Diffs:
------
diff -r 7f8091908b18 -r f5b4fa3221bb mail/src/main/java/javax/mail/event/MessageCountEvent.java
--- a/mail/src/main/java/javax/mail/event/MessageCountEvent.java Fri Jan 03 14:58:42 2014 -0800
+++ b/mail/src/main/java/javax/mail/event/MessageCountEvent.java Fri Jan 24 11:31:04 2014 -0800
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997-2014 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
@@ -49,11 +49,12 @@
  * Note that some folder types may only deliver MessageCountEvents at
  * certain times or after certain operations. IMAP in particular will
  * only notify the client of MessageCountEvents when a client issues a
- * new command.
- * Refer to RFC 2060 <A HREF="http://www.ietf.org/rfc/rfc2060.txt">
- * http://www.ietf.org/rfc/rfc2060.txt</A> for details.
- * A client may want "poll" the folder by occasionally calling the
- * <code>getMessageCount</code> or <code>isConnected</code> methods
+ * new command. Refer to
+ * <A HREF="http://www.ietf.org/rfc/rfc3501.txt" TARGET="_top">RFC 3501</A>
+ * for details.
+ * A client may want to "poll" the folder by occasionally calling the
+ * {_at_link javax.mail.Folder#getMessageCount getMessageCount} or
+ * {_at_link javax.mail.Folder#isOpen isOpen} methods
  * to solicit any such notifications.
  *
  * @author John Mani


diff -r f5b4fa3221bb -r c88d051bc82f mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java
--- a/mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java Fri Jan 24 11:31:04 2014 -0800
+++ b/mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java Fri Jan 24 13:49:50 2014 -0800
@@ -2680,8 +2680,9 @@
         try {
             os.write(DONE);
             os.flush();
- } catch (IOException ex) {
+ } catch (Exception ex) {
             // nothing to do, hope to detect it again later
+ logger.log(Level.FINEST, "Exception aborting IDLE", ex);
         }
     }
 


diff -r c88d051bc82f -r f1e6cb4e3b04 doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Fri Jan 24 13:49:50 2014 -0800
+++ b/doc/release/CHANGES.txt Fri Jan 24 16:26:09 2014 -0800
@@ -25,6 +25,7 @@
 K 6207 SMTP SASL support doesn't handle authentication failure properly
 K 6208 SASL authentication failures should not try other methods
 K 6238 add OAuth2 support to JavaMail
+K 6260 IMAP failures during close can leave connection unusable
 
 
                   CHANGES IN THE 1.5.1 RELEASE

diff -r c88d051bc82f -r f1e6cb4e3b04 mail/src/main/java/com/sun/mail/imap/IMAPFolder.java
--- a/mail/src/main/java/com/sun/mail/imap/IMAPFolder.java Fri Jan 24 13:49:50 2014 -0800
+++ b/mail/src/main/java/com/sun/mail/imap/IMAPFolder.java Fri Jan 24 16:26:09 2014 -0800
@@ -1384,6 +1384,7 @@
             if (!opened)
                 return;
 
+ boolean reuseProtocol = true;
             try {
                 waitIfIdle();
                 if (force) {
@@ -1412,15 +1413,30 @@
                                     protocol.hasCapability("UNSELECT"))
                                 protocol.unselect();
                             else {
+ // Unselect isn't supported so we need to
+ // select a folder to cause this one to be
+ // deselected without expunging messages.
+ // We try to do that by reopening the current
+ // folder read-only. If the current folder
+ // was renamed out from under us, the EXAMINE
+ // might fail, but that's ok because it still
+ // leaves us with the folder deselected.
                                 if (protocol != null) {
- protocol.examine(fullName);
- if (protocol != null) // XXX - unnecessary?
+ boolean selected = true;
+ try {
+ protocol.examine(fullName);
+ // success, folder still selected
+ } catch (CommandFailedException ex) {
+ // EXAMINE failed, folder is no
+ // longer selected
+ selected = false;
+ }
+ if (selected && protocol != null)
                                         protocol.close();
                                 }
                             }
                         } catch (ProtocolException pex2) {
- if (protocol != null)
- protocol.disconnect();
+ reuseProtocol = false; // something went wrong
                         }
                     } else {
                         if (protocol != null)
@@ -1432,7 +1448,7 @@
             } finally {
                 // cleanup if we haven't already
                 if (opened)
- cleanup(true);
+ cleanup(reuseProtocol);
             }
         }
     }

diff -r c88d051bc82f -r f1e6cb4e3b04 mail/src/test/java/com/sun/mail/imap/IMAPCloseFailureTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/test/java/com/sun/mail/imap/IMAPCloseFailureTest.java Fri Jan 24 16:26:09 2014 -0800
@@ -0,0 +1,136 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 2009-2014 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
+ * 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_1_1.html
+ * or packager/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 packager/legal/LICENSE.txt.
+ *
+ * GPL Classpath Exception:
+ * Oracle designates this particular file as subject to the "Classpath"
+ * exception as provided by Oracle in the GPL Version 2 section of the License
+ * file that accompanied this code.
+ *
+ * Modifications:
+ * If applicable, add the following below the License Header, with the fields
+ * enclosed by brackets [] replaced by your own identifying information:
+ * "Portions Copyright [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.
+ */
+
+package com.sun.mail.imap;
+
+import java.io.*;
+import java.util.Properties;
+
+import javax.mail.Session;
+import javax.mail.Store;
+import javax.mail.Folder;
+
+import org.junit.Test;
+import static org.junit.Assert.fail;
+
+/**
+ * Test that failures while closing a folder are handled properly.
+ */
+public final class IMAPCloseFailureTest {
+
+ private static final String HOST = "localhost";
+ private static final int PORT = 26422;
+
+ static class NoIMAPHandler extends IMAPHandler {
+ static boolean first = true;
+
+ public void examine() throws IOException {
+ if (first)
+ no("mailbox gone");
+ else
+ super.examine();
+ first = false;
+ }
+ }
+
+ static class BadIMAPHandler extends IMAPHandler {
+ static boolean first = true;
+
+ public void examine() throws IOException {
+ if (first)
+ bad("mailbox gone");
+ else
+ super.examine();
+ first = false;
+ }
+ }
+
+ @Test
+ public void testCloseNo() {
+ testClose(new NoIMAPHandler());
+ }
+
+ @Test
+ public void testCloseBad() {
+ testClose(new BadIMAPHandler());
+ }
+
+ public void testClose(IMAPHandler handler) {
+ IMAPServer server = null;
+ try {
+ server = new IMAPServer(handler, PORT);
+ server.start();
+ Thread.sleep(1000);
+
+ Properties properties = new Properties();
+ properties.setProperty("mail.imap.host", HOST);
+ properties.setProperty("mail.imap.port", "" + PORT);
+ Session session = Session.getInstance(properties);
+ //session.setDebug(true);
+
+ Store store = session.getStore("imap");
+ try {
+ store.connect("test", "test");
+ Folder f = store.getFolder("INBOX");
+ f.open(Folder.READ_WRITE);
+ f.close(false);
+ // Make sure that failure while closing doesn't leave us
+ // with a connection that can't be used to open a folder.
+ f.open(Folder.READ_WRITE);
+ f.close(false);
+ } catch (Exception ex) {
+ System.out.println(ex);
+ //ex.printStackTrace();
+ fail(ex.toString());
+ } finally {
+ if (store.isConnected())
+ store.close();
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail(e.getMessage());
+ } finally {
+ if (server != null) {
+ server.quit();
+ }
+ }
+ }
+}


diff -r f1e6cb4e3b04 -r 54e359ea2c07 doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Fri Jan 24 16:26:09 2014 -0800
+++ b/doc/release/CHANGES.txt Fri Jan 24 16:33:06 2014 -0800
@@ -26,6 +26,7 @@
 K 6208 SASL authentication failures should not try other methods
 K 6238 add OAuth2 support to JavaMail
 K 6260 IMAP failures during close can leave connection unusable
+K 6261 need way to monitor IMAP responses
 
 
                   CHANGES IN THE 1.5.1 RELEASE

diff -r f1e6cb4e3b04 -r 54e359ea2c07 mail/src/main/java/com/sun/mail/imap/IMAPStore.java
--- a/mail/src/main/java/com/sun/mail/imap/IMAPStore.java Fri Jan 24 16:26:09 2014 -0800
+++ b/mail/src/main/java/com/sun/mail/imap/IMAPStore.java Fri Jan 24 16:33:06 2014 -0800
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997-2014 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
@@ -219,6 +219,8 @@
     private String[] saslMechanisms;
     private boolean forcePasswordRefresh = false;
     // enable notification of IMAP responses
+ private boolean enableResponseEvents = false;
+ // enable notification of IMAP responses during IDLE
     private boolean enableImapEvents = false;
     private String guid; // for Yahoo! Mail IMAP
     private boolean throwSearchException = false;
@@ -569,10 +571,16 @@
             logger.config("enable forcePasswordRefresh");
 
         // check if enableimapevents is enabled
+ enableResponseEvents = PropUtil.getBooleanSessionProperty(session,
+ "mail." + name + ".enableresponseevents", false);
+ if (enableResponseEvents)
+ logger.config("enable IMAP response events");
+
+ // check if enableresponseevents is enabled
         enableImapEvents = PropUtil.getBooleanSessionProperty(session,
             "mail." + name + ".enableimapevents", false);
         if (enableImapEvents)
- logger.config("enable IMAP events");
+ logger.config("enable IMAP IDLE events");
 
         // check if message cache debugging set
         messageCacheDebug = PropUtil.getBooleanSessionProperty(session,
@@ -2079,6 +2087,8 @@
      * Response must be an OK, NO, BAD, or BYE response.
      */
     void handleResponseCode(Response r) {
+ if (enableResponseEvents)
+ notifyStoreListeners(IMAPStore.RESPONSE, r.toString());
         String s = r.getRest(); // get the text after the response
         boolean isAlert = false;
         if (s.startsWith("[")) { // a response code

diff -r f1e6cb4e3b04 -r 54e359ea2c07 mail/src/main/java/com/sun/mail/imap/package.html
--- a/mail/src/main/java/com/sun/mail/imap/package.html Fri Jan 24 16:26:09 2014 -0800
+++ b/mail/src/main/java/com/sun/mail/imap/package.html Fri Jan 24 16:33:06 2014 -0800
@@ -653,6 +653,21 @@
 </TR>
 
 <TR>
+<TD>mail.imap.enableresponseevents</TD>
+<TD>boolean</TD>
+<TD>
+Enable special IMAP-specific events to be delivered to the Store's
+<code>ConnectionListener</code>. If true, IMAP OK, NO, BAD, or BYE responses
+will be sent as <code>ConnectionEvent</code>s with a type of
+<code>IMAPStore.RESPONSE</code>. The event's message will be the
+raw IMAP response string.
+By default, these events are not sent.
+NOTE: This capability is highly experimental and likely will change
+in future releases.
+</TD>
+</TR>
+
+<TR>
 <TD>mail.imap.enableimapevents</TD>
 <TD>boolean</TD>
 <TD>