View Javadoc

1   /*****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.mailet.dates;
21  
22  import java.text.DateFormat;
23  import java.text.ParseException;
24  import java.text.SimpleDateFormat;
25  import java.util.Date;
26  import java.util.Locale;
27  import java.util.TimeZone;
28  
29  
30  /***
31   * This class is designed to be a synchronized wrapper for a
32   * <code>java.text.DateFormat</code> subclass.  In general,
33   * these subclasses (most notably the <code>java.text.SimpleDateFormat</code>
34   * classes are not thread safe, so we need to synchronize on the
35   * internal DateFormat for all delegated calls.
36   *
37   */
38  public class SynchronizedDateFormat implements SimplifiedDateFormat {
39      private final DateFormat internalDateFormat;
40  
41      /***
42       * Public constructor that mimics that of SimpleDateFormat.  See
43       * java.text.SimpleDateFormat for more details.
44       *
45       * @param pattern the pattern that defines this DateFormat
46       * @param locale the locale
47       */
48      public SynchronizedDateFormat(String pattern, Locale locale) {
49          internalDateFormat = new SimpleDateFormat(pattern, locale);
50      }
51  
52      /***
53       * <p>Wrapper method to allow child classes to synchronize a preexisting
54       * DateFormat.</p>
55       *
56       * <p>TODO: Investigate replacing this with a factory method.</p>
57       *
58       * @param the DateFormat to synchronize
59       */
60      protected SynchronizedDateFormat(DateFormat theDateFormat) {
61          internalDateFormat = theDateFormat;
62      }
63  
64      /***
65       * SimpleDateFormat will handle most of this for us, but we
66       * want to ensure thread safety, so we wrap the call in a
67       * synchronized block.
68       *
69       * @return java.lang.String
70       * @param d Date
71       */
72      public String format(Date d) {
73          synchronized (internalDateFormat) {
74             return internalDateFormat.format(d);
75          }
76      }
77  
78      /***
79       * Parses text from the beginning of the given string to produce a date.
80       * The method may not use the entire text of the given string.
81       * <p>
82       * This method is designed to be thread safe, so we wrap our delegated
83       * parse method in an appropriate synchronized block.
84       *
85       * @param source A <code>String</code> whose beginning should be parsed.
86       * @return A <code>Date</code> parsed from the string.
87       * @throws ParseException if the beginning of the specified string
88       *         cannot be parsed.
89       */
90      public Date parse(String source) throws ParseException {
91          synchronized (internalDateFormat) {
92              return internalDateFormat.parse(source);
93          }
94      }
95  
96      /***
97       * Sets the time zone of this SynchronizedDateFormat object.
98       * @param zone the given new time zone.
99       */
100     public void setTimeZone(TimeZone zone) {
101         synchronized(internalDateFormat) {
102             internalDateFormat.setTimeZone(zone);
103         }
104     }
105 
106     /***
107      * Gets the time zone.
108      * @return the time zone associated with this SynchronizedDateFormat.
109      */
110     public TimeZone getTimeZone() {
111         synchronized(internalDateFormat) {
112             return internalDateFormat.getTimeZone();
113         }
114     }
115 
116     /***
117      * Specify whether or not date/time parsing is to be lenient.  With
118      * lenient parsing, the parser may use heuristics to interpret inputs that
119      * do not precisely match this object's format.  With strict parsing,
120      * inputs must match this object's format.
121      * @param lenient when true, parsing is lenient
122      * @see java.util.Calendar#setLenient
123      */
124     public void setLenient(boolean lenient)
125     {
126         synchronized(internalDateFormat) {
127             internalDateFormat.setLenient(lenient);
128         }
129     }
130 
131     /***
132      * Tell whether date/time parsing is to be lenient.
133      * @return whether this SynchronizedDateFormat is lenient.
134      */
135     public boolean isLenient()
136     {
137         synchronized(internalDateFormat) {
138             return internalDateFormat.isLenient();
139         }
140     }
141 
142     /***
143      * Overrides hashCode
144      */
145     public int hashCode() {
146         synchronized(internalDateFormat) {
147             return internalDateFormat.hashCode();
148         }
149     }
150 
151     /***
152      * Overrides equals
153      */
154     public boolean equals(Object obj) {
155         if (this == obj) {
156             return true;
157         }
158         if (obj == null || getClass() != obj.getClass()) {
159             return false;
160         }
161         synchronized(internalDateFormat) {
162             return internalDateFormat.equals(obj);
163         }
164     }
165 
166 }