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.text.ParseException;
023import java.text.SimpleDateFormat;
024import java.util.ArrayList;
025import java.util.Collection;
026import java.util.Date;
027import java.util.List;
028import java.util.Locale;
029import java.util.TimeZone;
030
031import org.apache.james.mime4j.codec.DecodeMonitor;
032import org.apache.james.mime4j.dom.FieldParser;
033import org.apache.james.mime4j.dom.field.DateTimeField;
034import org.apache.james.mime4j.stream.Field;
035
036/**
037 * Date-time field such as <code>Date</code> or <code>Resent-Date</code>.
038 */
039public class DateTimeFieldLenientImpl extends AbstractField implements DateTimeField {
040
041    private static final String[] DEFAULT_DATE_FORMATS =  { 
042        "EEE, dd MMM yyyy HH:mm:ss ZZZZ", 
043        "dd MMM yyyy HH:mm:ss ZZZZ"};
044
045    private final List<String> datePatterns;
046
047    private boolean parsed = false;
048    private Date date;
049
050    DateTimeFieldLenientImpl(final Field rawField,
051            final Collection<String> dateParsers, final DecodeMonitor monitor) {
052        super(rawField, monitor);
053        this.datePatterns = new ArrayList<String>();
054        if (dateParsers != null) {
055            this.datePatterns.addAll(dateParsers);
056        } else {
057            for (String pattern: DEFAULT_DATE_FORMATS) {
058                this.datePatterns.add(pattern);
059            }
060        }
061    }
062
063    public Date getDate() {
064        if (!parsed) {
065            parse();
066        }
067        return date;
068    }
069
070    private void parse() {
071        parsed = true;
072        date = null;
073        String body = getBody();
074        for (String datePattern: datePatterns) {
075            try {
076                SimpleDateFormat parser = new SimpleDateFormat(datePattern, Locale.US);
077                parser.setTimeZone(TimeZone.getTimeZone("GMT"));
078                parser.setLenient(true);
079                date = parser.parse(body);
080                break;
081            } catch (ParseException ignore) {
082            }
083        }
084    }
085
086    public static final FieldParser<DateTimeField> PARSER = new FieldParser<DateTimeField>() {
087
088        public DateTimeField parse(final Field rawField, final DecodeMonitor monitor) {
089            return new DateTimeFieldLenientImpl(rawField, null, monitor);
090        }
091
092    };
093    
094    public static FieldParser<DateTimeField> createParser(final Collection<String> dateParsers) {
095        
096        return new FieldParser<DateTimeField>() {
097
098            public DateTimeField parse(final Field rawField, final DecodeMonitor monitor) {
099                return new DateTimeFieldLenientImpl(rawField, dateParsers, monitor);
100            }
101
102        };
103        
104    }
105    
106}