View Javadoc

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