source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/Touch.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 12.0 KB
Line 
1/*
2 * Copyright 2000-2005 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18package org.apache.tools.ant.taskdefs;
19
20import java.io.File;
21import java.io.IOException;
22import java.text.DateFormat;
23import java.text.ParseException;
24import java.text.SimpleDateFormat;
25import java.util.Locale;
26import java.util.Vector;
27import org.apache.tools.ant.BuildException;
28import org.apache.tools.ant.DirectoryScanner;
29import org.apache.tools.ant.Project;
30import org.apache.tools.ant.Task;
31import org.apache.tools.ant.types.Mapper;
32import org.apache.tools.ant.types.FileSet;
33import org.apache.tools.ant.types.FileList;
34import org.apache.tools.ant.util.FileUtils;
35import org.apache.tools.ant.util.FileNameMapper;
36
37/**
38 * Touch a file and/or fileset(s) and/or filelist(s);
39 * corresponds to the Unix touch command.
40 *
41 * <p>If the file to touch doesn't exist, an empty one is created.</p>
42 *
43 * @since Ant 1.1
44 *
45 * @ant.task category="filesystem"
46 */
47public class Touch extends Task {
48
49 private interface DateFormatFactory {
50 DateFormat getPrimaryFormat();
51 DateFormat getFallbackFormat();
52 }
53
54 private static final DateFormatFactory DEFAULT_DF_FACTORY
55 = new DateFormatFactory() {
56 /*
57 * The initial version used DateFormat.SHORT for the
58 * time format, which ignores seconds. If we want
59 * seconds as well, we need DateFormat.MEDIUM, which
60 * in turn would break all old build files.
61 *
62 * First try to parse with DateFormat.SHORT and if
63 * that fails with MEDIUM - throw an exception if both
64 * fail.
65 */
66 public DateFormat getPrimaryFormat() {
67 return DateFormat.getDateTimeInstance(DateFormat.SHORT,
68 DateFormat.SHORT, Locale.US);
69 }
70 public DateFormat getFallbackFormat() {
71 return DateFormat.getDateTimeInstance(DateFormat.SHORT,
72 DateFormat.MEDIUM, Locale.US);
73 }
74 };
75 private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
76
77 private File file;
78 private long millis = -1;
79 private String dateTime;
80 private Vector filesets = new Vector();
81 private Vector filelists = new Vector();
82 private boolean dateTimeConfigured;
83 private boolean mkdirs;
84 private boolean verbose = true;
85 private FileNameMapper fileNameMapper = null;
86 private DateFormatFactory dfFactory = DEFAULT_DF_FACTORY;
87
88 /**
89 * Construct a new <code>Touch</code> task.
90 */
91 public Touch() {
92 }
93
94 /**
95 * Sets a single source file to touch. If the file does not exist
96 * an empty file will be created.
97 * @param file the <code>File</code> to touch.
98 */
99 public void setFile(File file) {
100 this.file = file;
101 }
102
103 /**
104 * Set the new modification time of file(s) touched
105 * in milliseconds since midnight Jan 1 1970. Optional, default=now.
106 * @param millis the <code>long</code> timestamp to use.
107 */
108 public void setMillis(long millis) {
109 this.millis = millis;
110 }
111
112 /**
113 * Set the new modification time of file(s) touched
114 * in the format &quot;MM/DD/YYYY HH:MM AM <i>or</i> PM&quot;
115 * or &quot;MM/DD/YYYY HH:MM:SS AM <i>or</i> PM&quot;.
116 * Optional, default=now.
117 * @param dateTime the <code>String</code> date in the specified format.
118 */
119 public void setDatetime(String dateTime) {
120 if (this.dateTime != null) {
121 log("Resetting datetime attribute to " + dateTime, Project.MSG_VERBOSE);
122 }
123 this.dateTime = dateTime;
124 dateTimeConfigured = false;
125 }
126
127 /**
128 * Set whether nonexistent parent directories should be created
129 * when touching new files.
130 * @param mkdirs <code>boolean</code> whether to create parent directories.
131 * @since Ant 1.6.3
132 */
133 public void setMkdirs(boolean mkdirs) {
134 this.mkdirs = mkdirs;
135 }
136
137 /**
138 * Set whether the touch task will report every file it creates;
139 * defaults to <code>true</code>.
140 * @param verbose <code>boolean</code> flag.
141 * @since Ant 1.6.3
142 */
143 public void setVerbose(boolean verbose) {
144 this.verbose = verbose;
145 }
146
147 /**
148 * Set the format of the datetime attribute.
149 * @param pattern the <code>SimpleDateFormat</code>-compatible format pattern.
150 * @since Ant 1.6.3
151 */
152 public void setPattern(final String pattern) {
153 dfFactory = new DateFormatFactory() {
154 public DateFormat getPrimaryFormat() {
155 return new SimpleDateFormat(pattern);
156 }
157 public DateFormat getFallbackFormat() {
158 return null;
159 }
160 };
161 }
162
163 /**
164 * Add a <code>Mapper</code>.
165 * @param mapper the <code>Mapper</code> to add.
166 * @since Ant 1.6.3
167 */
168 public void addConfiguredMapper(Mapper mapper) {
169 add(mapper.getImplementation());
170 }
171
172 /**
173 * Add a <code>FileNameMapper</code>.
174 * @param fileNameMapper the <code>FileNameMapper</code> to add.
175 * @since Ant 1.6.3
176 * @throws BuildException if multiple mappers are added.
177 */
178 public void add(FileNameMapper fileNameMapper) throws BuildException {
179 if (this.fileNameMapper != null) {
180 throw new BuildException("Only one mapper may be added to the "
181 + getTaskName() + " task.");
182 }
183 this.fileNameMapper = fileNameMapper;
184 }
185
186 /**
187 * Add a set of files to touch.
188 * @param set the <code>Fileset</code> to add.
189 */
190 public void addFileset(FileSet set) {
191 filesets.addElement(set);
192 }
193
194 /**
195 * Add a filelist to touch.
196 * @param list the <code>Filelist</code> to add.
197 */
198 public void addFilelist(FileList list) {
199 filelists.addElement(list);
200 }
201
202 /**
203 * Check that this task has been configured properly.
204 * @throws BuildException if configuration errors are detected.
205 * @since Ant 1.6.3
206 */
207 protected synchronized void checkConfiguration() throws BuildException {
208 if (file == null && filesets.size() + filelists.size() == 0) {
209 throw new BuildException("Specify at least one source"
210 + "--a file, filelist or a fileset.");
211 }
212 if (file != null && file.exists() && file.isDirectory()) {
213 throw new BuildException("Use a fileset to touch directories.");
214 }
215 if (dateTime != null && !dateTimeConfigured) {
216 long workmillis = millis;
217 DateFormat df = dfFactory.getPrimaryFormat();
218 ParseException pe = null;
219 try {
220 workmillis = df.parse(dateTime).getTime();
221 } catch (ParseException peOne) {
222 df = dfFactory.getFallbackFormat();
223 if (df == null) {
224 pe = peOne;
225 } else {
226 try {
227 workmillis = df.parse(dateTime).getTime();
228 } catch (ParseException peTwo) {
229 pe = peTwo;
230 }
231 }
232 }
233 if (pe != null) {
234 throw new BuildException(pe.getMessage(), pe, getLocation());
235 }
236 if (workmillis < 0) {
237 throw new BuildException("Date of " + dateTime
238 + " results in negative "
239 + "milliseconds value "
240 + "relative to epoch "
241 + "(January 1, 1970, "
242 + "00:00:00 GMT).");
243 }
244 log("Setting millis to " + workmillis + " from datetime attribute",
245 ((millis < 0) ? Project.MSG_DEBUG : Project.MSG_VERBOSE));
246 setMillis(workmillis);
247 //only set if successful to this point:
248 dateTimeConfigured = true;
249 }
250 }
251
252 /**
253 * Execute the touch operation.
254 * @throws BuildException if an error occurs.
255 */
256 public void execute() throws BuildException {
257 checkConfiguration();
258 touch();
259 }
260
261 /**
262 * Does the actual work; assumes everything has been checked by now.
263 * @throws BuildException if an error occurs.
264 */
265 protected void touch() throws BuildException {
266 long defaultTimestamp = getTimestamp();
267
268 if (file != null) {
269 touch(file.getParentFile(), file.getName(), defaultTimestamp);
270 }
271 // deal with the filesets
272 for (int i = 0; i < filesets.size(); i++) {
273 FileSet fs = (FileSet) filesets.elementAt(i);
274 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
275 File fromDir = fs.getDir(getProject());
276
277 String[] srcFiles = ds.getIncludedFiles();
278 String[] srcDirs = ds.getIncludedDirectories();
279
280 for (int j = 0; j < srcFiles.length; j++) {
281 touch(fromDir, srcFiles[j], defaultTimestamp);
282 }
283 for (int j = 0; j < srcDirs.length; j++) {
284 touch(fromDir, srcDirs[j], defaultTimestamp);
285 }
286 }
287 // deal with the filelists
288 for (int i = 0; i < filelists.size(); i++) {
289 FileList fl = (FileList) filelists.elementAt(i);
290 File fromDir = fl.getDir(getProject());
291
292 String[] srcFiles = fl.getFiles(getProject());
293
294 for (int j = 0; j < srcFiles.length; j++) {
295 touch(fromDir, srcFiles[j], defaultTimestamp);
296 }
297 }
298 }
299
300 /**
301 * Touch a single file with the current timestamp (this.millis). This method
302 * does not interact with any nested mappers and remains for reasons of
303 * backwards-compatibility only.
304 * @param file file to touch
305 * @throws BuildException
306 * @deprecated
307 */
308 protected void touch(File file) {
309 touch(file, getTimestamp());
310 }
311
312 private long getTimestamp() {
313 return (millis < 0) ? System.currentTimeMillis() : millis;
314 }
315
316 private void touch(File fromDir, String filename, long defaultTimestamp) {
317 File f = FILE_UTILS.resolveFile(fromDir, filename);
318 if (fileNameMapper == null) {
319 touch(f, defaultTimestamp);
320 } else {
321 String[] mapped = fileNameMapper.mapFileName(filename);
322 if (mapped != null && mapped.length > 0) {
323 long modTime = (f.exists()) ? f.lastModified() : defaultTimestamp;
324 for (int i = 0; i < mapped.length; i++) {
325 touch(getProject().resolveFile(mapped[i]), modTime);
326 }
327 }
328 }
329 }
330
331 private void touch(File file, long modTime) {
332 if (!file.exists()) {
333 log("Creating " + file,
334 ((verbose) ? Project.MSG_INFO : Project.MSG_VERBOSE));
335 try {
336 FILE_UTILS.createNewFile(file, mkdirs);
337 } catch (IOException ioe) {
338 throw new BuildException("Could not create " + file, ioe,
339 getLocation());
340 }
341 }
342 if (!file.canWrite()) {
343 throw new BuildException("Can not change modification date of "
344 + "read-only file " + file);
345 }
346 FILE_UTILS.setFileLastModified(file, modTime);
347 }
348
349}
Note: See TracBrowser for help on using the repository browser.