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    
020    
021    package org.apache.mailet.base;
022    
023    import java.text.ParseException;
024    import java.util.Date;
025    import java.util.Locale;
026    import java.util.TimeZone;
027    
028    /**
029     * A thread-safe date formatting class to produce dates formatted in accord with the
030     * specifications of RFC 977.
031     *
032     */
033    public class RFC977DateFormat implements SimplifiedDateFormat {
034    
035        /**
036         * Internal date formatter for long date formats
037         */
038        private final SynchronizedDateFormat internalLongDateFormat;
039    
040        /**
041         * Internal date formatter for short date formats
042         */
043        private final SynchronizedDateFormat internalShortDateFormat;
044    
045        /**
046         * Constructor for RFC977DateFormat
047         */
048        public RFC977DateFormat() {
049            internalLongDateFormat = new SynchronizedDateFormat("yyyyMMdd HHmmss", Locale.ENGLISH);
050            internalShortDateFormat = new SynchronizedDateFormat("yyMMdd HHmmss", Locale.ENGLISH);
051        }
052    
053        /**
054         * This method returns the long form of the RFC977 Date
055         *
056         * @return java.lang.String
057         * @param d Date
058         */
059        public String format(Date d) {
060            return internalLongDateFormat.format(d);
061        }
062    
063        /**
064         * Parses text from the beginning of the given string to produce a date.
065         * The method may not use the entire text of the given string.
066         * <p>
067         * This method is designed to be thread safe, so we wrap our delegated
068         * parse method in an appropriate synchronized block.
069         *
070         * @param source A <code>String</code> whose beginning should be parsed.
071         * @return A <code>Date</code> parsed from the string.
072         * @throws ParseException if the beginning of the specified string
073         *         cannot be parsed.
074         */
075        public Date parse(String source) throws ParseException {
076            source = source.trim();
077            if (source.indexOf(' ') == 6) {
078                return internalShortDateFormat.parse(source);
079            } else {
080                return internalLongDateFormat.parse(source);
081            }
082        }
083    
084        /**
085         * Sets the time zone of this SynchronizedDateFormat object.
086         * @param zone the given new time zone.
087         */
088        public void setTimeZone(TimeZone zone) {
089            synchronized(this) {
090                internalShortDateFormat.setTimeZone(zone);
091                internalLongDateFormat.setTimeZone(zone);
092            }
093        }
094    
095        /**
096         * Gets the time zone.
097         * @return the time zone associated with this SynchronizedDateFormat.
098         */
099        public TimeZone getTimeZone() {
100            synchronized(this) {
101                return internalShortDateFormat.getTimeZone();
102            }
103        }
104    
105        /**
106         * Specify whether or not date/time parsing is to be lenient.  With
107         * lenient parsing, the parser may use heuristics to interpret inputs that
108         * do not precisely match this object's format.  With strict parsing,
109         * inputs must match this object's format.
110         * @param lenient when true, parsing is lenient
111         * @see java.util.Calendar#setLenient
112         */
113        public void setLenient(boolean lenient)
114        {
115            synchronized(this) {
116                internalShortDateFormat.setLenient(lenient);
117                internalLongDateFormat.setLenient(lenient);
118            }
119        }
120    
121        /**
122         * Tell whether date/time parsing is to be lenient.
123         * @return whether this SynchronizedDateFormat is lenient.
124         */
125        public boolean isLenient()
126        {
127            synchronized(this) {
128                return internalShortDateFormat.isLenient();
129            }
130        }
131    
132    
133        /**
134         * Overrides equals
135         */
136        public boolean equals(Object obj) {
137            if (this == obj) {
138                return true;
139            }
140            if (!(obj instanceof RFC977DateFormat)) {
141                return false;
142            }
143            RFC977DateFormat theOtherRFC977DateFormat = (RFC977DateFormat)obj;
144            synchronized (this) {
145                return ((internalShortDateFormat.equals(theOtherRFC977DateFormat.internalShortDateFormat)) &&
146                        (internalLongDateFormat.equals(theOtherRFC977DateFormat.internalLongDateFormat)));
147            }
148        }
149    
150        /**
151         * Overrides hashCode
152         */
153        public int hashCode() {
154            return internalLongDateFormat.hashCode() & internalShortDateFormat.hashCode();
155        }
156    
157    }