001/**************************************************************** 002 * Licensed to the Apache Software Foundation (ASF) under one * 003 * or more contributor license agreements. See the NOTICE file * 004 * distributed with this work for additional information * 005 * regarding copyright ownership. The ASF licenses this file * 006 * to you under the Apache License, Version 2.0 (the * 007 * "License"); you may not use this file except in compliance * 008 * with the License. You may obtain a copy of the License at * 009 * * 010 * http://www.apache.org/licenses/LICENSE-2.0 * 011 * * 012 * Unless required by applicable law or agreed to in writing, * 013 * software distributed under the License is distributed on an * 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 015 * KIND, either express or implied. See the License for the * 016 * specific language governing permissions and limitations * 017 * under the License. * 018 ****************************************************************/ 019 020package org.apache.james.mime4j.field; 021 022import java.io.StringReader; 023import java.util.Collections; 024import java.util.Date; 025import java.util.HashMap; 026import java.util.List; 027import java.util.Locale; 028import java.util.Map; 029 030import org.apache.james.mime4j.codec.DecodeMonitor; 031import org.apache.james.mime4j.dom.FieldParser; 032import org.apache.james.mime4j.dom.field.ContentDispositionField; 033import org.apache.james.mime4j.field.contentdisposition.parser.ContentDispositionParser; 034import org.apache.james.mime4j.field.contentdisposition.parser.ParseException; 035import org.apache.james.mime4j.field.contentdisposition.parser.TokenMgrError; 036import org.apache.james.mime4j.field.datetime.parser.DateTimeParser; 037import org.apache.james.mime4j.stream.Field; 038 039/** 040 * Represents a <code>Content-Disposition</code> field. 041 */ 042public class ContentDispositionFieldImpl extends AbstractField implements ContentDispositionField { 043 044 private boolean parsed = false; 045 046 private String dispositionType = ""; 047 private Map<String, String> parameters = new HashMap<String, String>(); 048 private ParseException parseException; 049 050 private boolean creationDateParsed; 051 private Date creationDate; 052 053 private boolean modificationDateParsed; 054 private Date modificationDate; 055 056 private boolean readDateParsed; 057 private Date readDate; 058 059 ContentDispositionFieldImpl(Field rawField, DecodeMonitor monitor) { 060 super(rawField, monitor); 061 } 062 063 /** 064 * Gets the exception that was raised during parsing of the field value, if 065 * any; otherwise, null. 066 */ 067 @Override 068 public ParseException getParseException() { 069 if (!parsed) 070 parse(); 071 072 return parseException; 073 } 074 075 /** 076 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#getDispositionType() 077 */ 078 public String getDispositionType() { 079 if (!parsed) 080 parse(); 081 082 return dispositionType; 083 } 084 085 /** 086 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#getParameter(java.lang.String) 087 */ 088 public String getParameter(String name) { 089 if (!parsed) 090 parse(); 091 092 return parameters.get(name.toLowerCase()); 093 } 094 095 /** 096 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#getParameters() 097 */ 098 public Map<String, String> getParameters() { 099 if (!parsed) 100 parse(); 101 102 return Collections.unmodifiableMap(parameters); 103 } 104 105 /** 106 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#isDispositionType(java.lang.String) 107 */ 108 public boolean isDispositionType(String dispositionType) { 109 if (!parsed) 110 parse(); 111 112 return this.dispositionType.equalsIgnoreCase(dispositionType); 113 } 114 115 /** 116 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#isInline() 117 */ 118 public boolean isInline() { 119 if (!parsed) 120 parse(); 121 122 return dispositionType.equals(DISPOSITION_TYPE_INLINE); 123 } 124 125 /** 126 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#isAttachment() 127 */ 128 public boolean isAttachment() { 129 if (!parsed) 130 parse(); 131 132 return dispositionType.equals(DISPOSITION_TYPE_ATTACHMENT); 133 } 134 135 /** 136 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#getFilename() 137 */ 138 public String getFilename() { 139 return getParameter(PARAM_FILENAME); 140 } 141 142 /** 143 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#getCreationDate() 144 */ 145 public Date getCreationDate() { 146 if (!creationDateParsed) { 147 creationDate = parseDate(PARAM_CREATION_DATE); 148 creationDateParsed = true; 149 } 150 151 return creationDate; 152 } 153 154 /** 155 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#getModificationDate() 156 */ 157 public Date getModificationDate() { 158 if (!modificationDateParsed) { 159 modificationDate = parseDate(PARAM_MODIFICATION_DATE); 160 modificationDateParsed = true; 161 } 162 163 return modificationDate; 164 } 165 166 /** 167 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#getReadDate() 168 */ 169 public Date getReadDate() { 170 if (!readDateParsed) { 171 readDate = parseDate(PARAM_READ_DATE); 172 readDateParsed = true; 173 } 174 175 return readDate; 176 } 177 178 /** 179 * @see org.apache.james.mime4j.dom.field.ContentDispositionField#getSize() 180 */ 181 public long getSize() { 182 String value = getParameter(PARAM_SIZE); 183 if (value == null) 184 return -1; 185 186 try { 187 long size = Long.parseLong(value); 188 return size < 0 ? -1 : size; 189 } catch (NumberFormatException e) { 190 return -1; 191 } 192 } 193 194 private Date parseDate(String paramName) { 195 String value = getParameter(paramName); 196 if (value == null) { 197 monitor.warn("Parsing " + paramName + " null", "returning null"); 198 return null; 199 } 200 201 try { 202 return new DateTimeParser(new StringReader(value)).parseAll() 203 .getDate(); 204 } catch (org.apache.james.mime4j.field.datetime.parser.ParseException e) { 205 if (monitor.isListening()) { 206 monitor.warn(paramName + " parameter is invalid: " + value, 207 paramName + " parameter is ignored"); 208 } 209 return null; 210 } catch (TokenMgrError e) { 211 monitor.warn(paramName + " parameter is invalid: " + value, 212 paramName + "parameter is ignored"); 213 return null; 214 } 215 } 216 217 private void parse() { 218 String body = getBody(); 219 220 ContentDispositionParser parser = new ContentDispositionParser( 221 new StringReader(body)); 222 try { 223 parser.parseAll(); 224 } catch (ParseException e) { 225 parseException = e; 226 } catch (TokenMgrError e) { 227 parseException = new ParseException(e.getMessage()); 228 } 229 230 final String dispositionType = parser.getDispositionType(); 231 232 if (dispositionType != null) { 233 this.dispositionType = dispositionType.toLowerCase(Locale.US); 234 235 List<String> paramNames = parser.getParamNames(); 236 List<String> paramValues = parser.getParamValues(); 237 238 if (paramNames != null && paramValues != null) { 239 final int len = Math.min(paramNames.size(), paramValues.size()); 240 for (int i = 0; i < len; i++) { 241 String paramName = paramNames.get(i).toLowerCase(Locale.US); 242 String paramValue = paramValues.get(i); 243 parameters.put(paramName, paramValue); 244 } 245 } 246 } 247 248 parsed = true; 249 } 250 251 public static final FieldParser<ContentDispositionField> PARSER = new FieldParser<ContentDispositionField>() { 252 253 public ContentDispositionField parse(final Field rawField, final DecodeMonitor monitor) { 254 return new ContentDispositionFieldImpl(rawField, monitor); 255 } 256 257 }; 258}