You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Delete.java 27 kB

PR: 19897 Submitted by: Peter Reilly This patch adds the add(Type) to the introspection rules and updates ConditionBase, FilterChain, Path, SelectorBase and TokenFilter to use the new introspection rule. ========================================= = Changed Files ========================================= src/main/org/apache/tools/ant/ProjectHelper.java add two methods used by introspection - getComponentClass and createComponent src/main/org/apache/tools/ant/IntrospectionHelper.java implement addTypeMethods add(Type) src/main/org/apache/tools/ant/filters/TokenFilter.java get TokenFilter to use add(Type) instead of dynamicconfigurator make all nested classes ProjectComponents src/main/org/apache/tools/ant/taskdefs/Delete.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/MatchingTask.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java add an add(Condition) method to demostrate use of add(Type) method src/main/org/apache/tools/ant/types/AbstractFileSet.java implement add(FileSelector) src/main/org/apache/tools/ant/types/FilterChain.java use add(ChainableReader) instead of DynamicConfigurator src/main/org/apache/tools/ant/types/Path.java add an add(Path) method src/main/org/apache/tools/ant/types/optional/ScriptFilter.java remove set/get project as parent imlements them now src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java implement the add(FileSelector) method src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java add an add(FileSelector) method ========================================= = New Files ========================================= src/etc/testcases/types/addtype.xml testcases for addtype src/testcases/org/apache/tools/ant/types/AddTypeTest.java test cases for add type git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274635 13f79535-47bb-0310-9956-ffa450edef68
22 years ago
PR: 19897 Submitted by: Peter Reilly This patch adds the add(Type) to the introspection rules and updates ConditionBase, FilterChain, Path, SelectorBase and TokenFilter to use the new introspection rule. ========================================= = Changed Files ========================================= src/main/org/apache/tools/ant/ProjectHelper.java add two methods used by introspection - getComponentClass and createComponent src/main/org/apache/tools/ant/IntrospectionHelper.java implement addTypeMethods add(Type) src/main/org/apache/tools/ant/filters/TokenFilter.java get TokenFilter to use add(Type) instead of dynamicconfigurator make all nested classes ProjectComponents src/main/org/apache/tools/ant/taskdefs/Delete.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/MatchingTask.java implement an add(FileSelector) method src/main/org/apache/tools/ant/taskdefs/condition/ConditionBase.java add an add(Condition) method to demostrate use of add(Type) method src/main/org/apache/tools/ant/types/AbstractFileSet.java implement add(FileSelector) src/main/org/apache/tools/ant/types/FilterChain.java use add(ChainableReader) instead of DynamicConfigurator src/main/org/apache/tools/ant/types/Path.java add an add(Path) method src/main/org/apache/tools/ant/types/optional/ScriptFilter.java remove set/get project as parent imlements them now src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java implement the add(FileSelector) method src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java add an add(FileSelector) method ========================================= = New Files ========================================= src/etc/testcases/types/addtype.xml testcases for addtype src/testcases/org/apache/tools/ant/types/AddTypeTest.java test cases for add type git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274635 13f79535-47bb-0310-9956-ffa450edef68
22 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.tools.ant.taskdefs;
  19. import java.io.File;
  20. import java.util.Arrays;
  21. import java.util.Vector;
  22. import java.util.Iterator;
  23. import java.util.Comparator;
  24. import org.apache.tools.ant.Project;
  25. import org.apache.tools.ant.BuildException;
  26. import org.apache.tools.ant.taskdefs.condition.Os;
  27. import org.apache.tools.ant.types.FileSet;
  28. import org.apache.tools.ant.types.PatternSet;
  29. import org.apache.tools.ant.types.ResourceCollection;
  30. import org.apache.tools.ant.types.resources.FileProvider;
  31. import org.apache.tools.ant.types.resources.Sort;
  32. import org.apache.tools.ant.types.resources.Restrict;
  33. import org.apache.tools.ant.types.resources.Resources;
  34. import org.apache.tools.ant.types.resources.FileResourceIterator;
  35. import org.apache.tools.ant.types.resources.comparators.Reverse;
  36. import org.apache.tools.ant.types.resources.comparators.FileSystem;
  37. import org.apache.tools.ant.types.resources.comparators.ResourceComparator;
  38. import org.apache.tools.ant.types.resources.selectors.Exists;
  39. import org.apache.tools.ant.types.resources.selectors.ResourceSelector;
  40. import org.apache.tools.ant.types.selectors.OrSelector;
  41. import org.apache.tools.ant.types.selectors.AndSelector;
  42. import org.apache.tools.ant.types.selectors.NotSelector;
  43. import org.apache.tools.ant.types.selectors.DateSelector;
  44. import org.apache.tools.ant.types.selectors.FileSelector;
  45. import org.apache.tools.ant.types.selectors.NoneSelector;
  46. import org.apache.tools.ant.types.selectors.SizeSelector;
  47. import org.apache.tools.ant.types.selectors.DepthSelector;
  48. import org.apache.tools.ant.types.selectors.DependSelector;
  49. import org.apache.tools.ant.types.selectors.ExtendSelector;
  50. import org.apache.tools.ant.types.selectors.SelectSelector;
  51. import org.apache.tools.ant.types.selectors.PresentSelector;
  52. import org.apache.tools.ant.types.selectors.ContainsSelector;
  53. import org.apache.tools.ant.types.selectors.FilenameSelector;
  54. import org.apache.tools.ant.types.selectors.MajoritySelector;
  55. import org.apache.tools.ant.types.selectors.ContainsRegexpSelector;
  56. import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector;
  57. import org.apache.tools.ant.util.FileUtils;
  58. /**
  59. * Deletes a file or directory, or set of files defined by a fileset.
  60. * The original delete task would delete a file, or a set of files
  61. * using the include/exclude syntax. The deltree task would delete a
  62. * directory tree. This task combines the functionality of these two
  63. * originally distinct tasks.
  64. * <p>Currently Delete extends MatchingTask. This is intended <i>only</i>
  65. * to provide backwards compatibility for a release. The future position
  66. * is to use nested filesets exclusively.</p>
  67. *
  68. * @since Ant 1.2
  69. *
  70. * @ant.task category="filesystem"
  71. */
  72. public class Delete extends MatchingTask {
  73. private static final int DELETE_RETRY_SLEEP_MILLIS = 10;
  74. private static final ResourceComparator REVERSE_FILESYSTEM = new Reverse(new FileSystem());
  75. private static final ResourceSelector EXISTS = new Exists();
  76. private static class ReverseDirs implements ResourceCollection {
  77. static final Comparator REVERSE = new Comparator() {
  78. public int compare(Object foo, Object bar) {
  79. return ((Comparable) foo).compareTo(bar) * -1;
  80. }
  81. };
  82. private Project project;
  83. private File basedir;
  84. private String[] dirs;
  85. ReverseDirs(Project project, File basedir, String[] dirs) {
  86. this.project = project;
  87. this.basedir = basedir;
  88. this.dirs = dirs;
  89. Arrays.sort(this.dirs, REVERSE);
  90. }
  91. public Iterator iterator() {
  92. return new FileResourceIterator(project, basedir, dirs);
  93. }
  94. public boolean isFilesystemOnly() { return true; }
  95. public int size() { return dirs.length; }
  96. }
  97. // CheckStyle:VisibilityModifier OFF - bc
  98. protected File file = null;
  99. protected File dir = null;
  100. protected Vector filesets = new Vector();
  101. protected boolean usedMatchingTask = false;
  102. // by default, remove matching empty dirs
  103. protected boolean includeEmpty = false;
  104. private int verbosity = Project.MSG_VERBOSE;
  105. private boolean quiet = false;
  106. private boolean failonerror = true;
  107. private boolean deleteOnExit = false;
  108. private Resources rcs = null;
  109. private static FileUtils FILE_UTILS = FileUtils.getFileUtils();
  110. // CheckStyle:VisibilityModifier ON
  111. /**
  112. * Set the name of a single file to be removed.
  113. *
  114. * @param file the file to be deleted
  115. */
  116. public void setFile(File file) {
  117. this.file = file;
  118. }
  119. /**
  120. * Set the directory from which files are to be deleted
  121. *
  122. * @param dir the directory path.
  123. */
  124. public void setDir(File dir) {
  125. this.dir = dir;
  126. getImplicitFileSet().setDir(dir);
  127. }
  128. /**
  129. * If true, list all names of deleted files.
  130. *
  131. * @param verbose "true" or "on"
  132. */
  133. public void setVerbose(boolean verbose) {
  134. if (verbose) {
  135. this.verbosity = Project.MSG_INFO;
  136. } else {
  137. this.verbosity = Project.MSG_VERBOSE;
  138. }
  139. }
  140. /**
  141. * If true and the file does not exist, do not display a diagnostic
  142. * message or modify the exit status to reflect an error.
  143. * This means that if a file or directory cannot be deleted,
  144. * then no error is reported. This setting emulates the
  145. * -f option to the Unix &quot;rm&quot; command.
  146. * Default is false meaning things are &quot;noisy&quot;
  147. * @param quiet "true" or "on"
  148. */
  149. public void setQuiet(boolean quiet) {
  150. this.quiet = quiet;
  151. if (quiet) {
  152. this.failonerror = false;
  153. }
  154. }
  155. /**
  156. * If false, note errors but continue.
  157. *
  158. * @param failonerror true or false
  159. */
  160. public void setFailOnError(boolean failonerror) {
  161. this.failonerror = failonerror;
  162. }
  163. /**
  164. * If true, on failure to delete, note the error and set
  165. * the deleteonexit flag, and continue
  166. *
  167. * @param deleteOnExit true or false
  168. */
  169. public void setDeleteOnExit(boolean deleteOnExit) {
  170. this.deleteOnExit = deleteOnExit;
  171. }
  172. /**
  173. * If true, delete empty directories.
  174. * @param includeEmpty if true delete empty directories (only
  175. * for filesets). Default is false.
  176. */
  177. public void setIncludeEmptyDirs(boolean includeEmpty) {
  178. this.includeEmpty = includeEmpty;
  179. }
  180. /**
  181. * Adds a set of files to be deleted.
  182. * @param set the set of files to be deleted
  183. */
  184. public void addFileset(FileSet set) {
  185. filesets.addElement(set);
  186. }
  187. /**
  188. * Add an arbitrary ResourceCollection to be deleted.
  189. * @param rc the filesystem-only ResourceCollection.
  190. */
  191. public void add(ResourceCollection rc) {
  192. if (rc == null) {
  193. return;
  194. }
  195. rcs = (rcs == null) ? new Resources() : rcs;
  196. rcs.add(rc);
  197. }
  198. /**
  199. * add a name entry on the include list
  200. * @return a NameEntry object to be configured
  201. */
  202. public PatternSet.NameEntry createInclude() {
  203. usedMatchingTask = true;
  204. return super.createInclude();
  205. }
  206. /**
  207. * add a name entry on the include files list
  208. * @return an NameEntry object to be configured
  209. */
  210. public PatternSet.NameEntry createIncludesFile() {
  211. usedMatchingTask = true;
  212. return super.createIncludesFile();
  213. }
  214. /**
  215. * add a name entry on the exclude list
  216. * @return an NameEntry object to be configured
  217. */
  218. public PatternSet.NameEntry createExclude() {
  219. usedMatchingTask = true;
  220. return super.createExclude();
  221. }
  222. /**
  223. * add a name entry on the include files list
  224. * @return an NameEntry object to be configured
  225. */
  226. public PatternSet.NameEntry createExcludesFile() {
  227. usedMatchingTask = true;
  228. return super.createExcludesFile();
  229. }
  230. /**
  231. * add a set of patterns
  232. * @return PatternSet object to be configured
  233. */
  234. public PatternSet createPatternSet() {
  235. usedMatchingTask = true;
  236. return super.createPatternSet();
  237. }
  238. /**
  239. * Sets the set of include patterns. Patterns may be separated by a comma
  240. * or a space.
  241. *
  242. * @param includes the string containing the include patterns
  243. */
  244. public void setIncludes(String includes) {
  245. usedMatchingTask = true;
  246. super.setIncludes(includes);
  247. }
  248. /**
  249. * Sets the set of exclude patterns. Patterns may be separated by a comma
  250. * or a space.
  251. *
  252. * @param excludes the string containing the exclude patterns
  253. */
  254. public void setExcludes(String excludes) {
  255. usedMatchingTask = true;
  256. super.setExcludes(excludes);
  257. }
  258. /**
  259. * Sets whether default exclusions should be used or not.
  260. *
  261. * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions
  262. * should be used, "false"|"off"|"no" when they
  263. * shouldn't be used.
  264. */
  265. public void setDefaultexcludes(boolean useDefaultExcludes) {
  266. usedMatchingTask = true;
  267. super.setDefaultexcludes(useDefaultExcludes);
  268. }
  269. /**
  270. * Sets the name of the file containing the includes patterns.
  271. *
  272. * @param includesfile A string containing the filename to fetch
  273. * the include patterns from.
  274. */
  275. public void setIncludesfile(File includesfile) {
  276. usedMatchingTask = true;
  277. super.setIncludesfile(includesfile);
  278. }
  279. /**
  280. * Sets the name of the file containing the includes patterns.
  281. *
  282. * @param excludesfile A string containing the filename to fetch
  283. * the include patterns from.
  284. */
  285. public void setExcludesfile(File excludesfile) {
  286. usedMatchingTask = true;
  287. super.setExcludesfile(excludesfile);
  288. }
  289. /**
  290. * Sets case sensitivity of the file system
  291. *
  292. * @param isCaseSensitive "true"|"on"|"yes" if file system is case
  293. * sensitive, "false"|"off"|"no" when not.
  294. */
  295. public void setCaseSensitive(boolean isCaseSensitive) {
  296. usedMatchingTask = true;
  297. super.setCaseSensitive(isCaseSensitive);
  298. }
  299. /**
  300. * Sets whether or not symbolic links should be followed.
  301. *
  302. * @param followSymlinks whether or not symbolic links should be followed
  303. */
  304. public void setFollowSymlinks(boolean followSymlinks) {
  305. usedMatchingTask = true;
  306. super.setFollowSymlinks(followSymlinks);
  307. }
  308. /**
  309. * add a "Select" selector entry on the selector list
  310. * @param selector the selector to be added
  311. */
  312. public void addSelector(SelectSelector selector) {
  313. usedMatchingTask = true;
  314. super.addSelector(selector);
  315. }
  316. /**
  317. * add an "And" selector entry on the selector list
  318. * @param selector the selector to be added
  319. */
  320. public void addAnd(AndSelector selector) {
  321. usedMatchingTask = true;
  322. super.addAnd(selector);
  323. }
  324. /**
  325. * add an "Or" selector entry on the selector list
  326. * @param selector the selector to be added
  327. */
  328. public void addOr(OrSelector selector) {
  329. usedMatchingTask = true;
  330. super.addOr(selector);
  331. }
  332. /**
  333. * add a "Not" selector entry on the selector list
  334. * @param selector the selector to be added
  335. */
  336. public void addNot(NotSelector selector) {
  337. usedMatchingTask = true;
  338. super.addNot(selector);
  339. }
  340. /**
  341. * add a "None" selector entry on the selector list
  342. * @param selector the selector to be added
  343. */
  344. public void addNone(NoneSelector selector) {
  345. usedMatchingTask = true;
  346. super.addNone(selector);
  347. }
  348. /**
  349. * add a majority selector entry on the selector list
  350. * @param selector the selector to be added
  351. */
  352. public void addMajority(MajoritySelector selector) {
  353. usedMatchingTask = true;
  354. super.addMajority(selector);
  355. }
  356. /**
  357. * add a selector date entry on the selector list
  358. * @param selector the selector to be added
  359. */
  360. public void addDate(DateSelector selector) {
  361. usedMatchingTask = true;
  362. super.addDate(selector);
  363. }
  364. /**
  365. * add a selector size entry on the selector list
  366. * @param selector the selector to be added
  367. */
  368. public void addSize(SizeSelector selector) {
  369. usedMatchingTask = true;
  370. super.addSize(selector);
  371. }
  372. /**
  373. * add a selector filename entry on the selector list
  374. * @param selector the selector to be added
  375. */
  376. public void addFilename(FilenameSelector selector) {
  377. usedMatchingTask = true;
  378. super.addFilename(selector);
  379. }
  380. /**
  381. * add an extended selector entry on the selector list
  382. * @param selector the selector to be added
  383. */
  384. public void addCustom(ExtendSelector selector) {
  385. usedMatchingTask = true;
  386. super.addCustom(selector);
  387. }
  388. /**
  389. * add a contains selector entry on the selector list
  390. * @param selector the selector to be added
  391. */
  392. public void addContains(ContainsSelector selector) {
  393. usedMatchingTask = true;
  394. super.addContains(selector);
  395. }
  396. /**
  397. * add a present selector entry on the selector list
  398. * @param selector the selector to be added
  399. */
  400. public void addPresent(PresentSelector selector) {
  401. usedMatchingTask = true;
  402. super.addPresent(selector);
  403. }
  404. /**
  405. * add a depth selector entry on the selector list
  406. * @param selector the selector to be added
  407. */
  408. public void addDepth(DepthSelector selector) {
  409. usedMatchingTask = true;
  410. super.addDepth(selector);
  411. }
  412. /**
  413. * add a depends selector entry on the selector list
  414. * @param selector the selector to be added
  415. */
  416. public void addDepend(DependSelector selector) {
  417. usedMatchingTask = true;
  418. super.addDepend(selector);
  419. }
  420. /**
  421. * add a regular expression selector entry on the selector list
  422. * @param selector the selector to be added
  423. */
  424. public void addContainsRegexp(ContainsRegexpSelector selector) {
  425. usedMatchingTask = true;
  426. super.addContainsRegexp(selector);
  427. }
  428. /**
  429. * add the modified selector
  430. * @param selector the selector to add
  431. * @since ant 1.6
  432. */
  433. public void addModified(ModifiedSelector selector) {
  434. usedMatchingTask = true;
  435. super.addModified(selector);
  436. }
  437. /**
  438. * add an arbitrary selector
  439. * @param selector the selector to be added
  440. * @since Ant 1.6
  441. */
  442. public void add(FileSelector selector) {
  443. usedMatchingTask = true;
  444. super.add(selector);
  445. }
  446. /**
  447. * Delete the file(s).
  448. * @exception BuildException if an error occurs
  449. */
  450. public void execute() throws BuildException {
  451. if (usedMatchingTask) {
  452. log("DEPRECATED - Use of the implicit FileSet is deprecated. "
  453. + "Use a nested fileset element instead.", quiet ? Project.MSG_VERBOSE : verbosity);
  454. }
  455. if (file == null && dir == null && filesets.size() == 0 && rcs == null) {
  456. throw new BuildException("At least one of the file or dir "
  457. + "attributes, or a nested resource collection, "
  458. + "must be set.");
  459. }
  460. if (quiet && failonerror) {
  461. throw new BuildException("quiet and failonerror cannot both be "
  462. + "set to true", getLocation());
  463. }
  464. // delete the single file
  465. if (file != null) {
  466. if (file.exists()) {
  467. if (file.isDirectory()) {
  468. log("Directory " + file.getAbsolutePath()
  469. + " cannot be removed using the file attribute. "
  470. + "Use dir instead.", quiet ? Project.MSG_VERBOSE : verbosity);
  471. } else {
  472. log("Deleting: " + file.getAbsolutePath());
  473. if (!delete(file)) {
  474. handle("Unable to delete file " + file.getAbsolutePath());
  475. }
  476. }
  477. } else if (isDanglingSymlink(file)) {
  478. log("Trying to delete file " + file.getAbsolutePath()
  479. + " which looks like a broken symlink.",
  480. quiet ? Project.MSG_VERBOSE : verbosity);
  481. if (!delete(file)) {
  482. handle("Unable to delete file " + file.getAbsolutePath());
  483. }
  484. } else {
  485. log("Could not find file " + file.getAbsolutePath()
  486. + " to delete.", quiet ? Project.MSG_VERBOSE : verbosity);
  487. }
  488. }
  489. // delete the directory
  490. if (dir != null && !usedMatchingTask) {
  491. if (dir.exists() && dir.isDirectory()) {
  492. /*
  493. If verbosity is MSG_VERBOSE, that mean we are doing
  494. regular logging (backwards as that sounds). In that
  495. case, we want to print one message about deleting the
  496. top of the directory tree. Otherwise, the removeDir
  497. method will handle messages for _all_ directories.
  498. */
  499. if (verbosity == Project.MSG_VERBOSE) {
  500. log("Deleting directory " + dir.getAbsolutePath());
  501. }
  502. removeDir(dir);
  503. } else if (isDanglingSymlink(dir)) {
  504. log("Trying to delete directory " + dir.getAbsolutePath()
  505. + " which looks like a broken symlink.",
  506. quiet ? Project.MSG_VERBOSE : verbosity);
  507. if (!delete(dir)) {
  508. handle("Unable to delete directory "
  509. + dir.getAbsolutePath());
  510. }
  511. }
  512. }
  513. Resources resourcesToDelete = new Resources();
  514. resourcesToDelete.setProject(getProject());
  515. Resources filesetDirs = new Resources();
  516. filesetDirs.setProject(getProject());
  517. FileSet implicit = null;
  518. if (usedMatchingTask && dir != null && dir.isDirectory()) {
  519. //add the files from the default fileset:
  520. implicit = getImplicitFileSet();
  521. implicit.setProject(getProject());
  522. filesets.add(implicit);
  523. }
  524. for (int i = 0, size = filesets.size(); i < size; i++) {
  525. FileSet fs = (FileSet) filesets.get(i);
  526. if (fs.getProject() == null) {
  527. log("Deleting fileset with no project specified;"
  528. + " assuming executing project", Project.MSG_VERBOSE);
  529. fs = (FileSet) fs.clone();
  530. fs.setProject(getProject());
  531. }
  532. File fsDir = fs.getDir();
  533. if (fsDir == null) {
  534. throw new BuildException(
  535. "File or Resource without directory or file specified");
  536. } else if (!fsDir.isDirectory()) {
  537. handle("Directory does not exist:" + fsDir);
  538. } else {
  539. resourcesToDelete.add(fs);
  540. if (includeEmpty) {
  541. filesetDirs.add(new ReverseDirs(getProject(), fsDir, fs
  542. .getDirectoryScanner().getIncludedDirectories()));
  543. }
  544. }
  545. }
  546. resourcesToDelete.add(filesetDirs);
  547. if (rcs != null) {
  548. // sort first to files, then dirs
  549. Restrict exists = new Restrict();
  550. exists.add(EXISTS);
  551. exists.add(rcs);
  552. Sort s = new Sort();
  553. s.add(REVERSE_FILESYSTEM);
  554. s.add(exists);
  555. resourcesToDelete.add(s);
  556. }
  557. try {
  558. if (resourcesToDelete.isFilesystemOnly()) {
  559. for (Iterator iter = resourcesToDelete.iterator(); iter.hasNext();) {
  560. // nonexistent resources could only occur if we already
  561. // deleted something from a fileset:
  562. File f = ((FileProvider) iter.next()).getFile();
  563. if (!f.exists()) {
  564. continue;
  565. }
  566. if (!(f.isDirectory()) || f.list().length == 0) {
  567. log("Deleting " + f, verbosity);
  568. if (!delete(f) && failonerror) {
  569. handle("Unable to delete "
  570. + (f.isDirectory() ? "directory " : "file ") + f);
  571. }
  572. }
  573. }
  574. } else {
  575. handle(getTaskName() + " handles only filesystem resources");
  576. }
  577. } catch (Exception e) {
  578. handle(e);
  579. } finally {
  580. if (implicit != null) {
  581. filesets.remove(implicit);
  582. }
  583. }
  584. }
  585. //************************************************************************
  586. // protected and private methods
  587. //************************************************************************
  588. private void handle(String msg) {
  589. handle(new BuildException(msg));
  590. }
  591. private void handle(Exception e) {
  592. if (failonerror) {
  593. throw (e instanceof BuildException)
  594. ? (BuildException) e : new BuildException(e);
  595. }
  596. log(e, quiet ? Project.MSG_VERBOSE : verbosity);
  597. }
  598. /**
  599. * Accommodate Windows bug encountered in both Sun and IBM JDKs.
  600. * Others possible. If the delete does not work, call System.gc(),
  601. * wait a little and try again.
  602. */
  603. private boolean delete(File f) {
  604. if (!f.delete()) {
  605. if (Os.isFamily("windows")) {
  606. System.gc();
  607. }
  608. try {
  609. Thread.sleep(DELETE_RETRY_SLEEP_MILLIS);
  610. } catch (InterruptedException ex) {
  611. // Ignore Exception
  612. }
  613. if (!f.delete()) {
  614. if (deleteOnExit) {
  615. int level = quiet ? Project.MSG_VERBOSE : Project.MSG_INFO;
  616. log("Failed to delete " + f + ", calling deleteOnExit."
  617. + " This attempts to delete the file when the Ant jvm"
  618. + " has exited and might not succeed.", level);
  619. f.deleteOnExit();
  620. return true;
  621. }
  622. return false;
  623. }
  624. }
  625. return true;
  626. }
  627. /**
  628. * Delete a directory
  629. *
  630. * @param d the directory to delete
  631. */
  632. protected void removeDir(File d) {
  633. String[] list = d.list();
  634. if (list == null) {
  635. list = new String[0];
  636. }
  637. for (int i = 0; i < list.length; i++) {
  638. String s = list[i];
  639. File f = new File(d, s);
  640. if (f.isDirectory()) {
  641. removeDir(f);
  642. } else {
  643. log("Deleting " + f.getAbsolutePath(), quiet ? Project.MSG_VERBOSE : verbosity);
  644. if (!delete(f)) {
  645. handle("Unable to delete file " + f.getAbsolutePath());
  646. }
  647. }
  648. }
  649. log("Deleting directory " + d.getAbsolutePath(), verbosity);
  650. if (!delete(d)) {
  651. handle("Unable to delete directory " + dir.getAbsolutePath());
  652. }
  653. }
  654. /**
  655. * remove an array of files in a directory, and a list of subdirectories
  656. * which will only be deleted if 'includeEmpty' is true
  657. * @param d directory to work from
  658. * @param files array of files to delete; can be of zero length
  659. * @param dirs array of directories to delete; can of zero length
  660. */
  661. protected void removeFiles(File d, String[] files, String[] dirs) {
  662. if (files.length > 0) {
  663. log("Deleting " + files.length + " files from "
  664. + d.getAbsolutePath(), quiet ? Project.MSG_VERBOSE : verbosity);
  665. for (int j = 0; j < files.length; j++) {
  666. File f = new File(d, files[j]);
  667. log("Deleting " + f.getAbsolutePath(),
  668. quiet ? Project.MSG_VERBOSE : verbosity);
  669. if (!delete(f)) {
  670. handle("Unable to delete file " + f.getAbsolutePath());
  671. }
  672. }
  673. }
  674. if (dirs.length > 0 && includeEmpty) {
  675. int dirCount = 0;
  676. for (int j = dirs.length - 1; j >= 0; j--) {
  677. File currDir = new File(d, dirs[j]);
  678. String[] dirFiles = currDir.list();
  679. if (dirFiles == null || dirFiles.length == 0) {
  680. log("Deleting " + currDir.getAbsolutePath(),
  681. quiet ? Project.MSG_VERBOSE : verbosity);
  682. if (!delete(currDir)) {
  683. handle("Unable to delete directory "
  684. + currDir.getAbsolutePath());
  685. } else {
  686. dirCount++;
  687. }
  688. }
  689. }
  690. if (dirCount > 0) {
  691. log("Deleted "
  692. + dirCount
  693. + " director" + (dirCount == 1 ? "y" : "ies")
  694. + " form " + d.getAbsolutePath(),
  695. quiet ? Project.MSG_VERBOSE : verbosity);
  696. }
  697. }
  698. }
  699. private boolean isDanglingSymlink(File f) {
  700. try {
  701. return FILE_UTILS.isDanglingSymbolicLink(f.getParentFile(),
  702. f.getName());
  703. } catch (java.io.IOException e) {
  704. log("Error while trying to detect " + f.getAbsolutePath()
  705. + " as broken symbolic link. " + e.getMessage(),
  706. quiet ? Project.MSG_VERBOSE : verbosity);
  707. return false;
  708. }
  709. }
  710. }