Author: bago
Date: Sat Jan 2 16:50:08 2010
New Revision: 895236
URL: http://svn.apache.org/viewvc?rev=895236&view=rev
Log:
Extracted "BasicMimeTokenStream" class from MimeTokenStream, so to isolate
dependency from Maximal/Default BodyDescriptor (preparing MIME4J-157)
Added:
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/BasicMimeTokenStream.java
(with props)
Modified:
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java
Added:
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/BasicMimeTokenStream.java
URL:
http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/BasicMimeTokenStream.java?rev=895236&view=auto
==============================================================================
---
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/BasicMimeTokenStream.java
(added)
+++
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/BasicMimeTokenStream.java
Sat Jan 2 16:50:08 2010
@@ -0,0 +1,325 @@
+/****************************************************************
+ * 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.parser;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.LinkedList;
+
+import org.apache.james.mime4j.MimeException;
+import org.apache.james.mime4j.codec.Base64InputStream;
+import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
+import org.apache.james.mime4j.io.LineNumberInputStream;
+import org.apache.james.mime4j.io.LineNumberSource;
+import org.apache.james.mime4j.util.CharsetUtil;
+import org.apache.james.mime4j.util.MimeUtil;
+
+/**
+ * <p>
+ * Parses MIME (or RFC822) message streams of bytes or characters.
+ * The stream is converted into an event stream.
+ * <p>
+ * <p>
+ * Typical usage:
+ * </p>
+ * <pre>
+ * MimeTokenStream stream = new MimeTokenStream();
+ * stream.parse(new FileInputStream("mime.msg"));
+ * for (int state = stream.getState();
+ * state != MimeTokenStream.T_END_OF_STREAM;
+ * state = stream.next()) {
+ * switch (state) {
+ * case MimeTokenStream.T_BODY:
+ * System.out.println("Body detected, contents = "
+ * + stream.getInputStream() + ", header data = "
+ * + stream.getBodyDescriptor());
+ * break;
+ * case MimeTokenStream.T_FIELD:
+ * System.out.println("Header field detected: "
+ * + stream.getField());
+ * break;
+ * case MimeTokenStream.T_START_MULTIPART:
+ * System.out.println("Multipart message detexted,"
+ * + " header data = "
+ * + stream.getBodyDescriptor());
+ * ...
+ * }
+ * }
+ * </pre>
+ * <p>Instances of {...@link BasicMimeTokenStream} are reusable: Invoking the
+ * method {...@link #parse(InputStream)} resets the token streams internal
+ * state. However, they are definitely <em>not</em> thread safe. If you
+ * have a multi threaded application, then the suggested use is to have
+ * one instance per thread.</p>
+ */
+public class BasicMimeTokenStream implements EntityStates, RecursionMode {
+
+ private final MimeEntityConfig config;
+ private final LinkedList<EntityStateMachine> entities = new
LinkedList<EntityStateMachine>();
+
+ private int state = T_END_OF_STREAM;
+ private EntityStateMachine currentStateMachine;
+ private int recursionMode = M_RECURSE;
+ private MimeEntity rootentity;
+
+ /**
+ * Constructs a standard (lax) stream.
+ * Optional validation events will be logged only.
+ * Use {...@link #createStrictValidationStream()} to create
+ * a stream that strictly validates the input.
+ */
+ public BasicMimeTokenStream() {
+ this(new MimeEntityConfig());
+ }
+
+ public BasicMimeTokenStream(final MimeEntityConfig config) {
+ super();
+ this.config = config;
+ }
+
+ public void doParse(InputStream stream,
+ MutableBodyDescriptor newBodyDescriptor, int start) {
+ LineNumberSource lineSource = null;
+ if (config.isCountLineNumbers()) {
+ LineNumberInputStream lineInput = new
LineNumberInputStream(stream);
+ lineSource = lineInput;
+ stream = lineInput;
+ }
+
+ rootentity = new MimeEntity(
+ lineSource,
+ stream,
+ newBodyDescriptor,
+ start,
+ T_END_MESSAGE,
+ config);
+
+ rootentity.setRecursionMode(recursionMode);
+ currentStateMachine = rootentity;
+ entities.clear();
+ entities.add(currentStateMachine);
+ state = currentStateMachine.getState();
+ }
+
+ /**
+ * Determines if this parser is currently in raw mode.
+ *
+ * @return <code>true</code> if in raw mode, <code>false</code>
+ * otherwise.
+ * @see #setRecursionMode(int)
+ */
+ public boolean isRaw() {
+ return recursionMode == M_RAW;
+ }
+
+ /**
+ * Gets the current recursion mode.
+ * The recursion mode specifies the approach taken to parsing parts.
+ * {...@link #M_RAW} mode does not parse the part at all.
+ * {...@link #M_RECURSE} mode recursively parses each mail
+ * when an <code>message/rfc822</code> part is encounted;
+ * {...@link #M_NO_RECURSE} does not.
+ * @return {...@link #M_RECURSE}, {...@link #M_RAW} or {...@link
#M_NO_RECURSE}
+ */
+ public int getRecursionMode() {
+ return recursionMode;
+ }
+
+ /**
+ * Sets the current recursion.
+ * The recursion mode specifies the approach taken to parsing parts.
+ * {...@link #M_RAW} mode does not parse the part at all.
+ * {...@link #M_RECURSE} mode recursively parses each mail
+ * when an <code>message/rfc822</code> part is encounted;
+ * {...@link #M_NO_RECURSE} does not.
+ * @param mode {...@link #M_RECURSE}, {...@link #M_RAW} or {...@link
#M_NO_RECURSE}
+ */
+ public void setRecursionMode(int mode) {
+ recursionMode = mode;
+ if (currentStateMachine != null) {
+ currentStateMachine.setRecursionMode(mode);
+ }
+ }
+
+ /**
+ * Finishes the parsing and stops reading lines.
+ * NOTE: No more lines will be parsed but the parser
+ * will still call
+ * {...@link ContentHandler#endMultipart()},
+ * {...@link ContentHandler#endBodyPart()},
+ * {...@link ContentHandler#endMessage()}, etc to match previous calls
+ * to
+ * {...@link ContentHandler#startMultipart(BodyDescriptor)},
+ * {...@link ContentHandler#startBodyPart()},
+ * {...@link ContentHandler#startMessage()}, etc.
+ */
+ public void stop() {
+ rootentity.stop();
+ }
+
+ /**
+ * Returns the current state.
+ */
+ public int getState() {
+ return state;
+ }
+
+ /**
+ * This method returns the raw entity, preamble, or epilogue contents.
+ * <p/>
+ * This method is valid, if {...@link #getState()} returns either of
+ * {...@link #T_RAW_ENTITY}, {...@link #T_PREAMBLE}, or {...@link
#T_EPILOGUE}.
+ *
+ * @return Data stream, depending on the current state.
+ * @throws IllegalStateException {...@link #getState()} returns an
+ * invalid value.
+ */
+ public InputStream getInputStream() {
+ return currentStateMachine.getContentStream();
+ }
+
+ /**
+ * This method returns a transfer decoded stream based on the MIME
+ * fields with the standard defaults.
+ * <p/>
+ * This method is valid, if {...@link #getState()} returns either of
+ * {...@link #T_RAW_ENTITY}, {...@link #T_PREAMBLE}, or {...@link
#T_EPILOGUE}.
+ *
+ * @return Data stream, depending on the current state.
+ * @throws IllegalStateException {...@link #getState()} returns an
+ * invalid value.
+ */
+ public InputStream getDecodedInputStream() {
+ BodyDescriptor bodyDescriptor = getBodyDescriptor();
+ String transferEncoding = bodyDescriptor.getTransferEncoding();
+ InputStream dataStream = currentStateMachine.getContentStream();
+ if (MimeUtil.isBase64Encoding(transferEncoding)) {
+ dataStream = new Base64InputStream(dataStream);
+ } else if (MimeUtil.isQuotedPrintableEncoded(transferEncoding)) {
+ dataStream = new QuotedPrintableInputStream(dataStream);
+ }
+ return dataStream;
+ }
+
+ /**
+ * Gets a reader configured for the current body or body part.
+ * The reader will return a transfer and charset decoded
+ * stream of characters based on the MIME fields with the standard
+ * defaults.
+ * This is a conveniance method and relies on {...@link #getInputStream()}.
+ * Consult the javadoc for that method for known limitations.
+ *
+ * @return <code>Reader</code>, not null
+ * @see #getInputStream
+ * @throws IllegalStateException {...@link #getState()} returns an
+ * invalid value
+ * @throws UnsupportedCharsetException if there is no JVM support
+ * for decoding the charset
+ * @throws IllegalCharsetNameException if the charset name specified
+ * in the mime type is illegal
+ */
+ public Reader getReader() {
+ final BodyDescriptor bodyDescriptor = getBodyDescriptor();
+ final String mimeCharset = bodyDescriptor.getCharset();
+ final Charset charset;
+ if (mimeCharset == null || "".equals(mimeCharset)) {
+ charset = CharsetUtil.US_ASCII;
+ } else {
+ charset = Charset.forName(mimeCharset);
+ }
+ final InputStream instream = getDecodedInputStream();
+ return new InputStreamReader(instream, charset);
+ }
+
+ /**
+ * <p>Gets a descriptor for the current entity.
+ * This method is valid if {...@link #getState()} returns:</p>
+ * <ul>
+ * <li>{...@link #T_BODY}</li>
+ * <li>{...@link #T_START_MULTIPART}</li>
+ * <li>{...@link #T_EPILOGUE}</li>
+ * <li>{...@link #T_PREAMBLE}</li>
+ * </ul>
+ * @return <code>BodyDescriptor</code>, not nulls
+ */
+ public BodyDescriptor getBodyDescriptor() {
+ return currentStateMachine.getBodyDescriptor();
+ }
+
+ /**
+ * This method is valid, if {...@link #getState()} returns {...@link
#T_FIELD}.
+ * @return String with the fields raw contents.
+ * @throws IllegalStateException {...@link #getState()} returns another
+ * value than {...@link #T_FIELD}.
+ */
+ public RawField getField() {
+ return currentStateMachine.getField();
+ }
+
+ /**
+ * This method advances the token stream to the next token.
+ * @throws IllegalStateException The method has been called, although
+ * {...@link #getState()} was already {...@link #T_END_OF_STREAM}.
+ */
+ public int next() throws IOException, MimeException {
+ if (state == T_END_OF_STREAM || currentStateMachine == null) {
+ throw new IllegalStateException("No more tokens are available.");
+ }
+ while (currentStateMachine != null) {
+ EntityStateMachine next = currentStateMachine.advance();
+ if (next != null) {
+ entities.add(next);
+ currentStateMachine = next;
+ }
+ state = currentStateMachine.getState();
+ if (state != T_END_OF_STREAM) {
+ return state;
+ }
+ entities.removeLast();
+ if (entities.isEmpty()) {
+ currentStateMachine = null;
+ } else {
+ currentStateMachine = entities.getLast();
+ currentStateMachine.setRecursionMode(recursionMode);
+ }
+ }
+ state = T_END_OF_STREAM;
+ return state;
+ }
+
+ /**
+ * Renders a state as a string suitable for logging.
+ * @param state
+ * @return rendered as string, not null
+ */
+ public static final String stateToString(int state) {
+ return AbstractEntity.stateToString(state);
+ }
+
+
+ protected MimeEntityConfig getConfig() {
+ return config;
+ }
+}
Propchange:
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/BasicMimeTokenStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/BasicMimeTokenStream.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java
URL:
http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java?rev=895236&r1=895235&r2=895236&view=diff
==============================================================================
---
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java
(original)
+++
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeStreamParser.java
Sat Jan 2 16:50:08 2010
@@ -48,19 +48,23 @@
private final MimeTokenStream mimeTokenStream;
- public MimeStreamParser(final MimeEntityConfig config) {
+ public MimeStreamParser(MimeTokenStream tokenStream) {
super();
- if (config != null) {
- mimeEntityConfig = config.clone();
- } else {
- mimeEntityConfig = new MimeEntityConfig();
- }
- this.mimeTokenStream = new MimeTokenStream(mimeEntityConfig);
+ this.mimeTokenStream = tokenStream;
+ this.mimeEntityConfig = tokenStream.getConfig();
this.contentDecoding = false;
}
+
+ public MimeStreamParser(final MimeEntityConfig config, boolean clone) {
+ this(new MimeTokenStream(clone ? config.clone() : config));
+ }
+
+ public MimeStreamParser(final MimeEntityConfig config) {
+ this(config != null ? config : new MimeEntityConfig(), config != null);
+ }
public MimeStreamParser() {
- this(null);
+ this(new MimeEntityConfig(), false);
}
/**
Modified:
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java
URL:
http://svn.apache.org/viewvc/james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java?rev=895236&r1=895235&r2=895236&view=diff
==============================================================================
---
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java
(original)
+++
james/mime4j/branches/cycleclean/core/src/main/java/org/apache/james/mime4j/parser/MimeTokenStream.java
Sat Jan 2 16:50:08 2010
@@ -19,22 +19,7 @@
package org.apache.james.mime4j.parser;
-import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.Charset;
-import java.nio.charset.IllegalCharsetNameException;
-import java.nio.charset.UnsupportedCharsetException;
-import java.util.LinkedList;
-
-import org.apache.james.mime4j.MimeException;
-import org.apache.james.mime4j.codec.Base64InputStream;
-import org.apache.james.mime4j.codec.QuotedPrintableInputStream;
-import org.apache.james.mime4j.io.LineNumberInputStream;
-import org.apache.james.mime4j.io.LineNumberSource;
-import org.apache.james.mime4j.util.CharsetUtil;
-import org.apache.james.mime4j.util.MimeUtil;
/**
* <p>
@@ -74,7 +59,7 @@
* have a multi threaded application, then the suggested use is to have
* one instance per thread.</p>
*/
-public class MimeTokenStream implements EntityStates, RecursionMode {
+public class MimeTokenStream extends BasicMimeTokenStream {
/**
* Creates a stream that creates a more detailed body descriptor.
@@ -98,14 +83,6 @@
return new MimeTokenStream(config);
}
- private final MimeEntityConfig config;
- private final LinkedList<EntityStateMachine> entities = new
LinkedList<EntityStateMachine>();
-
- private int state = T_END_OF_STREAM;
- private EntityStateMachine currentStateMachine;
- private int recursionMode = M_RECURSE;
- private MimeEntity rootentity;
-
/**
* Constructs a standard (lax) stream.
* Optional validation events will be logged only.
@@ -117,8 +94,7 @@
}
protected MimeTokenStream(final MimeEntityConfig config) {
- super();
- this.config = config;
+ super(config);
}
/** Instructs the {...@code MimeTokenStream} to parse the given streams
contents.
@@ -146,33 +122,13 @@
}
private void doParse(InputStream stream, String contentType) {
- entities.clear();
-
- LineNumberSource lineSource = null;
- if (config.isCountLineNumbers()) {
- LineNumberInputStream lineInput = new
LineNumberInputStream(stream);
- lineSource = lineInput;
- stream = lineInput;
- }
-
- MutableBodyDescriptor newBodyDescriptor = newBodyDescriptor(null);
+ MutableBodyDescriptor newBodyDescriptor = newBodyDescriptor();
int start = T_START_MESSAGE;
if (contentType != null) {
start = T_END_HEADER;
newBodyDescriptor.addField(new RawField("Content-Type",
contentType));
}
- rootentity = new MimeEntity(
- lineSource,
- stream,
- newBodyDescriptor,
- start,
- T_END_MESSAGE,
- config);
- rootentity.setRecursionMode(recursionMode);
- currentStateMachine = rootentity;
-
- entities.add(currentStateMachine);
- state = currentStateMachine.getState();
+ doParse(stream, newBodyDescriptor, start);
}
/**
@@ -180,208 +136,14 @@
* this in order to create body descriptors, that provide more specific
* information.
*/
- protected MutableBodyDescriptor newBodyDescriptor(BodyDescriptor pParent) {
+ protected MutableBodyDescriptor newBodyDescriptor() {
final MutableBodyDescriptor result;
- if (config.isMaximalBodyDescriptor()) {
- result = new MaximalBodyDescriptor(pParent);
+ if (getConfig().isMaximalBodyDescriptor()) {
+ result = new MaximalBodyDescriptor(null);
} else {
- result = new DefaultBodyDescriptor(pParent);
+ result = new DefaultBodyDescriptor(null);
}
return result;
}
- /**
- * Determines if this parser is currently in raw mode.
- *
- * @return <code>true</code> if in raw mode, <code>false</code>
- * otherwise.
- * @see #setRecursionMode(int)
- */
- public boolean isRaw() {
- return recursionMode == M_RAW;
- }
-
- /**
- * Gets the current recursion mode.
- * The recursion mode specifies the approach taken to parsing parts.
- * {...@link #M_RAW} mode does not parse the part at all.
- * {...@link #M_RECURSE} mode recursively parses each mail
- * when an <code>message/rfc822</code> part is encounted;
- * {...@link #M_NO_RECURSE} does not.
- * @return {...@link #M_RECURSE}, {...@link #M_RAW} or {...@link
#M_NO_RECURSE}
- */
- public int getRecursionMode() {
- return recursionMode;
- }
-
- /**
- * Sets the current recursion.
- * The recursion mode specifies the approach taken to parsing parts.
- * {...@link #M_RAW} mode does not parse the part at all.
- * {...@link #M_RECURSE} mode recursively parses each mail
- * when an <code>message/rfc822</code> part is encounted;
- * {...@link #M_NO_RECURSE} does not.
- * @param mode {...@link #M_RECURSE}, {...@link #M_RAW} or {...@link
#M_NO_RECURSE}
- */
- public void setRecursionMode(int mode) {
- recursionMode = mode;
- if (currentStateMachine != null) {
- currentStateMachine.setRecursionMode(mode);
- }
- }
-
- /**
- * Finishes the parsing and stops reading lines.
- * NOTE: No more lines will be parsed but the parser
- * will still call
- * {...@link ContentHandler#endMultipart()},
- * {...@link ContentHandler#endBodyPart()},
- * {...@link ContentHandler#endMessage()}, etc to match previous calls
- * to
- * {...@link ContentHandler#startMultipart(BodyDescriptor)},
- * {...@link ContentHandler#startBodyPart()},
- * {...@link ContentHandler#startMessage()}, etc.
- */
- public void stop() {
- rootentity.stop();
- }
-
- /**
- * Returns the current state.
- */
- public int getState() {
- return state;
- }
-
- /**
- * This method returns the raw entity, preamble, or epilogue contents.
- * <p/>
- * This method is valid, if {...@link #getState()} returns either of
- * {...@link #T_RAW_ENTITY}, {...@link #T_PREAMBLE}, or {...@link
#T_EPILOGUE}.
- *
- * @return Data stream, depending on the current state.
- * @throws IllegalStateException {...@link #getState()} returns an
- * invalid value.
- */
- public InputStream getInputStream() {
- return currentStateMachine.getContentStream();
- }
-
- /**
- * This method returns a transfer decoded stream based on the MIME
- * fields with the standard defaults.
- * <p/>
- * This method is valid, if {...@link #getState()} returns either of
- * {...@link #T_RAW_ENTITY}, {...@link #T_PREAMBLE}, or {...@link
#T_EPILOGUE}.
- *
- * @return Data stream, depending on the current state.
- * @throws IllegalStateException {...@link #getState()} returns an
- * invalid value.
- */
- public InputStream getDecodedInputStream() {
- BodyDescriptor bodyDescriptor = getBodyDescriptor();
- String transferEncoding = bodyDescriptor.getTransferEncoding();
- InputStream dataStream = currentStateMachine.getContentStream();
- if (MimeUtil.isBase64Encoding(transferEncoding)) {
- dataStream = new Base64InputStream(dataStream);
- } else if (MimeUtil.isQuotedPrintableEncoded(transferEncoding)) {
- dataStream = new QuotedPrintableInputStream(dataStream);
- }
- return dataStream;
- }
-
- /**
- * Gets a reader configured for the current body or body part.
- * The reader will return a transfer and charset decoded
- * stream of characters based on the MIME fields with the standard
- * defaults.
- * This is a conveniance method and relies on {...@link #getInputStream()}.
- * Consult the javadoc for that method for known limitations.
- *
- * @return <code>Reader</code>, not null
- * @see #getInputStream
- * @throws IllegalStateException {...@link #getState()} returns an
- * invalid value
- * @throws UnsupportedCharsetException if there is no JVM support
- * for decoding the charset
- * @throws IllegalCharsetNameException if the charset name specified
- * in the mime type is illegal
- */
- public Reader getReader() {
- final BodyDescriptor bodyDescriptor = getBodyDescriptor();
- final String mimeCharset = bodyDescriptor.getCharset();
- final Charset charset;
- if (mimeCharset == null || "".equals(mimeCharset)) {
- charset = CharsetUtil.US_ASCII;
- } else {
- charset = Charset.forName(mimeCharset);
- }
- final InputStream instream = getDecodedInputStream();
- return new InputStreamReader(instream, charset);
- }
-
- /**
- * <p>Gets a descriptor for the current entity.
- * This method is valid if {...@link #getState()} returns:</p>
- * <ul>
- * <li>{...@link #T_BODY}</li>
- * <li>{...@link #T_START_MULTIPART}</li>
- * <li>{...@link #T_EPILOGUE}</li>
- * <li>{...@link #T_PREAMBLE}</li>
- * </ul>
- * @return <code>BodyDescriptor</code>, not nulls
- */
- public BodyDescriptor getBodyDescriptor() {
- return currentStateMachine.getBodyDescriptor();
- }
-
- /**
- * This method is valid, if {...@link #getState()} returns {...@link
#T_FIELD}.
- * @return String with the fields raw contents.
- * @throws IllegalStateException {...@link #getState()} returns another
- * value than {...@link #T_FIELD}.
- */
- public RawField getField() {
- return currentStateMachine.getField();
- }
-
- /**
- * This method advances the token stream to the next token.
- * @throws IllegalStateException The method has been called, although
- * {...@link #getState()} was already {...@link #T_END_OF_STREAM}.
- */
- public int next() throws IOException, MimeException {
- if (state == T_END_OF_STREAM || currentStateMachine == null) {
- throw new IllegalStateException("No more tokens are available.");
- }
- while (currentStateMachine != null) {
- EntityStateMachine next = currentStateMachine.advance();
- if (next != null) {
- entities.add(next);
- currentStateMachine = next;
- }
- state = currentStateMachine.getState();
- if (state != T_END_OF_STREAM) {
- return state;
- }
- entities.removeLast();
- if (entities.isEmpty()) {
- currentStateMachine = null;
- } else {
- currentStateMachine = entities.getLast();
- currentStateMachine.setRecursionMode(recursionMode);
- }
- }
- state = T_END_OF_STREAM;
- return state;
- }
-
- /**
- * Renders a state as a string suitable for logging.
- * @param state
- * @return rendered as string, not null
- */
- public static final String stateToString(int state) {
- return AbstractEntity.stateToString(state);
- }
}