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

Save This Page
Home » apache-ant-1.7.1-src » org.apache.tools » ant » taskdefs » [javadoc | source]