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.

DependSet.java 9.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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.Iterator;
  21. import org.apache.tools.ant.BuildException;
  22. import org.apache.tools.ant.Project;
  23. import org.apache.tools.ant.types.Path;
  24. import org.apache.tools.ant.types.FileSet;
  25. import org.apache.tools.ant.types.FileList;
  26. import org.apache.tools.ant.types.Resource;
  27. import org.apache.tools.ant.types.TimeComparison;
  28. import org.apache.tools.ant.types.ResourceCollection;
  29. import org.apache.tools.ant.types.resources.Union;
  30. import org.apache.tools.ant.types.resources.Restrict;
  31. import org.apache.tools.ant.types.resources.Resources;
  32. import org.apache.tools.ant.types.resources.FileResource;
  33. import org.apache.tools.ant.types.resources.selectors.Not;
  34. import org.apache.tools.ant.types.resources.selectors.Exists;
  35. import org.apache.tools.ant.types.resources.selectors.ResourceSelector;
  36. import org.apache.tools.ant.types.resources.comparators.Reverse;
  37. import org.apache.tools.ant.types.resources.comparators.ResourceComparator;
  38. /**
  39. * Examines and removes out of date target files. If any of the target files
  40. * are out of date with respect to any of the source files, all target
  41. * files are removed. This is useful where dependencies cannot be
  42. * computed (for example, dynamically interpreted parameters or files
  43. * that need to stay in synch but are not directly linked) or where
  44. * the ant task in question could compute them but does not (for
  45. * example, the linked DTD for an XML file using the XSLT task).
  46. *
  47. * nested arguments:
  48. * <ul>
  49. * <li>sources (resource union describing the source resources to examine)
  50. * <li>srcfileset (fileset describing the source files to examine)
  51. * <li>srcfilelist (filelist describing the source files to examine)
  52. * <li>targets (path describing the target files to examine)
  53. * <li>targetfileset (fileset describing the target files to examine)
  54. * <li>targetfilelist (filelist describing the target files to examine)
  55. * </ul>
  56. * At least one of both source and target entities is required.
  57. * <p>
  58. * This task will examine each of the sources against each of the target files. If
  59. * any target files are out of date with respect to any of the sources, all targets
  60. * are removed. If any sources or targets do not exist, all targets are removed.
  61. * Hint: If missing files should be ignored, specify them as include patterns
  62. * in filesets, rather than using filelists.
  63. * </p><p>
  64. * This task attempts to optimize speed of dependency checking
  65. * by comparing only the dates of the oldest target file and the newest source.
  66. * </p><p>
  67. * Example uses:
  68. * <ul><li>
  69. * Record the fact that an XML file must be up to date with respect to its XSD
  70. * (Schema file), even though the XML file itself includes no reference to its XSD.
  71. * </li><li>
  72. * Record the fact that an XSL stylesheet includes other sub-stylesheets
  73. * </li><li>
  74. * Record the fact that java files must be recompiled if the ant build file changes
  75. * </li></ul>
  76. *
  77. * @ant.task category="filesystem"
  78. * @since Ant 1.4
  79. */
  80. public class DependSet extends MatchingTask {
  81. private static final ResourceSelector NOT_EXISTS = new Not(new Exists());
  82. private static final ResourceComparator DATE
  83. = new org.apache.tools.ant.types.resources.comparators.Date();
  84. private static final ResourceComparator REVERSE_DATE = new Reverse(DATE);
  85. private static final class NonExistent extends Restrict {
  86. private NonExistent(ResourceCollection rc) {
  87. super.add(rc);
  88. super.add(NOT_EXISTS);
  89. }
  90. }
  91. private static final class HideMissingBasedir
  92. implements ResourceCollection {
  93. private FileSet fs;
  94. private HideMissingBasedir(FileSet fs) {
  95. this.fs = fs;
  96. }
  97. public Iterator iterator() {
  98. return basedirExists() ? fs.iterator() : Resources.EMPTY_ITERATOR;
  99. }
  100. public int size() {
  101. return basedirExists() ? fs.size() : 0;
  102. }
  103. public boolean isFilesystemOnly() {
  104. return true;
  105. }
  106. private boolean basedirExists() {
  107. File basedir = fs.getDir();
  108. //trick to evoke "basedir not set" if null:
  109. return basedir == null || basedir.exists();
  110. }
  111. }
  112. private Union sources = null;
  113. private Path targets = null;
  114. /**
  115. * Create a nested sources element.
  116. * @return a Union instance.
  117. */
  118. public synchronized Union createSources() {
  119. sources = (sources == null) ? new Union() : sources;
  120. return sources;
  121. }
  122. /**
  123. * Add a set of source files.
  124. * @param fs the FileSet to add.
  125. */
  126. public void addSrcfileset(FileSet fs) {
  127. createSources().add(fs);
  128. }
  129. /**
  130. * Add a list of source files.
  131. * @param fl the FileList to add.
  132. */
  133. public void addSrcfilelist(FileList fl) {
  134. createSources().add(fl);
  135. }
  136. /**
  137. * Create a nested targets element.
  138. * @return a Union instance.
  139. */
  140. public synchronized Path createTargets() {
  141. targets = (targets == null) ? new Path(getProject()) : targets;
  142. return targets;
  143. }
  144. /**
  145. * Add a set of target files.
  146. * @param fs the FileSet to add.
  147. */
  148. public void addTargetfileset(FileSet fs) {
  149. createTargets().add(new HideMissingBasedir(fs));
  150. }
  151. /**
  152. * Add a list of target files.
  153. * @param fl the FileList to add.
  154. */
  155. public void addTargetfilelist(FileList fl) {
  156. createTargets().add(fl);
  157. }
  158. /**
  159. * Execute the task.
  160. * @throws BuildException if errors occur.
  161. */
  162. public void execute() throws BuildException {
  163. if (sources == null) {
  164. throw new BuildException(
  165. "At least one set of source resources must be specified");
  166. }
  167. if (targets == null) {
  168. throw new BuildException(
  169. "At least one set of target files must be specified");
  170. }
  171. //no sources = nothing to compare; no targets = nothing to delete:
  172. if (sources.size() > 0 && targets.size() > 0 && !uptodate(sources, targets)) {
  173. log("Deleting all target files.", Project.MSG_VERBOSE);
  174. Delete delete = new Delete();
  175. delete.bindToOwner(this);
  176. delete.add(targets);
  177. delete.perform();
  178. }
  179. }
  180. private boolean uptodate(ResourceCollection src, ResourceCollection target) {
  181. org.apache.tools.ant.types.resources.selectors.Date datesel
  182. = new org.apache.tools.ant.types.resources.selectors.Date();
  183. datesel.setMillis(System.currentTimeMillis());
  184. datesel.setWhen(TimeComparison.AFTER);
  185. logFuture(targets, datesel);
  186. int neTargets = new NonExistent(targets).size();
  187. if (neTargets > 0) {
  188. log(neTargets + " nonexistent targets", Project.MSG_VERBOSE);
  189. return false;
  190. }
  191. FileResource oldestTarget = (FileResource) getOldest(targets);
  192. log(oldestTarget + " is oldest target file", Project.MSG_VERBOSE);
  193. logFuture(sources, datesel);
  194. int neSources = new NonExistent(sources).size();
  195. if (neSources > 0) {
  196. log(neSources + " nonexistent sources", Project.MSG_VERBOSE);
  197. return false;
  198. }
  199. Resource newestSource = (Resource) getNewest(sources);
  200. log(newestSource.toLongString() + " is newest source", Project.MSG_VERBOSE);
  201. return oldestTarget.getLastModified() >= newestSource.getLastModified();
  202. }
  203. private void logFuture(ResourceCollection rc, ResourceSelector rsel) {
  204. Restrict r = new Restrict();
  205. r.add(rsel);
  206. r.add(rc);
  207. for (Iterator i = r.iterator(); i.hasNext();) {
  208. log("Warning: " + i.next() + " modified in the future.", Project.MSG_WARN);
  209. }
  210. }
  211. private Resource getXest(ResourceCollection rc, ResourceComparator c) {
  212. Iterator i = rc.iterator();
  213. if (!i.hasNext()) {
  214. return null;
  215. }
  216. Resource xest = (Resource) i.next();
  217. while (i.hasNext()) {
  218. Resource next = (Resource) i.next();
  219. if (c.compare(xest, next) < 0) {
  220. xest = next;
  221. }
  222. }
  223. return xest;
  224. }
  225. private Resource getOldest(ResourceCollection rc) {
  226. return getXest(rc, REVERSE_DATE);
  227. }
  228. private Resource getNewest(ResourceCollection rc) {
  229. return getXest(rc, DATE);
  230. }
  231. }