james-mime4j-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject svn commit: r1135622 - 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...
Date Tue, 14 Jun 2011 14:52:13 GMT
Author: olegk
Date: Tue Jun 14 14:52:12 2011
New Revision: 1135622

URL: http://svn.apache.org/viewvc?rev=1135622&view=rev
Log:
MIME4J-197: Lenient implementation of AddressBuilder

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/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java
    james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.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=1135622&r1=1135621&r2=1135622&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
Tue Jun 14 14:52:12 2011
@@ -20,6 +20,7 @@
 package org.apache.james.mime4j.stream;
 
 import java.util.ArrayList;
+import java.util.BitSet;
 import java.util.List;
 
 import org.apache.james.mime4j.MimeException;
@@ -32,9 +33,17 @@ import org.apache.james.mime4j.util.Cont
  */
 public class RawFieldParser {
 
-    static final int[] COLON                   = { ':' };
-    static final int[] EQUAL_OR_SEMICOLON      = { '=', ';' };
-    static final int[] SEMICOLON               = { ';' };
+    public static BitSet INIT_BITSET(int ... b) {
+        BitSet bitset = new BitSet(b.length);
+        for (int i = 0; i < b.length; i++) {
+            bitset.set(b[i]);
+        }
+        return bitset;
+    }
+
+    static final BitSet COLON                   = INIT_BITSET(':');
+    static final BitSet EQUAL_OR_SEMICOLON      = INIT_BITSET('=', ';');
+    static final BitSet SEMICOLON               = INIT_BITSET(';');
 
     public static final RawFieldParser DEFAULT = new RawFieldParser();
 
@@ -103,23 +112,12 @@ public class RawFieldParser {
         return new NameValuePair(name, value);
     }
 
-    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]) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public String parseToken(final ByteSequence buf, final ParserCursor cursor, final int[]
delimiters) {
+    public String parseToken(final ByteSequence buf, final ParserCursor cursor, final BitSet
delimiters) {
         StringBuilder dst = new StringBuilder();
         boolean whitespace = false;
         while (!cursor.atEnd()) {
             char current = (char) (buf.byteAt(cursor.getPos()) & 0xff);
-            if (isOneOf(current, delimiters)) {
+            if (delimiters != null && delimiters.get(current)) {
                 break;
             } else if (CharsetUtil.isWhitespace(current)) {
                 skipWhiteSpace(buf, cursor);
@@ -137,12 +135,12 @@ public class RawFieldParser {
         return dst.toString();
     }
 
-    public String parseValue(final ByteSequence buf, final ParserCursor cursor, final int[]
delimiters) {
+    public String parseValue(final ByteSequence buf, final ParserCursor cursor, final BitSet
delimiters) {
         StringBuilder dst = new StringBuilder();
         boolean whitespace = false;
         while (!cursor.atEnd()) {
             char current = (char) (buf.byteAt(cursor.getPos()) & 0xff);
-            if (isOneOf(current, delimiters)) {
+            if (delimiters != null && delimiters.get(current)) {
                 break;
             } else if (CharsetUtil.isWhitespace(current)) {
                 skipWhiteSpace(buf, cursor);
@@ -230,15 +228,16 @@ public class RawFieldParser {
             }
         }
     }
-    
-    public void copyContent(final ByteSequence buf, final ParserCursor cursor, final int[]
delimiters,
+
+    public void copyContent(final ByteSequence buf, final ParserCursor cursor, final BitSet
delimiters,
             final StringBuilder dst) {
         int pos = cursor.getPos();
         int indexFrom = cursor.getPos();
         int indexTo = cursor.getUpperBound();
         for (int i = indexFrom; i < indexTo; i++) {
             char current = (char) (buf.byteAt(i) & 0xff);
-            if (isOneOf(current, delimiters) || CharsetUtil.isWhitespace(current) || current
== '(') {
+            if ((delimiters != null && delimiters.get(current))
+                    || CharsetUtil.isWhitespace(current) || current == '(') {
                 break;
             } else {
                 pos++;

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=1135622&r1=1135621&r2=1135622&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
Tue Jun 14 14:52:12 2011
@@ -31,7 +31,7 @@ import junit.framework.TestCase;
 public class RawFieldParserTest extends TestCase {
 
     private RawFieldParser parser;
-    
+
     @Override
     protected void setUp() throws Exception {
         parser = new RawFieldParser();
@@ -48,7 +48,7 @@ public class RawFieldParserTest extends 
         Assert.assertEquals(3, cursor.getPos());
 
         StringBuilder strbuf1 = new StringBuilder();
-        parser.copyContent(raw, cursor, new int[] { ':' }, strbuf1);
+        parser.copyContent(raw, cursor, RawFieldParser.INIT_BITSET(':'), strbuf1);
 
         Assert.assertFalse(cursor.atEnd());
         Assert.assertEquals(6, cursor.getPos());
@@ -85,7 +85,7 @@ public class RawFieldParserTest extends 
         Assert.assertEquals(0, cursor.getPos());
 
         StringBuilder strbuf1 = new StringBuilder();
-        parser.copyContent(raw, cursor, new int[] { ':' }, strbuf1);
+        parser.copyContent(raw, cursor, RawFieldParser.INIT_BITSET(':'), strbuf1);
 
         Assert.assertFalse(cursor.atEnd());
         Assert.assertEquals("raw", strbuf1.toString());
@@ -134,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 = parser.parseToken(raw, cursor, new int[] { ';' });
+        String result = parser.parseToken(raw, cursor, RawFieldParser.INIT_BITSET(';'));
         Assert.assertEquals("stuff and some more stuff", result);
     }
 
@@ -142,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 = parser.parseToken(raw, cursor, new int[] { ';' });
+        String result = parser.parseToken(raw, cursor, RawFieldParser.INIT_BITSET(';'));
         Assert.assertEquals("stuff and some more stuff", result);
     }
 
@@ -150,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 = parser.parseValue(raw, cursor, new int[] { ';' });
+        String result = parser.parseValue(raw, cursor, RawFieldParser.INIT_BITSET(';'));
         Assert.assertEquals("stuff and  some more  stuff  ;", result);
     }
 
@@ -158,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 = parser.parseValue(raw, cursor, new int[] { ';' });
+        String result = parser.parseValue(raw, cursor, RawFieldParser.INIT_BITSET(';'));
         Assert.assertEquals("(stuff)(and)(some)(more)(stuff)", result);
     }
 

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=1135622&r1=1135621&r2=1135622&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
Tue Jun 14 14:52:12 2011
@@ -20,6 +20,7 @@
 package org.apache.james.mime4j.field;
 
 import java.util.ArrayList;
+import java.util.BitSet;
 import java.util.List;
 
 import org.apache.james.mime4j.codec.DecodeMonitor;
@@ -38,7 +39,7 @@ import org.apache.james.mime4j.util.Cont
 public class ContentLanguageFieldLenientImpl extends AbstractField implements ContentLanguageField
{
 
     private final static int   COMMA = ',';
-    private final static int[] DELIM = new int[] { COMMA };
+    private final static BitSet DELIM = RawFieldParser.INIT_BITSET(COMMA);
     
     private boolean parsed = false;
     private List<String> languages;

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=1135622&r1=1135621&r2=1135622&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
Tue Jun 14 14:52:12 2011
@@ -35,8 +35,6 @@ import org.apache.james.mime4j.util.Cont
  */
 public class ContentLocationFieldLenientImpl extends AbstractField implements ContentLocationField
{
 
-    private final static int[] DELIM = new int[] {};
-    
     private boolean parsed = false;
     private String location;
 
@@ -60,7 +58,7 @@ public class ContentLocationFieldLenient
         }
         RawFieldParser parser = RawFieldParser.DEFAULT;
         ParserCursor cursor = new ParserCursor(pos, buf.length());
-        String token = parser.parseValue(buf, cursor, DELIM);
+        String token = parser.parseValue(buf, cursor, null);
         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=1135622&r1=1135621&r2=1135622&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
Tue Jun 14 14:52:12 2011
@@ -19,6 +19,8 @@
 
 package org.apache.james.mime4j.field;
 
+import java.util.BitSet;
+
 import org.apache.james.mime4j.codec.DecodeMonitor;
 import org.apache.james.mime4j.dom.field.MimeVersionField;
 import org.apache.james.mime4j.stream.Field;
@@ -35,9 +37,7 @@ import org.apache.james.mime4j.util.Cont
 public class MimeVersionFieldLenientImpl extends AbstractField implements MimeVersionField
{
 
     private final static int FULL_STOP  = '.';
-    private final static int[] DELIM1   = new int[] { FULL_STOP };
-    private final static int[] DELIM2   = new int[] {};
-    
+    private final static BitSet DELIM = RawFieldParser.INIT_BITSET(FULL_STOP);
     
     public static final int DEFAULT_MINOR_VERSION = 0;
     public static final int DEFAULT_MAJOR_VERSION = 1;
@@ -67,7 +67,7 @@ public class MimeVersionFieldLenientImpl
         }
         RawFieldParser parser = RawFieldParser.DEFAULT;
         ParserCursor cursor = new ParserCursor(pos, buf.length());
-        String token1 = parser.parseValue(buf, cursor, DELIM1);
+        String token1 = parser.parseValue(buf, cursor, DELIM);
         try {
             major = Integer.parseInt(token1);
             if (major < 0) {
@@ -78,7 +78,7 @@ public class MimeVersionFieldLenientImpl
         if (!cursor.atEnd() && buf.byteAt(cursor.getPos()) == FULL_STOP) {
             cursor.updatePos(cursor.getPos() + 1);
         }
-        String token2 = parser.parseValue(buf, cursor, DELIM2);
+        String token2 = parser.parseValue(buf, cursor, null);
         try {
             minor = Integer.parseInt(token2);
             if (minor < 0) {

Modified: 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=1135622&r1=1135621&r2=1135622&view=diff
==============================================================================
--- james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java
(original)
+++ james/mime4j/trunk/dom/src/main/java/org/apache/james/mime4j/field/address/LenientAddressBuilder.java
Tue Jun 14 14:52:12 2011
@@ -20,9 +20,14 @@
 package org.apache.james.mime4j.field.address;
 
 import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collections;
 import java.util.List;
 
+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.stream.ParserCursor;
 import org.apache.james.mime4j.stream.RawFieldParser;
@@ -37,11 +42,14 @@ public class LenientAddressBuilder {
     private static final int CLOSING_BRACKET   = '>';
     private static final int COMMA             = ',';
     private static final int COLON             = ':';
+    private static final int SEMICOLON         = ';';
 
-    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 };
+    private static final BitSet AT_AND_CLOSING_BRACKET = RawFieldParser.INIT_BITSET(AT, CLOSING_BRACKET);
+    private static final BitSet CLOSING_BRACKET_ONLY   = RawFieldParser.INIT_BITSET(CLOSING_BRACKET);
+    private static final BitSet COMMA_AND_COLON        = RawFieldParser.INIT_BITSET(COMMA,
COLON);
+    private static final BitSet COMMA_ONLY             = RawFieldParser.INIT_BITSET(COMMA);
+    private static final BitSet COLON_ONLY             = RawFieldParser.INIT_BITSET(COLON);
+    private static final BitSet SEMICOLON_ONLY         = RawFieldParser.INIT_BITSET(SEMICOLON);
 
     public static final LenientAddressBuilder DEFAULT = new LenientAddressBuilder();
 
@@ -52,11 +60,11 @@ public class LenientAddressBuilder {
         this.parser = new RawFieldParser();
     }
 
-    String parseDomain(final ByteSequence buf, final ParserCursor cursor, final int[] delimiters)
{
+    String parseDomain(final ByteSequence buf, final ParserCursor cursor, final BitSet delimiters)
{
         StringBuilder dst = new StringBuilder();
         while (!cursor.atEnd()) {
             char current = (char) (buf.byteAt(cursor.getPos()) & 0xff);
-            if (RawFieldParser.isOneOf(current, delimiters)) {
+            if (delimiters != null && delimiters.get(current)) {
                 break;
             } else if (CharsetUtil.isWhitespace(current)) {
                 this.parser.skipWhiteSpace(buf, cursor);
@@ -103,10 +111,9 @@ public class LenientAddressBuilder {
     }
 
     Mailbox parseMailboxAddress(
-            final String openingText,
-            final ByteSequence buf, final ParserCursor cursor, final int[] delimiters) {
+            final String openingText, final ByteSequence buf, final ParserCursor cursor)
{
         if (cursor.atEnd()) {
-            return null;
+            return new Mailbox(null, null, openingText, null);
         }
         int pos = cursor.getPos();
         char current = (char) (buf.byteAt(pos) & 0xff);
@@ -152,17 +159,29 @@ public class LenientAddressBuilder {
         return new Mailbox(openingText, domainList, localPart, domain);
     }
 
+    private Mailbox createMailbox(final String localPart) {
+        if (localPart != null && localPart.length() > 0) {
+            return new Mailbox(null, null, localPart, null);
+        } else {
+            return null;
+        }
+    }
+
     public Mailbox parseMailbox(
-            final ByteSequence buf, final ParserCursor cursor, final int[] delimiters) {
-        String openingText = this.parser.parseValue(buf, cursor, AT_AND_OPENING_BRACKET);
+            final ByteSequence buf, final ParserCursor cursor, final BitSet delimiters) {
+        BitSet bitset = RawFieldParser.INIT_BITSET(AT, OPENING_BRACKET);
+        if (delimiters != null) {
+            bitset.or(delimiters);
+        }
+        String openingText = this.parser.parseValue(buf, cursor, bitset);
         if (cursor.atEnd()) {
-            return new Mailbox(null, null, openingText, null);
+            return createMailbox(openingText);
         }
         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);
+            return parseMailboxAddress(openingText, buf, cursor);
         } else if (current == AT) {
             // localPart @ domain form
             cursor.updatePos(pos + 1);
@@ -170,8 +189,7 @@ public class LenientAddressBuilder {
             String domain = parseDomain(buf, cursor, delimiters);
             return new Mailbox(null, null, localPart, domain);
         } else {
-            // should never happen
-            return new Mailbox(null, null, openingText, null);
+            return createMailbox(openingText);
         }
     }
 
@@ -181,4 +199,116 @@ public class LenientAddressBuilder {
         return parseMailbox(raw, cursor, null);
     }
 
+    List<Mailbox> parseMailboxes(
+            final ByteSequence buf, final ParserCursor cursor, final BitSet delimiters) {
+        BitSet bitset = RawFieldParser.INIT_BITSET(COMMA);
+        if (delimiters != null) {
+            bitset.or(delimiters);
+        }
+        List<Mailbox> mboxes = new ArrayList<Mailbox>();
+        while (!cursor.atEnd()) {
+            int pos = cursor.getPos();
+            int current = (char) (buf.byteAt(pos) & 0xff);
+            if (delimiters != null && delimiters.get(current)) {
+                break;
+            } else if (current == COMMA) {
+                cursor.updatePos(pos + 1);
+            } else {
+                Mailbox mbox = parseMailbox(buf, cursor, bitset);
+                if (mbox != null) {
+                    mboxes.add(mbox);
+                }
+            }
+        }
+        return mboxes;
+    }
+
+    public Group parseGroup(final ByteSequence buf, final ParserCursor cursor) {
+        String name = this.parser.parseToken(buf, cursor, COLON_ONLY);
+        if (cursor.atEnd()) {
+            return new Group(name, Collections.<Mailbox>emptyList());
+        }
+        int pos = cursor.getPos();
+        int current = (char) (buf.byteAt(pos) & 0xff);
+        if (current == COLON) {
+            cursor.updatePos(pos + 1);
+        }
+        List<Mailbox> mboxes = parseMailboxes(buf, cursor, SEMICOLON_ONLY);
+        return new Group(name, mboxes);
+    }
+
+    public Group parseGroup(final String text) {
+        ByteSequence raw = ContentUtil.encode(text);
+        ParserCursor cursor = new ParserCursor(0, text.length());
+        return parseGroup(raw, cursor);
+    }
+
+    public Address parseAddress(
+            final ByteSequence buf, final ParserCursor cursor, final BitSet delimiters) {
+        BitSet bitset = RawFieldParser.INIT_BITSET(COLON, AT, OPENING_BRACKET);
+        if (delimiters != null) {
+            bitset.or(delimiters);
+        }
+        String openingText = this.parser.parseValue(buf, cursor, bitset);
+        if (cursor.atEnd()) {
+            return createMailbox(openingText);
+        }
+        int pos = cursor.getPos();
+        char current = (char) (buf.byteAt(pos) & 0xff);
+        if (current == OPENING_BRACKET) {
+            // name <localPart @ domain> form
+            return parseMailboxAddress(openingText, buf, cursor);
+        } 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 if (current == COLON) {
+            // group-name: localPart @ domain, name <localPart @ domain>; form
+            cursor.updatePos(pos + 1);
+            String name = openingText;
+            List<Mailbox> mboxes = parseMailboxes(buf, cursor, SEMICOLON_ONLY);
+            if (!cursor.atEnd()) {
+                pos = cursor.getPos();
+                current = (char) (buf.byteAt(pos) & 0xff);
+                if (current == SEMICOLON) {
+                    cursor.updatePos(pos + 1);
+                }
+            }
+            return new Group(name, mboxes);
+        } else {
+            return createMailbox(openingText);
+        }
+    }
+
+    public Address parseAddress(final String text) {
+        ByteSequence raw = ContentUtil.encode(text);
+        ParserCursor cursor = new ParserCursor(0, text.length());
+        return parseAddress(raw, cursor, null);
+    }
+
+    public AddressList parseAddressList(final ByteSequence buf, final ParserCursor cursor)
{
+        List<Address> addresses = new ArrayList<Address>();
+        while (!cursor.atEnd()) {
+            int pos = cursor.getPos();
+            int current = (char) (buf.byteAt(pos) & 0xff);
+            if (current == COMMA) {
+                cursor.updatePos(pos + 1);
+            } else {
+                Address address = parseAddress(buf, cursor, COMMA_ONLY);
+                if (address != null) {
+                    addresses.add(address);
+                }
+            }
+        }
+        return new AddressList(addresses, false);
+    }
+
+    public AddressList parseAddressList(final String text) {
+        ByteSequence raw = ContentUtil.encode(text);
+        ParserCursor cursor = new ParserCursor(0, text.length());
+        return parseAddressList(raw, cursor);
+    }
+
 }

Modified: 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=1135622&r1=1135621&r2=1135622&view=diff
==============================================================================
--- james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java
(original)
+++ james/mime4j/trunk/dom/src/test/java/org/apache/james/mime4j/field/address/LenientAddressBuilderTest.java
Tue Jun 14 14:52:12 2011
@@ -19,11 +19,18 @@
 
 package org.apache.james.mime4j.field.address;
 
+import java.util.List;
+
 import junit.framework.TestCase;
 
+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.stream.ParserCursor;
+import org.apache.james.mime4j.stream.RawFieldParser;
 import org.apache.james.mime4j.util.ByteSequence;
 import org.apache.james.mime4j.util.ContentUtil;
 
@@ -36,63 +43,63 @@ public class LenientAddressBuilderTest e
         parser = LenientAddressBuilder.DEFAULT;
     }
 
-    public void testParseDomain() throws ParseException {
+    public void testParseDomain() throws Exception {
         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[] {';'});
+        String domain = parser.parseDomain(raw, cursor, RawFieldParser.INIT_BITSET(';'));
         assertEquals("machine.example.com", domain);
     }
 
-    public void testParseAddress() throws ParseException {
+    public void testParseMailboxAddress() throws Exception {
         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[] {';'});
+        Mailbox mailbox = parser.parseMailboxAddress(null, raw, cursor);
         assertEquals("some one@somehost.somewhere.com", mailbox.getAddress());
     }
 
-    public void testParseAddressQuotedLocalPart() throws ParseException {
+    public void testParseAddressQuotedLocalPart() throws Exception {
         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[] {';'});
+        Mailbox mailbox = parser.parseMailboxAddress(null, raw, cursor);
         assertEquals("some  one@somehost.somewhere.com", mailbox.getAddress());
     }
 
-    public void testParseAddressTruncated() throws ParseException {
+    public void testParseAddressTruncated() throws Exception {
         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[] {';'});
+        Mailbox mailbox = parser.parseMailboxAddress(null, raw, cursor);
         assertEquals("some one", mailbox.getAddress());
     }
 
-    public void testParseAddressTrailingComments() throws ParseException {
+    public void testParseAddressTrailingComments() throws Exception {
         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[] {';'});
+        Mailbox mailbox = parser.parseMailboxAddress(null, raw, cursor);
         assertEquals("someone@somehost.somewhere.com", mailbox.getAddress());
         assertEquals(';', raw.byteAt(cursor.getPos()));
     }
 
-    public void testParseAddressTrailingGarbage() throws ParseException {
+    public void testParseAddressTrailingGarbage() throws Exception {
         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[] {';'});
+        Mailbox mailbox = parser.parseMailboxAddress(null, raw, cursor);
         assertEquals("someone@somehost.somewhere.com", mailbox.getAddress());
         assertEquals('g', raw.byteAt(cursor.getPos()));
     }
 
-    public void testParseRoute() throws ParseException {
+    public void testParseRoute() throws Exception {
         String s = "  @a, @b, @c :me@home";
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
@@ -106,7 +113,7 @@ public class LenientAddressBuilderTest e
         assertEquals('m', raw.byteAt(cursor.getPos()));
     }
 
-    public void testParseNoRoute() throws ParseException {
+    public void testParseNoRoute() throws Exception {
         String s = "stuff";
         ByteSequence raw = ContentUtil.encode(s);
         ParserCursor cursor = new ParserCursor(0, s.length());
@@ -115,7 +122,7 @@ public class LenientAddressBuilderTest e
         assertNull(route);
     }
 
-    public void testParseMailbox() throws ParseException {
+    public void testParseMailbox() throws Exception {
         Mailbox mailbox1 = parser.parseMailbox("John Doe <jdoe@machine(comment).  example>");
         assertEquals("John Doe", mailbox1.getName());
         assertEquals("jdoe", mailbox1.getLocalPart());
@@ -141,21 +148,21 @@ public class LenientAddressBuilderTest e
         assertEquals("hans.mueller@acme.org", mailbox5.getAddress());
     }
 
-    public void testParseMailboxNonASCII() throws ParseException {
+    public void testParseMailboxNonASCII() throws Exception {
         Mailbox mailbox1 = parser.parseMailbox(
                 "Hans M\374ller <hans.mueller@acme.org>");
         assertEquals("Hans M\374ller", mailbox1.getName());
         assertEquals("hans.mueller@acme.org", mailbox1.getAddress());
     }
 
-    public void testParsePartialQuotes() throws ParseException {
+    public void testParsePartialQuotes() throws Exception {
         Mailbox mailbox1 = parser.parseMailbox(
                 "Hans \"M\374ller\" is a good fella <hans.mueller@acme.org>");
         assertEquals("Hans M\374ller is a good fella", mailbox1.getName());
         assertEquals("hans.mueller@acme.org", mailbox1.getAddress());
     }
 
-    public void testParseMailboxObsoleteSynatax() throws ParseException {
+    public void testParseMailboxObsoleteSynatax() throws Exception {
         Mailbox mailbox1 = parser.parseMailbox("< (route)(obsolete) " +
                 "@host1.domain1 , @host2 . domain2:  foo@bar.org>");
         assertEquals(null, mailbox1.getName());
@@ -168,4 +175,199 @@ public class LenientAddressBuilderTest e
         assertEquals("host2.domain2", domainList.get(1));
     }
 
+    public void testParseMailboxEmpty() throws Exception {
+        Mailbox mailbox1 = parser.parseMailbox("  ");
+        assertNull(mailbox1);
+    }
+
+    public void testParseMailboxList() throws Exception {
+        String s = "a , b, ,,, c, d,;garbage";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+        List<Mailbox> mailboxes = parser.parseMailboxes(raw, cursor, RawFieldParser.INIT_BITSET(';'));
+        assertEquals(4, mailboxes.size());
+
+        Mailbox mailbox1 = mailboxes.get(0);
+        assertEquals("a", mailbox1.getAddress());
+        Mailbox mailbox2 = mailboxes.get(1);
+        assertEquals("b", mailbox2.getAddress());
+        Mailbox mailbox3 = mailboxes.get(2);
+        assertEquals("c", mailbox3.getAddress());
+        Mailbox mailbox4 = mailboxes.get(3);
+        assertEquals("d", mailbox4.getAddress());
+        assertEquals(';', raw.byteAt(cursor.getPos()));
+    }
+
+    public void testParseMailboxListEmpty() throws Exception {
+        String s = "   ";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+        List<Mailbox> mailboxes = parser.parseMailboxes(raw, cursor, RawFieldParser.INIT_BITSET(';'));
+        assertEquals(0, mailboxes.size());
+    }
+
+    public void testParseGroup() throws Exception {
+        String s = "group: john.doe@acme.org, Mary Smith <mary@example.net>";
+        ByteSequence raw = ContentUtil.encode(s);
+        ParserCursor cursor = new ParserCursor(0, s.length());
+        Group group = parser.parseGroup(raw, cursor);
+        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 {
+        Group group = parser.parseGroup("john.doe@acme.org");
+        assertEquals("john.doe@acme.org", group.getName());
+
+        MailboxList mailboxes = group.getMailboxes();
+        assertEquals(0, mailboxes.size());
+    }
+
+    public void testParseAddress() throws Exception {
+        Address address = parser.parseAddress("Mary Smith <mary@example.net>");
+        assertTrue(address instanceof Mailbox);
+        Mailbox mbox = (Mailbox) address;
+        assertEquals("Mary Smith", mbox.getName());
+        assertEquals("mary@example.net", mbox.getAddress());
+
+        address = parser.parseAddress("group: Mary Smith <mary@example.net>;");
+        assertTrue(address instanceof Group);
+        Group group = (Group) address;
+        assertEquals("group", group.getName());
+        MailboxList mailboxes = group.getMailboxes();
+        assertEquals(1, mailboxes.size());
+        mbox = mailboxes.get(0);
+        assertEquals("Mary Smith", mbox.getName());
+        assertEquals("mary@example.net", mbox.getAddress());
+    }
+
+    public void testParseAddressList() throws Exception {
+        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  <mary@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 Exception {
+        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 Exception {
+        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 Exception {
+        assertEquals(0, parser.parseAddressList("").size());
+        assertEquals(0, parser.parseAddressList("  \t   \t ").size());
+        assertEquals(0, parser.parseAddressList("  \t  ,  , , ,,, , \t ").size());
+    }
+
+    public void testSimpleForm() throws Exception {
+        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 Exception {
+        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 Exception {
+
+        // 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 <Neuman@BBN-TENEXA>");
+        parser.parseAddressList("Neuman@BBN-TENEXA");
+        parser.parseAddressList("\"George, Ted\" <Shared@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 <WhoZiWhatZit@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 <Balsa@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 <you@work.com>,
them@play.com ;");
+
+    }
+
 }



Mime
View raw message