Skip to content

Commit

Permalink
Proposed refactoring for MIME4J-116.
Browse files Browse the repository at this point in the history
FieldParser has been moved to the dom package and field parsing is expected to happen inside the MutableBodyDescriptor implementation.
Minimal/MaximalBodyDescriptor implementations takes a FieldParser instance and a boolean saying if they are expected to parse every field supported by the FieldParser or only the one used for the descriptor results, so that EntityBuilder doesn't have to know the FieldParser again.

git-svn-id: https://svn.apache.org/repos/asf/james/mime4j/branches/mime4j-116-refactoring@1138155 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
Stefano Bagnara committed Jun 21, 2011
1 parent d930946 commit 2c8ac52
Show file tree
Hide file tree
Showing 46 changed files with 197 additions and 208 deletions.
Expand Up @@ -26,7 +26,7 @@
import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.stream.BodyDescriptor;
import org.apache.james.mime4j.stream.EntityState;
import org.apache.james.mime4j.stream.FieldParser;
import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.MimeEntityConfig;
import org.apache.james.mime4j.stream.MimeTokenStream;
import org.apache.james.mime4j.stream.MutableBodyDescriptorFactory;
Expand Down Expand Up @@ -66,9 +66,8 @@ public MimeStreamParser(
final MimeEntityConfig config,
boolean clone,
final DecodeMonitor monitor,
final FieldParser<?> fieldParser,
final MutableBodyDescriptorFactory bodyDescFactory) {
this(new MimeTokenStream(clone ? config.clone() : config, monitor, fieldParser, bodyDescFactory));
this(new MimeTokenStream(clone ? config.clone() : config, monitor, bodyDescFactory));
}

public MimeStreamParser(final MimeEntityConfig config, boolean clone) {
Expand All @@ -78,18 +77,17 @@ public MimeStreamParser(final MimeEntityConfig config, boolean clone) {
public MimeStreamParser(
final MimeEntityConfig config,
final DecodeMonitor monitor,
final FieldParser<?> fieldParser,
final MutableBodyDescriptorFactory bodyDescFactory) {
this(config != null ? config : new MimeEntityConfig(), config != null,
monitor, fieldParser, bodyDescFactory);
monitor, bodyDescFactory);
}

public MimeStreamParser(final MimeEntityConfig config) {
this(config, null, null, null);
this(config, null, null);
}

public MimeStreamParser() {
this(new MimeEntityConfig(), false, null, null, null);
this(new MimeEntityConfig(), false, null, null);
}

/**
Expand Down Expand Up @@ -119,10 +117,10 @@ public void setContentDecoding(boolean b) {
*/
public void parse(InputStream inputStream) throws MimeException, IOException {
if (mimeEntityConfig.getHeadlessParsing() != null) {
mimeTokenStream.parseHeadless(inputStream, mimeEntityConfig.getHeadlessParsing());
Field contentType = mimeTokenStream.parseHeadless(inputStream, mimeEntityConfig.getHeadlessParsing());
handler.startMessage();
handler.startHeader();
handler.field(new RawField("Content-Type", mimeEntityConfig.getHeadlessParsing()));
handler.field(contentType);
handler.endHeader();
} else {
mimeTokenStream.parse(inputStream);
Expand Down
Expand Up @@ -39,7 +39,6 @@ abstract class AbstractEntity implements EntityStateMachine {
protected final MimeEntityConfig config;
protected final DecodeMonitor monitor;
protected final FieldBuilder fieldBuilder;
protected final FieldParser<?> fieldParser;
protected final MutableBodyDescriptor body;

private final ByteArrayBuffer linebuf;
Expand All @@ -56,15 +55,13 @@ abstract class AbstractEntity implements EntityStateMachine {
EntityState endState,
DecodeMonitor monitor,
FieldBuilder fieldBuilder,
FieldParser<?> fieldParser,
MutableBodyDescriptor body) {
this.config = config;
this.state = startState;
this.startState = startState;
this.endState = endState;
this.monitor = monitor;
this.fieldBuilder = fieldBuilder;
this.fieldParser = fieldParser;
this.body = body;
this.linebuf = new ByteArrayBuffer(64);
this.lineCount = 0;
Expand Down Expand Up @@ -149,12 +146,9 @@ protected boolean nextField() throws MimeException, IOException {
if (rawfield.getDelimiterIdx() != rawfield.getName().length()) {
monitor(Event.OBSOLETE_HEADER);
}
if (fieldParser != null) {
field = fieldParser.parse(rawfield, monitor);
} else {
field = rawfield;
}
body.addField(field);
Field newfield = body.addField(rawfield);
if (newfield != null) field = newfield;
else field = rawfield;
return true;
} catch (MimeException e) {
monitor(Event.INVALID_HEADER);
Expand Down
Expand Up @@ -101,7 +101,7 @@ public MutableBodyDescriptor newChild() {
*
* @param field the MIME field.
*/
public void addField(Field field) throws MimeException {
public Field addField(RawField field) throws MimeException {
String name = field.getName().toLowerCase(Locale.US);

if (name.equals("content-transfer-encoding") && !contentTransferEncSet) {
Expand Down Expand Up @@ -129,6 +129,7 @@ public void addField(Field field) throws MimeException {
} else if (name.equals("content-type") && !contentTypeSet) {
parseContentType(field);
}
return null;
}

private void parseContentType(Field field) throws MimeException {
Expand Down
Expand Up @@ -53,9 +53,8 @@ class MimeEntity extends AbstractEntity {
EntityState endState,
DecodeMonitor monitor,
FieldBuilder fieldBuilder,
FieldParser<?> fieldParser,
MutableBodyDescriptor body) {
super(config, startState, endState, monitor, fieldBuilder, fieldParser, body);
super(config, startState, endState, monitor, fieldBuilder, body);
this.lineSource = lineSource;
this.inbuffer = new BufferedLineReaderInputStream(
instream,
Expand All @@ -75,7 +74,7 @@ class MimeEntity extends AbstractEntity {
MutableBodyDescriptor body) {
this(lineSource, instream, config, startState, endState,
config.isStrictParsing() ? DecodeMonitor.STRICT : DecodeMonitor.SILENT,
new DefaultFieldBuilder(config.getMaxHeaderLen()), null, body);
new DefaultFieldBuilder(config.getMaxHeaderLen()), body);
}

MimeEntity(
Expand All @@ -86,19 +85,18 @@ class MimeEntity extends AbstractEntity {
this(lineSource, instream, config,
EntityState.T_START_MESSAGE, EntityState.T_END_MESSAGE,
config.isStrictParsing() ? DecodeMonitor.STRICT : DecodeMonitor.SILENT,
new DefaultFieldBuilder(config.getMaxHeaderLen()), null, body);
new DefaultFieldBuilder(config.getMaxHeaderLen()), body);
}

MimeEntity(
LineNumberSource lineSource,
InputStream instream,
FieldBuilder fieldBuilder,
FieldParser<?> fieldParser,
MutableBodyDescriptor body) {
this(lineSource, instream, new MimeEntityConfig(),
EntityState.T_START_MESSAGE, EntityState.T_END_MESSAGE,
DecodeMonitor.SILENT,
fieldBuilder, fieldParser, body);
fieldBuilder, body);
}

MimeEntity(
Expand All @@ -108,7 +106,7 @@ class MimeEntity extends AbstractEntity {
this(lineSource, instream, new MimeEntityConfig(),
EntityState.T_START_MESSAGE, EntityState.T_END_MESSAGE,
DecodeMonitor.SILENT,
new DefaultFieldBuilder(-1), null, body);
new DefaultFieldBuilder(-1), body);
}

public RecursionMode getRecursionMode() {
Expand Down Expand Up @@ -279,7 +277,6 @@ private EntityStateMachine nextMimeEntity(EntityState startState, EntityState en
endState,
monitor,
fieldBuilder,
fieldParser,
body.newChild());
mimeentity.setRecursionMode(recursionMode);
return mimeentity;
Expand Down
Expand Up @@ -75,7 +75,6 @@ public class MimeTokenStream {
private final MimeEntityConfig config;
private final DecodeMonitor monitor;
private final FieldBuilder fieldBuilder;
private final FieldParser<?> fieldParser;
private final MutableBodyDescriptorFactory bodyDescFactory;
private final LinkedList<EntityStateMachine> entities = new LinkedList<EntityStateMachine>();

Expand All @@ -97,35 +96,31 @@ public MimeTokenStream() {
}

public MimeTokenStream(final MimeEntityConfig config) {
this(config, null, null, null, null);
this(config, null, null, null);
}

public MimeTokenStream(
final MimeEntityConfig config,
final FieldParser<?> fieldParser,
final MutableBodyDescriptorFactory bodyDescFactory) {
this(config, null, null, fieldParser, bodyDescFactory);
this(config, null, null, bodyDescFactory);
}

public MimeTokenStream(
final MimeEntityConfig config,
final DecodeMonitor monitor,
final FieldParser<?> fieldParser,
final MutableBodyDescriptorFactory bodyDescFactory) {
this(config, monitor, null, fieldParser, bodyDescFactory);
this(config, monitor, null, bodyDescFactory);
}

public MimeTokenStream(
final MimeEntityConfig config,
final DecodeMonitor monitor,
final FieldBuilder fieldBuilder,
final FieldParser<?> fieldParser,
final MutableBodyDescriptorFactory bodyDescFactory) {
super();
this.config = config;
this.fieldBuilder = fieldBuilder != null ? fieldBuilder :
new DefaultFieldBuilder(config.getMaxHeaderLen());
this.fieldParser = fieldParser;
this.monitor = monitor != null ? monitor :
(config.isStrictParsing() ? DecodeMonitor.STRICT : DecodeMonitor.SILENT);
this.bodyDescFactory = bodyDescFactory;
Expand All @@ -139,26 +134,31 @@ public void parse(InputStream stream) {
doParse(stream, newBodyDescriptor(), EntityState.T_START_MESSAGE);
}

/** Instructs the {@code MimeTokenStream} to parse the given content with
/**
* <p>Instructs the {@code MimeTokenStream} to parse the given content with
* the content type. The message stream is assumed to have no message header
* and is expected to begin with a message body. This can be the case when
* the message content is transmitted using a different transport protocol
* such as HTTP.
* <p/>
* If the {@code MimeTokenStream} has already been in use, resets the streams
* internal state.
* such as HTTP.</p>
* <p>If the {@code MimeTokenStream} has already been in use, resets the
* streams internal state.</p>
* @return a parsed Field representing the input contentType
*/
public void parseHeadless(InputStream stream, String contentType) {
public Field parseHeadless(InputStream stream, String contentType) {
if (contentType == null) {
throw new IllegalArgumentException("Content type may not be null");
}
Field newContentType;
MutableBodyDescriptor newBodyDescriptor = newBodyDescriptor();
try {
newBodyDescriptor.addField(new RawField("Content-Type", contentType));
RawField rawContentType = new RawField("Content-Type", contentType);
newContentType = newBodyDescriptor.addField(rawContentType);
if (newContentType == null) newContentType = rawContentType;
} catch (MimeException ex) {
// should never happen
throw new IllegalArgumentException(ex.getMessage());
}

doParse(stream, newBodyDescriptor, EntityState.T_END_HEADER);
try {
next();
Expand All @@ -169,6 +169,7 @@ public void parseHeadless(InputStream stream, String contentType) {
// This should never happen
throw new IllegalStateException(e);
}
return newContentType;
}

/**
Expand Down Expand Up @@ -203,7 +204,6 @@ public void doParse(InputStream stream,
EntityState.T_END_MESSAGE,
monitor,
fieldBuilder,
fieldParser,
newBodyDescriptor);

rootentity.setRecursionMode(recursionMode);
Expand Down
Expand Up @@ -30,8 +30,10 @@ public interface MutableBodyDescriptor extends BodyDescriptor {
/**
* Adds a field to the body descriptor.
* @param field the MIME field.
*
* @return null or an elaborated field representing the same data.
*/
void addField(Field field) throws MimeException;
Field addField(RawField field) throws MimeException;

MutableBodyDescriptor newChild();

Expand Down
Expand Up @@ -666,7 +666,7 @@ public RawField build() throws MimeException {

MimeEntity entity = new MimeEntity(
lineInput,
rawstream, fieldBuilder, null, new DefaultBodyDescriptor());
rawstream, fieldBuilder, new DefaultBodyDescriptor());


assertEquals(EntityState.T_START_MESSAGE, entity.getState());
Expand Down
Expand Up @@ -17,11 +17,13 @@
* under the License. *
****************************************************************/

package org.apache.james.mime4j.stream;
package org.apache.james.mime4j.dom;

import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.field.ParsedField;
import org.apache.james.mime4j.stream.Field;

public interface FieldParser<T extends Field> {
public interface FieldParser<T extends ParsedField> {

T parse(Field rawField, DecodeMonitor monitor);

Expand Down
Expand Up @@ -20,12 +20,12 @@
package org.apache.james.mime4j.field;

import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.FieldParser;
import org.apache.james.mime4j.dom.address.AddressList;
import org.apache.james.mime4j.dom.field.AddressListField;
import org.apache.james.mime4j.field.address.AddressBuilder;
import org.apache.james.mime4j.field.address.ParseException;
import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.FieldParser;

/**
* Address list field such as <code>To</code> or <code>Reply-To</code>.
Expand Down
Expand Up @@ -22,12 +22,12 @@
import java.util.Collections;

import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.FieldParser;
import org.apache.james.mime4j.dom.address.AddressList;
import org.apache.james.mime4j.dom.address.Mailbox;
import org.apache.james.mime4j.dom.field.AddressListField;
import org.apache.james.mime4j.field.address.LenientAddressBuilder;
import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.FieldParser;
import org.apache.james.mime4j.stream.ParserCursor;
import org.apache.james.mime4j.stream.RawField;
import org.apache.james.mime4j.util.ByteSequence;
Expand Down
Expand Up @@ -20,9 +20,9 @@
package org.apache.james.mime4j.field;

import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.FieldParser;
import org.apache.james.mime4j.dom.field.ContentDescriptionField;
import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.FieldParser;

/**
* Represents a <code>Content-Description</code> field.
Expand Down
Expand Up @@ -28,13 +28,13 @@
import java.util.Map;

import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.FieldParser;
import org.apache.james.mime4j.dom.field.ContentDispositionField;
import org.apache.james.mime4j.field.contentdisposition.parser.ContentDispositionParser;
import org.apache.james.mime4j.field.contentdisposition.parser.ParseException;
import org.apache.james.mime4j.field.contentdisposition.parser.TokenMgrError;
import org.apache.james.mime4j.field.datetime.parser.DateTimeParser;
import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.FieldParser;

/**
* Represents a <code>Content-Disposition</code> field.
Expand Down
Expand Up @@ -32,9 +32,9 @@
import java.util.TimeZone;

import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.FieldParser;
import org.apache.james.mime4j.dom.field.ContentDispositionField;
import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.FieldParser;
import org.apache.james.mime4j.stream.NameValuePair;
import org.apache.james.mime4j.stream.RawBody;
import org.apache.james.mime4j.stream.RawField;
Expand Down
Expand Up @@ -20,9 +20,9 @@
package org.apache.james.mime4j.field;

import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.FieldParser;
import org.apache.james.mime4j.dom.field.ContentIdField;
import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.FieldParser;

/**
* Represents a <code>Content-Transfer-Encoding</code> field.
Expand Down
Expand Up @@ -25,11 +25,11 @@
import java.util.List;

import org.apache.james.mime4j.codec.DecodeMonitor;
import org.apache.james.mime4j.dom.FieldParser;
import org.apache.james.mime4j.dom.field.ContentLanguageField;
import org.apache.james.mime4j.field.language.parser.ContentLanguageParser;
import org.apache.james.mime4j.field.language.parser.ParseException;
import org.apache.james.mime4j.stream.Field;
import org.apache.james.mime4j.stream.FieldParser;

/**
* Represents a <code>Content-Transfer-Encoding</code> field.
Expand Down

0 comments on commit 2c8ac52

Please sign in to comment.