Author: mwiederkehr
Date: Wed Jan 28 22:35:38 2009
New Revision: 738651
URL: http://svn.apache.org/viewvc?rev=738651&view=rev
Log:
MIME4J-108: added ContentDispositionField
Added:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentDispositionField.java
james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/
james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/ContentDispositionParser.jj
james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/ParseException.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/ContentDispositionFieldTest.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/contentdisposition/
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/contentdisposition/ContentDispositionTest.java
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Field.java
Added:
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=738651&view=auto
==============================================================================
---
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentDispositionField.java
(added)
+++
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/ContentDispositionField.java
Wed Jan 28 22:35:38 2009
@@ -0,0 +1,326 @@
+/****************************************************************
+ * 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.field;
+
+import java.io.StringReader;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import
org.apache.james.mime4j.field.contentdisposition.parser.ContentDispositionParser;
+import org.apache.james.mime4j.field.contentdisposition.parser.TokenMgrError;
+import org.apache.james.mime4j.field.datetime.parser.DateTimeParser;
+import org.apache.james.mime4j.field.ParseException;
+
+/**
+ * Represents a <code>Content-Disposition</code> field.
+ */
+public class ContentDispositionField extends Field {
+ private static Log log = LogFactory.getLog(ContentDispositionField.class);
+
+ /** The <code>inline</code> disposition type. */
+ public static final String DISPOSITION_TYPE_INLINE = "inline";
+
+ /** The <code>attachment</code> disposition type. */
+ public static final String DISPOSITION_TYPE_ATTACHMENT = "attachment";
+
+ /** The name of the <code>filename</code> parameter. */
+ public static final String PARAM_FILENAME = "filename";
+
+ /** The name of the <code>creation-date</code> parameter. */
+ public static final String PARAM_CREATION_DATE = "creation-date";
+
+ /** The name of the <code>modification-date</code> parameter. */
+ public static final String PARAM_MODIFICATION_DATE = "modification-date";
+
+ /** The name of the <code>read-date</code> parameter. */
+ public static final String PARAM_READ_DATE = "read-date";
+
+ /** The name of the <code>size</code> parameter. */
+ public static final String PARAM_SIZE = "size";
+
+ private boolean parsed = false;
+
+ private String dispositionType = "";
+ private Map<String, String> parameters = new HashMap<String, String>();
+ private ParseException parseException;
+
+ private boolean creationDateParsed;
+ private Date creationDate;
+
+ private boolean modificationDateParsed;
+ private Date modificationDate;
+
+ private boolean readDateParsed;
+ private Date readDate;
+
+ ContentDispositionField(String name, String body, String raw) {
+ super(name, body, raw);
+ }
+
+ /**
+ * Gets the exception that was raised during parsing of the field value, if
+ * any; otherwise, null.
+ */
+ @Override
+ public ParseException getParseException() {
+ if (!parsed)
+ parse();
+
+ return parseException;
+ }
+
+ /**
+ * Gets the disposition type defined in this Content-Disposition field.
+ *
+ * @return the disposition type or an empty string if not set.
+ */
+ public String getDispositionType() {
+ if (!parsed)
+ parse();
+
+ return dispositionType;
+ }
+
+ /**
+ * Gets the value of a parameter. Parameter names are case-insensitive.
+ *
+ * @param name
+ * the name of the parameter to get.
+ * @return the parameter value or <code>null</code> if not set.
+ */
+ public String getParameter(String name) {
+ if (!parsed)
+ parse();
+
+ return parameters.get(name.toLowerCase());
+ }
+
+ /**
+ * Gets all parameters.
+ *
+ * @return the parameters.
+ */
+ public Map<String, String> getParameters() {
+ if (!parsed)
+ parse();
+
+ return Collections.unmodifiableMap(parameters);
+ }
+
+ /**
+ * Determines if the disposition type of this field matches the given one.
+ *
+ * @param dispositionType
+ * the disposition type to match against.
+ * @return <code>true</code> if the disposition type of this field
+ * matches, <code>false</code> otherwise.
+ */
+ public boolean isDispositionType(String dispositionType) {
+ if (!parsed)
+ parse();
+
+ return this.dispositionType.equalsIgnoreCase(dispositionType);
+ }
+
+ /**
+ * Return <code>true</code> if the disposition type of this field is
+ * <i>inline</i>, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the disposition type of this field is
+ * <i>inline</i>, <code>false</code> otherwise.
+ */
+ public boolean isInline() {
+ if (!parsed)
+ parse();
+
+ return dispositionType.equals(DISPOSITION_TYPE_INLINE);
+ }
+
+ /**
+ * Return <code>true</code> if the disposition type of this field is
+ * <i>attachment</i>, <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if the disposition type of this field is
+ * <i>attachment</i>, <code>false</code> otherwise.
+ */
+ public boolean isAttachment() {
+ if (!parsed)
+ parse();
+
+ return dispositionType.equals(DISPOSITION_TYPE_ATTACHMENT);
+ }
+
+ /**
+ * Gets the value of the <code>filename</code> parameter if set.
+ *
+ * @return the <code>filename</code> parameter value or <code>null</code>
+ * if not set.
+ */
+ public String getFilename() {
+ return getParameter(PARAM_FILENAME);
+ }
+
+ /**
+ * Gets the value of the <code>creation-date</code> parameter if set and
+ * valid.
+ *
+ * @return the <code>creation-date</code> parameter value or
+ * <code>null</code> if not set or invalid.
+ */
+ public Date getCreationDate() {
+ if (!creationDateParsed) {
+ creationDate = parseDate(PARAM_CREATION_DATE);
+ creationDateParsed = true;
+ }
+
+ return creationDate;
+ }
+
+ /**
+ * Gets the value of the <code>modification-date</code> parameter if set
+ * and valid.
+ *
+ * @return the <code>modification-date</code> parameter value or
+ * <code>null</code> if not set or invalid.
+ */
+ public Date getModificationDate() {
+ if (!modificationDateParsed) {
+ modificationDate = parseDate(PARAM_MODIFICATION_DATE);
+ modificationDateParsed = true;
+ }
+
+ return modificationDate;
+ }
+
+ /**
+ * Gets the value of the <code>read-date</code> parameter if set and
+ * valid.
+ *
+ * @return the <code>read-date</code> parameter value or <code>null</code>
+ * if not set or invalid.
+ */
+ public Date getReadDate() {
+ if (!readDateParsed) {
+ readDate = parseDate(PARAM_READ_DATE);
+ readDateParsed = true;
+ }
+
+ return readDate;
+ }
+
+ /**
+ * Gets the value of the <code>size</code> parameter if set and valid.
+ *
+ * @return the <code>size</code> parameter value or <code>-1</code> if
+ * not set or invalid.
+ */
+ public long getSize() {
+ String value = getParameter(PARAM_SIZE);
+ if (value == null)
+ return -1;
+
+ try {
+ long size = Long.parseLong(value);
+ return size < 0 ? -1 : size;
+ } catch (NumberFormatException e) {
+ return -1;
+ }
+ }
+
+ private Date parseDate(String paramName) {
+ String value = getParameter(paramName);
+ if (value == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Parsing " + paramName + " null");
+ }
+ return null;
+ }
+
+ try {
+ return new DateTimeParser(new StringReader(value)).parseAll()
+ .getDate();
+ } catch (ParseException e) {
+ if (log.isDebugEnabled()) {
+ log.debug("Parsing " + paramName + " '" + value + "': "
+ + e.getMessage());
+ }
+ return null;
+ } catch (org.apache.james.mime4j.field.datetime.parser.TokenMgrError
e) {
+ if (log.isDebugEnabled()) {
+ log.debug("Parsing " + paramName + " '" + value + "': "
+ + e.getMessage());
+ }
+ return null;
+ }
+ }
+
+ private void parse() {
+ String body = getBody();
+
+ ContentDispositionParser parser = new ContentDispositionParser(
+ new StringReader(body));
+ try {
+ parser.parseAll();
+ } catch (ParseException e) {
+ if (log.isDebugEnabled()) {
+ log.debug("Parsing value '" + body + "': " + e.getMessage());
+ }
+ parseException = e;
+ } catch (TokenMgrError e) {
+ if (log.isDebugEnabled()) {
+ log.debug("Parsing value '" + body + "': " + e.getMessage());
+ }
+ parseException = new ParseException(e.getMessage());
+ }
+
+ final String dispositionType = parser.getDispositionType();
+
+ if (dispositionType != null) {
+ this.dispositionType = dispositionType.toLowerCase(Locale.US);
+
+ List<String> paramNames = parser.getParamNames();
+ List<String> paramValues = parser.getParamValues();
+
+ if (paramNames != null && paramValues != null) {
+ final int len = Math.min(paramNames.size(),
paramValues.size());
+ for (int i = 0; i < len; i++) {
+ String paramName =
paramNames.get(i).toLowerCase(Locale.US);
+ String paramValue = paramValues.get(i);
+ parameters.put(paramName, paramValue);
+ }
+ }
+ }
+
+ parsed = true;
+ }
+
+ public static class Parser implements FieldParser {
+ public Field parse(final String name, final String body,
+ final String raw) {
+ return new ContentDispositionField(name, body, raw);
+ }
+ }
+}
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java?rev=738651&r1=738650&r2=738651&view=diff
==============================================================================
---
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
(original)
+++
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/DefaultFieldParser.java
Wed Jan 28 22:35:38 2009
@@ -24,6 +24,7 @@
public DefaultFieldParser() {
setFieldParser(Field.CONTENT_TRANSFER_ENCODING, new
ContentTransferEncodingField.Parser());
setFieldParser(Field.CONTENT_TYPE, new ContentTypeField.Parser());
+ setFieldParser(Field.CONTENT_DISPOSITION, new
ContentDispositionField.Parser());
final DateTimeField.Parser dateTimeParser = new DateTimeField.Parser();
setFieldParser(Field.DATE, dateTimeParser);
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Field.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Field.java?rev=738651&r1=738650&r2=738651&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Field.java
(original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/field/Field.java
Wed Jan 28 22:35:38 2009
@@ -47,9 +47,10 @@
public static final String RESENT_DATE = "Resent-Date";
public static final String SUBJECT = "Subject";
+
public static final String CONTENT_TYPE = "Content-Type";
- public static final String CONTENT_TRANSFER_ENCODING =
- "Content-Transfer-Encoding";
+ public static final String CONTENT_TRANSFER_ENCODING =
"Content-Transfer-Encoding";
+ public static final String CONTENT_DISPOSITION = "Content-Disposition";
public static final String MESSAGE_ID = "Message-ID";
@@ -79,6 +80,7 @@
* <tr><th>Class returned</th><th>Field names</th></tr>
* <tr><td>{...@link ContentTypeField}</td><td>Content-Type</td></tr>
* <tr><td>{...@link
ContentTransferEncodingField}</td><td>Content-Transfer-Encoding</td></tr>
+ * <tr><td>{...@link
ContentDispositionField}</td><td>Content-Disposition</td></tr>
* <tr><td>{...@link DateTimeField}</td><td>Date, Resent-Date</td></tr>
* <tr><td>{...@link MailboxField}</td><td>Sender,
Resent-Sender</td></tr>
* <tr><td>{...@link MailboxListField}</td><td>From,
Resent-From</td></tr>
Added:
james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/ContentDispositionParser.jj
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/ContentDispositionParser.jj?rev=738651&view=auto
==============================================================================
---
james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/ContentDispositionParser.jj
(added)
+++
james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/ContentDispositionParser.jj
Wed Jan 28 22:35:38 2009
@@ -0,0 +1,231 @@
+/****************************************************************
+ * 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. *
+ ****************************************************************/
+
+
+/**
+ * RFC2183 Content-Disposition parser.
+ */
+
+options {
+ STATIC=false;
+ LOOKAHEAD=1;
+ JDK_VERSION = "1.5";
+ OUTPUT_DIRECTORY =
"../../../../../../../../../target/generated-sources/javacc";
+ //DEBUG_PARSER=true;
+ //DEBUG_TOKEN_MANAGER=true;
+}
+
+PARSER_BEGIN(ContentDispositionParser)
+/****************************************************************
+ * 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.field.contentdisposition.parser;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class ContentDispositionParser {
+
+ private String dispositionType;
+ private List<String> paramNames = new ArrayList<String>();
+ private List<String> paramValues = new ArrayList<String>();
+
+ public String getDispositionType() {
+ return dispositionType;
+ }
+
+ public List<String> getParamNames() {
+ return paramNames;
+ }
+
+ public List<String> getParamValues() {
+ return paramValues;
+ }
+
+ public static void main(String args[]) throws ParseException {
+ while (true) {
+ try {
+ ContentDispositionParser parser = new ContentDispositionParser(
+ System.in);
+ parser.parseLine();
+ } catch (Exception x) {
+ x.printStackTrace();
+ return;
+ }
+ }
+ }
+}
+
+PARSER_END(ContentDispositionParser)
+
+void parseLine() :
+{}
+{
+ parse() ["\r"] "\n"
+}
+
+void parseAll() :
+{}
+{
+ parse() <EOF>
+}
+
+void parse() :
+{
+ Token dispositionType;
+}
+{
+ dispositionType=<ATOKEN>
+ {
+ this.dispositionType = dispositionType.image;
+ }
+ ( ";" parameter() )*
+}
+
+void parameter() :
+{
+ Token attrib;
+ String val;
+}
+{
+ attrib=<ATOKEN> "=" val=value()
+ {
+ paramNames.add(attrib.image);
+ paramValues.add(val);
+ }
+}
+
+String value() :
+{Token t;}
+{
+( t=<ATOKEN>
+| t=<DIGITS>
+| t=<QUOTEDSTRING>
+)
+ { return t.image; }
+}
+
+
+
+SPECIAL_TOKEN :
+{
+ < WS: ( [" ", "\t"] )+ >
+}
+
+TOKEN_MGR_DECLS :
+{
+ // Keeps track of how many levels of comment nesting
+ // we've encountered. This is only used when the 2nd
+ // level is reached, for example ((this)), not (this).
+ // This is because the outermost level must be treated
+ // specially anyway, because the outermost ")" has a
+ // different token type than inner ")" instances.
+ static int commentNest;
+}
+
+MORE :
+{
+ // starts a comment
+ "(" : INCOMMENT
+}
+
+<INCOMMENT>
+SKIP :
+{
+ // ends a comment
+ < COMMENT: ")" > : DEFAULT
+ // if this is ever changed to not be a SKIP, need
+ // to make sure matchedToken.token = token.toString()
+ // is called.
+}
+
+<INCOMMENT>
+MORE :
+{
+ < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
+| "(" { commentNest = 1; } : NESTED_COMMENT
+| < <ANY>>
+}
+
+<NESTED_COMMENT>
+MORE :
+{
+ < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
+| "(" { ++commentNest; }
+| ")" { --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT); }
+| < <ANY>>
+}
+
+
+
+// QUOTED STRINGS
+
+MORE :
+{
+ "\"" { image.deleteCharAt(image.length() - 1); } : INQUOTEDSTRING
+}
+
+<INQUOTEDSTRING>
+MORE :
+{
+ < <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); }
+| < (~["\"", "\\"])+ >
+}
+
+<INQUOTEDSTRING>
+TOKEN :
+{
+ < QUOTEDSTRING: "\"" > { matchedToken.image = image.substring(0,
image.length() - 1); } : DEFAULT
+}
+
+
+TOKEN :
+{
+ < DIGITS: ( ["0"-"9"] )+ >
+}
+
+TOKEN :
+{
+ < ATOKEN: ( ~[" ", "\t", "(", ")", "<", ">", "@", ",", ";", ":", "\\",
"\"", "/", "[", "]", "?", "="] )+ >
+}
+
+
+// GLOBALS
+
+<*>
+TOKEN :
+{
+ < #QUOTEDPAIR: "\\" <ANY> >
+| < #ANY: ~[] >
+}
Added:
james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/ParseException.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/ParseException.java?rev=738651&view=auto
==============================================================================
---
james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/ParseException.java
(added)
+++
james/mime4j/trunk/src/main/javacc/org/apache/james/mime4j/field/contentdisposition/ParseException.java
Wed Jan 28 22:35:38 2009
@@ -0,0 +1,220 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0
*/
+/****************************************************************
+ * 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.field.contentdisposition.parser;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * Changes for Mime4J:
+ * extends org.apache.james.mime4j.field.ParseException
+ * added serialVersionUID
+ * added constructor ParseException(Throwable)
+ * default detail message is "Cannot parse field"
+ */
+public class ParseException extends
org.apache.james.mime4j.field.ParseException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * This constructor is used by the method "generateParseException"
+ * in the generated parser. Calling this constructor generates
+ * a new object of this type with the fields "currentToken",
+ * "expectedTokenSequences", and "tokenImage" set. The boolean
+ * flag "specialConstructor" is also set to true to indicate that
+ * this constructor was used to create this object.
+ * This constructor calls its super class with the empty string
+ * to force the "toString" method of parent class "Throwable" to
+ * print the error message in the form:
+ * ParseException: <result of getMessage>
+ */
+ public ParseException(Token currentTokenVal,
+ int[][] expectedTokenSequencesVal,
+ String[] tokenImageVal
+ )
+ {
+ super("");
+ specialConstructor = true;
+ currentToken = currentTokenVal;
+ expectedTokenSequences = expectedTokenSequencesVal;
+ tokenImage = tokenImageVal;
+ }
+
+ /**
+ * The following constructors are for use by you for whatever
+ * purpose you can think of. Constructing the exception in this
+ * manner makes the exception behave in the normal way - i.e., as
+ * documented in the class "Throwable". The fields "errorToken",
+ * "expectedTokenSequences", and "tokenImage" do not contain
+ * relevant information. The JavaCC generated code does not use
+ * these constructors.
+ */
+
+ public ParseException() {
+ super("Cannot parse field");
+ specialConstructor = false;
+ }
+
+ public ParseException(Throwable cause) {
+ super(cause);
+ specialConstructor = false;
+ }
+
+ public ParseException(String message) {
+ super(message);
+ specialConstructor = false;
+ }
+
+ /**
+ * This variable determines which constructor was used to create
+ * this object and thereby affects the semantics of the
+ * "getMessage" method (see below).
+ */
+ protected boolean specialConstructor;
+
+ /**
+ * This is the last token that has been consumed successfully. If
+ * this object has been created due to a parse error, the token
+ * followng this token will (therefore) be the first error token.
+ */
+ public Token currentToken;
+
+ /**
+ * Each entry in this array is an array of integers. Each array
+ * of integers represents a sequence of tokens (by their ordinal
+ * values) that is expected at this point of the parse.
+ */
+ public int[][] expectedTokenSequences;
+
+ /**
+ * This is a reference to the "tokenImage" array of the generated
+ * parser within which the parse error occurred. This array is
+ * defined in the generated ...Constants interface.
+ */
+ public String[] tokenImage;
+
+ /**
+ * This method has the standard behavior when this object has been
+ * created using the standard constructors. Otherwise, it uses
+ * "currentToken" and "expectedTokenSequences" to generate a parse
+ * error message and returns it. If this object has been created
+ * due to a parse error, and you do not catch it (it gets thrown
+ * from the parser), then this method is called during the printing
+ * of the final stack trace, and hence the correct error message
+ * gets displayed.
+ */
+ public String getMessage() {
+ if (!specialConstructor) {
+ return super.getMessage();
+ }
+ StringBuffer expected = new StringBuffer();
+ int maxSize = 0;
+ for (int i = 0; i < expectedTokenSequences.length; i++) {
+ if (maxSize < expectedTokenSequences[i].length) {
+ maxSize = expectedTokenSequences[i].length;
+ }
+ for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+ expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" ");
+ }
+ if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] !=
0) {
+ expected.append("...");
+ }
+ expected.append(eol).append(" ");
+ }
+ String retval = "Encountered \"";
+ Token tok = currentToken.next;
+ for (int i = 0; i < maxSize; i++) {
+ if (i != 0) retval += " ";
+ if (tok.kind == 0) {
+ retval += tokenImage[0];
+ break;
+ }
+ retval += add_escapes(tok.image);
+ tok = tok.next;
+ }
+ retval += "\" at line " + currentToken.next.beginLine + ", column " +
currentToken.next.beginColumn;
+ retval += "." + eol;
+ if (expectedTokenSequences.length == 1) {
+ retval += "Was expecting:" + eol + " ";
+ } else {
+ retval += "Was expecting one of:" + eol + " ";
+ }
+ retval += expected.toString();
+ return retval;
+ }
+
+ /**
+ * The end of line string for this machine.
+ */
+ protected String eol = System.getProperty("line.separator", "\n");
+
+ /**
+ * Used to convert raw characters to their escaped version
+ * when these raw version cannot be used as part of an ASCII
+ * string literal.
+ */
+ protected String add_escapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i))
+ {
+ case 0 :
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4,
s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
+ }
+ return retval.toString();
+ }
+
+}
Added:
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/ContentDispositionFieldTest.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/ContentDispositionFieldTest.java?rev=738651&view=auto
==============================================================================
---
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/ContentDispositionFieldTest.java
(added)
+++
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/ContentDispositionFieldTest.java
Wed Jan 28 22:35:38 2009
@@ -0,0 +1,209 @@
+/****************************************************************
+ * 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.field;
+
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+import org.apache.log4j.BasicConfigurator;
+
+public class ContentDispositionFieldTest extends TestCase {
+
+ @Override
+ public void setUp() {
+ BasicConfigurator.resetConfiguration();
+ BasicConfigurator.configure();
+ }
+
+ public void testDispositionTypeWithSemiColonNoParams() throws Exception {
+ ContentDispositionField f = null;
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline;");
+ assertEquals("inline", f.getDispositionType());
+ }
+
+ public void testGetDispositionType() throws Exception {
+ ContentDispositionField f = null;
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: attachment");
+ assertEquals("attachment", f.getDispositionType());
+
+ f = (ContentDispositionField) Field
+ .parse("content-disposition: InLiNe ");
+ assertEquals("inline", f.getDispositionType());
+
+ f = (ContentDispositionField) Field
+ .parse("CONTENT-DISPOSITION: x-yada ;" + " param = yada");
+ assertEquals("x-yada", f.getDispositionType());
+
+ f = (ContentDispositionField) Field.parse("CONTENT-DISPOSITION: ");
+ assertEquals("", f.getDispositionType());
+ }
+
+ public void testGetParameter() throws Exception {
+ ContentDispositionField f = null;
+
+ f = (ContentDispositionField) Field
+ .parse("CONTENT-DISPOSITION: inline ;"
+ + " filename=yada yada");
+ assertEquals("yada", f.getParameter("filename"));
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: x-yada;"
+ + " fileNAme= \"ya:\\\"*da\"; " + "\tSIZE\t = 1234");
+ assertEquals("ya:\"*da", f.getParameter("filename"));
+ assertEquals("1234", f.getParameter("size"));
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: x-yada; "
+ + "fileNAme= \"ya \\\"\\\"\tda \\\"\"; "
+ + "\tx-Yada\t = \"\\\"hepp\\\" =us\t-ascii\"");
+ assertEquals("ya \"\"\tda \"", f.getParameter("filename"));
+ assertEquals("\"hepp\" =us\t-ascii", f.getParameter("x-yada"));
+ }
+
+ public void testIsDispositionType() throws Exception {
+ ContentDispositionField f = null;
+
+ f = (ContentDispositionField)
Field.parse("Content-Disposition:INline");
+ assertTrue(f.isDispositionType("InLiNe"));
+ assertFalse(f.isDispositionType("NiLiNe"));
+ assertTrue(f.isInline());
+ assertFalse(f.isAttachment());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: attachment");
+ assertTrue(f.isDispositionType("ATTACHMENT"));
+ assertFalse(f.isInline());
+ assertTrue(f.isAttachment());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: x-something");
+ assertTrue(f.isDispositionType("x-SomeThing"));
+ assertFalse(f.isInline());
+ assertFalse(f.isAttachment());
+ }
+
+ public void testGetFilename() throws Exception {
+ ContentDispositionField f = null;
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline; filename=yada.txt");
+ assertEquals("yada.txt", f.getFilename());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline; filename=yada yada.txt");
+ assertEquals("yada", f.getFilename());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline; filename=\"yada
yada.txt\"");
+ assertEquals("yada yada.txt", f.getFilename());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline");
+ assertNull(f.getFilename());
+ }
+
+ public void testGetCreationDate() throws Exception {
+ ContentDispositionField f = null;
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline; "
+ + "creation-date=\"Tue, 01 Jan 1970 00:00:00 +0000\"");
+ assertEquals(new Date(0), f.getCreationDate());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline; "
+ + "creation-date=Tue, 01 Jan 1970 00:00:00 +0000");
+ assertNull(f.getCreationDate());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: attachment");
+ assertNull(f.getCreationDate());
+ }
+
+ public void testGetModificationDate() throws Exception {
+ ContentDispositionField f = null;
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline; "
+ + "modification-date=\"Tue, 01 Jan 1970 00:00:00
+0000\"");
+ assertEquals(new Date(0), f.getModificationDate());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline; "
+ + "modification-date=\"Wed, 12 Feb 1997 16:29:51
-0500\"");
+ assertEquals(new Date(855782991000l), f.getModificationDate());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline; "
+ + "modification-date=yesterday");
+ assertNull(f.getModificationDate());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: attachment");
+ assertNull(f.getModificationDate());
+ }
+
+ public void testGetReadDate() throws Exception {
+ ContentDispositionField f = null;
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline; "
+ + "read-date=\"Tue, 01 Jan 1970 00:00:00 +0000\"");
+ assertEquals(new Date(0), f.getReadDate());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: inline; read-date=");
+ assertNull(f.getReadDate());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: attachment");
+ assertNull(f.getReadDate());
+ }
+
+ public void testGetSize() throws Exception {
+ ContentDispositionField f = null;
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: attachment; size=0");
+ assertEquals(0, f.getSize());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: attachment; size=matters");
+ assertEquals(-1, f.getSize());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: attachment");
+ assertEquals(-1, f.getSize());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: attachment; size=-12");
+ assertEquals(-1, f.getSize());
+
+ f = (ContentDispositionField) Field
+ .parse("Content-Disposition: attachment; size=12");
+ assertEquals(12, f.getSize());
+ }
+
+}
Added:
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/contentdisposition/ContentDispositionTest.java
URL:
http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/contentdisposition/ContentDispositionTest.java?rev=738651&view=auto
==============================================================================
---
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/contentdisposition/ContentDispositionTest.java
(added)
+++
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/field/contentdisposition/ContentDispositionTest.java
Wed Jan 28 22:35:38 2009
@@ -0,0 +1,15 @@
+package org.apache.james.mime4j.field.contentdisposition;
+
+import junit.framework.TestCase;
+
+import org.apache.james.mime4j.MimeException;
+import org.apache.james.mime4j.field.contentdisposition.parser.ParseException;
+
+public class ContentDispositionTest extends TestCase {
+
+ public void testExceptionTree() {
+ // make sure that our ParseException extends MimeException.
+ assertTrue(MimeException.class.isAssignableFrom(ParseException.class));
+ }
+
+}