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 mw...@apache.org on 2009/02/27 17:45:03 UTC
svn commit: r748583 [1/2] - in /james/mime4j/trunk/src:
main/java/org/apache/james/mime4j/field/
main/java/org/apache/james/mime4j/message/
main/java/org/apache/james/mime4j/parser/
main/java/org/apache/james/mime4j/util/ test/java/org/apache/james/mim...
Author: mwiederkehr
Date: Fri Feb 27 16:45:02 2009
New Revision: 748583
URL: http://svn.apache.org/viewvc?rev=748583&view=rev
Log:
Fix for MIME4J-118: MIME stream parser handles non-ASCII fields incorrectly
Added:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ByteSequence.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ContentUtil.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/EmptyByteSequence.java
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/AbstractField.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/AddressListField.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentDispositionField.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentTransferEncodingField.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentTypeField.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DateTimeField.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/FieldParser.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Fields.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/MailboxField.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/MailboxListField.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/UnstructuredField.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Message.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/MessageBuilder.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/MessageWriter.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Multipart.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/Field.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/RawField.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ByteArrayBuffer.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/descriptor/BaseTestForBodyDescriptors.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/FieldsTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/EntityTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/ExampleMessagesRoundtripTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/HeaderTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageParserTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MessageWriteToTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/message/MultipartFormTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/parser/MimeStreamParserTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/parser/TestHandler.java
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/AbstractField.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/AbstractField.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/AbstractField.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/AbstractField.java Fri Feb 27 16:45:02 2009
@@ -24,6 +24,8 @@
import org.apache.james.mime4j.MimeException;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
+import org.apache.james.mime4j.util.ContentUtil;
import org.apache.james.mime4j.util.MimeUtil;
/**
@@ -31,23 +33,37 @@
*/
public abstract class AbstractField implements Field {
- private static final String FIELD_NAME_PATTERN =
- "^([\\x21-\\x39\\x3b-\\x7e]+):";
- private static final Pattern fieldNamePattern =
- Pattern.compile(FIELD_NAME_PATTERN);
-
+ private static final Pattern FIELD_NAME_PATTERN = Pattern
+ .compile("^([\\x21-\\x39\\x3b-\\x7e]+):");
+
private static final DefaultFieldParser parser = new DefaultFieldParser();
private final String name;
private final String body;
- private final String raw;
+ private final ByteSequence raw;
- protected AbstractField(final String name, final String body, final String raw) {
+ protected AbstractField(final String name, final String body, final ByteSequence raw) {
this.name = name;
this.body = body;
this.raw = raw;
}
-
+
+ /**
+ * Parses the given byte sequence and returns an instance of the
+ * <code>Field</code> class. The type of the class returned depends on the
+ * field name; see {@link #parse(String)} for a table of field names and
+ * their corresponding classes.
+ *
+ * @param raw the bytes to parse.
+ * @return a <code>Field</code> instance.
+ * @throws MimeException if the raw string cannot be split into field name and body.
+ * @see #isValidField()
+ */
+ public static Field parse(final ByteSequence raw) throws MimeException {
+ String rawStr = ContentUtil.decode(raw);
+ return parse(raw, rawStr);
+ }
+
/**
* Parses the given string and returns an instance of the
* <code>Field</code> class. The type of the class returned depends on
@@ -65,69 +81,19 @@
* <tr><td>{@link UnstructuredField}</td><td>Subject and others</td></tr>
* </table>
*
- * @param raw the string to parse.
+ * @param rawStr the string to parse.
* @return a <code>Field</code> instance.
* @throws MimeException if the raw string cannot be split into field name and body.
* @see #isValidField()
*/
- public static Field parse(final String raw) throws MimeException {
-
- /*
- * Unfold the field.
- */
- final String unfolded = MimeUtil.unfold(raw);
-
- /*
- * Split into name and value.
- */
- final Matcher fieldMatcher = fieldNamePattern.matcher(unfolded);
- if (!fieldMatcher.find()) {
- throw new MimeException("Invalid field in string");
- }
- final String name = fieldMatcher.group(1);
-
- String body = unfolded.substring(fieldMatcher.end());
- if (body.length() > 0 && body.charAt(0) == ' ') {
- body = body.substring(1);
- }
-
- return parser.parse(name, body, raw);
- }
-
- /**
- * Parses the given field name and field body strings and returns an
- * instance of the <code>Field</code> class. The type of the class
- * returned depends on the field name (see {@link #parse(String)}).
- * <p>
- * This method is convenient for creating or manipulating messages because
- * contrary to {@link #parse(String)} it does not throw a
- * {@link MimeException}.
- * <p>
- * Note that this method does not fold the header field; the specified field
- * body should already have been folded into multiple lines prior to calling
- * this method if folding is desired.
- *
- * @param name
- * the field name.
- * @param body
- * the field body (a.k.a value).
- * @return a <code>Field</code> instance.
- */
- public static Field parse(String name, String body) {
- if (body.length() > 0 && body.charAt(0) == ' ') {
- body = body.substring(1);
- }
-
- String raw = name + ": " + body;
-
- // Unfold body
- body = MimeUtil.unfold(body);
-
- return parser.parse(name, body, raw);
+ public static Field parse(final String rawStr) throws MimeException {
+ ByteSequence raw = ContentUtil.encode(rawStr);
+ return parse(raw, rawStr);
}
/**
* Gets the default parser used to parse fields.
+ *
* @return the default field parser
*/
public static DefaultFieldParser getParser() {
@@ -149,7 +115,7 @@
*
* @return the original raw field string.
*/
- public String getRaw() {
+ public ByteSequence getRaw() {
return raw;
}
@@ -227,11 +193,33 @@
return FieldName.TO.equalsIgnoreCase(name);
}
- /**
- * @see #getRaw()
- */
@Override
public String toString() {
- return raw;
+ return name + ": " + body;
+ }
+
+ private static Field parse(final ByteSequence raw, final String rawStr)
+ throws MimeException {
+ /*
+ * Unfold the field.
+ */
+ final String unfolded = MimeUtil.unfold(rawStr);
+
+ /*
+ * Split into name and value.
+ */
+ final Matcher fieldMatcher = FIELD_NAME_PATTERN.matcher(unfolded);
+ if (!fieldMatcher.find()) {
+ throw new MimeException("Invalid field in string");
+ }
+ final String name = fieldMatcher.group(1);
+
+ String body = unfolded.substring(fieldMatcher.end());
+ if (body.length() > 0 && body.charAt(0) == ' ') {
+ body = body.substring(1);
+ }
+
+ return parser.parse(name, body, raw);
}
+
}
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/AddressListField.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/AddressListField.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/AddressListField.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/AddressListField.java Fri Feb 27 16:45:02 2009
@@ -24,6 +24,7 @@
import org.apache.james.mime4j.field.address.AddressList;
import org.apache.james.mime4j.field.address.parser.ParseException;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
/**
* Address list field such as <code>To</code> or <code>Reply-To</code>.
@@ -36,7 +37,7 @@
private AddressList addressList;
private ParseException parseException;
- AddressListField(String name, String body, String raw) {
+ AddressListField(String name, String body, ByteSequence raw) {
super(name, body, raw);
}
@@ -72,7 +73,7 @@
static final FieldParser PARSER = new FieldParser() {
public Field parse(final String name, final String body,
- final String raw) {
+ final ByteSequence raw) {
return new AddressListField(name, body, raw);
}
};
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentDispositionField.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentDispositionField.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentDispositionField.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentDispositionField.java Fri Feb 27 16:45:02 2009
@@ -33,6 +33,7 @@
import org.apache.james.mime4j.field.contentdisposition.parser.TokenMgrError;
import org.apache.james.mime4j.field.datetime.parser.DateTimeParser;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
/**
* Represents a <code>Content-Disposition</code> field.
@@ -76,7 +77,7 @@
private boolean readDateParsed;
private Date readDate;
- ContentDispositionField(String name, String body, String raw) {
+ ContentDispositionField(String name, String body, ByteSequence raw) {
super(name, body, raw);
}
@@ -319,7 +320,7 @@
static final FieldParser PARSER = new FieldParser() {
public Field parse(final String name, final String body,
- final String raw) {
+ final ByteSequence raw) {
return new ContentDispositionField(name, body, raw);
}
};
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentTransferEncodingField.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentTransferEncodingField.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentTransferEncodingField.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentTransferEncodingField.java Fri Feb 27 16:45:02 2009
@@ -20,6 +20,7 @@
package org.apache.james.mime4j.field;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
import org.apache.james.mime4j.util.MimeUtil;
/**
@@ -28,7 +29,7 @@
public class ContentTransferEncodingField extends AbstractField {
private String encoding;
- ContentTransferEncodingField(String name, String body, String raw) {
+ ContentTransferEncodingField(String name, String body, ByteSequence raw) {
super(name, body, raw);
encoding = body.trim().toLowerCase();
}
@@ -58,7 +59,7 @@
static final FieldParser PARSER = new FieldParser() {
public Field parse(final String name, final String body,
- final String raw) {
+ final ByteSequence raw) {
return new ContentTransferEncodingField(name, body, raw);
}
};
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentTypeField.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentTypeField.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentTypeField.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentTypeField.java Fri Feb 27 16:45:02 2009
@@ -31,6 +31,7 @@
import org.apache.james.mime4j.field.contenttype.parser.ParseException;
import org.apache.james.mime4j.field.contenttype.parser.TokenMgrError;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
/**
* Represents a <code>Content-Type</code> field.
@@ -62,7 +63,7 @@
private Map<String, String> parameters = new HashMap<String, String>();
private ParseException parseException;
- ContentTypeField(String name, String body, String raw) {
+ ContentTypeField(String name, String body, ByteSequence raw) {
super(name, body, raw);
}
@@ -251,7 +252,7 @@
static final FieldParser PARSER = new FieldParser() {
public Field parse(final String name, final String body,
- final String raw) {
+ final ByteSequence raw) {
return new ContentTypeField(name, body, raw);
}
};
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DateTimeField.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DateTimeField.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DateTimeField.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DateTimeField.java Fri Feb 27 16:45:02 2009
@@ -28,6 +28,7 @@
import org.apache.james.mime4j.field.datetime.parser.ParseException;
import org.apache.james.mime4j.field.datetime.parser.TokenMgrError;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
/**
* Date-time field such as <code>Date</code> or <code>Resent-Date</code>.
@@ -40,7 +41,7 @@
private Date date;
private ParseException parseException;
- DateTimeField(String name, String body, String raw) {
+ DateTimeField(String name, String body, ByteSequence raw) {
super(name, body, raw);
}
@@ -82,7 +83,7 @@
static final FieldParser PARSER = new FieldParser() {
public Field parse(final String name, final String body,
- final String raw) {
+ final ByteSequence raw) {
return new DateTimeField(name, body, raw);
}
};
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DelegatingFieldParser.java Fri Feb 27 16:45:02 2009
@@ -23,6 +23,7 @@
import java.util.Map;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
public class DelegatingFieldParser implements FieldParser {
@@ -46,7 +47,7 @@
return field;
}
- public Field parse(final String name, final String body, final String raw) {
+ public Field parse(final String name, final String body, final ByteSequence raw) {
final FieldParser parser = getParser(name);
return parser.parse(name, body, raw);
}
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/FieldParser.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/FieldParser.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/FieldParser.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/FieldParser.java Fri Feb 27 16:45:02 2009
@@ -20,9 +20,10 @@
package org.apache.james.mime4j.field;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
public interface FieldParser {
- Field parse(final String name, final String body, final String raw);
+ Field parse(final String name, final String body, final ByteSequence raw);
}
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Fields.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Fields.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Fields.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Fields.java Fri Feb 27 16:45:02 2009
@@ -31,6 +31,8 @@
import org.apache.james.mime4j.field.address.Address;
import org.apache.james.mime4j.field.address.Mailbox;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
+import org.apache.james.mime4j.util.ContentUtil;
import org.apache.james.mime4j.util.MimeUtil;
/**
@@ -602,7 +604,8 @@
private static <F extends Field> F parse(FieldParser parser,
String fieldName, String fieldBody) {
- String raw = MimeUtil.fold(fieldName + ": " + fieldBody, 0);
+ String rawStr = MimeUtil.fold(fieldName + ": " + fieldBody, 0);
+ ByteSequence raw = ContentUtil.encode(rawStr);
Field field = parser.parse(fieldName, fieldBody, raw);
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/MailboxField.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/MailboxField.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/MailboxField.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/MailboxField.java Fri Feb 27 16:45:02 2009
@@ -26,6 +26,7 @@
import org.apache.james.mime4j.field.address.MailboxList;
import org.apache.james.mime4j.field.address.parser.ParseException;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
/**
* Mailbox field such as <code>Sender</code> or <code>Resent-Sender</code>.
@@ -38,7 +39,7 @@
private Mailbox mailbox;
private ParseException parseException;
- MailboxField(final String name, final String body, final String raw) {
+ MailboxField(final String name, final String body, final ByteSequence raw) {
super(name, body, raw);
}
@@ -77,7 +78,7 @@
static final FieldParser PARSER = new FieldParser() {
public Field parse(final String name, final String body,
- final String raw) {
+ final ByteSequence raw) {
return new MailboxField(name, body, raw);
}
};
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/MailboxListField.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/MailboxListField.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/MailboxListField.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/MailboxListField.java Fri Feb 27 16:45:02 2009
@@ -25,6 +25,7 @@
import org.apache.james.mime4j.field.address.MailboxList;
import org.apache.james.mime4j.field.address.parser.ParseException;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
/**
* Mailbox-list field such as <code>From</code> or <code>Resent-From</code>.
@@ -37,7 +38,7 @@
private MailboxList mailboxList;
private ParseException parseException;
- MailboxListField(final String name, final String body, final String raw) {
+ MailboxListField(final String name, final String body, final ByteSequence raw) {
super(name, body, raw);
}
@@ -73,7 +74,7 @@
static final FieldParser PARSER = new FieldParser() {
public Field parse(final String name, final String body,
- final String raw) {
+ final ByteSequence raw) {
return new MailboxListField(name, body, raw);
}
};
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/UnstructuredField.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/UnstructuredField.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/UnstructuredField.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/UnstructuredField.java Fri Feb 27 16:45:02 2009
@@ -21,6 +21,7 @@
import org.apache.james.mime4j.codec.DecoderUtil;
import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
/**
* Simple unstructured field such as <code>Subject</code>.
@@ -30,7 +31,7 @@
private String value;
- UnstructuredField(String name, String body, String raw) {
+ UnstructuredField(String name, String body, ByteSequence raw) {
super(name, body, raw);
}
@@ -51,7 +52,7 @@
static final FieldParser PARSER = new FieldParser() {
public Field parse(final String name, final String body,
- final String raw) {
+ final ByteSequence raw) {
return new UnstructuredField(name, body, raw);
}
};
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Message.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Message.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Message.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Message.java Fri Feb 27 16:45:02 2009
@@ -146,18 +146,16 @@
/**
* Write the content to the given output stream using the
- * {@link MessageWriter#STRICT_ERROR STRICT_ERROR} message writer.
+ * {@link MessageWriter#DEFAULT default} message writer.
*
* @param out
* the output stream to write to.
* @throws IOException
* in case of an I/O error
- * @throws MimeIOException
- * in case of a MIME protocol violation
* @see MessageWriter
*/
- public void writeTo(OutputStream out) throws IOException, MimeIOException {
- MessageWriter.STRICT_ERROR.writeEntity(this, out);
+ public void writeTo(OutputStream out) throws IOException {
+ MessageWriter.DEFAULT.writeEntity(this, out);
}
/**
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/MessageBuilder.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/MessageBuilder.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/MessageBuilder.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/MessageBuilder.java Fri Feb 27 16:45:02 2009
@@ -32,6 +32,8 @@
import org.apache.james.mime4j.parser.Field;
import org.apache.james.mime4j.parser.MimeStreamParser;
import org.apache.james.mime4j.storage.StorageProvider;
+import org.apache.james.mime4j.util.ByteArrayBuffer;
+import org.apache.james.mime4j.util.ByteSequence;
import org.apache.james.mime4j.util.MimeUtil;
/**
@@ -183,12 +185,8 @@
*/
public void epilogue(InputStream is) throws MimeException, IOException {
expect(Multipart.class);
- StringBuilder sb = new StringBuilder(128);
- int b;
- while ((b = is.read()) != -1) {
- sb.append((char) b);
- }
- ((Multipart) stack.peek()).setEpilogue(sb.toString());
+ ByteSequence bytes = loadStream(is);
+ ((Multipart) stack.peek()).setEpilogueRaw(bytes);
}
/**
@@ -196,12 +194,8 @@
*/
public void preamble(InputStream is) throws MimeException, IOException {
expect(Multipart.class);
- StringBuilder sb = new StringBuilder(128);
- int b;
- while ((b = is.read()) != -1) {
- sb.append((char) b);
- }
- ((Multipart) stack.peek()).setPreamble(sb.toString());
+ ByteSequence bytes = loadStream(is);
+ ((Multipart) stack.peek()).setPreambleRaw(bytes);
}
/**
@@ -212,4 +206,15 @@
throw new UnsupportedOperationException("Not supported");
}
+ private static ByteSequence loadStream(InputStream in) throws IOException {
+ ByteArrayBuffer bab = new ByteArrayBuffer(64);
+
+ int b;
+ while ((b = in.read()) != -1) {
+ bab.append(b);
+ }
+
+ return bab;
+ }
+
}
\ No newline at end of file
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/MessageWriter.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/MessageWriter.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/MessageWriter.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/MessageWriter.java Fri Feb 27 16:45:02 2009
@@ -19,77 +19,36 @@
package org.apache.james.mime4j.message;
-import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CodingErrorAction;
-import org.apache.james.mime4j.MimeIOException;
import org.apache.james.mime4j.codec.CodecUtil;
import org.apache.james.mime4j.field.ContentTypeField;
import org.apache.james.mime4j.field.FieldName;
import org.apache.james.mime4j.parser.Field;
-import org.apache.james.mime4j.util.CharsetUtil;
+import org.apache.james.mime4j.util.ByteArrayBuffer;
+import org.apache.james.mime4j.util.ByteSequence;
+import org.apache.james.mime4j.util.ContentUtil;
import org.apache.james.mime4j.util.MimeUtil;
/**
* Writes a message (or a part of a message) to an output stream.
* <p>
- * This class cannot be instantiated; instead the three static instances
- * {@link #STRICT_ERROR}, {@link #STRICT_IGNORE} or {@link #LENIENT} implement
- * different strategies for encoding header fields and preamble and epilogue of
- * a multipart.
+ * This class cannot be instantiated; instead the static instance
+ * {@link #DEFAULT} implements the default strategy for writing a message.
* <p>
- * This class can also be subclassed to implement custom strategies for writing
+ * This class may be subclassed to implement custom strategies for writing
* messages.
*/
public class MessageWriter {
- private static final Charset LENIENT_FALLBACK_CHARSET = CharsetUtil.ISO_8859_1;
- private static final String CRLF = CharsetUtil.CRLF;
- private static final int WRITER_BUFFER_SIZE = 4096;
+ private static final byte[] CRLF = { '\r', '\n' };
+ private static final byte[] DASHES = { '-', '-' };
/**
- * A message writer that uses US-ASCII for encoding and throws
- * {@link MimeIOException} if a non ASCII character is encountered.
+ * The default message writer.
*/
- public static final MessageWriter STRICT_ERROR = new MessageWriter();
-
- /**
- * A message writer that uses US-ASCII for encoding but ignores non ASCII
- * characters.
- */
- public static final MessageWriter STRICT_IGNORE = new MessageWriter() {
- @Override
- protected CharsetEncoder getCharsetEncoder(ContentTypeField contentType) {
- return ignoreEncoder(CharsetUtil.DEFAULT_CHARSET);
- }
- };
-
- /**
- * A message writer that uses the charset of the Content-Type header for
- * encoding.
- */
- public static final MessageWriter LENIENT = new MessageWriter() {
- @Override
- protected CharsetEncoder getCharsetEncoder(ContentTypeField contentType) {
- if (contentType == null) {
- return ignoreEncoder(LENIENT_FALLBACK_CHARSET);
- } else {
- String charset = contentType.getCharset();
- if (charset != null) {
- return ignoreEncoder(CharsetUtil.getCharset(charset));
- } else {
- return ignoreEncoder(LENIENT_FALLBACK_CHARSET);
- }
- }
- }
- };
+ public static final MessageWriter DEFAULT = new MessageWriter();
/**
* Protected constructor prevents direct instantiation.
@@ -107,11 +66,8 @@
* the OutputStream to write to.
* @throws IOException
* if an I/O error occurs.
- * @throws MimeIOException
- * in case of a MIME protocol violation
*/
- public void writeBody(Body body, OutputStream out) throws IOException,
- MimeIOException {
+ public void writeBody(Body body, OutputStream out) throws IOException {
if (body instanceof Message) {
writeEntity((Message) body, out);
} else if (body instanceof Multipart) {
@@ -120,8 +76,6 @@
((SingleBody) body).writeTo(out);
} else
throw new IllegalArgumentException("Unsupported body class");
-
- out.flush();
}
/**
@@ -134,17 +88,13 @@
* the OutputStream to write to.
* @throws IOException
* if an I/O error occurs.
- * @throws MimeIOException
- * in case of a MIME protocol violation
*/
- public void writeEntity(Entity entity, OutputStream out)
- throws IOException, MimeIOException {
+ public void writeEntity(Entity entity, OutputStream out) throws IOException {
final Header header = entity.getHeader();
if (header == null)
throw new IllegalArgumentException("Missing header");
writeHeader(header, out);
- out.flush();
final Body body = entity.getBody();
if (body == null)
@@ -171,42 +121,31 @@
* the OutputStream to write to.
* @throws IOException
* if an I/O error occurs.
- * @throws MimeIOException
- * in case of a MIME protocol violation
*/
public void writeMultipart(Multipart multipart, OutputStream out)
- throws IOException, MimeIOException {
+ throws IOException {
ContentTypeField contentType = getContentType(multipart);
- String boundary = getBoundary(contentType);
+ ByteSequence boundary = getBoundary(contentType);
- Writer writer = getWriter(contentType, out);
+ writeBytes(multipart.getPreambleRaw(), out);
+ out.write(CRLF);
- try {
- writer.write(multipart.getPreamble());
- writer.write(CRLF);
-
- for (BodyPart bodyPart : multipart.getBodyParts()) {
- writer.write("--");
- writer.write(boundary);
- writer.write(CRLF);
- writer.flush();
-
- writeEntity(bodyPart, out);
- writer.write(CRLF);
- }
-
- writer.write("--");
- writer.write(boundary);
- writer.write("--");
- writer.write(CRLF);
-
- writer.write(multipart.getEpilogue());
-
- writer.flush();
- } catch (CharacterCodingException e) {
- throw new MimeIOException("Multipart violates RFC 822");
+ for (BodyPart bodyPart : multipart.getBodyParts()) {
+ out.write(DASHES);
+ writeBytes(boundary, out);
+ out.write(CRLF);
+
+ writeEntity(bodyPart, out);
+ out.write(CRLF);
}
+
+ out.write(DASHES);
+ writeBytes(boundary, out);
+ out.write(DASHES);
+ out.write(CRLF);
+
+ writeBytes(multipart.getEpilogueRaw(), out);
}
/**
@@ -219,37 +158,17 @@
* the OutputStream to write to.
* @throws IOException
* if an I/O error occurs.
- * @throws MimeIOException
- * in case of a MIME protocol violation
*/
- public void writeHeader(Header header, OutputStream out)
- throws IOException, MimeIOException {
- Writer writer = getWriter((ContentTypeField) header
- .getField(FieldName.CONTENT_TYPE), out);
-
- try {
- for (Field field : header) {
- writer.write(field.getRaw());
- writer.write(CRLF);
- }
-
- writer.write(CRLF);
- writer.flush();
- } catch (CharacterCodingException e) {
- throw new MimeIOException("Header violates RFC 822");
+ public void writeHeader(Header header, OutputStream out) throws IOException {
+ for (Field field : header) {
+ writeBytes(field.getRaw(), out);
+ out.write(CRLF);
}
- }
- CharsetEncoder getCharsetEncoder(ContentTypeField contentType) {
- return CharsetUtil.DEFAULT_CHARSET.newEncoder();
+ out.write(CRLF);
}
- CharsetEncoder ignoreEncoder(Charset charset) {
- return charset.newEncoder().onMalformedInput(CodingErrorAction.REPLACE)
- .onUnmappableCharacter(CodingErrorAction.REPLACE);
- }
-
- private OutputStream encodeStream(OutputStream out, String encoding,
+ protected OutputStream encodeStream(OutputStream out, String encoding,
boolean binaryBody) throws IOException {
if (MimeUtil.isBase64Encoding(encoding)) {
return CodecUtil.wrapBase64(out);
@@ -280,20 +199,23 @@
return contentType;
}
- private String getBoundary(ContentTypeField contentType) {
+ private ByteSequence getBoundary(ContentTypeField contentType) {
String boundary = contentType.getBoundary();
if (boundary == null)
throw new IllegalArgumentException(
"Multipart boundary not specified");
- return boundary;
+ return ContentUtil.encode(boundary);
}
- private Writer getWriter(ContentTypeField contentType, OutputStream out) {
- CharsetEncoder encoder = getCharsetEncoder(contentType);
-
- return new BufferedWriter(new OutputStreamWriter(out, encoder),
- WRITER_BUFFER_SIZE);
+ private void writeBytes(ByteSequence byteSequence, OutputStream out)
+ throws IOException {
+ if (byteSequence instanceof ByteArrayBuffer) {
+ ByteArrayBuffer bab = (ByteArrayBuffer) byteSequence;
+ out.write(bab.buffer(), 0, bab.length());
+ } else {
+ out.write(byteSequence.toByteArray());
+ }
}
}
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Multipart.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Multipart.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Multipart.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/message/Multipart.java Fri Feb 27 16:45:02 2009
@@ -23,24 +23,37 @@
import java.util.LinkedList;
import java.util.List;
+import org.apache.james.mime4j.util.ByteSequence;
+import org.apache.james.mime4j.util.ContentUtil;
+
/**
- * Represents a MIME multipart body (see RFC 2045).A multipart body has a
+ * Represents a MIME multipart body (see RFC 2045).A multipart body has a
* ordered list of body parts. The multipart body also has a preamble and
- * epilogue. The preamble consists of whatever characters appear before the
- * first body part while the epilogue consists of whatever characters come
- * after the last body part.
+ * epilogue. The preamble consists of whatever characters appear before the
+ * first body part while the epilogue consists of whatever characters come after
+ * the last body part.
*/
public class Multipart implements Body {
- private String preamble = "";
- private String epilogue = "";
+
private List<BodyPart> bodyParts = new LinkedList<BodyPart>();
private Entity parent = null;
+
+ private ByteSequence preamble;
+ private transient String preambleStrCache;
+ private ByteSequence epilogue;
+ private transient String epilogueStrCache;
+
private String subType;
/**
* Creates a new empty <code>Multipart</code> instance.
*/
public Multipart(String subType) {
+ preamble = ByteSequence.EMPTY;
+ preambleStrCache = "";
+ epilogue = ByteSequence.EMPTY;
+ epilogueStrCache = "";
+
this.subType = subType;
}
@@ -64,45 +77,48 @@
*/
public Multipart(Multipart other) {
preamble = other.preamble;
+ preambleStrCache = other.preambleStrCache;
epilogue = other.epilogue;
-
+ epilogueStrCache = other.epilogueStrCache;
+
for (BodyPart otherBodyPart : other.bodyParts) {
BodyPart bodyPartCopy = new BodyPart(otherBodyPart);
addBodyPart(bodyPartCopy);
}
-
+
subType = other.subType;
}
/**
- * Gets the multipart sub-type. E.g. <code>alternative</code> (the default)
- * or <code>parallel</code>. See RFC 2045 for common sub-types and their
- * meaning.
+ * Gets the multipart sub-type. E.g. <code>alternative</code> (the
+ * default) or <code>parallel</code>. See RFC 2045 for common sub-types
+ * and their meaning.
*
* @return the multipart sub-type.
*/
public String getSubType() {
return subType;
}
-
+
/**
- * Sets the multipart sub-type. E.g. <code>alternative</code>
- * or <code>parallel</code>. See RFC 2045 for common sub-types and their
+ * Sets the multipart sub-type. E.g. <code>alternative</code> or
+ * <code>parallel</code>. See RFC 2045 for common sub-types and their
* meaning.
*
- * @param subType the sub-type.
+ * @param subType
+ * the sub-type.
*/
public void setSubType(String subType) {
this.subType = subType;
}
-
+
/**
* @see org.apache.james.mime4j.message.Body#getParent()
*/
public Entity getParent() {
return parent;
}
-
+
/**
* @see org.apache.james.mime4j.message.Body#setParent(org.apache.james.mime4j.message.Entity)
*/
@@ -114,24 +130,6 @@
}
/**
- * Gets the epilogue.
- *
- * @return the epilogue.
- */
- public String getEpilogue() {
- return epilogue;
- }
-
- /**
- * Sets the epilogue.
- *
- * @param epilogue the epilogue.
- */
- public void setEpilogue(String epilogue) {
- this.epilogue = epilogue;
- }
-
- /**
* Returns the number of body parts.
*
* @return number of <code>BodyPart</code> objects.
@@ -139,7 +137,7 @@
public int getCount() {
return bodyParts.size();
}
-
+
/**
* Gets the list of body parts. The list is immutable.
*
@@ -148,11 +146,12 @@
public List<BodyPart> getBodyParts() {
return Collections.unmodifiableList(bodyParts);
}
-
+
/**
* Sets the list of body parts.
*
- * @param bodyParts the new list of <code>BodyPart</code> objects.
+ * @param bodyParts
+ * the new list of <code>BodyPart</code> objects.
*/
public void setBodyParts(List<BodyPart> bodyParts) {
this.bodyParts = bodyParts;
@@ -160,20 +159,21 @@
bodyPart.setParent(parent);
}
}
-
+
/**
* Adds a body part to the end of the list of body parts.
*
- * @param bodyPart the body part.
+ * @param bodyPart
+ * the body part.
*/
public void addBodyPart(BodyPart bodyPart) {
if (bodyPart == null)
throw new IllegalArgumentException();
-
+
bodyParts.add(bodyPart);
bodyPart.setParent(parent);
}
-
+
/**
* Inserts a body part at the specified position in the list of body parts.
*
@@ -188,11 +188,11 @@
public void addBodyPart(BodyPart bodyPart, int index) {
if (bodyPart == null)
throw new IllegalArgumentException();
-
+
bodyParts.add(index, bodyPart);
bodyPart.setParent(parent);
}
-
+
/**
* Removes the body part at the specified position in the list of body
* parts.
@@ -209,7 +209,7 @@
bodyPart.setParent(null);
return bodyPart;
}
-
+
/**
* Replaces the body part at the specified position in the list of body
* parts with the specified body part.
@@ -229,30 +229,79 @@
BodyPart replacedBodyPart = bodyParts.set(index, bodyPart);
if (bodyPart == replacedBodyPart)
- throw new IllegalArgumentException("Cannot replace body part with itself");
+ throw new IllegalArgumentException(
+ "Cannot replace body part with itself");
bodyPart.setParent(parent);
replacedBodyPart.setParent(null);
return replacedBodyPart;
}
-
+
+ // package private for now; might become public someday
+ ByteSequence getPreambleRaw() {
+ return preamble;
+ }
+
+ void setPreambleRaw(ByteSequence preamble) {
+ this.preamble = preamble;
+ this.preambleStrCache = null;
+ }
+
/**
* Gets the preamble.
*
* @return the preamble.
*/
public String getPreamble() {
- return preamble;
+ if (preambleStrCache == null) {
+ preambleStrCache = ContentUtil.decode(preamble);
+ }
+ return preambleStrCache;
}
-
+
/**
* Sets the preamble.
*
- * @param preamble the preamble.
+ * @param preamble
+ * the preamble.
*/
public void setPreamble(String preamble) {
- this.preamble = preamble;
+ this.preamble = ContentUtil.encode(preamble);
+ this.preambleStrCache = preamble;
+ }
+
+ // package private for now; might become public someday
+ ByteSequence getEpilogueRaw() {
+ return epilogue;
+ }
+
+ void setEpilogueRaw(ByteSequence epilogue) {
+ this.epilogue = epilogue;
+ this.epilogueStrCache = null;
+ }
+
+ /**
+ * Gets the epilogue.
+ *
+ * @return the epilogue.
+ */
+ public String getEpilogue() {
+ if (epilogueStrCache == null) {
+ epilogueStrCache = ContentUtil.decode(epilogue);
+ }
+ return epilogueStrCache;
+ }
+
+ /**
+ * Sets the epilogue.
+ *
+ * @param epilogue
+ * the epilogue.
+ */
+ public void setEpilogue(String epilogue) {
+ this.epilogue = ContentUtil.encode(epilogue);
+ this.epilogueStrCache = epilogue;
}
/**
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/AbstractEntity.java Fri Feb 27 16:45:02 2009
@@ -33,7 +33,6 @@
import org.apache.james.mime4j.io.MaxHeaderLimitException;
import org.apache.james.mime4j.io.MaxLineLimitException;
import org.apache.james.mime4j.util.ByteArrayBuffer;
-import org.apache.james.mime4j.util.CharArrayBuffer;
import org.apache.james.mime4j.util.CharsetUtil;
/**
@@ -52,7 +51,6 @@
protected int state;
private final ByteArrayBuffer linebuf;
- private final CharArrayBuffer fieldbuf;
private int lineCount;
private Field field;
@@ -92,7 +90,6 @@
this.config = config;
this.body = newBodyDescriptor(parent);
this.linebuf = new ByteArrayBuffer(64);
- this.fieldbuf = new CharArrayBuffer(64);
this.lineCount = 0;
this.endOfHeader = false;
this.headerCount = 0;
@@ -125,13 +122,14 @@
protected abstract LineReaderInputStream getDataStream();
- private void fillFieldBuffer() throws IOException, MimeException {
- if (endOfHeader) {
- return;
- }
+ private ByteArrayBuffer fillFieldBuffer() throws IOException, MimeException {
+ if (endOfHeader)
+ throw new IllegalStateException();
+
int maxLineLen = config.getMaxLineLen();
LineReaderInputStream instream = getDataStream();
- fieldbuf.clear();
+ ByteArrayBuffer fieldbuf = new ByteArrayBuffer(64);
+
for (;;) {
// If there's still data stuck in the line buffer
// copy it to the field buffer
@@ -140,7 +138,7 @@
throw new MaxLineLimitException("Maximum line length limit exceeded");
}
if (len > 0) {
- fieldbuf.append(linebuf, 0, len);
+ fieldbuf.append(linebuf.buffer(), 0, len);
}
linebuf.clear();
if (instream.readLine(linebuf) == -1) {
@@ -169,6 +167,8 @@
}
}
}
+
+ return fieldbuf;
}
protected boolean parseField() throws MimeException, IOException {
@@ -180,42 +180,37 @@
if (headerCount >= maxHeaderLimit) {
throw new MaxHeaderLimitException("Maximum header limit exceeded");
}
-
- fillFieldBuffer();
+
+ ByteArrayBuffer fieldbuf = fillFieldBuffer();
headerCount++;
-
+
// Strip away line delimiter
int len = fieldbuf.length();
- if (len > 0 && fieldbuf.charAt(len - 1) == '\n') {
+ if (len > 0 && fieldbuf.byteAt(len - 1) == '\n') {
len--;
}
- if (len > 0 && fieldbuf.charAt(len - 1) == '\r') {
+ if (len > 0 && fieldbuf.byteAt(len - 1) == '\r') {
len--;
}
fieldbuf.setLength(len);
boolean valid = true;
- String fieldName = null;
- String fieldValue = null;
-
- int pos = fieldbuf.indexOf(':');
+ int pos = fieldbuf.indexOf((byte) ':');
if (pos <= 0) {
monitor(Event.INALID_HEADER);
valid = false;
} else {
- fieldName = fieldbuf.substring(0, pos);
- for (int i = 0; i < fieldName.length(); i++) {
- if (!fieldChars.get(fieldName.charAt(i))) {
+ for (int i = 0; i < pos; i++) {
+ if (!fieldChars.get(fieldbuf.byteAt(i) & 0xff)) {
monitor(Event.INALID_HEADER);
valid = false;
break;
}
}
- fieldValue = fieldbuf.substring(pos + 1, fieldbuf.length());
}
if (valid) {
- field = new RawField(fieldName, fieldValue, fieldbuf.toString());
+ field = new RawField(fieldbuf, pos);
body.addField(field);
return true;
}
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/Field.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/Field.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/Field.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/Field.java Fri Feb 27 16:45:02 2009
@@ -19,6 +19,8 @@
package org.apache.james.mime4j.parser;
+import org.apache.james.mime4j.util.ByteSequence;
+
/**
* Abstract MIME field.
*/
@@ -39,10 +41,10 @@
String getBody();
/**
- * Gets the original raw field string.
+ * Gets the original raw field bytes.
*
- * @return the original raw field string.
+ * @return the original raw field bytes.
*/
- String getRaw();
+ ByteSequence getRaw();
}
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/MimeEntity.java Fri Feb 27 16:45:02 2009
@@ -32,6 +32,8 @@
import org.apache.james.mime4j.io.LineReaderInputStream;
import org.apache.james.mime4j.io.LineReaderInputStreamAdaptor;
import org.apache.james.mime4j.io.MimeBoundaryInputStream;
+import org.apache.james.mime4j.util.ByteSequence;
+import org.apache.james.mime4j.util.ContentUtil;
import org.apache.james.mime4j.util.MimeUtil;
public class MimeEntity extends AbstractEntity {
@@ -94,12 +96,10 @@
throw new IllegalStateException("Invalid state: " + stateToString(state));
}
skipHeader = true;
- body.addField(new RawField(
- "Content-Type",
- contentType,
- "Content-Type: " +contentType));
+ ByteSequence raw = ContentUtil.encode("Content-Type: " + contentType);
+ body.addField(new RawField(raw, 12));
}
-
+
@Override
protected int getLineNumber() {
if (lineSource == null)
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/RawField.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/RawField.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/RawField.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/parser/RawField.java Fri Feb 27 16:45:02 2009
@@ -19,37 +19,58 @@
package org.apache.james.mime4j.parser;
+import org.apache.james.mime4j.util.ByteSequence;
+import org.apache.james.mime4j.util.ContentUtil;
+
/**
* The basic immutable MIME field.
*/
-public class RawField implements Field {
+class RawField implements Field {
+
+ private final ByteSequence raw;
+ private int colonIdx;
+
+ private String name;
+ private String body;
- private final String name;
- private final String body;
- private final String raw;
-
- public RawField(String name, String body, String raw) {
- super();
- this.name = name;
- this.body = body;
+ public RawField(ByteSequence raw, int colonIdx) {
this.raw = raw;
+ this.colonIdx = colonIdx;
}
public String getName() {
- return this.name;
+ if (name == null) {
+ name = parseName();
+ }
+
+ return name;
}
public String getBody() {
- return this.body;
+ if (body == null) {
+ body = parseBody();
+ }
+
+ return body;
}
- public String getRaw() {
- return this.raw;
+ public ByteSequence getRaw() {
+ return raw;
}
@Override
public String toString() {
- return this.raw;
+ return getName() + ':' + getBody();
+ }
+
+ private String parseName() {
+ return ContentUtil.decode(raw, 0, colonIdx);
+ }
+
+ private String parseBody() {
+ int offset = colonIdx + 1;
+ int length = raw.length() - offset;
+ return ContentUtil.decode(raw, offset, length);
}
}
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ByteArrayBuffer.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ByteArrayBuffer.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ByteArrayBuffer.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ByteArrayBuffer.java Fri Feb 27 16:45:02 2009
@@ -19,10 +19,11 @@
package org.apache.james.mime4j.util;
+
/**
* A resizable byte array.
*/
-public final class ByteArrayBuffer {
+public final class ByteArrayBuffer implements ByteSequence {
private byte[] buffer;
private int len;
@@ -35,6 +36,26 @@
this.buffer = new byte[capacity];
}
+ public ByteArrayBuffer(byte[] bytes, boolean dontCopy) {
+ this(bytes, bytes.length, dontCopy);
+ }
+
+ public ByteArrayBuffer(byte[] bytes, int len, boolean dontCopy) {
+ if (bytes == null)
+ throw new IllegalArgumentException();
+ if (len < 0 || len > bytes.length)
+ throw new IllegalArgumentException();
+
+ if (dontCopy) {
+ this.buffer = bytes;
+ } else {
+ this.buffer = new byte[len];
+ System.arraycopy(bytes, 0, this.buffer, 0, len);
+ }
+
+ this.len = len;
+ }
+
private void expand(int newlen) {
byte newbuffer[] = new byte[Math.max(this.buffer.length << 1, newlen)];
System.arraycopy(this.buffer, 0, newbuffer, 0, this.len);
@@ -103,7 +124,10 @@
return b;
}
- public int byteAt(int i) {
+ public byte byteAt(int i) {
+ if (i < 0 || i >= this.len)
+ throw new IndexOutOfBoundsException();
+
return this.buffer[i];
}
@@ -118,7 +142,29 @@
public byte[] buffer() {
return this.buffer;
}
-
+
+ public int indexOf(byte b) {
+ return indexOf(b, 0, this.len);
+ }
+
+ public int indexOf(byte b, int beginIndex, int endIndex) {
+ if (beginIndex < 0) {
+ beginIndex = 0;
+ }
+ if (endIndex > this.len) {
+ endIndex = this.len;
+ }
+ if (beginIndex > endIndex) {
+ return -1;
+ }
+ for (int i = beginIndex; i < endIndex; i++) {
+ if (this.buffer[i] == b) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
public void setLength(int len) {
if (len < 0 || len > this.buffer.length) {
throw new IndexOutOfBoundsException();
@@ -138,5 +184,5 @@
public String toString() {
return new String(toByteArray());
}
-
+
}
Added: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ByteSequence.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ByteSequence.java?rev=748583&view=auto
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ByteSequence.java (added)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ByteSequence.java Fri Feb 27 16:45:02 2009
@@ -0,0 +1,58 @@
+/****************************************************************
+ * 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.util;
+
+/**
+ * An immutable sequence of bytes.
+ */
+public interface ByteSequence {
+
+ /**
+ * An empty byte sequence.
+ */
+ ByteSequence EMPTY = new EmptyByteSequence();
+
+ /**
+ * Returns the length of this byte sequence.
+ *
+ * @return the number of <code>byte</code>s in this sequence.
+ */
+ int length();
+
+ /**
+ * Returns the <code>byte</code> value at the specified index.
+ *
+ * @param index
+ * the index of the <code>byte</code> value to be returned.
+ * @return the corresponding <code>byte</code> value
+ * @throws IndexOutOfBoundsException
+ * if <code>index < 0 || index >= length()</code>.
+ */
+ byte byteAt(int index);
+
+ /**
+ * Copies the contents of this byte sequence into a newly allocated byte
+ * array and returns that array.
+ *
+ * @return a byte array holding a copy of this byte sequence.
+ */
+ byte[] toByteArray();
+
+}
Added: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ContentUtil.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ContentUtil.java?rev=748583&view=auto
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ContentUtil.java (added)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/ContentUtil.java Fri Feb 27 16:45:02 2009
@@ -0,0 +1,138 @@
+/****************************************************************
+ * 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.util;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * Utility methods for converting textual content of a message.
+ */
+public class ContentUtil {
+
+ private ContentUtil() {
+ }
+
+ /**
+ * Encodes the specified string into an immutable sequence of bytes using
+ * the US-ASCII charset.
+ *
+ * @param string
+ * string to encode.
+ * @return encoded string as an immutable sequence of bytes.
+ */
+ public static ByteSequence encode(String string) {
+ return encode(CharsetUtil.US_ASCII, string);
+ }
+
+ /**
+ * Encodes the specified string into an immutable sequence of bytes using
+ * the specified charset.
+ *
+ * @param charset
+ * Java charset to be used for the conversion.
+ * @param string
+ * string to encode.
+ * @return encoded string as an immutable sequence of bytes.
+ */
+ public static ByteSequence encode(Charset charset, String string) {
+ ByteBuffer encoded = charset.encode(CharBuffer.wrap(string));
+ ByteArrayBuffer bab = new ByteArrayBuffer(encoded.remaining());
+ bab.append(encoded.array(), encoded.position(), encoded.remaining());
+ return bab;
+ }
+
+ /**
+ * Decodes the specified sequence of bytes into a string using the US-ASCII
+ * charset.
+ *
+ * @param byteSequence
+ * sequence of bytes to decode.
+ * @return decoded string.
+ */
+ public static String decode(ByteSequence byteSequence) {
+ return decode(CharsetUtil.US_ASCII, byteSequence, 0, byteSequence
+ .length());
+ }
+
+ /**
+ * Decodes the specified sequence of bytes into a string using the specified
+ * charset.
+ *
+ * @param charset
+ * Java charset to be used for the conversion.
+ * @param byteSequence
+ * sequence of bytes to decode.
+ * @return decoded string.
+ */
+ public static String decode(Charset charset, ByteSequence byteSequence) {
+ return decode(charset, byteSequence, 0, byteSequence.length());
+ }
+
+ /**
+ * Decodes a sub-sequence of the specified sequence of bytes into a string
+ * using the US-ASCII charset.
+ *
+ * @param byteSequence
+ * sequence of bytes to decode.
+ * @param offset
+ * offset into the byte sequence.
+ * @param length
+ * number of bytes.
+ * @return decoded string.
+ */
+ public static String decode(ByteSequence byteSequence, int offset,
+ int length) {
+ return decode(CharsetUtil.US_ASCII, byteSequence, offset, length);
+ }
+
+ /**
+ * Decodes a sub-sequence of the specified sequence of bytes into a string
+ * using the specified charset.
+ *
+ * @param charset
+ * Java charset to be used for the conversion.
+ * @param byteSequence
+ * sequence of bytes to decode.
+ * @param offset
+ * offset into the byte sequence.
+ * @param length
+ * number of bytes.
+ * @return decoded string.
+ */
+ public static String decode(Charset charset, ByteSequence byteSequence,
+ int offset, int length) {
+ if (byteSequence instanceof ByteArrayBuffer) {
+ ByteArrayBuffer bab = (ByteArrayBuffer) byteSequence;
+ return decode(charset, bab.buffer(), offset, length);
+ } else {
+ byte[] bytes = byteSequence.toByteArray();
+ return decode(charset, bytes, offset, length);
+ }
+ }
+
+ private static String decode(Charset charset, byte[] buffer, int offset,
+ int length) {
+ return charset.decode(ByteBuffer.wrap(buffer, offset, length))
+ .toString();
+ }
+
+}
Added: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/EmptyByteSequence.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/EmptyByteSequence.java?rev=748583&view=auto
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/EmptyByteSequence.java (added)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/util/EmptyByteSequence.java Fri Feb 27 16:45:02 2009
@@ -0,0 +1,36 @@
+/****************************************************************
+ * 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.util;
+
+final class EmptyByteSequence implements ByteSequence {
+ private static final byte[] EMPTY_BYTES = {};
+
+ public int length() {
+ return 0;
+ }
+
+ public byte byteAt(int index) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ public byte[] toByteArray() {
+ return EMPTY_BYTES;
+ }
+}
\ No newline at end of file
Modified: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/descriptor/BaseTestForBodyDescriptors.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/descriptor/BaseTestForBodyDescriptors.java?rev=748583&r1=748582&r2=748583&view=diff
==============================================================================
--- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/descriptor/BaseTestForBodyDescriptors.java (original)
+++ james/mime4j/trunk/src/test/java/org/apache/james/mime4j/descriptor/BaseTestForBodyDescriptors.java Fri Feb 27 16:45:02 2009
@@ -19,12 +19,11 @@
package org.apache.james.mime4j.descriptor;
-import org.apache.james.mime4j.descriptor.BodyDescriptor;
-import org.apache.james.mime4j.descriptor.MutableBodyDescriptor;
-import org.apache.james.mime4j.field.AbstractField;
-
import junit.framework.TestCase;
+import org.apache.james.mime4j.parser.Field;
+import org.apache.james.mime4j.util.ByteSequence;
+
public abstract class BaseTestForBodyDescriptors extends TestCase {
protected abstract MutableBodyDescriptor newBodyDescriptor();
@@ -35,7 +34,7 @@
MutableBodyDescriptor bd = null;
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type ", "text/plain; charset=ISO-8859-1; "
+ bd.addField(new TestField("Content-Type ", "text/plain; charset=ISO-8859-1; "
+ "boundary=foo; param1=value1; param2=value2; param3=value3"));
assertEquals(3, bd.getContentTypeParameters().size());
assertEquals("value1", bd.getContentTypeParameters().get("param1"));
@@ -43,7 +42,7 @@
assertEquals("value3", bd.getContentTypeParameters().get("param3"));
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type ", "text/plain; param1=value1; param2=value2;"
+ bd.addField(new TestField("Content-Type ", "text/plain; param1=value1; param2=value2;"
+ " param3=value3"));
assertEquals(3, bd.getContentTypeParameters().size());
assertEquals("value1", bd.getContentTypeParameters().get("param1"));
@@ -51,7 +50,7 @@
assertEquals("value3", bd.getContentTypeParameters().get("param3"));
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type ", "text/plain; "
+ bd.addField(new TestField("Content-Type ", "text/plain; "
+ "param1= \" value with\tspaces \" ; "
+ "param2=\"\\\"value4 with escaped \\\" \\\"\";"));
assertEquals(2, bd.getContentTypeParameters().size());
@@ -63,7 +62,7 @@
* The parameter value should be \n\"
*/
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type ", "text/plain; param=\"\\n\\\\\\\"\""));
+ bd.addField(new TestField("Content-Type ", "text/plain; param=\"\\n\\\\\\\"\""));
assertEquals(1, bd.getContentTypeParameters().size());
assertEquals("\\n\\\"", bd.getContentTypeParameters().get("param"));
}
@@ -75,10 +74,10 @@
* Make sure that only the first Content-Type header added is used.
*/
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type ", "text/plain; charset=ISO-8859-1"));
+ bd.addField(new TestField("Content-Type ", "text/plain; charset=ISO-8859-1"));
assertEquals("text/plain", bd.getMimeType());
assertEquals("iso-8859-1", bd.getCharset());
- bd.addField(AbstractField.parse("Content-Type ", "text/html; charset=us-ascii"));
+ bd.addField(new TestField("Content-Type ", "text/html; charset=us-ascii"));
assertEquals("text/plain", bd.getMimeType());
assertEquals("iso-8859-1", bd.getCharset());
}
@@ -87,32 +86,32 @@
MutableBodyDescriptor bd = null;
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type ", "text/PLAIN"));
+ bd.addField(new TestField("Content-Type ", "text/PLAIN"));
assertEquals("text/plain", bd.getMimeType());
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type ", "text/PLAIN;"));
+ bd.addField(new TestField("Content-Type ", "text/PLAIN;"));
assertEquals("text/plain", bd.getMimeType());
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("content-type", " TeXt / html "));
+ bd.addField(new TestField("content-type", " TeXt / html "));
assertEquals("text/html", bd.getMimeType());
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("CONTENT-TYPE", " x-app/yada ; param = yada"));
+ bd.addField(new TestField("CONTENT-TYPE", " x-app/yada ; param = yada"));
assertEquals("x-app/yada", bd.getMimeType());
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("CONTENT-TYPE", " yada"));
+ bd.addField(new TestField("CONTENT-TYPE", " yada"));
assertEquals("text/plain", bd.getMimeType());
/*
* Make sure that only the first Content-Type header added is used.
*/
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type ", "text/plain"));
+ bd.addField(new TestField("Content-Type ", "text/plain"));
assertEquals("text/plain", bd.getMimeType());
- bd.addField(AbstractField.parse("Content-Type ", "text/html"));
+ bd.addField(new TestField("Content-Type ", "text/html"));
assertEquals("text/plain", bd.getMimeType());
/*
@@ -122,19 +121,19 @@
MutableBodyDescriptor parent = null;
parent = newBodyDescriptor();
- parent.addField(AbstractField.parse("Content-Type", "mutlipart/alternative; boundary=foo"));
+ parent.addField(new TestField("Content-Type", "mutlipart/alternative; boundary=foo"));
child = newBodyDescriptor(parent);
assertEquals("text/plain", child.getMimeType());
- child.addField(AbstractField.parse("Content-Type", " child/type"));
+ child.addField(new TestField("Content-Type", " child/type"));
assertEquals("child/type", child.getMimeType());
parent = newBodyDescriptor();
- parent.addField(AbstractField.parse("Content-Type", "multipart/digest; boundary=foo"));
+ parent.addField(new TestField("Content-Type", "multipart/digest; boundary=foo"));
child = newBodyDescriptor(parent);
assertEquals("message/rfc822", child.getMimeType());
- child.addField(AbstractField.parse("Content-Type", " child/type"));
+ child.addField(new TestField("Content-Type", " child/type"));
assertEquals("child/type", child.getMimeType());
}
@@ -147,39 +146,39 @@
*/
bd = newBodyDescriptor();
assertEquals("us-ascii", bd.getCharset());
- bd.addField(AbstractField.parse("Content-Type ", "text/type; charset=ISO-8859-1"));
+ bd.addField(new TestField("Content-Type ", "text/type; charset=ISO-8859-1"));
assertEquals("iso-8859-1", bd.getCharset());
bd = newBodyDescriptor();
assertEquals("us-ascii", bd.getCharset());
- bd.addField(AbstractField.parse("Content-Type ", "text/type"));
+ bd.addField(new TestField("Content-Type ", "text/type"));
assertEquals("us-ascii", bd.getCharset());
/*
* Test boundary.
*/
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type", "text/html; boundary=yada yada"));
+ bd.addField(new TestField("Content-Type", "text/html; boundary=yada yada"));
assertNull(bd.getBoundary());
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type", "multipart/yada; boundary=yada"));
+ bd.addField(new TestField("Content-Type", "multipart/yada; boundary=yada"));
assertEquals("yada", bd.getBoundary());
/*
* Test some weird parameters.
*/
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type", "multipart/yada; boundary=yada yada"));
+ bd.addField(new TestField("Content-Type", "multipart/yada; boundary=yada yada"));
assertEquals("yada", bd.getBoundary());
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type", "multipart/yada; boUNdarY= ya:*da; \tcharset\t = big5"));
+ bd.addField(new TestField("Content-Type", "multipart/yada; boUNdarY= ya:*da; \tcharset\t = big5"));
assertEquals("ya:*da", bd.getBoundary());
assertEquals("big5", bd.getCharset());
bd = newBodyDescriptor();
- bd.addField(AbstractField.parse("Content-Type", "multipart/yada; boUNdarY= \"ya \\\"\\\"\tda \\\"\"; "
+ bd.addField(new TestField("Content-Type", "multipart/yada; boUNdarY= \"ya \\\"\\\"\tda \\\"\"; "
+ "\tcharset\t = \"\\\"hepp\\\" =us\t-ascii\""));
assertEquals("ya \"\"\tda \"", bd.getBoundary());
assertEquals("\"hepp\" =us\t-ascii", bd.getCharset());
@@ -192,23 +191,47 @@
bd = newBodyDescriptor();
assertEquals(-1, bd.getContentLength());
- bd.addField(AbstractField.parse("Content-Length", "9901"));
+ bd.addField(new TestField("Content-Length", "9901"));
assertEquals(9901, bd.getContentLength());
// only the first content-length counts
- bd.addField(AbstractField.parse("Content-Length", "1239901"));
+ bd.addField(new TestField("Content-Length", "1239901"));
assertEquals(9901, bd.getContentLength());
}
public void testDoDefaultToUsAsciiWhenUntyped() throws Exception {
MutableBodyDescriptor descriptor = newBodyDescriptor();
- descriptor.addField(AbstractField.parse("To", "me@example.org"));
+ descriptor.addField(new TestField("To", "me@example.org"));
assertEquals("us-ascii", descriptor.getCharset());
}
public void testDoNotDefaultToUsAsciiForNonTextTypes() throws Exception {
MutableBodyDescriptor descriptor = newBodyDescriptor();
- descriptor.addField(AbstractField.parse("Content-Type", "image/png; name=blob.png"));
+ descriptor.addField(new TestField("Content-Type", "image/png; name=blob.png"));
assertNull(descriptor.getCharset());
}
+
+ private static final class TestField implements Field {
+
+ private final String name;
+ private final String body;
+
+ public TestField(String name, String body){
+ this.name = name;
+ this.body = body;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public ByteSequence getRaw() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
}