Author: rdonkin Date: Wed Feb 20 10:37:05 2008 New Revision: 629567 URL: http://svn.apache.org/viewvc?rev=629567&view=rev Log: Allow getInputStream for the contents of a multipart message. This allows more efficient then reading of data.
Added: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/MultipartStreamTest.java Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/Cursor.java james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeTokenStream.java james/mime4j/trunk/src/main/java/org/apache/james/mime4j/StreamCursor.java Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/Cursor.java URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/Cursor.java?rev=629567&r1=629566&r2=629567&view=diff ============================================================================== --- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/Cursor.java (original) +++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/Cursor.java Wed Feb 20 10:37:05 2008 @@ -97,7 +97,7 @@ * Advances the cursor. * @return the next byte * @throws IOException - * @see #getStream() + * @see #nextSection() */ public byte advance() throws IOException; @@ -105,6 +105,11 @@ * Gets a stream to read the contents of the next section of the message. * @return <code>InputStream</code>, not null */ - public InputStream getStream(); + public InputStream nextSection(); + /** + * Gets a stream to read the contents of the rest of this message. + * @return <code>InputStream</code>, not null + */ + public InputStream rest(); } Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeTokenStream.java URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeTokenStream.java?rev=629567&r1=629566&r2=629567&view=diff ============================================================================== --- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeTokenStream.java (original) +++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeTokenStream.java Wed Feb 20 10:37:05 2008 @@ -302,6 +302,7 @@ abstract static class StateMachine { int state; abstract int next() throws IOException, MimeException; + abstract InputStream read(); } private static class RawEntity extends StateMachine { @@ -314,6 +315,9 @@ state = T_END_OF_STREAM; return state; } + InputStream read() { + return stream; + } } private abstract class Entity extends StateMachine { @@ -348,7 +352,7 @@ cursor.boundary(boundary); if (isRaw()) { - currentStateMachine = new RawEntity(cursor.getStream()); + currentStateMachine = new RawEntity(cursor.nextSection()); } else { currentStateMachine = new BodyPart(cursor.nextMimePartCursor(), body); } @@ -397,7 +401,11 @@ break; case T_START_MULTIPART: cursor.boundary(body.getBoundary()); - state = T_PREAMBLE; + if (cursor.isEnded()) { + state = T_END_MULTIPART; + } else { + state = T_PREAMBLE; + } break; case T_PREAMBLE: return setParseBodyPartState(); @@ -421,6 +429,19 @@ return state; } + InputStream read() { + switch (getState()) { + case T_PREAMBLE: + case T_EPILOGUE: + case T_BODY: + return cursor.nextSection(); + case T_START_MULTIPART: + return cursor.rest(); + default: + throw new IllegalStateException("Expected state to be either of T_RAW_ENTITY, T_PREAMBLE, or T_EPILOGUE."); + } + } + private void initHeaderParsing() throws IOException, MimeException { body = newBodyDescriptor(parent); startLineNumber = lineNumber = cursor.getLineNumber(); @@ -544,7 +565,7 @@ private int parseMessage(Cursor cursor, BodyDescriptor parent) { switch (recursionMode) { case M_RAW: - currentStateMachine = new RawEntity(cursor.getStream()); + currentStateMachine = new RawEntity(cursor.nextSection()); break; case M_NO_RECURSE: // expected to be called only at start of paring @@ -753,16 +774,7 @@ * invalid value. */ public InputStream getInputStream() { - switch (getState()) { - case T_RAW_ENTITY: - return ((RawEntity) currentStateMachine).stream; - case T_PREAMBLE: - case T_EPILOGUE: - case T_BODY: - return ((Entity) currentStateMachine).cursor.getStream(); - default: - throw new IllegalStateException("Expected state to be either of T_RAW_ENTITY, T_PREAMBLE, or T_EPILOGUE."); - } + return currentStateMachine.read(); } /** Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/StreamCursor.java URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/StreamCursor.java?rev=629567&r1=629566&r2=629567&view=diff ============================================================================== --- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/StreamCursor.java (original) +++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/StreamCursor.java Wed Feb 20 10:37:05 2008 @@ -132,9 +132,9 @@ } /** - * @see Cursor#getStream() + * @see Cursor#nextSection() */ - public InputStream getStream() { + public InputStream nextSection() { InputStream result = stream; if (result == null) { @@ -147,6 +147,12 @@ * @see Cursor#advance() */ public byte advance() throws IOException { - return (byte) getStream().read(); + return (byte) nextSection().read(); } + + public InputStream rest() { + return contents; + } + + } Added: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/MultipartStreamTest.java URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/MultipartStreamTest.java?rev=629567&view=auto ============================================================================== --- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/MultipartStreamTest.java (added) +++ james/mime4j/trunk/src/test/java/org/apache/james/mime4j/MultipartStreamTest.java Wed Feb 20 10:37:05 2008 @@ -0,0 +1,126 @@ +package org.apache.james.mime4j; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + +import org.apache.commons.io.IOUtils; + +import junit.framework.TestCase; + +public class MultipartStreamTest extends TestCase { + + private static final Charset US_ASCII = Charset.forName("us-ascii"); + + private static final String BODY = "A Preamble\r\n" + + "--1729\r\n\r\n" + + "Simple plain text\r\n" + + "--1729\r\n" + + "Content-Type: text/plain; charset=US-ASCII\r\n\r\n" + + "Some more text\r\n" + + "--1729--\r\n"; + public static final String MESSAGE = "To: Road Runner <[EMAIL PROTECTED]>\r\n" + + "From: Wile E. Cayote <[EMAIL PROTECTED]>\r\n" + + "Date: Tue, 12 Feb 2008 17:34:09 +0000 (GMT)\r\n" + + "Subject: Mail\r\n" + + "Content-Type: multipart/mixed;boundary=1729\r\n\r\n" + + BODY; + + public static final String COMPLEX_MESSAGE = "To: Wile E. Cayote <[EMAIL PROTECTED]>\r\n" + + "From: Road Runner <[EMAIL PROTECTED]>\r\n" + + "Date: Tue, 19 Feb 2008 17:34:09 +0000 (GMT)\r\n" + + "Subject: Mail\r\n" + + "Content-Type: multipart/mixed;boundary=42\r\n\r\n" + + "A little preamble\r\n" + + "--42\r\n" + + "Content-Type: text/plain; charset=US-ASCII\r\n\r\n" + + "Rhubard!\r\n" + + "--42\r\n" + + "Content-Type: message/rfc822\r\n\r\n" + + MESSAGE + + "\r\n" + + "--42\r\n" + + "Content-Type: text/plain; charset=US-ASCII\r\n\r\n" + + "Custard!" + + "\r\n" + + "--42--\r\n"; + + MimeTokenStream parser; + + protected void setUp() throws Exception { + super.setUp(); + parser = new MimeTokenStream(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testShouldSupplyInputStreamForSimpleBody() throws Exception { + parser.parse(new ByteArrayInputStream(US_ASCII.encode(MESSAGE).array())); + checkState(MimeTokenStream.T_START_HEADER); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_END_HEADER); + checkState(MimeTokenStream.T_START_MULTIPART); + InputStream out = parser.getInputStream(); + assertEquals(BODY, IOUtils.toString(out, "us-ascii")); + checkState(MimeTokenStream.T_END_MULTIPART); + } + + public void testInputStreamShouldReadOnlyMessage() throws Exception { + parser.parse(new ByteArrayInputStream(US_ASCII.encode(COMPLEX_MESSAGE).array())); + checkState(MimeTokenStream.T_START_HEADER); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_END_HEADER); + checkState(MimeTokenStream.T_START_MULTIPART); + checkState(MimeTokenStream.T_PREAMBLE); + checkState(MimeTokenStream.T_START_BODYPART); + checkState(MimeTokenStream.T_START_HEADER); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_END_HEADER); + checkState(MimeTokenStream.T_BODY); + checkState(MimeTokenStream.T_END_BODYPART); + checkState(MimeTokenStream.T_START_BODYPART); + checkState(MimeTokenStream.T_START_HEADER); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_END_HEADER); + checkState(MimeTokenStream.T_START_MESSAGE); + checkState(MimeTokenStream.T_START_HEADER); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_END_HEADER); + checkState(MimeTokenStream.T_START_MULTIPART); + InputStream out = parser.getInputStream(); + assertEquals(BODY, IOUtils.toString(out, "us-ascii")); + checkState(MimeTokenStream.T_END_MULTIPART); + checkState(MimeTokenStream.T_END_MESSAGE); + //TODO: + //checkState(MimeTokenStream.T_END_BODYPART); + checkState(MimeTokenStream.T_START_BODYPART); + checkState(MimeTokenStream.T_START_HEADER); + checkState(MimeTokenStream.T_FIELD); + checkState(MimeTokenStream.T_END_HEADER); + checkState(MimeTokenStream.T_BODY); + checkState(MimeTokenStream.T_END_BODYPART); + checkState(MimeTokenStream.T_EPILOGUE); + checkState(MimeTokenStream.T_END_MULTIPART); + checkState(MimeTokenStream.T_END_MESSAGE); + checkState(MimeTokenStream.T_END_OF_STREAM); + } + + private void checkState(final int state) throws IOException, MimeException { + assertEquals(MimeTokenStream.stateToString(state), MimeTokenStream.stateToString(parser.next())); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]