You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mime4j-dev@james.apache.org by ol...@apache.org on 2011/06/09 17:17:29 UTC

svn commit: r1133920 - in /james/mime4j/trunk: core/src/main/java/org/apache/james/mime4j/stream/ core/src/test/java/org/apache/james/mime4j/stream/ dom/src/main/java/org/apache/james/mime4j/field/ dom/src/main/java/org/apache/james/mime4j/field/addres...

Author: olegk
Date: Thu Jun  9 15:17:28 2011
New Revision: 1133920

URL: http://svn.apache.org/viewvc?rev=1133920&view=rev
Log:
MIME4J-197: Lenient implementation of Mailbox parser; refactored AddressBuilder and AddressFormatter test cases

Added:
    james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java   (with props)
    james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressBuilderTest.java   (with props)
    james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressFormatterTest.java   (with props)
    james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java   (with props)
Modified:
    james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java
    james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java
    james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldLenientImpl.java
    james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldLenientImpl.java
    james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldLenientImpl.java
    james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/AddressTest.java

Modified: james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java?rev=1133920&r1=1133919&r2=1133920&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java (original)
+++ james/mime4j/trunk/core/src/main/java/org/apache/james/mime4j/stream/RawFieldParser.java Thu Jun  9 15:17:28 2011
@@ -103,7 +103,7 @@ public class RawFieldParser {
         return new NameValuePair(name, value);
     }
 
-    static boolean isOneOf(final int ch, final int[] chs) {
+    public static boolean isOneOf(final int ch, final int[] chs) {
         if (chs != null) {
             for (int i = 0; i < chs.length; i++) {
                 if (ch == chs[i]) {
@@ -114,7 +114,7 @@ public class RawFieldParser {
         return false;
     }
 
-    public static String parseToken(final ByteSequence buf, final ParserCursor cursor, final int[] delimiters) {
+    public String parseToken(final ByteSequence buf, final ParserCursor cursor, final int[] delimiters) {
         StringBuilder dst = new StringBuilder();
         boolean whitespace = false;
         while (!cursor.atEnd()) {
@@ -137,7 +137,7 @@ public class RawFieldParser {
         return dst.toString();
     }
 
-    public static String parseValue(final ByteSequence buf, final ParserCursor cursor, final int[] delimiters) {
+    public String parseValue(final ByteSequence buf, final ParserCursor cursor, final int[] delimiters) {
         StringBuilder dst = new StringBuilder();
         boolean whitespace = false;
         while (!cursor.atEnd()) {
@@ -166,7 +166,7 @@ public class RawFieldParser {
         return dst.toString();
     }
 
-    public static void skipWhiteSpace(final ByteSequence buf, final ParserCursor cursor) {
+    public void skipWhiteSpace(final ByteSequence buf, final ParserCursor cursor) {
         int pos = cursor.getPos();
         int indexFrom = cursor.getPos();
         int indexTo = cursor.getUpperBound();
@@ -181,7 +181,7 @@ public class RawFieldParser {
         cursor.updatePos(pos);
     }
 
-    public static void skipComment(final ByteSequence buf, final ParserCursor cursor) {
+    public void skipComment(final ByteSequence buf, final ParserCursor cursor) {
         if (cursor.atEnd()) {
             return;
         }
@@ -218,7 +218,20 @@ public class RawFieldParser {
         cursor.updatePos(pos);
     }
 
-    public static void copyContent(final ByteSequence buf, final ParserCursor cursor, final int[] delimiters,
+    public void skipAllWhiteSpace(final ByteSequence buf, final ParserCursor cursor) {
+        while (!cursor.atEnd()) {
+            char current = (char) (buf.byteAt(cursor.getPos()) & 0xff);
+            if (CharsetUtil.isWhitespace(current)) {
+                skipWhiteSpace(buf, cursor);
+            } else if (current == '(') {
+                skipComment(buf, cursor);
+            } else {
+                break;
+            }
+        }
+    }
+    
+    public void copyContent(final ByteSequence buf, final ParserCursor cursor, final int[] delimiters,
             final StringBuilder dst) {
         int pos = cursor.getPos();
         int indexFrom = cursor.getPos();
@@ -235,7 +248,7 @@ public class RawFieldParser {
         cursor.updatePos(pos);
     }
 
-    public static void copyQuotedContent(final ByteSequence buf, final ParserCursor cursor,
+    public void copyQuotedContent(final ByteSequence buf, final ParserCursor cursor,
             final StringBuilder dst) {
         if (cursor.atEnd()) {
             return;

Modified: james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java?rev=1133920&r1=1133919&r2=1133920&view=diff
==============================================================================
--- james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java (original)
+++ james/mime4j/trunk/core/src/test/java/org/apache/james/mime4j/stream/RawFieldParserTest.java Thu Jun  9 15:17:28 2011
@@ -30,18 +30,25 @@ import junit.framework.TestCase;
 
 public class RawFieldParserTest extends TestCase {
 
+    private RawFieldParser parser;
+    
+    @Override
+    protected void setUp() throws Exception {
+        parser = new RawFieldParser();
+    }
+
     public void testBasicTokenParsing() throws Exception {
         String s = "   raw: \" some stuff \"";
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
 
-        RawFieldParser.skipWhiteSpace(raw, cursor);
+        parser.skipWhiteSpace(raw, cursor);
 
         Assert.assertFalse(cursor.atEnd());
         Assert.assertEquals(3, cursor.getPos());
 
         StringBuilder strbuf1 = new StringBuilder();
-        RawFieldParser.copyContent(raw, cursor, new int[] { ':' }, strbuf1);
+        parser.copyContent(raw, cursor, new int[] { ':' }, strbuf1);
 
         Assert.assertFalse(cursor.atEnd());
         Assert.assertEquals(6, cursor.getPos());
@@ -49,21 +56,21 @@ public class RawFieldParserTest extends 
         Assert.assertEquals(':', raw.byteAt(cursor.getPos()));
         cursor.updatePos(cursor.getPos() + 1);
 
-        RawFieldParser.skipWhiteSpace(raw, cursor);
+        parser.skipWhiteSpace(raw, cursor);
 
         Assert.assertFalse(cursor.atEnd());
         Assert.assertEquals(8, cursor.getPos());
 
         StringBuilder strbuf2 = new StringBuilder();
-        RawFieldParser.copyQuotedContent(raw, cursor, strbuf2);
+        parser.copyQuotedContent(raw, cursor, strbuf2);
 
         Assert.assertTrue(cursor.atEnd());
         Assert.assertEquals(" some stuff ", strbuf2.toString());
 
-        RawFieldParser.copyQuotedContent(raw, cursor, strbuf2);
+        parser.copyQuotedContent(raw, cursor, strbuf2);
         Assert.assertTrue(cursor.atEnd());
 
-        RawFieldParser.skipWhiteSpace(raw, cursor);
+        parser.skipWhiteSpace(raw, cursor);
         Assert.assertTrue(cursor.atEnd());
     }
 
@@ -72,25 +79,25 @@ public class RawFieldParserTest extends 
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
 
-        RawFieldParser.skipWhiteSpace(raw, cursor);
+        parser.skipWhiteSpace(raw, cursor);
 
         Assert.assertFalse(cursor.atEnd());
         Assert.assertEquals(0, cursor.getPos());
 
         StringBuilder strbuf1 = new StringBuilder();
-        RawFieldParser.copyContent(raw, cursor, new int[] { ':' }, strbuf1);
+        parser.copyContent(raw, cursor, new int[] { ':' }, strbuf1);
 
         Assert.assertFalse(cursor.atEnd());
         Assert.assertEquals("raw", strbuf1.toString());
         Assert.assertEquals(':', raw.byteAt(cursor.getPos()));
         cursor.updatePos(cursor.getPos() + 1);
 
-        RawFieldParser.skipWhiteSpace(raw, cursor);
+        parser.skipWhiteSpace(raw, cursor);
 
         Assert.assertFalse(cursor.atEnd());
 
         StringBuilder strbuf2 = new StringBuilder();
-        RawFieldParser.copyQuotedContent(raw, cursor, strbuf2);
+        parser.copyQuotedContent(raw, cursor, strbuf2);
 
         Assert.assertTrue(cursor.atEnd());
         Assert.assertEquals("\"some\\stuff\\", strbuf2.toString());
@@ -101,7 +108,7 @@ public class RawFieldParserTest extends 
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
         StringBuilder strbuf1 = new StringBuilder();
-        RawFieldParser.copyQuotedContent(raw, cursor, strbuf1);
+        parser.copyQuotedContent(raw, cursor, strbuf1);
         Assert.assertEquals("stuff and more stuff  ", strbuf1.toString());
     }
 
@@ -110,7 +117,7 @@ public class RawFieldParserTest extends 
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
 
-        RawFieldParser.skipComment(raw, cursor);
+        parser.skipComment(raw, cursor);
         Assert.assertTrue(cursor.atEnd());
     }
 
@@ -119,7 +126,7 @@ public class RawFieldParserTest extends 
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
 
-        RawFieldParser.skipComment(raw, cursor);
+        parser.skipComment(raw, cursor);
         Assert.assertTrue(cursor.atEnd());
     }
 
@@ -127,7 +134,7 @@ public class RawFieldParserTest extends 
         String s = "  stuff and   \tsome\tmore  stuff  ;";
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
-        String result = RawFieldParser.parseToken(raw, cursor, new int[] { ';' });
+        String result = parser.parseToken(raw, cursor, new int[] { ';' });
         Assert.assertEquals("stuff and some more stuff", result);
     }
 
@@ -135,7 +142,7 @@ public class RawFieldParserTest extends 
         String s = " (blah-blah)  stuff(blah-blah) and some mo(blah-blah)re  stuff (blah-blah) ;";
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
-        String result = RawFieldParser.parseToken(raw, cursor, new int[] { ';' });
+        String result = parser.parseToken(raw, cursor, new int[] { ';' });
         Assert.assertEquals("stuff and some more stuff", result);
     }
 
@@ -143,7 +150,7 @@ public class RawFieldParserTest extends 
         String s = "  stuff and    \" some more \"   \"stuff  ;";
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
-        String result = RawFieldParser.parseValue(raw, cursor, new int[] { ';' });
+        String result = parser.parseValue(raw, cursor, new int[] { ';' });
         Assert.assertEquals("stuff and  some more  stuff  ;", result);
     }
 
@@ -151,7 +158,7 @@ public class RawFieldParserTest extends 
         String s = " (blah blah)  \"(stuff)(and)(some)(more)(stuff)\" (yada yada) ";
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
-        String result = RawFieldParser.parseValue(raw, cursor, new int[] { ';' });
+        String result = parser.parseValue(raw, cursor, new int[] { ';' });
         Assert.assertEquals("(stuff)(and)(some)(more)(stuff)", result);
     }
 
@@ -159,8 +166,6 @@ public class RawFieldParserTest extends 
         String s = "raw: stuff;\r\n  more stuff";
         ByteSequence raw = ContentUtil.encode(s);
 
-        RawFieldParser parser = new RawFieldParser();
-
         RawField field = parser.parseField(raw);
         Assert.assertSame(raw, field.getRaw());
         Assert.assertEquals("raw", field.getName());
@@ -172,8 +177,6 @@ public class RawFieldParserTest extends 
         String s = "raw:stuff";
         ByteSequence raw = ContentUtil.encode(s);
 
-        RawFieldParser parser = new RawFieldParser();
-
         RawField field = parser.parseField(raw);
         Assert.assertSame(raw, field.getRaw());
         Assert.assertEquals("raw", field.getName());
@@ -185,8 +188,6 @@ public class RawFieldParserTest extends 
         String s = "raw  \t  : stuff;\r\n  more stuff";
         ByteSequence raw = ContentUtil.encode(s);
 
-        RawFieldParser parser = new RawFieldParser();
-
         RawField field = parser.parseField(raw);
         Assert.assertSame(raw, field.getRaw());
         Assert.assertEquals("raw", field.getName());
@@ -198,8 +199,6 @@ public class RawFieldParserTest extends 
         String s = "raw    stuff;\r\n  more stuff";
         ByteSequence raw = ContentUtil.encode(s);
 
-        RawFieldParser parser = new RawFieldParser();
-
         try {
             parser.parseField(raw);
             fail("MimeException should have been thrown");
@@ -211,8 +210,6 @@ public class RawFieldParserTest extends 
         String s = "raw    \t \t";
         ByteSequence raw = ContentUtil.encode(s);
 
-        RawFieldParser parser = new RawFieldParser();
-
         try {
             parser.parseField(raw);
             fail("MimeException should have been thrown");
@@ -221,7 +218,6 @@ public class RawFieldParserTest extends 
     }
 
     public void testNameValueParseBasics() {
-        RawFieldParser parser = new RawFieldParser();
         String s = "test";
         ByteSequence buf = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
@@ -330,7 +326,6 @@ public class RawFieldParserTest extends 
     }
 
     public void testNameValueListParseBasics() {
-        RawFieldParser parser = new RawFieldParser();
         ByteSequence buf = ContentUtil.encode(
                 "test; test1 =  stuff   ; test2 =  \"stuff; stuff\"; test3=\"stuff");
         ParserCursor cursor = new ParserCursor(0, buf.length());
@@ -350,7 +345,6 @@ public class RawFieldParserTest extends 
 
     public void testNameValueListParseEmpty() {
         ByteSequence buf = ContentUtil.encode("    ");
-        RawFieldParser parser = new RawFieldParser();
         ParserCursor cursor = new ParserCursor(0, buf.length());
         List<NameValuePair> params = parser.parseParameters(buf, cursor);
         assertEquals(0, params.size());
@@ -359,7 +353,6 @@ public class RawFieldParserTest extends 
     public void testNameValueListParseEscaped() {
         ByteSequence buf = ContentUtil.encode(
           "test1 =  \"\\\"stuff\\\"\"; test2= \"\\\\\"; test3 = \"stuff; stuff\"");
-        RawFieldParser parser = new RawFieldParser();
         ParserCursor cursor = new ParserCursor(0, buf.length());
         List<NameValuePair> params = parser.parseParameters(buf, cursor);
         assertEquals(3, params.size());
@@ -375,7 +368,6 @@ public class RawFieldParserTest extends 
         ByteSequence buf = ContentUtil.encode(
                 "  text/plain ; charset=ISO-8859-1; "
                 + "boundary=foo; param1=value1; param2=\"value2\"; param3=value3");
-        RawFieldParser parser = new RawFieldParser();
         ParserCursor cursor = new ParserCursor(0, buf.length());
         RawBody body = parser.parseRawBody(buf, cursor);
         assertNotNull(body);
@@ -398,7 +390,6 @@ public class RawFieldParserTest extends 
         ByteSequence buf = ContentUtil.encode(
                 "  text/(nothing special)plain ; charset=(latin)ISO-8859-1; "
                 + "boundary=foo(bar);");
-        RawFieldParser parser = new RawFieldParser();
         ParserCursor cursor = new ParserCursor(0, buf.length());
         RawBody body = parser.parseRawBody(buf, cursor);
         assertNotNull(body);
@@ -414,7 +405,6 @@ public class RawFieldParserTest extends 
     public void testRawBodyParseEmptyParam() {
         ByteSequence buf = ContentUtil.encode(
                 "multipart/alternative;; boundary=\"boundary\"");
-        RawFieldParser parser = new RawFieldParser();
         ParserCursor cursor = new ParserCursor(0, buf.length());
         RawBody body = parser.parseRawBody(buf, cursor);
         assertNotNull(body);
@@ -430,7 +420,6 @@ public class RawFieldParserTest extends 
     public void testRawBodyParseFolded() {
         ByteSequence buf = ContentUtil.encode(
                 "multipart/alternative; boundary=\"simple\r\n boundary\"");
-        RawFieldParser parser = new RawFieldParser();
         ParserCursor cursor = new ParserCursor(0, buf.length());
         RawBody body = parser.parseRawBody(buf, cursor);
         assertNotNull(body);

Modified: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldLenientImpl.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldLenientImpl.java?rev=1133920&r1=1133919&r2=1133920&view=diff
==============================================================================
--- james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldLenientImpl.java (original)
+++ james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/ContentLanguageFieldLenientImpl.java Thu Jun  9 15:17:28 2011
@@ -61,9 +61,10 @@ public class ContentLanguageFieldLenient
             buf = ContentUtil.encode(body);
             pos = 0;
         }
+        RawFieldParser parser = RawFieldParser.DEFAULT;
         ParserCursor cursor = new ParserCursor(pos, buf.length());
         for (;;) {
-            String token = RawFieldParser.parseToken(buf, cursor, DELIM);
+            String token = parser.parseToken(buf, cursor, DELIM);
             if (token.length() > 0) {
                 languages.add(token);
             }

Modified: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldLenientImpl.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldLenientImpl.java?rev=1133920&r1=1133919&r2=1133920&view=diff
==============================================================================
--- james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldLenientImpl.java (original)
+++ james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/ContentLocationFieldLenientImpl.java Thu Jun  9 15:17:28 2011
@@ -58,8 +58,9 @@ public class ContentLocationFieldLenient
             buf = ContentUtil.encode(body);
             pos = 0;
         }
+        RawFieldParser parser = RawFieldParser.DEFAULT;
         ParserCursor cursor = new ParserCursor(pos, buf.length());
-        String token = RawFieldParser.parseValue(buf, cursor, DELIM);
+        String token = parser.parseValue(buf, cursor, DELIM);
         StringBuilder sb = new StringBuilder(token.length());
         for (int i = 0; i < token.length(); i++) {
             char ch = token.charAt(i);

Modified: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldLenientImpl.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldLenientImpl.java?rev=1133920&r1=1133919&r2=1133920&view=diff
==============================================================================
--- james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldLenientImpl.java (original)
+++ james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/MimeVersionFieldLenientImpl.java Thu Jun  9 15:17:28 2011
@@ -65,8 +65,9 @@ public class MimeVersionFieldLenientImpl
             buf = ContentUtil.encode(body);
             pos = 0;
         }
+        RawFieldParser parser = RawFieldParser.DEFAULT;
         ParserCursor cursor = new ParserCursor(pos, buf.length());
-        String token1 = RawFieldParser.parseValue(buf, cursor, DELIM1);
+        String token1 = parser.parseValue(buf, cursor, DELIM1);
         try {
             major = Integer.parseInt(token1);
             if (major < 0) {
@@ -77,7 +78,7 @@ public class MimeVersionFieldLenientImpl
         if (!cursor.atEnd() && buf.byteAt(cursor.getPos()) == FULL_STOP) {
             cursor.updatePos(cursor.getPos() + 1);
         }
-        String token2 = RawFieldParser.parseValue(buf, cursor, DELIM2);
+        String token2 = parser.parseValue(buf, cursor, DELIM2);
         try {
             minor = Integer.parseInt(token2);
             if (minor < 0) {

Added: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java?rev=1133920&view=auto
==============================================================================
--- james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java (added)
+++ james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java Thu Jun  9 15:17:28 2011
@@ -0,0 +1,184 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mime4j.field.address;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.james.mime4j.dom.address.DomainList;
+import org.apache.james.mime4j.dom.address.Mailbox;
+import org.apache.james.mime4j.stream.ParserCursor;
+import org.apache.james.mime4j.stream.RawFieldParser;
+import org.apache.james.mime4j.util.ByteSequence;
+import org.apache.james.mime4j.util.CharsetUtil;
+import org.apache.james.mime4j.util.ContentUtil;
+
+public class LenientAddressBuilder {
+
+    private static final int AT                = '@';
+    private static final int OPENING_BRACKET   = '<';
+    private static final int CLOSING_BRACKET   = '>';
+    private static final int COMMA             = ',';
+    private static final int COLON             = ':';
+
+    private static final int[] AT_AND_OPENING_BRACKET = new int[] { AT, OPENING_BRACKET };
+    private static final int[] AT_AND_CLOSING_BRACKET = new int[] { AT, CLOSING_BRACKET };
+    private static final int[] CLOSING_BRACKET_ONLY   = new int[] { CLOSING_BRACKET };
+    private static final int[] COMMA_AND_COLON        = new int[] { COMMA, COLON };
+
+    public static final LenientAddressBuilder DEFAULT = new LenientAddressBuilder();
+
+    private final RawFieldParser parser;
+
+    protected LenientAddressBuilder() {
+        super();
+        this.parser = new RawFieldParser();
+    }
+
+    String parseDomain(final ByteSequence buf, final ParserCursor cursor, final int[] delimiters) {
+        StringBuilder dst = new StringBuilder();
+        while (!cursor.atEnd()) {
+            char current = (char) (buf.byteAt(cursor.getPos()) & 0xff);
+            if (RawFieldParser.isOneOf(current, delimiters)) {
+                break;
+            } else if (CharsetUtil.isWhitespace(current)) {
+                this.parser.skipWhiteSpace(buf, cursor);
+            } else if (current == '(') {
+                this.parser.skipComment(buf, cursor);
+            } else {
+                this.parser.copyContent(buf, cursor, delimiters, dst);
+            }
+        }
+        return dst.toString();
+    }
+
+    DomainList parseRoute(final ByteSequence buf, final ParserCursor cursor) {
+        List<String> domains = null;
+        while (!cursor.atEnd()) {
+            this.parser.skipAllWhiteSpace(buf, cursor);
+            int pos = cursor.getPos();
+            int current = (char) (buf.byteAt(pos) & 0xff);
+            if (current == AT) {
+                cursor.updatePos(pos + 1);
+            } else {
+                break;
+            }
+            String s = parseDomain(buf, cursor, COMMA_AND_COLON);
+            if (s != null && s.length() > 0) {
+                if (domains == null) {
+                    domains = new ArrayList<String>();
+                }
+                domains.add(s);
+            }
+            pos = cursor.getPos();
+            current = (char) (buf.byteAt(pos) & 0xff);
+            if (current == COMMA) {
+                cursor.updatePos(pos + 1);
+                continue;
+            } else if (current == COLON) {
+                cursor.updatePos(pos + 1);
+                break;
+            } else {
+                break;
+            }
+        }
+        return domains != null ? new DomainList(domains, true) : null;
+    }
+
+    Mailbox parseMailboxAddress(
+            final String openingText,
+            final ByteSequence buf, final ParserCursor cursor, final int[] delimiters) {
+        if (cursor.atEnd()) {
+            return null;
+        }
+        int pos = cursor.getPos();
+        char current = (char) (buf.byteAt(pos) & 0xff);
+        if (current == OPENING_BRACKET) {
+            cursor.updatePos(pos + 1);
+        } else {
+            return new Mailbox(null, null, openingText, null);
+        }
+        DomainList domainList = parseRoute(buf, cursor);
+        String localPart = this.parser.parseValue(buf, cursor, AT_AND_CLOSING_BRACKET);
+        if (cursor.atEnd()) {
+            return new Mailbox(openingText, domainList, localPart, null);
+        }
+        pos = cursor.getPos();
+        current = (char) (buf.byteAt(pos) & 0xff);
+        if (current == AT) {
+            cursor.updatePos(pos + 1);
+        } else {
+            return new Mailbox(openingText, domainList, localPart, null);
+        }
+        String domain = parseDomain(buf, cursor, CLOSING_BRACKET_ONLY);
+        if (cursor.atEnd()) {
+            return new Mailbox(openingText, domainList, localPart, domain);
+        }
+        pos = cursor.getPos();
+        current = (char) (buf.byteAt(pos) & 0xff);
+        if (current == CLOSING_BRACKET) {
+            cursor.updatePos(pos + 1);
+        } else {
+            return new Mailbox(openingText, domainList, localPart, domain);
+        }
+        while (!cursor.atEnd()) {
+            pos = cursor.getPos();
+            current = (char) (buf.byteAt(pos) & 0xff);
+            if (CharsetUtil.isWhitespace(current)) {
+                this.parser.skipWhiteSpace(buf, cursor);
+            } else if (current == '(') {
+                this.parser.skipComment(buf, cursor);
+            } else {
+                break;
+            }
+        }
+        return new Mailbox(openingText, domainList, localPart, domain);
+    }
+
+    public Mailbox parseMailbox(
+            final ByteSequence buf, final ParserCursor cursor, final int[] delimiters) {
+        String openingText = this.parser.parseValue(buf, cursor, AT_AND_OPENING_BRACKET);
+        if (cursor.atEnd()) {
+            return new Mailbox(null, null, openingText, null);
+        }
+        int pos = cursor.getPos();
+        char current = (char) (buf.byteAt(pos) & 0xff);
+        if (current == OPENING_BRACKET) {
+            // name <localPart @ domain> form
+            return parseMailboxAddress(openingText, buf, cursor, delimiters);
+        } else if (current == AT) {
+            // localPart @ domain form
+            cursor.updatePos(pos + 1);
+            String localPart = openingText;
+            String domain = parseDomain(buf, cursor, delimiters);
+            return new Mailbox(null, null, localPart, domain);
+        } else {
+            // should never happen
+            return new Mailbox(null, null, openingText, null);
+        }
+    }
+
+    public Mailbox parseMailbox(final String text) {
+        ByteSequence raw = ContentUtil.encode(text);
+        ParserCursor cursor = new ParserCursor(0, text.length());
+        return parseMailbox(raw, cursor, null);
+    }
+
+}

Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/AddressTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/AddressTest.java?rev=1133920&r1=1133919&r2=1133920&view=diff
==============================================================================
--- james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/AddressTest.java (original)
+++ james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/AddressTest.java Thu Jun  9 15:17:28 2011
@@ -20,16 +20,13 @@
 package org.apache.james.mime4j.field.address;
 
 import org.apache.james.mime4j.MimeException;
-import org.apache.james.mime4j.dom.address.Address;
 import org.apache.james.mime4j.dom.address.AddressList;
 import org.apache.james.mime4j.dom.address.DomainList;
-import org.apache.james.mime4j.dom.address.Group;
 import org.apache.james.mime4j.dom.address.Mailbox;
 import org.apache.james.mime4j.dom.address.MailboxList;
 import org.apache.james.mime4j.field.address.ParseException;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import junit.framework.TestCase;
@@ -41,139 +38,6 @@ public class AddressTest extends TestCas
         assertTrue(MimeException.class.isAssignableFrom(ParseException.class));
     }
 
-    public void testParse1() throws ParseException {
-        AddressList addrList = AddressBuilder.DEFAULT.parseAddressList(
-                "John Doe <jdoe@machine(comment).  example>");
-        assertEquals(1, addrList.size());
-        Mailbox mailbox = (Mailbox)addrList.get(0);
-        assertEquals("John Doe", mailbox.getName());
-        assertEquals("jdoe", mailbox.getLocalPart());
-        assertEquals("machine.example", mailbox.getDomain());
-    }
-
-    public void testParse2() throws ParseException {
-        AddressList addrList = AddressBuilder.DEFAULT.parseAddressList(
-                "Mary Smith \t    \t\t  <ma...@example.net>");
-        assertEquals(1, addrList.size());
-        Mailbox mailbox = (Mailbox)addrList.get(0);
-        assertEquals("Mary Smith", mailbox.getName());
-        assertEquals("mary", mailbox.getLocalPart());
-        assertEquals("example.net", mailbox.getDomain());
-    }
-
-    public void testEmptyGroup() throws ParseException {
-        AddressList addrList = AddressBuilder.DEFAULT.parseAddressList("undisclosed-recipients:;");
-        assertEquals(1, addrList.size());
-        Group group = (Group)addrList.get(0);
-        assertEquals(0, group.getMailboxes().size());
-        assertEquals("undisclosed-recipients", group.getName());
-    }
-
-    public void testMessyGroupAndMailbox() throws ParseException {
-        AddressList addrList = AddressBuilder.DEFAULT.parseAddressList(
-                "Marketing  folks :  Jane Smith < jane @ example . net >," +
-                " \" Jack \\\"Jackie\\\" Jones \" < jjones@example.com > (comment(comment)); ,, (comment)  ," +
-                " <@example . net,@example(ignore\\)).com:(ignore)john@(ignore)example.net>");
-        assertEquals(2, addrList.size());
-
-        Group group = (Group)addrList.get(0);
-        assertEquals("Marketing  folks", group.getName());
-        assertEquals(2, group.getMailboxes().size());
-
-        Mailbox mailbox1 = group.getMailboxes().get(0);
-        Mailbox mailbox2 = group.getMailboxes().get(1);
-
-        assertEquals("Jane Smith", mailbox1.getName());
-        assertEquals("jane", mailbox1.getLocalPart());
-        assertEquals("example.net", mailbox1.getDomain());
-
-        assertEquals(" Jack \"Jackie\" Jones ", mailbox2.getName());
-        assertEquals("jjones", mailbox2.getLocalPart());
-        assertEquals("example.com", mailbox2.getDomain());
-
-        Mailbox mailbox = (Mailbox)addrList.get(1);
-        assertEquals("john", mailbox.getLocalPart());
-        assertEquals("example.net", mailbox.getDomain());
-        assertEquals(2, mailbox.getRoute().size());
-        assertEquals("example.net", mailbox.getRoute().get(0));
-        assertEquals("example.com", mailbox.getRoute().get(1));
-    }
-
-    public void testEmptyAddressList() throws ParseException {
-        assertEquals(0, AddressBuilder.DEFAULT.parseAddressList("  \t   \t ").size());
-        assertEquals(0, AddressBuilder.DEFAULT.parseAddressList("  \t  ,  , , ,,, , \t ").size());
-    }
-
-    public void testSimpleForm() throws ParseException {
-        AddressList addrList = AddressBuilder.DEFAULT.parseAddressList("\"a b c d e f g\" (comment) @example.net");
-        assertEquals(1, addrList.size());
-        Mailbox mailbox = (Mailbox)addrList.get(0);
-        assertEquals("a b c d e f g", mailbox.getLocalPart());
-        assertEquals("example.net", mailbox.getDomain());
-    }
-
-    public void testFlatten() throws ParseException {
-        AddressList addrList = AddressBuilder.DEFAULT.parseAddressList("dev : one@example.com, two@example.com; , ,,, marketing:three@example.com ,four@example.com;, five@example.com");
-        assertEquals(3, addrList.size());
-        assertEquals(5, addrList.flatten().size());
-    }
-
-    public void testTortureTest() throws ParseException {
-
-        // Source: http://mailformat.dan.info/headers/from.html
-        // (Commented out pending confirmation of legality--I think the local-part is illegal.) 
-        // AddressList.parse("\"Guy Macon\" <guymacon+\" http://www.guymacon.com/ \"00@spamcop.net>");
-
-        // Taken mostly from RFC822.
-
-        // Just make sure these are recognized as legal address lists;
-        // there shouldn't be any aspect of the RFC that is tested here
-        // but not in the other unit tests.
-
-        AddressBuilder.DEFAULT.parseAddressList("Alfred Neuman <Ne...@BBN-TENEXA>");
-        AddressBuilder.DEFAULT.parseAddressList("Neuman@BBN-TENEXA");
-        AddressBuilder.DEFAULT.parseAddressList("\"George, Ted\" <Sh...@Group.Arpanet>");
-        AddressBuilder.DEFAULT.parseAddressList("Wilt . (the Stilt) Chamberlain@NBA.US");
-
-        // NOTE: In RFC822 8.1.5, the following example did not have "Galloping Gourmet"
-        // in double-quotes.  I can only assume this was a typo, since 6.2.4 specifically
-        // disallows spaces in unquoted local-part.
-        AddressBuilder.DEFAULT.parseAddressList("     Gourmets:  Pompous Person <Wh...@Cordon-Bleu>," +
-                "                Childs@WGBH.Boston, \"Galloping Gourmet\"@" +
-                "                ANT.Down-Under (Australian National Television)," +
-                "                Cheapie@Discount-Liquors;," +
-                "       Cruisers:  Port@Portugal, Jones@SEA;," +
-                "         Another@Somewhere.SomeOrg");
-
-        // NOTE: In RFC822 8.3.3, the following example ended with a lone ">" after
-        // Tops-20-Host.  I can only assume this was a typo, since 6.1 clearly shows
-        // ">" requires a matching "<".
-        AddressBuilder.DEFAULT.parseAddressList("Important folk:" +
-                "                   Tom Softwood <Ba...@Tree.Root>," +
-                "                   \"Sam Irving\"@Other-Host;," +
-                "                 Standard Distribution:" +
-                "                   /main/davis/people/standard@Other-Host," +
-                "                   \"<Jones>standard.dist.3\"@Tops-20-Host;");
-
-        // The following are from a Usenet post by Dan J. Bernstein:
-        // http://groups.google.com/groups?selm=1996Aug1418.21.01.28081%40koobera.math.uic.edu
-        AddressBuilder.DEFAULT.parseAddressList("\":sysmail\"@  Some-Group.\t         Some-Org, Muhammed.(I am  the greatest) Ali @(the)Vegas.WBA");
-        AddressBuilder.DEFAULT.parseAddressList("me@home.com (comment (nested (deeply\\))))");
-        AddressBuilder.DEFAULT.parseAddressList("mailing list: me@home.com, route two <yo...@work.com>, them@play.com ;");
-
-    }
-
-    public void testLexicalError() {
-        // ensure that TokenMgrError doesn't get thrown
-        try {
-            AddressBuilder.DEFAULT.parseAddressList(")");
-            fail("Expected parsing error");
-        }
-        catch (ParseException e) {
-
-        }
-    }
-    
     public void testNullConstructorAndBadUsage() {
         AddressList al = new AddressList(null, false);
         assertEquals(0, al.size());
@@ -192,27 +56,6 @@ public class AddressTest extends TestCas
     }
 
     
-    public void testAddressList() throws ParseException {
-        AddressList addlist = AddressBuilder.DEFAULT.parseAddressList("foo@example.com, bar@example.com, third@example.com");
-        List<Address> al = new ArrayList<Address>();
-        al.add(addlist.get(0));
-
-        // shared arraylist
-        AddressList dl = new AddressList(al, true);
-        assertEquals(1, dl.size());
-        al.add(addlist.get(1));
-        assertEquals(2, dl.size());
-        
-        // cloned arraylist
-        AddressList dlcopy = new AddressList(al, false);
-        assertEquals(2, dlcopy.size());
-        al.add(addlist.get(2));
-        assertEquals(2, dlcopy.size());
-        
-        // check route string
-        assertEquals(2, dlcopy.flatten().size());
-    }
-
     public void testEmptyDomainList() {
         DomainList dl = new DomainList(null, false);
         assertEquals(0, dl.size());
@@ -285,142 +128,6 @@ public class AddressTest extends TestCas
         assertEquals(2, mlcopy.size());
     }
     
-    public void testGroupSerialization() {
-        List<Mailbox> al = new ArrayList<Mailbox>();
-        al.add(new Mailbox("test", "example.com"));
-        al.add(new Mailbox("Foo!", "foo", "example.com"));
-        DomainList dl = new DomainList(new ArrayList<String>(
-                Arrays.asList(new String[] {"foo.example.com"})), true);
-        Mailbox mailbox = new Mailbox("Foo Bar", dl, "foo2", "example.com");
-        assertSame(dl, mailbox.getRoute());
-        al.add(mailbox);
-        Group g = new Group("group", new MailboxList(al, false));
-        String s = AddressFormatter.DEFAULT.format(g, false);
-        assertEquals("group: test@example.com, Foo! <fo...@example.com>, Foo Bar <fo...@example.com>;", s);
-    }
-    
-    public void testEmptyQuotedStringBeforeDotAtomInLocalPart() throws Exception {
-        /*
-         * This used to give a StringIndexOutOfBoundsException instead of the expected
-         * ParseException
-         */
-        try {
-            AddressBuilder.DEFAULT.parseAddressList("\"\"bar@bar.com");
-            fail("ParseException expected");
-        } catch (ParseException pe) {
-        }
-    }
-    
-    public void testMailboxGetEncodedString() throws Exception {
-        Mailbox m1 = new Mailbox("john.doe", "acme.org");
-        assertEquals("john.doe@acme.org", AddressFormatter.DEFAULT.encode(m1));
-        Mailbox m2 = new Mailbox("john doe", "acme.org");
-        assertEquals("\"john doe\"@acme.org", AddressFormatter.DEFAULT.encode(m2));
-        Mailbox m3 = new Mailbox("John Doe", "john.doe", "acme.org");
-        assertEquals("John Doe <jo...@acme.org>", AddressFormatter.DEFAULT.encode(m3));
-        Mailbox m4 = new Mailbox("John Doe @Home", "john.doe", "acme.org");
-        assertEquals("\"John Doe @Home\" <jo...@acme.org>", AddressFormatter.DEFAULT.encode(m4));
-        Mailbox m5 = new Mailbox("Hans M\374ller", "hans.mueller", "acme.org");
-        assertEquals("=?ISO-8859-1?Q?Hans_M=FCller?= <ha...@acme.org>",
-                AddressFormatter.DEFAULT.encode(m5));
-    }
-
-    public void testGroupGetEncodedString() throws Exception {
-        List<Mailbox> al = new ArrayList<Mailbox>();
-        al.add(new Mailbox("test", "example.com"));
-        al.add(new Mailbox("Foo!", "foo", "example.com"));
-        al.add(new Mailbox("Hans M\374ller", "hans.mueller", "acme.org"));
-        Group g = new Group("group @work", new MailboxList(al, false));
-        assertEquals("\"group @work\": test@example.com, "
-                + "Foo! <fo...@example.com>, =?ISO-8859-1?Q?Hans_M=FCller?="
-                + " <ha...@acme.org>;", AddressFormatter.DEFAULT.encode(g));
-    }
-
-    public void testEmptyGroupGetEncodedString() throws Exception {
-        MailboxList emptyMailboxes = new MailboxList(null, true);
-        Group g = new Group("Undisclosed recipients", emptyMailboxes);
-        assertEquals("Undisclosed recipients:;", AddressFormatter.DEFAULT.encode(g));
-    }
-
-    public void testParseAddress() throws Exception {
-        Address address = AddressBuilder.DEFAULT.parseAddress("Mary Smith <ma...@example.net>");
-        assertTrue(address instanceof Mailbox);
-        assertEquals("Mary Smith", ((Mailbox) address).getName());
-        assertEquals("mary@example.net", ((Mailbox) address).getAddress());
-
-        address = AddressBuilder.DEFAULT.parseAddress("group: Mary Smith <ma...@example.net>;");
-        assertTrue(address instanceof Group);
-        assertEquals("group", ((Group) address).getName());
-        assertEquals("Mary Smith", ((Group) address).getMailboxes().get(0)
-                .getName());
-        assertEquals("mary@example.net", ((Group) address).getMailboxes()
-                .get(0).getAddress());
-
-        try {
-            AddressBuilder.DEFAULT.parseGroup("john.doe@acme.org, jane.doe@acme.org");
-            fail();
-        } catch (ParseException expected) {
-        }
-    }
-    
-    public void testParseGroup() throws Exception {
-        Group group = AddressBuilder.DEFAULT.parseGroup(
-                "group: john.doe@acme.org, Mary Smith <ma...@example.net>;");
-        assertEquals("group", group.getName());
-
-        MailboxList mailboxes = group.getMailboxes();
-        assertEquals(2, mailboxes.size());
-
-        Mailbox mailbox1 = mailboxes.get(0);
-        assertNull(mailbox1.getName());
-        assertEquals("john.doe@acme.org", mailbox1.getAddress());
-
-        Mailbox mailbox2 = mailboxes.get(1);
-        assertEquals("Mary Smith", mailbox2.getName());
-        assertEquals("mary@example.net", mailbox2.getAddress());
-
-        try {
-            AddressBuilder.DEFAULT.parseGroup("john.doe@acme.org");
-            fail();
-        } catch (ParseException expected) {
-        }
-
-        try {
-            AddressBuilder.DEFAULT.parseGroup("g1: john.doe@acme.org;, g2: mary@example.net;");
-            fail();
-        } catch (ParseException expected) {
-        }
-    }
-
-    public void testParseMailbox() throws Exception {
-        Mailbox mailbox1 = AddressBuilder.DEFAULT.parseMailbox("john.doe@acme.org");
-        assertNull(mailbox1.getName());
-        assertEquals("john.doe@acme.org", mailbox1.getAddress());
-
-        Mailbox mailbox2 = AddressBuilder.DEFAULT.parseMailbox("Mary Smith <ma...@example.net>");
-        assertEquals("Mary Smith", mailbox2.getName());
-        assertEquals("mary@example.net", mailbox2.getAddress());
-
-        // non-ascii should be allowed in quoted strings
-        Mailbox mailbox3 = AddressBuilder.DEFAULT.parseMailbox(
-                "\"Hans M\374ller\" <ha...@acme.org>");
-        assertEquals("Hans M\374ller", mailbox3.getName());
-        assertEquals("hans.mueller@acme.org", mailbox3.getAddress());
-
-        try {
-            AddressBuilder.DEFAULT.parseMailbox("g: Mary Smith <ma...@example.net>;");
-            fail();
-        } catch (ParseException expected) {
-        }
-
-        try {
-            AddressBuilder.DEFAULT.parseMailbox(
-                    "Mary Smith <ma...@example.net>, hans.mueller@acme.org");
-            fail();
-        } catch (ParseException expected) {
-        }
-    }
-
     public void testMailboxEquals() throws Exception {
         Mailbox m1 = new Mailbox("john.doe", "acme.org");
         Mailbox m2 = new Mailbox("john doe", "acme.org");

Added: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressBuilderTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressBuilderTest.java?rev=1133920&view=auto
==============================================================================
--- james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressBuilderTest.java (added)
+++ james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressBuilderTest.java Thu Jun  9 15:17:28 2011
@@ -0,0 +1,300 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mime4j.field.address;
+
+import org.apache.james.mime4j.dom.address.Address;
+import org.apache.james.mime4j.dom.address.AddressList;
+import org.apache.james.mime4j.dom.address.DomainList;
+import org.apache.james.mime4j.dom.address.Group;
+import org.apache.james.mime4j.dom.address.Mailbox;
+import org.apache.james.mime4j.dom.address.MailboxList;
+import org.apache.james.mime4j.field.address.ParseException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+public class DefaultAddressBuilderTest extends TestCase {
+
+    private AddressBuilder parser;
+
+    @Override
+    protected void setUp() throws Exception {
+        parser = AddressBuilder.DEFAULT;
+    }
+
+    public void testParseMailbox() throws ParseException {
+        Mailbox mailbox1 = parser.parseMailbox("John Doe <jdoe@machine(comment).  example>");
+        assertEquals("John Doe", mailbox1.getName());
+        assertEquals("jdoe", mailbox1.getLocalPart());
+        assertEquals("machine.example", mailbox1.getDomain());
+
+        Mailbox mailbox2 = parser.parseMailbox("Mary Smith \t    \t\t  <ma...@example.net>");
+        assertEquals("Mary Smith", mailbox2.getName());
+        assertEquals("mary", mailbox2.getLocalPart());
+        assertEquals("example.net", mailbox2.getDomain());
+
+        Mailbox mailbox3 = parser.parseMailbox("john.doe@acme.org");
+        assertNull(mailbox3.getName());
+        assertEquals("john.doe@acme.org", mailbox3.getAddress());
+
+        Mailbox mailbox4 = parser.parseMailbox("Mary Smith <ma...@example.net>");
+        assertEquals("Mary Smith", mailbox4.getName());
+        assertEquals("mary@example.net", mailbox4.getAddress());
+
+        // non-ascii should be allowed in quoted strings
+        Mailbox mailbox5 = parser.parseMailbox(
+                "\"Hans M\374ller\" <ha...@acme.org>");
+        assertEquals("Hans M\374ller", mailbox5.getName());
+        assertEquals("hans.mueller@acme.org", mailbox5.getAddress());
+
+    }
+
+    public void testParseMailboxObsoleteSynatax() throws ParseException {
+        Mailbox mailbox1 = parser.parseMailbox("< (route)(obsolete) " +
+                "@host1.domain1 , @host2 . domain2:  foo@bar.org>");
+        assertEquals(null, mailbox1.getName());
+        assertEquals("foo", mailbox1.getLocalPart());
+        assertEquals("bar.org", mailbox1.getDomain());
+        DomainList domainList = mailbox1.getRoute();
+        assertNotNull(domainList);
+        assertEquals(2, domainList.size());
+        assertEquals("host1.domain1", domainList.get(0));
+        assertEquals("host2.domain2", domainList.get(1));
+    }
+
+    public void testParseInvalidMailbox() throws Exception {
+        try {
+            parser.parseMailbox("g: Mary Smith <ma...@example.net>;");
+            fail();
+        } catch (ParseException expected) {
+        }
+        try {
+            parser.parseMailbox("Mary Smith <ma...@example.net>, hans.mueller@acme.org");
+            fail();
+        } catch (ParseException expected) {
+        }
+    }
+
+    public void testParseAddressList() throws ParseException {
+        AddressList addrList1 = parser.parseAddressList("John Doe <jdoe@machine(comment).  example>");
+        assertEquals(1, addrList1.size());
+        Mailbox mailbox1 = (Mailbox)addrList1.get(0);
+        assertEquals("John Doe", mailbox1.getName());
+        assertEquals("jdoe", mailbox1.getLocalPart());
+        assertEquals("machine.example", mailbox1.getDomain());
+
+        AddressList addrList2 = parser.parseAddressList("Mary Smith \t    \t\t  <ma...@example.net>");
+        assertEquals(1, addrList2.size());
+        Mailbox mailbox2 = (Mailbox)addrList2.get(0);
+        assertEquals("Mary Smith", mailbox2.getName());
+        assertEquals("mary", mailbox2.getLocalPart());
+        assertEquals("example.net", mailbox2.getDomain());
+    }
+
+    public void testEmptyGroup() throws ParseException {
+        AddressList addrList = parser.parseAddressList("undisclosed-recipients:;");
+        assertEquals(1, addrList.size());
+        Group group = (Group)addrList.get(0);
+        assertEquals(0, group.getMailboxes().size());
+        assertEquals("undisclosed-recipients", group.getName());
+    }
+
+    public void testMessyGroupAndMailbox() throws ParseException {
+        AddressList addrList = parser.parseAddressList(
+                "Marketing  folks :  Jane Smith < jane @ example . net >," +
+                " \" Jack \\\"Jackie\\\" Jones \" < jjones@example.com > (comment(comment)); ,, (comment)  ," +
+                " <@example . net,@example(ignore\\)).com:(ignore)john@(ignore)example.net>");
+        assertEquals(2, addrList.size());
+
+        Group group = (Group)addrList.get(0);
+        assertEquals("Marketing  folks", group.getName());
+        assertEquals(2, group.getMailboxes().size());
+
+        Mailbox mailbox1 = group.getMailboxes().get(0);
+        Mailbox mailbox2 = group.getMailboxes().get(1);
+
+        assertEquals("Jane Smith", mailbox1.getName());
+        assertEquals("jane", mailbox1.getLocalPart());
+        assertEquals("example.net", mailbox1.getDomain());
+
+        assertEquals(" Jack \"Jackie\" Jones ", mailbox2.getName());
+        assertEquals("jjones", mailbox2.getLocalPart());
+        assertEquals("example.com", mailbox2.getDomain());
+
+        Mailbox mailbox = (Mailbox)addrList.get(1);
+        assertEquals("john", mailbox.getLocalPart());
+        assertEquals("example.net", mailbox.getDomain());
+        assertEquals(2, mailbox.getRoute().size());
+        assertEquals("example.net", mailbox.getRoute().get(0));
+        assertEquals("example.com", mailbox.getRoute().get(1));
+    }
+
+    public void testEmptyAddressList() throws ParseException {
+        assertEquals(0, parser.parseAddressList("  \t   \t ").size());
+        assertEquals(0, parser.parseAddressList("  \t  ,  , , ,,, , \t ").size());
+    }
+
+    public void testSimpleForm() throws ParseException {
+        AddressList addrList = parser.parseAddressList("\"a b c d e f g\" (comment) @example.net");
+        assertEquals(1, addrList.size());
+        Mailbox mailbox = (Mailbox)addrList.get(0);
+        assertEquals("a b c d e f g", mailbox.getLocalPart());
+        assertEquals("example.net", mailbox.getDomain());
+    }
+
+    public void testFlatten() throws ParseException {
+        AddressList addrList = parser.parseAddressList("dev : one@example.com, two@example.com; , ,,, marketing:three@example.com ,four@example.com;, five@example.com");
+        assertEquals(3, addrList.size());
+        assertEquals(5, addrList.flatten().size());
+    }
+
+    public void testTortureTest() throws ParseException {
+
+        // Source: http://mailformat.dan.info/headers/from.html
+        // (Commented out pending confirmation of legality--I think the local-part is illegal.)
+        // AddressList.parse("\"Guy Macon\" <guymacon+\" http://www.guymacon.com/ \"00@spamcop.net>");
+
+        // Taken mostly from RFC822.
+
+        // Just make sure these are recognized as legal address lists;
+        // there shouldn't be any aspect of the RFC that is tested here
+        // but not in the other unit tests.
+
+        parser.parseAddressList("Alfred Neuman <Ne...@BBN-TENEXA>");
+        parser.parseAddressList("Neuman@BBN-TENEXA");
+        parser.parseAddressList("\"George, Ted\" <Sh...@Group.Arpanet>");
+        parser.parseAddressList("Wilt . (the Stilt) Chamberlain@NBA.US");
+
+        // NOTE: In RFC822 8.1.5, the following example did not have "Galloping Gourmet"
+        // in double-quotes.  I can only assume this was a typo, since 6.2.4 specifically
+        // disallows spaces in unquoted local-part.
+        parser.parseAddressList("     Gourmets:  Pompous Person <Wh...@Cordon-Bleu>," +
+                "                Childs@WGBH.Boston, \"Galloping Gourmet\"@" +
+                "                ANT.Down-Under (Australian National Television)," +
+                "                Cheapie@Discount-Liquors;," +
+                "       Cruisers:  Port@Portugal, Jones@SEA;," +
+                "         Another@Somewhere.SomeOrg");
+
+        // NOTE: In RFC822 8.3.3, the following example ended with a lone ">" after
+        // Tops-20-Host.  I can only assume this was a typo, since 6.1 clearly shows
+        // ">" requires a matching "<".
+        parser.parseAddressList("Important folk:" +
+                "                   Tom Softwood <Ba...@Tree.Root>," +
+                "                   \"Sam Irving\"@Other-Host;," +
+                "                 Standard Distribution:" +
+                "                   /main/davis/people/standard@Other-Host," +
+                "                   \"<Jones>standard.dist.3\"@Tops-20-Host;");
+
+        // The following are from a Usenet post by Dan J. Bernstein:
+        // http://groups.google.com/groups?selm=1996Aug1418.21.01.28081%40koobera.math.uic.edu
+        parser.parseAddressList("\":sysmail\"@  Some-Group.\t         Some-Org, Muhammed.(I am  the greatest) Ali @(the)Vegas.WBA");
+        parser.parseAddressList("me@home.com (comment (nested (deeply\\))))");
+        parser.parseAddressList("mailing list: me@home.com, route two <yo...@work.com>, them@play.com ;");
+
+    }
+
+    public void testLexicalError() {
+        // ensure that TokenMgrError doesn't get thrown
+        try {
+            parser.parseAddressList(")");
+            fail("Expected parsing error");
+        }
+        catch (ParseException e) {
+        }
+    }
+
+    public void testAddressList() throws ParseException {
+        AddressList addlist = parser.parseAddressList("foo@example.com, bar@example.com, third@example.com");
+        List<Address> al = new ArrayList<Address>();
+        al.add(addlist.get(0));
+
+        // shared arraylist
+        AddressList dl = new AddressList(al, true);
+        assertEquals(1, dl.size());
+        al.add(addlist.get(1));
+        assertEquals(2, dl.size());
+
+        // cloned arraylist
+        AddressList dlcopy = new AddressList(al, false);
+        assertEquals(2, dlcopy.size());
+        al.add(addlist.get(2));
+        assertEquals(2, dlcopy.size());
+
+        // check route string
+        assertEquals(2, dlcopy.flatten().size());
+    }
+
+    public void testParseAddress() throws Exception {
+        Address address = parser.parseAddress("Mary Smith <ma...@example.net>");
+        assertTrue(address instanceof Mailbox);
+        assertEquals("Mary Smith", ((Mailbox) address).getName());
+        assertEquals("mary@example.net", ((Mailbox) address).getAddress());
+
+        address = parser.parseAddress("group: Mary Smith <ma...@example.net>;");
+        assertTrue(address instanceof Group);
+        assertEquals("group", ((Group) address).getName());
+        assertEquals("Mary Smith", ((Group) address).getMailboxes().get(0)
+                .getName());
+        assertEquals("mary@example.net", ((Group) address).getMailboxes()
+                .get(0).getAddress());
+    }
+
+    public void testParseInvalidAddress() throws Exception {
+        try {
+            parser.parseGroup("john.doe@acme.org, jane.doe@acme.org");
+            fail();
+        } catch (ParseException expected) {
+        }
+    }
+
+    public void testParseGroup() throws Exception {
+        Group group = parser.parseGroup(
+                "group: john.doe@acme.org, Mary Smith <ma...@example.net>;");
+        assertEquals("group", group.getName());
+
+        MailboxList mailboxes = group.getMailboxes();
+        assertEquals(2, mailboxes.size());
+
+        Mailbox mailbox1 = mailboxes.get(0);
+        assertNull(mailbox1.getName());
+        assertEquals("john.doe@acme.org", mailbox1.getAddress());
+
+        Mailbox mailbox2 = mailboxes.get(1);
+        assertEquals("Mary Smith", mailbox2.getName());
+        assertEquals("mary@example.net", mailbox2.getAddress());
+    }
+
+    public void testParseInvalidGroup() throws Exception {
+        try {
+            parser.parseGroup("john.doe@acme.org");
+            fail();
+        } catch (ParseException expected) {
+        }
+
+        try {
+            parser.parseGroup("g1: john.doe@acme.org;, g2: mary@example.net;");
+            fail();
+        } catch (ParseException expected) {
+        }
+    }
+
+}

Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressBuilderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressBuilderTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressBuilderTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressFormatterTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressFormatterTest.java?rev=1133920&view=auto
==============================================================================
--- james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressFormatterTest.java (added)
+++ james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressFormatterTest.java Thu Jun  9 15:17:28 2011
@@ -0,0 +1,86 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mime4j.field.address;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.james.mime4j.dom.address.DomainList;
+import org.apache.james.mime4j.dom.address.Group;
+import org.apache.james.mime4j.dom.address.Mailbox;
+import org.apache.james.mime4j.dom.address.MailboxList;
+
+public class DefaultAddressFormatterTest extends TestCase {
+
+    private AddressFormatter formatter;
+
+    @Override
+    protected void setUp() throws Exception {
+        formatter = AddressFormatter.DEFAULT;
+    }
+
+    public void testGroupSerialization() {
+        List<Mailbox> al = new ArrayList<Mailbox>();
+        al.add(new Mailbox("test", "example.com"));
+        al.add(new Mailbox("Foo!", "foo", "example.com"));
+        DomainList dl = new DomainList(new ArrayList<String>(
+                Arrays.asList(new String[] {"foo.example.com"})), true);
+        Mailbox mailbox = new Mailbox("Foo Bar", dl, "foo2", "example.com");
+        assertSame(dl, mailbox.getRoute());
+        al.add(mailbox);
+        Group g = new Group("group", new MailboxList(al, false));
+        String s = formatter.format(g, false);
+        assertEquals("group: test@example.com, Foo! <fo...@example.com>, Foo Bar <fo...@example.com>;", s);
+    }
+
+    public void testMailboxGetEncodedString() throws Exception {
+        Mailbox m1 = new Mailbox("john.doe", "acme.org");
+        assertEquals("john.doe@acme.org", formatter.encode(m1));
+        Mailbox m2 = new Mailbox("john doe", "acme.org");
+        assertEquals("\"john doe\"@acme.org", formatter.encode(m2));
+        Mailbox m3 = new Mailbox("John Doe", "john.doe", "acme.org");
+        assertEquals("John Doe <jo...@acme.org>", formatter.encode(m3));
+        Mailbox m4 = new Mailbox("John Doe @Home", "john.doe", "acme.org");
+        assertEquals("\"John Doe @Home\" <jo...@acme.org>", formatter.encode(m4));
+        Mailbox m5 = new Mailbox("Hans M\374ller", "hans.mueller", "acme.org");
+        assertEquals("=?ISO-8859-1?Q?Hans_M=FCller?= <ha...@acme.org>", formatter.encode(m5));
+    }
+
+    public void testGroupGetEncodedString() throws Exception {
+        List<Mailbox> al = new ArrayList<Mailbox>();
+        al.add(new Mailbox("test", "example.com"));
+        al.add(new Mailbox("Foo!", "foo", "example.com"));
+        al.add(new Mailbox("Hans M\374ller", "hans.mueller", "acme.org"));
+        Group g = new Group("group @work", new MailboxList(al, false));
+        assertEquals("\"group @work\": test@example.com, "
+                + "Foo! <fo...@example.com>, =?ISO-8859-1?Q?Hans_M=FCller?="
+                + " <ha...@acme.org>;", formatter.encode(g));
+    }
+
+    public void testEmptyGroupGetEncodedString() throws Exception {
+        MailboxList emptyMailboxes = new MailboxList(null, true);
+        Group g = new Group("Undisclosed recipients", emptyMailboxes);
+        assertEquals("Undisclosed recipients:;", formatter.encode(g));
+    }
+
+}

Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressFormatterTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressFormatterTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/DefaultAddressFormatterTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java?rev=1133920&view=auto
==============================================================================
--- james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java (added)
+++ james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java Thu Jun  9 15:17:28 2011
@@ -0,0 +1,171 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mime4j.field.address;
+
+import junit.framework.TestCase;
+
+import org.apache.james.mime4j.dom.address.DomainList;
+import org.apache.james.mime4j.dom.address.Mailbox;
+import org.apache.james.mime4j.stream.ParserCursor;
+import org.apache.james.mime4j.util.ByteSequence;
+import org.apache.james.mime4j.util.ContentUtil;
+
+public class LenientAddressBuilderTest extends TestCase {
+
+    private LenientAddressBuilder parser;
+
+    @Override
+    protected void setUp() throws Exception {
+        parser = LenientAddressBuilder.DEFAULT;
+    }
+
+    public void testParseDomain() throws ParseException {
+        String s = "machine (comment).  example (dot). com  ; more stuff";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+
+        String domain = parser.parseDomain(raw, cursor, new int[] {';'});
+        assertEquals("machine.example.com", domain);
+    }
+
+    public void testParseAddress() throws ParseException {
+        String s = "<  some  one @ some host . some where . com >";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+
+        Mailbox mailbox = parser.parseMailboxAddress(null, raw, cursor, new int[] {';'});
+        assertEquals("some one@somehost.somewhere.com", mailbox.getAddress());
+    }
+
+    public void testParseAddressQuotedLocalPart() throws ParseException {
+        String s = "<  \"some  one\"   @ some host . some where . com >";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+
+        Mailbox mailbox = parser.parseMailboxAddress(null, raw, cursor, new int[] {';'});
+        assertEquals("some  one@somehost.somewhere.com", mailbox.getAddress());
+    }
+
+    public void testParseAddressTruncated() throws ParseException {
+        String s = "<  some  one  ";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+
+        Mailbox mailbox = parser.parseMailboxAddress(null, raw, cursor, new int[] {';'});
+        assertEquals("some one", mailbox.getAddress());
+    }
+
+    public void testParseAddressTrailingComments() throws ParseException {
+        String s = "< someone@somehost.somewhere.com  > (garbage) ; ";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+
+        Mailbox mailbox = parser.parseMailboxAddress(null, raw, cursor, new int[] {';'});
+        assertEquals("someone@somehost.somewhere.com", mailbox.getAddress());
+        assertEquals(';', raw.byteAt(cursor.getPos()));
+    }
+
+    public void testParseAddressTrailingGarbage() throws ParseException {
+        String s = "< someone@somehost.somewhere.com  > garbage) ; ";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+
+        Mailbox mailbox = parser.parseMailboxAddress(null, raw, cursor, new int[] {';'});
+        assertEquals("someone@somehost.somewhere.com", mailbox.getAddress());
+        assertEquals('g', raw.byteAt(cursor.getPos()));
+    }
+
+    public void testParseRoute() throws ParseException {
+        String s = "  @a, @b, @c :me@home";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+
+        DomainList route = parser.parseRoute(raw, cursor);
+        assertNotNull(route);
+        assertEquals(3, route.size());
+        assertEquals("a", route.get(0));
+        assertEquals("b", route.get(1));
+        assertEquals("c", route.get(2));
+        assertEquals('m', raw.byteAt(cursor.getPos()));
+    }
+
+    public void testParseNoRoute() throws ParseException {
+        String s = "stuff";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+
+        DomainList route = parser.parseRoute(raw, cursor);
+        assertNull(route);
+    }
+
+    public void testParseMailbox() throws ParseException {
+        Mailbox mailbox1 = parser.parseMailbox("John Doe <jdoe@machine(comment).  example>");
+        assertEquals("John Doe", mailbox1.getName());
+        assertEquals("jdoe", mailbox1.getLocalPart());
+        assertEquals("machine.example", mailbox1.getDomain());
+
+        Mailbox mailbox2 = parser.parseMailbox("Mary Smith \t    \t\t  <ma...@example.net>");
+        assertEquals("Mary Smith", mailbox2.getName());
+        assertEquals("mary", mailbox2.getLocalPart());
+        assertEquals("example.net", mailbox2.getDomain());
+
+        Mailbox mailbox3 = parser.parseMailbox("john.doe@acme.org");
+        assertNull(mailbox3.getName());
+        assertEquals("john.doe@acme.org", mailbox3.getAddress());
+
+        Mailbox mailbox4 = parser.parseMailbox("Mary Smith <ma...@example.net>");
+        assertEquals("Mary Smith", mailbox4.getName());
+        assertEquals("mary@example.net", mailbox4.getAddress());
+
+        // non-ascii should be allowed in quoted strings
+        Mailbox mailbox5 = parser.parseMailbox(
+                "\"Hans M\374ller\" <ha...@acme.org>");
+        assertEquals("Hans M\374ller", mailbox5.getName());
+        assertEquals("hans.mueller@acme.org", mailbox5.getAddress());
+    }
+
+    public void testParseMailboxNonASCII() throws ParseException {
+        Mailbox mailbox1 = parser.parseMailbox(
+                "Hans M\374ller <ha...@acme.org>");
+        assertEquals("Hans M\374ller", mailbox1.getName());
+        assertEquals("hans.mueller@acme.org", mailbox1.getAddress());
+    }
+
+    public void testParsePartialQuotes() throws ParseException {
+        Mailbox mailbox1 = parser.parseMailbox(
+                "Hans \"M\374ller\" is a good fella <ha...@acme.org>");
+        assertEquals("Hans M\374ller is a good fella", mailbox1.getName());
+        assertEquals("hans.mueller@acme.org", mailbox1.getAddress());
+    }
+
+    public void testParseMailboxObsoleteSynatax() throws ParseException {
+        Mailbox mailbox1 = parser.parseMailbox("< (route)(obsolete) " +
+                "@host1.domain1 , @host2 . domain2:  foo@bar.org>");
+        assertEquals(null, mailbox1.getName());
+        assertEquals("foo", mailbox1.getLocalPart());
+        assertEquals("bar.org", mailbox1.getDomain());
+        DomainList domainList = mailbox1.getRoute();
+        assertNotNull(domainList);
+        assertEquals(2, domainList.size());
+        assertEquals("host1.domain1", domainList.get(0));
+        assertEquals("host2.domain2", domainList.get(1));
+    }
+
+}

Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain