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 }