1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.net.ftp.parser;
17
18 import java.text.DateFormatSymbols;
19 import java.text.ParseException;
20 import java.text.ParsePosition;
21 import java.text.SimpleDateFormat;
22 import java.util.Calendar;
23 import java.util.Date;
24 import java.util.TimeZone;
25
26 import org.apache.commons.net.ftp.Configurable;
27 import org.apache.commons.net.ftp.FTPClientConfig;
28
29 /**
30 * Default implementation of the {@link FTPTimestampParser FTPTimestampParser}
31 * interface also implements the {@link org.apache.commons.net.ftp.Configurable Configurable}
32 * interface to allow the parsing to be configured from the outside.
33 *
34 * @see ConfigurableFTPFileEntryParserImpl
35 * @since 1.4
36 */
37 public class FTPTimestampParserImpl implements
38 FTPTimestampParser, Configurable
39 {
40
41
42 private SimpleDateFormat defaultDateFormat;
43 private SimpleDateFormat recentDateFormat;
44
45
46 /**
47 * The only constructor for this class.
48 */
49 public FTPTimestampParserImpl() {
50 setDefaultDateFormat(DEFAULT_SDF);
51 setRecentDateFormat(DEFAULT_RECENT_SDF);
52 }
53
54 /**
55 * Implements the one {@link FTPTimestampParser#parseTimestamp(String) method}
56 * in the {@link FTPTimestampParser FTPTimestampParser} interface
57 * according to this algorithm:
58 *
59 * If the recentDateFormat member has been defined, try to parse the
60 * supplied string with that. If that parse fails, or if the recentDateFormat
61 * member has not been defined, attempt to parse with the defaultDateFormat
62 * member. If that fails, throw a ParseException.
63 *
64 * @see org.apache.commons.net.ftp.parser.FTPTimestampParser#parseTimestamp(java.lang.String)
65 */
66
67
68
69 public Calendar parseTimestamp(String timestampStr) throws ParseException {
70 Calendar now = Calendar.getInstance();
71 now.setTimeZone(this.getServerTimeZone());
72
73 Calendar working = Calendar.getInstance();
74 working.setTimeZone(this.getServerTimeZone());
75 ParsePosition pp = new ParsePosition(0);
76
77 Date parsed = null;
78 if (this.recentDateFormat != null) {
79 parsed = recentDateFormat.parse(timestampStr, pp);
80 }
81 if (parsed != null && pp.getIndex() == timestampStr.length())
82 {
83 working.setTime(parsed);
84 working.set(Calendar.YEAR, now.get(Calendar.YEAR));
85 if (working.after(now)) {
86 working.add(Calendar.YEAR, -1);
87 }
88 } else {
89 pp = new ParsePosition(0);
90 parsed = defaultDateFormat.parse(timestampStr, pp);
91
92
93
94
95
96
97
98 if (parsed != null && pp.getIndex() == timestampStr.length()) {
99 working.setTime(parsed);
100 } else {
101 throw new ParseException(
102 "Timestamp could not be parsed with older or recent DateFormat",
103 pp.getIndex());
104 }
105 }
106 return working;
107 }
108
109 /**
110 * @return Returns the defaultDateFormat.
111 */
112 public SimpleDateFormat getDefaultDateFormat() {
113 return defaultDateFormat;
114 }
115 /**
116 * @return Returns the defaultDateFormat pattern string.
117 */
118 public String getDefaultDateFormatString() {
119 return defaultDateFormat.toPattern();
120 }
121 /**
122 * @param defaultDateFormat The defaultDateFormat to be set.
123 */
124 private void setDefaultDateFormat(String format) {
125 if (format != null) {
126 this.defaultDateFormat = new SimpleDateFormat(format);
127 this.defaultDateFormat.setLenient(false);
128 }
129 }
130 /**
131 * @return Returns the recentDateFormat.
132 */
133 public SimpleDateFormat getRecentDateFormat() {
134 return recentDateFormat;
135 }
136 /**
137 * @return Returns the recentDateFormat.
138 */
139 public String getRecentDateFormatString() {
140 return recentDateFormat.toPattern();
141 }
142 /**
143 * @param recentDateFormat The recentDateFormat to set.
144 */
145 private void setRecentDateFormat(String format) {
146 if (format != null) {
147 this.recentDateFormat = new SimpleDateFormat(format);
148 this.recentDateFormat.setLenient(false);
149 }
150 }
151
152 /**
153 * @return returns an array of 12 strings representing the short
154 * month names used by this parse.
155 */
156 public String[] getShortMonths() {
157 return defaultDateFormat.getDateFormatSymbols().getShortMonths();
158 }
159
160
161 /**
162 * @return Returns the serverTimeZone used by this parser.
163 */
164 public TimeZone getServerTimeZone() {
165 return this.defaultDateFormat.getTimeZone();
166 }
167 /**
168 * sets a TimeZone represented by the supplied ID string into all
169 * of the parsers used by this server.
170 * @param serverTimeZone Time Id java.util.TimeZone id used by
171 * the ftp server. If null the client's local time zone is assumed.
172 */
173 private void setServerTimeZone(String serverTimeZoneId) {
174 TimeZone serverTimeZone = TimeZone.getDefault();
175 if (serverTimeZoneId != null) {
176 serverTimeZone = TimeZone.getTimeZone(serverTimeZoneId);
177 }
178 this.defaultDateFormat.setTimeZone(serverTimeZone);
179 if (this.recentDateFormat != null) {
180 this.recentDateFormat.setTimeZone(serverTimeZone);
181 }
182 }
183
184 /**
185 * Implementation of the {@link Configurable Configurable}
186 * interface. Configures this <code>FTPTimestampParser</code> according
187 * to the following logic:
188 * <p>
189 * Set up the {@link FTPClientConfig#setDefaultDateFormatStr(java.lang.String) defaultDateFormat}
190 * and optionally the {@link FTPClientConfig#setRecentDateFormatStr(String) recentDateFormat}
191 * to values supplied in the config based on month names configured as follows:
192 * </p><p><ul>
193 * <li>If a {@link FTPClientConfig#setShortMonthNames(String) shortMonthString}
194 * has been supplied in the <code>config</code>, use that to parse parse timestamps.</li>
195 * <li>Otherwise, if a {@link FTPClientConfig#setServerLanguageCode(String) serverLanguageCode}
196 * has been supplied in the <code>config</code>, use the month names represented
197 * by that {@link FTPClientConfig#lookupDateFormatSymbols(String) language}
198 * to parse timestamps.</li>
199 * <li>otherwise use default English month names</li>
200 * </ul></p><p>
201 * Finally if a {@link org.apache.commons.net.ftp.FTPClientConfig#setServerTimeZoneId(String) serverTimeZoneId}
202 * has been supplied via the config, set that into all date formats that have
203 * been configured.
204 * </p>
205 */
206 public void configure(FTPClientConfig config) {
207 DateFormatSymbols dfs = null;
208
209 String languageCode = config.getServerLanguageCode();
210 String shortmonths = config.getShortMonthNames();
211 if (shortmonths != null) {
212 dfs = FTPClientConfig.getDateFormatSymbols(shortmonths);
213 } else if (languageCode != null) {
214 dfs = FTPClientConfig.lookupDateFormatSymbols(languageCode);
215 } else {
216 dfs = FTPClientConfig.lookupDateFormatSymbols("en");
217 }
218
219
220 String recentFormatString = config.getRecentDateFormatStr();
221 if (recentFormatString == null) {
222 this.recentDateFormat = null;
223 } else {
224 this.recentDateFormat = new SimpleDateFormat(recentFormatString, dfs);
225 this.recentDateFormat.setLenient(false);
226 }
227
228 String defaultFormatString = config.getDefaultDateFormatStr();
229 if (defaultFormatString == null) {
230 throw new IllegalArgumentException("defaultFormatString cannot be null");
231 }
232 this.defaultDateFormat = new SimpleDateFormat(defaultFormatString, dfs);
233 this.defaultDateFormat.setLenient(false);
234
235 setServerTimeZone(config.getServerTimeZoneId());
236 }
237 }