commits@javamail.java.net

[javamail~mercurial:782] Fix and exclude some FindBugs errors.

From: <shannon_at_java.net>
Date: Fri, 16 Oct 2015 18:44:46 +0000

Project: javamail
Repository: mercurial
Revision: 782
Author: shannon
Date: 2015-10-15 21:58:50 UTC
Link:

Log Message:
------------
Be sure to close folder on test failure.
IdleManager can deadlock when not busy - bug 7026
Improve choice of port number for test server.
IMAP Folder methods throw runtime exceptions when connection drops - bug 7027
InternetAddress doesn't detect some illegal newlines - bug 7028
Fix and exclude some FindBugs errors.


Revisions:
----------
777
778
779
780
781
782


Modified Paths:
---------------
mail/src/test/java/com/sun/mail/imap/IMAPIdleManagerTest.java
doc/release/CHANGES.txt
mail/src/main/java/com/sun/mail/imap/IdleManager.java
mail/src/test/java/com/sun/mail/pop3/POP3Handler.java
mail/src/test/java/com/sun/mail/test/TestServer.java
mail/src/main/java/com/sun/mail/imap/IMAPFolder.java
mail/src/main/java/javax/mail/internet/InternetAddress.java
mail/exclude.xml
mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java


Added Paths:
------------
mail/src/test/java/javax/mail/internet/InternetAddressExtraTest.java


Diffs:
------
diff -r 996e4c69f94d -r 67425bae4588 mail/src/test/java/com/sun/mail/imap/IMAPIdleManagerTest.java
--- a/mail/src/test/java/com/sun/mail/imap/IMAPIdleManagerTest.java Fri Oct 09 17:01:38 2015 -0700
+++ b/mail/src/test/java/com/sun/mail/imap/IMAPIdleManagerTest.java Thu Oct 15 13:32:50 2015 -0700
@@ -106,9 +106,10 @@
             idleManager = new IdleManager(session, executor);
 
             final IMAPStore store = (IMAPStore)session.getStore("imap");
+ Folder folder = null;
             try {
                 store.connect("test", "test");
- Folder folder = store.getFolder("INBOX");
+ folder = store.getFolder("INBOX");
                 folder.open(Folder.READ_WRITE);
                 idleManager.watch(folder);
                 handler.waitForIdle();
@@ -125,9 +126,12 @@
                 assertEquals(3, count);
             } catch (Exception ex) {
                 System.out.println(ex);
- //ex.printStackTrace();
+ ex.printStackTrace();
                 fail(ex.toString());
             } finally {
+ try {
+ folder.close(false);
+ } catch (Exception ex2) { }
                 store.close();
             }
         } catch (final Exception e) {
@@ -198,9 +202,10 @@
             idleManager = new IdleManager(session, executor);
 
             final IMAPStore store = (IMAPStore)session.getStore("imap");
+ Folder folder = null;
             try {
                 store.connect("test", "test");
- Folder folder = store.getFolder("INBOX");
+ folder = store.getFolder("INBOX");
                 folder.open(Folder.READ_WRITE);
                 idleManager.watch(folder);
                 handler.waitForIdle();
@@ -214,10 +219,13 @@
             } catch (MessagingException mex) {
                 // success!
             } catch (Exception ex) {
- System.out.println(ex);
- //ex.printStackTrace();
+ System.out.println("Failed with exception: " + ex);
+ ex.printStackTrace();
                 fail(ex.toString());
             } finally {
+ try {
+ folder.close(false);
+ } catch (Exception ex2) { }
                 store.close();
             }
         } catch (final Exception e) {


diff -r 67425bae4588 -r 6fbb33e5800c doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Thu Oct 15 13:32:50 2015 -0700
+++ b/doc/release/CHANGES.txt Thu Oct 15 13:34:29 2015 -0700
@@ -34,6 +34,7 @@
 K 7009 whitespace line at beginning confuses InternetHeaders
 K 7014 IndexOutOfBoundsException reading IMAP literal when connection fails
 K 7019 IdleManager dies with CancelledKeyException
+K 7026 IdleManager can deadlock when not busy
 
 
                   CHANGES IN THE 1.5.4 RELEASE

diff -r 67425bae4588 -r 6fbb33e5800c mail/src/main/java/com/sun/mail/imap/IdleManager.java
--- a/mail/src/main/java/com/sun/mail/imap/IdleManager.java Thu Oct 15 13:32:50 2015 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/IdleManager.java Thu Oct 15 13:34:29 2015 -0700
@@ -279,7 +279,7 @@
                  */
                 do {
                     processKeys();
- } while (selector.selectNow() > 0);
+ } while (selector.selectNow() > 0 || !toAbort.isEmpty());
             }
         } catch (InterruptedIOException ex) {
             logger.log(Level.FINEST, "IdleManager interrupted", ex);


diff -r 6fbb33e5800c -r a722b6284431 mail/src/test/java/com/sun/mail/pop3/POP3Handler.java
--- a/mail/src/test/java/com/sun/mail/pop3/POP3Handler.java Thu Oct 15 13:34:29 2015 -0700
+++ b/mail/src/test/java/com/sun/mail/pop3/POP3Handler.java Thu Oct 15 14:07:49 2015 -0700
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright (c) 2009-2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009-2015 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
@@ -122,7 +122,8 @@
         this.currentLine = this.reader.readLine();
 
         if (this.currentLine == null) {
- LOGGER.severe("Current line is null!");
+ // probably just EOF because the socket was closed
+ //LOGGER.severe("Current line is null!");
             this.exit();
             return;
         }

diff -r 6fbb33e5800c -r a722b6284431 mail/src/test/java/com/sun/mail/test/TestServer.java
--- a/mail/src/test/java/com/sun/mail/test/TestServer.java Thu Oct 15 13:34:29 2015 -0700
+++ b/mail/src/test/java/com/sun/mail/test/TestServer.java Thu Oct 15 14:07:49 2015 -0700
@@ -45,7 +45,7 @@
 import java.io.IOException;
 import java.net.ServerSocket;
 import java.net.Socket;
-//import javax.net.ssl.SSLServerSocketFactory;
+import java.net.InetSocketAddress;
 import javax.net.ssl.*;
 
 /**
@@ -85,10 +85,41 @@
     public TestServer(final ProtocolHandler handler, final boolean isSSL)
                                 throws IOException {
         this.handler = handler;
+
+ /*
+ * Allowing the JDK to pick a port number sometimes results in it
+ * picking a number that's already in use by another process, but
+ * no error is returned. Picking it ourself allows us to make sure
+ * that it's not used before we pick it. Hopefully the socket
+ * creation will fail if the port is already in use.
+ *
+ * XXX - perhaps we should use Random to choose a port number in
+ * the emphemeral range, in case a lot of low port numbers are
+ * already in use.
+ */
+ for (int port = 49152; port < 50000 /*65535*/; port++) {
+ /*
+ if (isListening(port))
+ continue;
+ */
+ try {
+ serverSocket = createServerSocket(port, isSSL);
+ return;
+ } catch (IOException ex) {
+ // ignore
+ }
+ return;
+ }
+ throw new RuntimeException("Can't find unused port");
+ }
+
+ private static ServerSocket createServerSocket(int port, boolean isSSL)
+ throws IOException {
+ ServerSocket ss;
         if (isSSL) {
             SSLServerSocketFactory sf =
                 (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
- serverSocket = sf.createServerSocket(0);
+ ss = sf.createServerSocket(port);
             // enable only the anonymous cipher suites so we don't have to
             // create a server certificate
             List<String> anon = new ArrayList<String>();
@@ -98,10 +129,11 @@
                     anon.add(suites[i]);
                 }
             }
- ((SSLServerSocket)serverSocket).setEnabledCipherSuites(
- anon.toArray(new String[anon.size()]));
+ ((SSLServerSocket)ss).setEnabledCipherSuites(
+ anon.toArray(new String[anon.size()]));
         } else
- serverSocket = new ServerSocket(0);
+ ss = new ServerSocket(port);
+ return ss;
     }
 
     /**
@@ -129,6 +161,23 @@
     /**
      * {_at_inheritDoc}
      */
+ public void start() {
+ super.start();
+ // don't return until server is really listening
+ // XXX - this might not be necessary
+ for (int tries = 0; tries < 10; tries++) {
+ if (isListening(getPort()))
+ return;
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException ex) { }
+ }
+ throw new RuntimeException("Server isn't listening");
+ }
+
+ /**
+ * {_at_inheritDoc}
+ */
     public void run() {
         try {
             keepOn = true;
@@ -148,4 +197,17 @@
             quit();
         }
     }
+
+ private static boolean isListening(int port) {
+ try {
+ Socket s = new Socket();
+ s.connect(new InetSocketAddress("localhost", port), 100);
+ // it's listening!
+ s.close();
+ return true;
+ } catch (Exception ex) {
+ //System.out.println(ex);
+ }
+ return false;
+ }
 }


diff -r a722b6284431 -r a9761c3219a6 doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Thu Oct 15 14:07:49 2015 -0700
+++ b/doc/release/CHANGES.txt Thu Oct 15 14:09:39 2015 -0700
@@ -35,6 +35,7 @@
 K 7014 IndexOutOfBoundsException reading IMAP literal when connection fails
 K 7019 IdleManager dies with CancelledKeyException
 K 7026 IdleManager can deadlock when not busy
+K 7027 IMAP Folder methods throw runtime exceptions when connection drops
 
 
                   CHANGES IN THE 1.5.4 RELEASE

diff -r a722b6284431 -r a9761c3219a6 mail/src/main/java/com/sun/mail/imap/IMAPFolder.java
--- a/mail/src/main/java/com/sun/mail/imap/IMAPFolder.java Thu Oct 15 14:07:49 2015 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/IMAPFolder.java Thu Oct 15 14:09:39 2015 -0700
@@ -811,9 +811,9 @@
      * Check whether this folder has new messages.
      */
     public synchronized boolean hasNewMessages() throws MessagingException {
- if (opened) { // If we are open, we already have this information
- // Folder is open, make sure information is up to date
- synchronized(messageCacheLock) {
+ synchronized (messageCacheLock) {
+ if (opened) { // If we are open, we already have this information
+ // Folder is open, make sure information is up to date
                 // tickle the folder and store connections.
                 try {
                     keepConnectionAlive(true);
@@ -1129,7 +1129,15 @@
      */
     public synchronized void fetch(Message[] msgs, FetchProfile fp)
                         throws MessagingException {
- checkOpened();
+ // cache this information in case connection is closed and
+ // protocol is set to null
+ boolean isRev1;
+ FetchItem[] fitems;
+ synchronized (messageCacheLock) {
+ checkOpened();
+ isRev1 = protocol.isREV1();
+ fitems = protocol.getFetchItems();
+ }
 
         StringBuffer command = new StringBuffer();
         boolean first = true;
@@ -1153,7 +1161,7 @@
         }
         if (fp.contains(IMAPFolder.FetchProfileItem.HEADERS)) {
             allHeaders = true;
- if (protocol.isREV1())
+ if (isRev1)
                 command.append(first ?
                             "BODY.PEEK[HEADER]" : " BODY.PEEK[HEADER]");
             else
@@ -1162,7 +1170,7 @@
         }
         if (fp.contains(IMAPFolder.FetchProfileItem.MESSAGE)) {
             allHeaders = true;
- if (protocol.isREV1())
+ if (isRev1)
                 command.append(first ? "BODY.PEEK[]" : " BODY.PEEK[]");
             else
                 command.append(first ? "RFC822" : " RFC822");
@@ -1181,14 +1189,13 @@
             if (hdrs.length > 0) {
                 if (!first)
                     command.append(" ");
- command.append(createHeaderCommand(hdrs));
+ command.append(createHeaderCommand(hdrs, isRev1));
             }
         }
 
         /*
          * Add any additional extension fetch items.
          */
- FetchItem[] fitems = protocol.getFetchItems();
         for (int i = 0; i < fitems.length; i++) {
             if (fp.contains(fitems[i].getFetchProfileItem())) {
                 if (command.length() != 0)
@@ -1201,7 +1208,10 @@
             new IMAPMessage.FetchProfileCondition(fp, fitems);
 
         // Acquire the Folder's MessageCacheLock.
- synchronized(messageCacheLock) {
+ synchronized (messageCacheLock) {
+
+ // check again to make sure folder is still open
+ checkOpened();
 
             // Apply the test, and get the sequence-number set for
             // the messages that need to be prefetched.
@@ -1304,10 +1314,10 @@
      * Create the appropriate IMAP FETCH command items to fetch the
      * requested headers.
      */
- private String createHeaderCommand(String[] hdrs) {
+ private String createHeaderCommand(String[] hdrs, boolean isRev1) {
         StringBuffer sb;
 
- if (protocol.isREV1())
+ if (isRev1)
             sb = new StringBuffer("BODY.PEEK[HEADER.FIELDS (");
         else
             sb = new StringBuffer("RFC822.HEADER.LINES (");
@@ -1318,7 +1328,7 @@
             sb.append(hdrs[i]);
         }
 
- if (protocol.isREV1())
+ if (isRev1)
             sb.append(")]");
         else
             sb.append(")");
@@ -1537,96 +1547,95 @@
      * Get the total message count.
      */
     public synchronized int getMessageCount() throws MessagingException {
- if (!opened) {
- checkExists();
- // If this folder is not yet open, we use STATUS to
- // get the total message count
- try {
- Status status = getStatus();
- return status.total;
- } catch (BadCommandException bex) {
- // doesn't support STATUS, probably vanilla IMAP4 ..
- // lets try EXAMINE
- IMAPProtocol p = null;
-
- try {
- p = getStoreProtocol(); // XXX
- MailboxInfo minfo = p.examine(fullName);
- p.close();
- return minfo.total;
+ synchronized (messageCacheLock) {
+ if (opened) {
+ // Folder is open, we know what the total message count is ..
+ // tickle the folder and store connections.
+ try {
+ keepConnectionAlive(true);
+ return total;
+ } catch (ConnectionException cex) {
+ throw new FolderClosedException(this, cex.getMessage());
                 } catch (ProtocolException pex) {
- // Give up.
                     throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(p);
- }
- } catch (ConnectionException cex) {
- throw new StoreClosedException(store, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
+ }
             }
         }
 
- // Folder is open, we know what the total message count is ..
- synchronized(messageCacheLock) {
- // tickle the folder and store connections.
+ // If this folder is not yet open, we use STATUS to
+ // get the total message count
+ checkExists();
+ try {
+ Status status = getStatus();
+ return status.total;
+ } catch (BadCommandException bex) {
+ // doesn't support STATUS, probably vanilla IMAP4 ..
+ // lets try EXAMINE
+ IMAPProtocol p = null;
+
             try {
- keepConnectionAlive(true);
- return total;
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
+ p = getStoreProtocol(); // XXX
+ MailboxInfo minfo = p.examine(fullName);
+ p.close();
+ return minfo.total;
             } catch (ProtocolException pex) {
+ // Give up.
                 throw new MessagingException(pex.getMessage(), pex);
+ } finally {
+ releaseStoreProtocol(p);
             }
+ } catch (ConnectionException cex) {
+ throw new StoreClosedException(store, cex.getMessage());
+ } catch (ProtocolException pex) {
+ throw new MessagingException(pex.getMessage(), pex);
         }
     }
 
     /**
      * Get the new message count.
      */
- public synchronized int getNewMessageCount()
- throws MessagingException {
- if (!opened) {
- checkExists();
- // If this folder is not yet open, we use STATUS to
- // get the new message count
- try {
- Status status = getStatus();
- return status.recent;
- } catch (BadCommandException bex) {
- // doesn't support STATUS, probably vanilla IMAP4 ..
- // lets try EXAMINE
- IMAPProtocol p = null;
-
- try {
- p = getStoreProtocol(); // XXX
- MailboxInfo minfo = p.examine(fullName);
- p.close();
- return minfo.recent;
+ public synchronized int getNewMessageCount() throws MessagingException {
+ synchronized (messageCacheLock) {
+ if (opened) {
+ // Folder is open, we know what the new message count is ..
+ // tickle the folder and store connections.
+ try {
+ keepConnectionAlive(true);
+ return recent;
+ } catch (ConnectionException cex) {
+ throw new FolderClosedException(this, cex.getMessage());
                 } catch (ProtocolException pex) {
- // Give up.
                     throw new MessagingException(pex.getMessage(), pex);
- } finally {
- releaseStoreProtocol(p);
- }
- } catch (ConnectionException cex) {
- throw new StoreClosedException(store, cex.getMessage());
- } catch (ProtocolException pex) {
- throw new MessagingException(pex.getMessage(), pex);
+ }
             }
         }
 
- // Folder is open, we know what the new message count is ..
- synchronized(messageCacheLock) {
- // tickle the folder and store connections.
+ // If this folder is not yet open, we use STATUS to
+ // get the new message count
+ checkExists();
+ try {
+ Status status = getStatus();
+ return status.recent;
+ } catch (BadCommandException bex) {
+ // doesn't support STATUS, probably vanilla IMAP4 ..
+ // lets try EXAMINE
+ IMAPProtocol p = null;
+
             try {
- keepConnectionAlive(true);
- return recent;
- } catch (ConnectionException cex) {
- throw new FolderClosedException(this, cex.getMessage());
+ p = getStoreProtocol(); // XXX
+ MailboxInfo minfo = p.examine(fullName);
+ p.close();
+ return minfo.recent;
             } catch (ProtocolException pex) {
+ // Give up.
                 throw new MessagingException(pex.getMessage(), pex);
+ } finally {
+ releaseStoreProtocol(p);
             }
+ } catch (ConnectionException cex) {
+ throw new StoreClosedException(store, cex.getMessage());
+ } catch (ProtocolException pex) {
+ throw new MessagingException(pex.getMessage(), pex);
         }
     }
 
@@ -1740,6 +1749,23 @@
     }
 
     /**
+ * {_at_inheritDoc}
+ */
+ @Override
+ public synchronized Message[] getMessages() throws MessagingException {
+ /*
+ * Need to override Folder method to throw FolderClosedException
+ * instead of IllegalStateException if not really closed.
+ */
+ checkOpened();
+ int total = getMessageCount();
+ Message[] msgs = new Message[total];
+ for (int i = 1; i <= total; i++)
+ msgs[i - 1] = messageCache.getMessage(i);
+ return msgs;
+ }
+
+ /**
      * Append the given messages into this folder.
      */
     public synchronized void appendMessages(Message[] msgs)
@@ -3796,6 +3822,9 @@
     protected void keepConnectionAlive(boolean keepStoreAlive)
                     throws ProtocolException {
 
+ assert Thread.holdsLock(messageCacheLock);
+ if (protocol == null) // in case connection was closed
+ return;
         if (System.currentTimeMillis() - protocol.getTimestamp() > 1000) {
             waitIfIdle();
             if (protocol != null)


diff -r a9761c3219a6 -r f09caad515ba doc/release/CHANGES.txt
--- a/doc/release/CHANGES.txt Thu Oct 15 14:09:39 2015 -0700
+++ b/doc/release/CHANGES.txt Thu Oct 15 14:21:50 2015 -0700
@@ -36,6 +36,7 @@
 K 7019 IdleManager dies with CancelledKeyException
 K 7026 IdleManager can deadlock when not busy
 K 7027 IMAP Folder methods throw runtime exceptions when connection drops
+K 7028 InternetAddress doesn't detect some illegal newlines
 
 
                   CHANGES IN THE 1.5.4 RELEASE

diff -r a9761c3219a6 -r f09caad515ba mail/src/main/java/javax/mail/internet/InternetAddress.java
--- a/mail/src/main/java/javax/mail/internet/InternetAddress.java Thu Oct 15 14:09:39 2015 -0700
+++ b/mail/src/main/java/javax/mail/internet/InternetAddress.java Thu Oct 15 14:21:50 2015 -0700
@@ -1211,6 +1211,22 @@
                     inquote = true;
                 }
                 continue;
+ } else if (c == '\r') {
+ // peek ahead, next char must be LF
+ if (i + 1 < len && addr.charAt(i + 1) != '\n')
+ throw new AddressException(
+ "Quoted local address contains CR without LF", addr);
+ } else if (c == '\n') {
+ /*
+ * CRLF followed by whitespace is allowed in a quoted string.
+ * We allowed naked LF, but ensure LF is always followed by
+ * whitespace to prevent spoofing the end of the header.
+ */
+ if (i + 1 < len && addr.charAt(i + 1) != ' ' &&
+ addr.charAt(i + 1) != '\t')
+ throw new AddressException(
+ "Quoted local address contains newline without whitespace",
+ addr);
             }
             if (inquote)
                 continue;
@@ -1255,11 +1271,20 @@
 
         if (addr.charAt(start) == '.')
             throw new AddressException("Domain starts with dot", addr);
+ boolean inliteral = false;
         for (i = start; i < len; i++) {
             c = addr.charAt(i);
- if (c == '[')
- return; // domain literal, don't validate
- if (c <= 040 || c >= 0177)
+ if (c == '[') {
+ if (i != start)
+ throw new AddressException(
+ "Domain literal not at start of domain", addr);
+ inliteral = true; // domain literal, don't validate
+ } else if (c == ']') {
+ if (i != len - 1)
+ throw new AddressException(
+ "Domain literal end not at end of domain", addr);
+ inliteral = false;
+ } else if (c <= 040 || c >= 0177)
                 throw new AddressException(
                                 "Domain contains control or whitespace", addr);
             // RFC 2822 rule
@@ -1275,12 +1300,14 @@
              * <let-dig-hyp> ::= <let-dig> | "-"
              * <let-dig> ::= <letter> | <digit>
              */
- if (!(Character.isLetterOrDigit(c) || c == '-' || c == '.'))
- throw new AddressException(
- "Domain contains illegal character", addr);
- if (c == '.' && lastc == '.')
- throw new AddressException(
- "Domain contains dot-dot", addr);
+ if (!inliteral) {
+ if (!(Character.isLetterOrDigit(c) || c == '-' || c == '.'))
+ throw new AddressException(
+ "Domain contains illegal character", addr);
+ if (c == '.' && lastc == '.')
+ throw new AddressException(
+ "Domain contains dot-dot", addr);
+ }
             lastc = c;
         }
         if (lastc == '.')

diff -r a9761c3219a6 -r f09caad515ba mail/src/test/java/javax/mail/internet/InternetAddressExtraTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mail/src/test/java/javax/mail/internet/InternetAddressExtraTest.java Thu Oct 15 14:21:50 2015 -0700
@@ -0,0 +1,87 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright (c) 1997-2015 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 javax.mail.internet;
+
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.AddressException;
+
+import org.junit.Test;
+
+import static org.junit.Assert.fail;
+
+/**
+ * Test Internet address parsing that can't be tested using paramterized test.
+ *
+ * @author Bill Shannon
+ */
+
+public class InternetAddressExtraTest {
+ @Test
+ public void testNewlineInDomainLiteral() throws Exception {
+ InternetAddress ia = new InternetAddress("test@[\r\nfoo]", "test");
+ try {
+ ia.validate();
+ fail("validation succeeded");
+ } catch (AddressException ex) {
+ // success!
+ }
+ }
+
+ @Test
+ public void testNewlineInLocal() throws Exception {
+ InternetAddress ia =
+ new InternetAddress("\"test\r\nfoo\"@example.com", "test");
+ try {
+ ia.validate();
+ fail("validation succeeded");
+ } catch (AddressException ex) {
+ // success!
+ }
+ }
+
+ @Test
+ public void testNewlineInLocalWithWhitespace() throws Exception {
+ InternetAddress ia =
+ new InternetAddress("\"test\r\n foo\"@example.com", "test");
+ ia.validate();
+ // success!
+ }
+}


diff -r f09caad515ba -r a03425201934 mail/exclude.xml
--- a/mail/exclude.xml Thu Oct 15 14:21:50 2015 -0700
+++ b/mail/exclude.xml Thu Oct 15 14:58:50 2015 -0700
@@ -171,6 +171,7 @@
             <Method name="authlogin"/>
             <Method name="authntlm"/>
             <Method name="authplain"/>
+ <Method name="authoauth2"/>
             <Method name="sasllogin"/>
         </Or>
         <Bug pattern="REC_CATCH_EXCEPTION"/>
@@ -370,6 +371,16 @@
     </Match>
 
     <!--
+ This string comparison using == is to determine whether the
+ String object is the original default String object.
+ -->
+ <Match>
+ <Class name="com.sun.mail.smtp.SMTPTransport"/>
+ <Method name="authenticate"/>
+ <Bug pattern="ES_COMPARING_STRINGS_WITH_EQ"/>
+ </Match>
+
+ <!--
         ByteArrayInputStream.available guarantees to return the full number
         of bytes left in the buffer, and ByteArrayInputStream.read guarantees
         to read all the bytes, so we don't really need to check the return

diff -r f09caad515ba -r a03425201934 mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java
--- a/mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java Thu Oct 15 14:21:50 2015 -0700
+++ b/mail/src/main/java/com/sun/mail/imap/protocol/IMAPProtocol.java Thu Oct 15 14:58:50 2015 -0700
@@ -129,8 +129,10 @@
             this.name = name;
             noauthdebug =
                 !PropUtil.getBooleanProperty(props, "mail.debug.auth", false);
+
+ // in case it was not initialized in processGreeting
             referralException = PropUtil.getBooleanProperty(props,
- "mail." + name + ".referralexception", false);
+ prefix + ".referralexception", false);
 
             if (capabilities == null)
                 capability();
@@ -300,6 +302,9 @@
         }
         if (r.isOK()) { // check if it's OK
             // XXX - is a REFERRAL response code really allowed here?
+ // XXX - referralException hasn't been initialized in c'tor yet
+ referralException = PropUtil.getBooleanProperty(props,
+ prefix + ".referralexception", false);
             if (referralException)
                 checkReferral(r);
             setCapabilities(r);