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 [email protected]", 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 [email protected]",
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 = "< [email protected] > (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("[email protected]", mailbox.getAddress());
assertEquals(';', raw.byteAt(cursor.getPos()));
}
- public void testParseAddressTrailingGarbage() throws ParseException {
+ public void testParseAddressTrailingGarbage() throws Exception {
String s = "< [email protected] > 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("[email protected]", 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("[email protected]", mailbox5.getAddress());
}
- public void testParseMailboxNonASCII() throws ParseException {
+ public void testParseMailboxNonASCII() throws Exception {
Mailbox mailbox1 = parser.parseMailbox(
"Hans M\374ller <[email protected]>");
assertEquals("Hans M\374ller", mailbox1.getName());
assertEquals("[email protected]", mailbox1.getAddress());
}
- public void testParsePartialQuotes() throws ParseException {
+ public void testParsePartialQuotes() throws Exception {
Mailbox mailbox1 = parser.parseMailbox(
"Hans \"M\374ller\" is a good fella <[email protected]>");
assertEquals("Hans M\374ller is a good fella", mailbox1.getName());
assertEquals("[email protected]", mailbox1.getAddress());
}
- public void testParseMailboxObsoleteSynatax() throws ParseException {
+ public void testParseMailboxObsoleteSynatax() throws Exception {
Mailbox mailbox1 = parser.parseMailbox("< (route)(obsolete) " +
"@host1.domain1 , @host2 . domain2: [email protected]>");
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: [email protected], Mary Smith <[email protected]>";
+ 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("[email protected]", mailbox1.getAddress());
+
+ Mailbox mailbox2 = mailboxes.get(1);
+ assertEquals("Mary Smith", mailbox2.getName());
+ assertEquals("[email protected]", mailbox2.getAddress());
+ }
+
+ public void testParseInvalidGroup() throws Exception {
+ Group group = parser.parseGroup("[email protected]");
+ assertEquals("[email protected]", group.getName());
+
+ MailboxList mailboxes = group.getMailboxes();
+ assertEquals(0, mailboxes.size());
+ }
+
+ public void testParseAddress() throws Exception {
+ Address address = parser.parseAddress("Mary Smith <[email protected]>");
+ assertTrue(address instanceof Mailbox);
+ Mailbox mbox = (Mailbox) address;
+ assertEquals("Mary Smith", mbox.getName());
+ assertEquals("[email protected]", mbox.getAddress());
+
+ address = parser.parseAddress("group: Mary Smith <[email protected]>;");
+ 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("[email protected]", 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
<[email protected]>");
+ 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 \" < [email protected] >
(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 :
[email protected], [email protected]; , ,,, marketing:[email protected]
,[email protected];, [email protected]");
+ 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/ \"[email protected]>");
+
+ // 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\" <[email protected]>");
+ parser.parseAddressList("Wilt . (the Stilt) [email protected]");
+
+ // 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>," +
+ " [email protected], \"Galloping Gourmet\"@" +
+ " ANT.Down-Under (Australian National
Television)," +
+ " Cheapie@Discount-Liquors;," +
+ " Cruisers: Port@Portugal, Jones@SEA;," +
+ " [email protected]");
+
+ // 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 <[email protected]>," +
+ " \"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("[email protected] (comment (nested
(deeply\\))))");
+ parser.parseAddressList("mailing list: [email protected], route two
<[email protected]>, [email protected] ;");
+
+ }
+
}