001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs;
020:
021: import java.text.SimpleDateFormat;
022: import java.util.Calendar;
023: import java.util.Date;
024: import java.util.Enumeration;
025: import java.util.HashMap;
026: import java.util.Locale;
027: import java.util.Map;
028: import java.util.NoSuchElementException;
029: import java.util.StringTokenizer;
030: import java.util.TimeZone;
031: import java.util.Vector;
032: import org.apache.tools.ant.BuildException;
033: import org.apache.tools.ant.Location;
034: import org.apache.tools.ant.Project;
035: import org.apache.tools.ant.Task;
036: import org.apache.tools.ant.types.EnumeratedAttribute;
037:
038: /**
039: * Sets properties to the current time, or offsets from the current time.
040: * The default properties are TSTAMP, DSTAMP and TODAY;
041: *
042: * @since Ant 1.1
043: * @ant.task category="utility"
044: */
045: public class Tstamp extends Task {
046:
047: private Vector customFormats = new Vector();
048: private String prefix = "";
049:
050: /**
051: * Set a prefix for the properties. If the prefix does not end with a "."
052: * one is automatically added.
053: * @param prefix the prefix to use.
054: * @since Ant 1.5
055: */
056: public void setPrefix(String prefix) {
057: this .prefix = prefix;
058: if (!this .prefix.endsWith(".")) {
059: this .prefix += ".";
060: }
061: }
062:
063: /**
064: * create the timestamps. Custom ones are done before
065: * the standard ones, to get their retaliation in early.
066: * @throws BuildException on error.
067: */
068: public void execute() throws BuildException {
069: try {
070: Date d = new Date();
071:
072: Enumeration i = customFormats.elements();
073: while (i.hasMoreElements()) {
074: CustomFormat cts = (CustomFormat) i.nextElement();
075: cts.execute(getProject(), d, getLocation());
076: }
077:
078: SimpleDateFormat dstamp = new SimpleDateFormat("yyyyMMdd");
079: setProperty("DSTAMP", dstamp.format(d));
080:
081: SimpleDateFormat tstamp = new SimpleDateFormat("HHmm");
082: setProperty("TSTAMP", tstamp.format(d));
083:
084: SimpleDateFormat today = new SimpleDateFormat(
085: "MMMM d yyyy", Locale.US);
086: setProperty("TODAY", today.format(d));
087:
088: } catch (Exception e) {
089: throw new BuildException(e);
090: }
091: }
092:
093: /**
094: * create a custom format with the current prefix.
095: * @return a ready to fill-in format
096: */
097: public CustomFormat createFormat() {
098: CustomFormat cts = new CustomFormat();
099: customFormats.addElement(cts);
100: return cts;
101: }
102:
103: /**
104: * helper that encapsulates prefix logic and property setting
105: * policy (i.e. we use setNewProperty instead of setProperty).
106: */
107: private void setProperty(String name, String value) {
108: getProject().setNewProperty(prefix + name, value);
109: }
110:
111: /**
112: * This nested element that allows a property to be set
113: * to the current date and time in a given format.
114: * The date/time patterns are as defined in the
115: * Java SimpleDateFormat class.
116: * The format element also allows offsets to be applied to
117: * the time to generate different time values.
118: * @todo consider refactoring out into a re-usable element.
119: */
120: public class CustomFormat {
121: private TimeZone timeZone;
122: private String propertyName;
123: private String pattern;
124: private String language;
125: private String country;
126: private String variant;
127: private int offset = 0;
128: private int field = Calendar.DATE;
129:
130: /**
131: * Create a format
132: */
133: public CustomFormat() {
134: }
135:
136: /**
137: * The property to receive the date/time string in the given pattern
138: * @param propertyName the name of the property.
139: */
140: public void setProperty(String propertyName) {
141: this .propertyName = propertyName;
142: }
143:
144: /**
145: * The date/time pattern to be used. The values are as
146: * defined by the Java SimpleDateFormat class.
147: * @param pattern the pattern to use.
148: * @see java.text.SimpleDateFormat
149: */
150: public void setPattern(String pattern) {
151: this .pattern = pattern;
152: }
153:
154: /**
155: * The locale used to create date/time string.
156: * The general form is "language, country, variant" but
157: * either variant or variant and country may be omitted.
158: * For more information please refer to documentation
159: * for the java.util.Locale class.
160: * @param locale the locale to use.
161: * @see java.util.Locale
162: */
163: public void setLocale(String locale) {
164: StringTokenizer st = new StringTokenizer(locale,
165: " \t\n\r\f,");
166: try {
167: language = st.nextToken();
168: if (st.hasMoreElements()) {
169: country = st.nextToken();
170: if (st.hasMoreElements()) {
171: variant = st.nextToken();
172: if (st.hasMoreElements()) {
173: throw new BuildException(
174: "bad locale format", getLocation());
175: }
176: }
177: } else {
178: country = "";
179: }
180: } catch (NoSuchElementException e) {
181: throw new BuildException("bad locale format", e,
182: getLocation());
183: }
184: }
185:
186: /**
187: * The timezone to use for displaying time.
188: * The values are as defined by the Java TimeZone class.
189: * @param id the timezone value.
190: * @see java.util.TimeZone
191: */
192: public void setTimezone(String id) {
193: timeZone = TimeZone.getTimeZone(id);
194: }
195:
196: /**
197: * The numeric offset to the current time.
198: * @param offset the offset to use.
199: */
200: public void setOffset(int offset) {
201: this .offset = offset;
202: }
203:
204: /**
205: * Set the unit type (using String).
206: * @param unit the unit to use.
207: * @deprecated since 1.5.x.
208: * setUnit(String) is deprecated and is replaced with
209: * setUnit(Tstamp.Unit) to make Ant's
210: * Introspection mechanism do the work and also to
211: * encapsulate operations on the unit in its own
212: * class.
213: */
214: public void setUnit(String unit) {
215: log("DEPRECATED - The setUnit(String) method has been deprecated."
216: + " Use setUnit(Tstamp.Unit) instead.");
217: Unit u = new Unit();
218: u.setValue(unit);
219: field = u.getCalendarField();
220: }
221:
222: /**
223: * The unit of the offset to be applied to the current time.
224: * Valid Values are
225: * <ul>
226: * <li>millisecond</li>
227: * <li>second</li>
228: * <li>minute</li>
229: * <li>hour</li>
230: * <li>day</li>
231: * <li>week</li>
232: * <li>month</li>
233: * <li>year</li>
234: * </ul>
235: * The default unit is day.
236: * @param unit the unit to use.
237: */
238: public void setUnit(Unit unit) {
239: field = unit.getCalendarField();
240: }
241:
242: /**
243: * validate parameter and execute the format.
244: * @param project project to set property in.
245: * @param date date to use as a starting point.
246: * @param location line in file (for errors)
247: */
248: public void execute(Project project, Date date,
249: Location location) {
250: if (propertyName == null) {
251: throw new BuildException(
252: "property attribute must be provided", location);
253: }
254:
255: if (pattern == null) {
256: throw new BuildException(
257: "pattern attribute must be provided", location);
258: }
259:
260: SimpleDateFormat sdf;
261: if (language == null) {
262: sdf = new SimpleDateFormat(pattern);
263: } else if (variant == null) {
264: sdf = new SimpleDateFormat(pattern, new Locale(
265: language, country));
266: } else {
267: sdf = new SimpleDateFormat(pattern, new Locale(
268: language, country, variant));
269: }
270: if (offset != 0) {
271: Calendar calendar = Calendar.getInstance();
272: calendar.setTime(date);
273: calendar.add(field, offset);
274: date = calendar.getTime();
275: }
276: if (timeZone != null) {
277: sdf.setTimeZone(timeZone);
278: }
279: Tstamp.this .setProperty(propertyName, sdf.format(date));
280: }
281: }
282:
283: /**
284: * set of valid units to use for time offsets.
285: */
286: public static class Unit extends EnumeratedAttribute {
287:
288: private static final String MILLISECOND = "millisecond";
289: private static final String SECOND = "second";
290: private static final String MINUTE = "minute";
291: private static final String HOUR = "hour";
292: private static final String DAY = "day";
293: private static final String WEEK = "week";
294: private static final String MONTH = "month";
295: private static final String YEAR = "year";
296:
297: private static final String[] UNITS = { MILLISECOND, SECOND,
298: MINUTE, HOUR, DAY, WEEK, MONTH, YEAR };
299:
300: private Map calendarFields = new HashMap();
301:
302: /** Constructor for Unit enumerated type. */
303: public Unit() {
304: calendarFields.put(MILLISECOND, new Integer(
305: Calendar.MILLISECOND));
306: calendarFields.put(SECOND, new Integer(Calendar.SECOND));
307: calendarFields.put(MINUTE, new Integer(Calendar.MINUTE));
308: calendarFields.put(HOUR, new Integer(Calendar.HOUR_OF_DAY));
309: calendarFields.put(DAY, new Integer(Calendar.DATE));
310: calendarFields
311: .put(WEEK, new Integer(Calendar.WEEK_OF_YEAR));
312: calendarFields.put(MONTH, new Integer(Calendar.MONTH));
313: calendarFields.put(YEAR, new Integer(Calendar.YEAR));
314: }
315:
316: /**
317: * Convert the value to int unit value.
318: * @return an int value.
319: */
320: public int getCalendarField() {
321: String key = getValue().toLowerCase();
322: Integer i = (Integer) calendarFields.get(key);
323: return i.intValue();
324: }
325:
326: /**
327: * Get the valid values.
328: * @return the value values.
329: */
330: public String[] getValues() {
331: return UNITS;
332: }
333: }
334: }
|