1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.net.ftp.parser;
19
20 import java.text.DateFormatSymbols;
21 import java.text.ParseException;
22 import java.text.ParsePosition;
23 import java.text.SimpleDateFormat;
24 import java.util.Calendar;
25 import java.util.Date;
26 import java.util.TimeZone;
27
28 import org.apache.commons.net.ftp.Configurable;
29 import org.apache.commons.net.ftp.FTPClientConfig;
30
31
32
33
34
35
36
37
38
39 public class FTPTimestampParserImpl implements
40 FTPTimestampParser, Configurable
41 {
42
43
44 private SimpleDateFormat defaultDateFormat;
45 private SimpleDateFormat recentDateFormat;
46 private boolean lenientFutureDates = false;
47
48
49
50
51
52 public FTPTimestampParserImpl() {
53 setDefaultDateFormat(DEFAULT_SDF);
54 setRecentDateFormat(DEFAULT_RECENT_SDF);
55 }
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 public Calendar parseTimestamp(String timestampStr) throws ParseException {
75 Calendar now = Calendar.getInstance();
76 return parseTimestamp(timestampStr, now);
77 }
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 public Calendar parseTimestamp(String timestampStr, Calendar serverTime) throws ParseException {
94 Calendar working = (Calendar) serverTime.clone();
95 working.setTimeZone(getServerTimeZone());
96
97 Date parsed = null;
98
99 if (recentDateFormat != null) {
100 Calendar now = (Calendar) serverTime.clone();
101 now.setTimeZone(this.getServerTimeZone());
102 if (lenientFutureDates) {
103
104
105 now.add(Calendar.DATE, 1);
106 }
107
108
109
110
111
112
113
114
115
116 String year = Integer.toString(now.get(Calendar.YEAR));
117 String timeStampStrPlusYear = timestampStr + " " + year;
118 SimpleDateFormat hackFormatter = new SimpleDateFormat(recentDateFormat.toPattern() + " yyyy",
119 recentDateFormat.getDateFormatSymbols());
120 hackFormatter.setLenient(false);
121 hackFormatter.setTimeZone(recentDateFormat.getTimeZone());
122 ParsePosition pp = new ParsePosition(0);
123 parsed = hackFormatter.parse(timeStampStrPlusYear, pp);
124
125 if (parsed != null && pp.getIndex() == timeStampStrPlusYear.length()) {
126 working.setTime(parsed);
127 if (working.after(now)) {
128 working.add(Calendar.YEAR, -1);
129 }
130 return working;
131 }
132 }
133
134 ParsePosition pp = new ParsePosition(0);
135 parsed = defaultDateFormat.parse(timestampStr, pp);
136
137
138
139
140
141
142
143 if (parsed != null && pp.getIndex() == timestampStr.length()) {
144 working.setTime(parsed);
145 } else {
146 throw new ParseException(
147 "Timestamp '"+timestampStr+"' could not be parsed using a server time of "
148 +serverTime.getTime().toString(),
149 pp.getErrorIndex());
150 }
151 return working;
152 }
153
154
155
156
157 public SimpleDateFormat getDefaultDateFormat() {
158 return defaultDateFormat;
159 }
160
161
162
163 public String getDefaultDateFormatString() {
164 return defaultDateFormat.toPattern();
165 }
166
167
168
169 private void setDefaultDateFormat(String format) {
170 if (format != null) {
171 this.defaultDateFormat = new SimpleDateFormat(format);
172 this.defaultDateFormat.setLenient(false);
173 }
174 }
175
176
177
178 public SimpleDateFormat getRecentDateFormat() {
179 return recentDateFormat;
180 }
181
182
183
184 public String getRecentDateFormatString() {
185 return recentDateFormat.toPattern();
186 }
187
188
189
190 private void setRecentDateFormat(String format) {
191 if (format != null) {
192 this.recentDateFormat = new SimpleDateFormat(format);
193 this.recentDateFormat.setLenient(false);
194 }
195 }
196
197
198
199
200
201 public String[] getShortMonths() {
202 return defaultDateFormat.getDateFormatSymbols().getShortMonths();
203 }
204
205
206
207
208
209 public TimeZone getServerTimeZone() {
210 return this.defaultDateFormat.getTimeZone();
211 }
212
213
214
215
216
217
218 private void setServerTimeZone(String serverTimeZoneId) {
219 TimeZone serverTimeZone = TimeZone.getDefault();
220 if (serverTimeZoneId != null) {
221 serverTimeZone = TimeZone.getTimeZone(serverTimeZoneId);
222 }
223 this.defaultDateFormat.setTimeZone(serverTimeZone);
224 if (this.recentDateFormat != null) {
225 this.recentDateFormat.setTimeZone(serverTimeZone);
226 }
227 }
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252 public void configure(FTPClientConfig config) {
253 DateFormatSymbols dfs = null;
254
255 String languageCode = config.getServerLanguageCode();
256 String shortmonths = config.getShortMonthNames();
257 if (shortmonths != null) {
258 dfs = FTPClientConfig.getDateFormatSymbols(shortmonths);
259 } else if (languageCode != null) {
260 dfs = FTPClientConfig.lookupDateFormatSymbols(languageCode);
261 } else {
262 dfs = FTPClientConfig.lookupDateFormatSymbols("en");
263 }
264
265
266 String recentFormatString = config.getRecentDateFormatStr();
267 if (recentFormatString == null) {
268 this.recentDateFormat = null;
269 } else {
270 this.recentDateFormat = new SimpleDateFormat(recentFormatString, dfs);
271 this.recentDateFormat.setLenient(false);
272 }
273
274 String defaultFormatString = config.getDefaultDateFormatStr();
275 if (defaultFormatString == null) {
276 throw new IllegalArgumentException("defaultFormatString cannot be null");
277 }
278 this.defaultDateFormat = new SimpleDateFormat(defaultFormatString, dfs);
279 this.defaultDateFormat.setLenient(false);
280
281 setServerTimeZone(config.getServerTimeZoneId());
282
283 this.lenientFutureDates = config.isLenientFutureDates();
284 }
285
286
287
288 boolean isLenientFutureDates() {
289 return lenientFutureDates;
290 }
291
292
293
294 void setLenientFutureDates(boolean lenientFutureDates) {
295 this.lenientFutureDates = lenientFutureDates;
296 }
297 }