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

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

initial import of LiRK3

File size: 14.4 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.util.Enumeration;
23import org.apache.tools.ant.Project;
24import org.apache.tools.ant.BuildException;
25import org.apache.tools.ant.DirectoryScanner;
26import org.apache.tools.ant.types.FileSet;
27import org.apache.tools.ant.types.FilterSet;
28import org.apache.tools.ant.types.FilterSetCollection;
29
30/**
31 * Moves a file or directory to a new file or directory.
32 * By default, the
33 * destination file is overwritten if it already exists.
34 * When <i>overwrite</i> is
35 * turned off, then files are only moved if the source file is
36 * newer than the destination file, or when the destination file does
37 * not exist.
38 *
39 * <p>Source files and directories are only deleted when the file or
40 * directory has been copied to the destination successfully. Filtering
41 * also works.</p>
42 *
43 * <p>This implementation is based on Arnout Kuiper's initial design
44 * document, the following mailing list discussions, and the
45 * copyfile/copydir tasks.</p>
46 *
47 *
48 * @since Ant 1.2
49 *
50 * @ant.task category="filesystem"
51 */
52public class Move extends Copy {
53
54 /**
55 * Constructor of object.
56 * This sets the forceOverwrite attribute of the Copy parent class
57 * to true.
58 *
59 */
60 public Move() {
61 super();
62 setOverwrite(true);
63 }
64
65 // inherit doc
66 protected void validateAttributes() throws BuildException {
67 if (file != null && file.isDirectory()) {
68 if ((destFile != null && destDir != null)
69 || (destFile == null && destDir == null)) {
70 throw new BuildException("One and only one of tofile and todir "
71 + "must be set.");
72 }
73 destFile = (destFile == null)
74 ? new File(destDir, file.getName()) : destFile;
75 destDir = (destDir == null)
76 ? destFile.getParentFile() : destDir;
77
78 completeDirMap.put(file, destFile);
79 file = null;
80 } else {
81 super.validateAttributes();
82 }
83 }
84
85//************************************************************************
86// protected and private methods
87//************************************************************************
88
89 /**
90 * Override copy's doFileOperations to move the
91 * files instead of copying them.
92 */
93 protected void doFileOperations() {
94 //Attempt complete directory renames, if any, first.
95 if (completeDirMap.size() > 0) {
96 Enumeration e = completeDirMap.keys();
97 while (e.hasMoreElements()) {
98 File fromDir = (File) e.nextElement();
99 File toDir = (File) completeDirMap.get(fromDir);
100 boolean renamed = false;
101 try {
102 log("Attempting to rename dir: " + fromDir
103 + " to " + toDir, verbosity);
104 renamed =
105 renameFile(fromDir, toDir, filtering, forceOverwrite);
106 } catch (IOException ioe) {
107 String msg = "Failed to rename dir " + fromDir
108 + " to " + toDir
109 + " due to " + ioe.getMessage();
110 throw new BuildException(msg, ioe, getLocation());
111 }
112 if (!renamed) {
113 FileSet fs = new FileSet();
114 fs.setProject(getProject());
115 fs.setDir(fromDir);
116 addFileset(fs);
117 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
118 String[] files = ds.getIncludedFiles();
119 String[] dirs = ds.getIncludedDirectories();
120 scan(fromDir, toDir, files, dirs);
121 }
122 }
123 }
124 int moveCount = fileCopyMap.size();
125 if (moveCount > 0) { // files to move
126 log("Moving " + moveCount + " file"
127 + ((moveCount == 1) ? "" : "s")
128 + " to " + destDir.getAbsolutePath());
129
130 Enumeration e = fileCopyMap.keys();
131 while (e.hasMoreElements()) {
132 String fromFile = (String) e.nextElement();
133
134 File f = new File(fromFile);
135 boolean selfMove = false;
136 if (f.exists()) { //Is this file still available to be moved?
137 String[] toFiles = (String[]) fileCopyMap.get(fromFile);
138 for (int i = 0; i < toFiles.length; i++) {
139 String toFile = (String) toFiles[i];
140
141 if (fromFile.equals(toFile)) {
142 log("Skipping self-move of " + fromFile, verbosity);
143 selfMove = true;
144
145 // if this is the last time through the loop then
146 // move will not occur, but that's what we want
147 continue;
148 }
149 File d = new File(toFile);
150 if ((i + 1) == toFiles.length && !selfMove) {
151 // Only try to move if this is the last mapped file
152 // and one of the mappings isn't to itself
153 moveFile(f, d, filtering, forceOverwrite);
154 } else {
155 copyFile(f, d, filtering, forceOverwrite);
156 }
157 }
158 }
159 }
160 }
161
162 if (includeEmpty) {
163 Enumeration e = dirCopyMap.keys();
164 int createCount = 0;
165 while (e.hasMoreElements()) {
166 String fromDirName = (String) e.nextElement();
167 String[] toDirNames = (String[]) dirCopyMap.get(fromDirName);
168 boolean selfMove = false;
169 for (int i = 0; i < toDirNames.length; i++) {
170
171 if (fromDirName.equals(toDirNames[i])) {
172 log("Skipping self-move of " + fromDirName, verbosity);
173 selfMove = true;
174 continue;
175 }
176
177 File d = new File(toDirNames[i]);
178 if (!d.exists()) {
179 if (!d.mkdirs()) {
180 log("Unable to create directory "
181 + d.getAbsolutePath(), Project.MSG_ERR);
182 } else {
183 createCount++;
184 }
185 }
186 }
187
188 File fromDir = new File(fromDirName);
189 if (!selfMove && okToDelete(fromDir)) {
190 deleteDir(fromDir);
191 }
192
193 }
194
195 if (createCount > 0) {
196 log("Moved " + dirCopyMap.size()
197 + " empty director"
198 + (dirCopyMap.size() == 1 ? "y" : "ies")
199 + " to " + createCount
200 + " empty director"
201 + (createCount == 1 ? "y" : "ies") + " under "
202 + destDir.getAbsolutePath());
203 }
204 }
205 }
206
207 /**
208 * Try to move the file via a rename, but if this fails or filtering
209 * is enabled, copy the file then delete the sourceFile.
210 */
211 private void moveFile(File fromFile, File toFile,
212 boolean filtering, boolean overwrite) {
213 boolean moved = false;
214 try {
215 log("Attempting to rename: " + fromFile
216 + " to " + toFile, verbosity);
217 moved = renameFile(fromFile, toFile, filtering, forceOverwrite);
218 } catch (IOException ioe) {
219 String msg = "Failed to rename " + fromFile
220 + " to " + toFile
221 + " due to " + ioe.getMessage();
222 throw new BuildException(msg, ioe, getLocation());
223 }
224
225 if (!moved) {
226 copyFile(fromFile, toFile, filtering, overwrite);
227 if (!fromFile.delete()) {
228 throw new BuildException("Unable to delete "
229 + "file "
230 + fromFile.getAbsolutePath());
231 }
232 }
233 }
234
235 /**
236 * Copy fromFile to toFile.
237 * @param fromFile
238 * @param toFile
239 * @param filtering
240 * @param overwrite
241 */
242 private void copyFile(File fromFile, File toFile,
243 boolean filtering, boolean overwrite) {
244 try {
245 log("Copying " + fromFile + " to " + toFile,
246 verbosity);
247
248 FilterSetCollection executionFilters =
249 new FilterSetCollection();
250 if (filtering) {
251 executionFilters
252 .addFilterSet(getProject().getGlobalFilterSet());
253 }
254 for (Enumeration filterEnum =
255 getFilterSets().elements();
256 filterEnum.hasMoreElements();) {
257 executionFilters
258 .addFilterSet((FilterSet) filterEnum
259 .nextElement());
260 }
261
262 getFileUtils().copyFile(fromFile, toFile, executionFilters,
263 getFilterChains(),
264 forceOverwrite,
265 getPreserveLastModified(),
266 getEncoding(),
267 getOutputEncoding(),
268 getProject());
269
270 } catch (IOException ioe) {
271 String msg = "Failed to copy " + fromFile
272 + " to " + toFile
273 + " due to " + ioe.getMessage();
274 throw new BuildException(msg, ioe, getLocation());
275 }
276 }
277
278
279 /**
280 * Its only ok to delete a directory tree if there are
281 * no files in it.
282 * @param d the directory to check
283 * @return true if a deletion can go ahead
284 */
285 protected boolean okToDelete(File d) {
286 String[] list = d.list();
287 if (list == null) {
288 return false;
289 } // maybe io error?
290
291 for (int i = 0; i < list.length; i++) {
292 String s = list[i];
293 File f = new File(d, s);
294 if (f.isDirectory()) {
295 if (!okToDelete(f)) {
296 return false;
297 }
298 } else {
299 return false; // found a file
300 }
301 }
302
303 return true;
304 }
305
306 /**
307 * Go and delete the directory tree.
308 * @param d the directory to delete
309 */
310 protected void deleteDir(File d) {
311 deleteDir(d, false);
312 }
313
314 /**
315 * Go and delete the directory tree.
316 * @param d the directory to delete
317 * @param deleteFiles whether to delete files
318 */
319 protected void deleteDir(File d, boolean deleteFiles) {
320 String[] list = d.list();
321 if (list == null) {
322 return;
323 } // on an io error list() can return null
324
325 for (int i = 0; i < list.length; i++) {
326 String s = list[i];
327 File f = new File(d, s);
328 if (f.isDirectory()) {
329 deleteDir(f);
330 } else if (deleteFiles && !(f.delete())) {
331 throw new BuildException("Unable to delete file "
332 + f.getAbsolutePath());
333 } else {
334 throw new BuildException("UNEXPECTED ERROR - The file "
335 + f.getAbsolutePath()
336 + " should not exist!");
337 }
338 }
339 log("Deleting directory " + d.getAbsolutePath(), verbosity);
340 if (!d.delete()) {
341 throw new BuildException("Unable to delete directory "
342 + d.getAbsolutePath());
343 }
344 }
345
346 /**
347 * Attempts to rename a file from a source to a destination.
348 * If overwrite is set to true, this method overwrites existing file
349 * even if the destination file is newer. Otherwise, the source file is
350 * renamed only if the destination file is older than it.
351 * Method then checks if token filtering is used. If it is, this method
352 * returns false assuming it is the responsibility to the copyFile method.
353 *
354 * @param sourceFile the file to rename
355 * @param destFile the destination file
356 * @param filtering if true, filtering is in operation, file will
357 * be copied/deleted instead of renamed
358 * @param overwrite if true force overwrite even if destination file
359 * is newer than source file
360 * @return true if the file was renamed
361 * @exception IOException if an error occurs
362 * @exception BuildException if an error occurs
363 */
364 protected boolean renameFile(File sourceFile, File destFile,
365 boolean filtering, boolean overwrite)
366 throws IOException, BuildException {
367
368 boolean renamed = false;
369 if ((getFilterSets().size() + getFilterChains().size() == 0)
370 && !(filtering || destFile.isDirectory())) {
371 // ensure that parent dir of dest file exists!
372 File parent = destFile.getParentFile();
373 if (parent != null && !parent.exists()) {
374 parent.mkdirs();
375 }
376 if (destFile.isFile() && !destFile.delete()) {
377 throw new BuildException("Unable to remove existing "
378 + "file " + destFile);
379 }
380 renamed = sourceFile.renameTo(destFile);
381 }
382 return renamed;
383 }
384}
Note: See TracBrowser for help on using the repository browser.