stevel      2004/11/18 08:00:18

  Modified:    src/main/org/apache/tools/ant/taskdefs/optional/repository
                        Repository.java Library.java MavenRepository.java
                        HttpRepository.java RepositoryRef.java
                        GetLibraries.java
               src/etc/testcases/taskdefs/optional getlibraries.xml
               src/testcases/org/apache/tools/ant/taskdefs/optional/repository
                        GetLibrariesTest.java
               src/main/org/apache/tools/ant/taskdefs Get.java
  Added:       src/main/org/apache/tools/ant/taskdefs/repository
                        EnabledLibraryElement.java
                        ScheduledUpdatePolicy.java
                        EnabledLibraryElementList.java
                        AbsentFilesPolicy.java TimestampPolicy.java
                        BaseLibraryPolicy.java LibraryPolicy.java
                        ForceUpdatePolicy.java NoUpdatePolicy.java
                        AssertDownloaded.java
  Log:
  Updated <getlibraries> code, plus new classes. After this
  checkin I'm about to move and rename some of the existing stuff.
  
  Revision  Changes    Path
  1.3       +9 -2      
ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/Repository.java
  
  Index: Repository.java
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/Repository.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Repository.java   2 Nov 2004 23:37:21 -0000       1.2
  +++ Repository.java   18 Nov 2004 16:00:17 -0000      1.3
  @@ -99,11 +99,18 @@
       /**
        * fetch a library from the repository
        *
  -     * @param library
  +     * @param library library to fetch
        *
  +     * @param useTimestamp flag to indicate the timestamp of the lib should 
be used
        * @return
        */
  -    public abstract boolean fetch(Library library) throws IOException;
  +    public abstract boolean fetch(Library library, boolean useTimestamp) 
throws IOException;
   
   
  +    /**
  +     * this is a string that uniquely describes the repository
  +     * and can be used for equality tests <i>across</i> instances. 
  +     * @return
  +     */
  +    public abstract String getRepositoryURI();
   }
  
  
  
  1.3       +126 -52   
ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/Library.java
  
  Index: Library.java
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/Library.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Library.java      30 Oct 2004 21:03:44 -0000      1.2
  +++ Library.java      18 Nov 2004 16:00:17 -0000      1.3
  @@ -18,8 +18,9 @@
   package org.apache.tools.ant.taskdefs.optional.repository;
   
   import org.apache.tools.ant.BuildException;
  -import org.apache.tools.ant.Project;
  +import org.apache.tools.ant.taskdefs.repository.EnabledLibraryElement;
   import org.apache.tools.ant.types.Path;
  +import org.apache.tools.ant.util.FileUtils;
   
   import java.io.File;
   
  @@ -28,7 +29,30 @@
    *
    * @since Ant1.7
    */
  -public class Library {
  +public class Library implements EnabledLibraryElement {
  +
  +    /**
  +     * enabled flag
  +     */
  +    private boolean enabled = true;
  +
  +    /**
  +     * turn policy on/off
  +     *
  +     * @param enabled
  +     */
  +    public void setEnabled(boolean enabled) {
  +        this.enabled = enabled;
  +    }
  +
  +    /**
  +     * are we enabled
  +     *
  +     * @return true if [EMAIL PROTECTED] #enabled} is set
  +     */
  +    public boolean getEnabled() {
  +        return enabled;
  +    }
   
       //project "ant"
       private String project;
  @@ -52,14 +76,12 @@
       private File libraryFile;
   
       /**
  -     * if clause
  +     * we fetch every library by default; note the enabled/disabled
  +     * flag has precedence, and this flag is not visible in the XML
        */
  -    private String ifClause;
  +    private boolean toFetch=true;
   
  -    /**
  -     * unless clause
  -     */
  -    private String unlessClause;
  +    private boolean fetched=false;
   
       public static final String ERROR_NO_ARCHIVE = "No archive defined";
       public static final String ERROR_NO_PROJECT = "No project defined";
  @@ -70,6 +92,7 @@
        * suffix
        */
       private String suffix = "jar";
  +    public static final String ERROR_FILE_IS_A_DIR = "Library file is a 
directory:";
   
   
       /**
  @@ -155,38 +178,6 @@
       }
   
       /**
  -     * a property that must be set for the library to be considered a 
dependency
  -     * @return
  -     */
  -    public String getIf() {
  -        return ifClause;
  -    }
  -
  -    /**
  -     * a property that must be set for the library to be considered a 
dependency
  -     * @param ifClause
  -     */
  -    public void setIf(String ifClause) {
  -        this.ifClause = ifClause;
  -    }
  -
  -    /**
  -     * a property that must be unset for the library to be considered a 
dependency
  -     * @return
  -     */
  -    public String getUnless() {
  -        return unlessClause;
  -    }
  -
  -    /**
  -     * a property that must be unset for the library to be considered a 
dependency
  -     * @param unlessClause
  -     */
  -    public void setUnless(String unlessClause) {
  -        this.unlessClause = unlessClause;
  -    }
  -
  -    /**
        * get the library file
        * (only non-null after binding)
        * @return library file or null
  @@ -196,6 +187,14 @@
       }
   
       /**
  +     * set the library file.
  +     * @param libraryFile
  +     */
  +    public void setLibraryFile(File libraryFile) {
  +        this.libraryFile = libraryFile;
  +    }
  +
  +    /**
        * fault if the field is null or empty
        *
        * @param field
  @@ -241,10 +240,16 @@
        */
       public void bind(File baseDir) {
           validate();
  +        FileUtils fileUtils=FileUtils.newFileUtils();
  +
           if (destinationName == null) {
  -            destinationName = getNormalFilename();
  +            destinationName = getMavenPath('/');
  +        }
  +        libraryFile = fileUtils.resolveFile(baseDir, destinationName);
  +        if(libraryFile.isDirectory()) {
  +            throw new BuildException(ERROR_FILE_IS_A_DIR
  +                +libraryFile);
           }
  -        libraryFile = new File(baseDir, destinationName);
       }
   
       /**
  @@ -310,21 +315,40 @@
           return libraryFile.getAbsolutePath();
       }
   
  +
       /**
  -     * test for being enabled
  -     * @param project
  +     * prefixed to avoid ant picking up on it, this sets
  +     * the fetch/no-fetch flag.
  +     * @param toFetch
  +     */
  +    public void _setToFetch(boolean toFetch) {
  +        this.toFetch = toFetch;
  +    }
  +
  +    /**
  +     * get the fetch flag.
        * @return
        */
  -    public boolean isEnabled(Project project) {
  -        if (unlessClause != null && project.getProperty(unlessClause) != 
null) {
  -            return false;
  -        }
  -        if (ifClause == null) {
  -            return true;
  -        }
  -        return project.getProperty(ifClause) != null;
  +    public boolean isToFetch() {
  +        return toFetch;
       }
   
  +    /**
  +     * get a flag that marks if a file is fetched
  +     * @return
  +     */
  +    public boolean wasFetched() {
  +        return fetched;
  +    }
  +
  +    /**
  +     * another not-for-end-users attribute; a flag set to true if the
  +     * library has been fetched.
  +     * @param fetched
  +     */
  +    public void _setFetched(boolean fetched) {
  +        this.fetched = fetched;
  +    }
   
       /**
        * add our location to a filepath
  @@ -335,5 +359,55 @@
           pathElement.setLocation(getLibraryFile());
       }
   
  +    /**
  +     * equality test uses archive, destinationName, project, suffix and 
version
  +     * fields (any of which can be null)
  +     * @param o
  +     * @return
  +     */
  +    public boolean equals(Object o) {
  +        if (this == o) {
  +            return true;
  +        }
  +        if (!(o instanceof Library)) {
  +            return false;
  +        }
  +
  +        final Library library = (Library) o;
  +
  +        if (archive != null ? !archive.equals(library.archive) : 
library.archive != null) {
  +            return false;
  +        }
  +        if (destinationName != null ? !destinationName.equals(
  +                library.destinationName) : library.destinationName != null) {
  +            return false;
  +        }
  +        if (project != null ? !project.equals(library.project) : 
library.project != null) {
  +            return false;
  +        }
  +        if (suffix != null ? !suffix.equals(library.suffix) : library.suffix 
!= null) {
  +            return false;
  +        }
  +        if (version != null ? !version.equals(library.version) : 
library.version != null) {
  +            return false;
  +        }
  +
  +        return true;
  +    }
  +
  +    /**
  +     * Hash code uses the name fields as [EMAIL PROTECTED] #equals(Object)}
  +     * This sequence
  +     * @return
  +     */
  +    public int hashCode() {
  +        int result;
  +        result = (project != null ? project.hashCode() : 0);
  +        result = 29 * result + (version != null ? version.hashCode() : 0);
  +        result = 29 * result + (archive != null ? archive.hashCode() : 0);
  +        result = 29 * result + (destinationName != null ? 
destinationName.hashCode() : 0);
  +        result = 29 * result + (suffix != null ? suffix.hashCode() : 0);
  +        return result;
  +    }
   
   }
  
  
  
  1.3       +14 -6     
ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/MavenRepository.java
  
  Index: MavenRepository.java
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/MavenRepository.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- MavenRepository.java      2 Nov 2004 23:37:21 -0000       1.2
  +++ MavenRepository.java      18 Nov 2004 16:00:17 -0000      1.3
  @@ -19,10 +19,9 @@
   
   import org.apache.tools.ant.util.FileUtils;
   
  -import java.io.IOException;
   import java.io.File;
   import java.io.FileInputStream;
  -import java.io.FileReader;
  +import java.io.IOException;
   import java.io.InputStreamReader;
   import java.io.Reader;
   import java.net.URL;
  @@ -91,17 +90,28 @@
       }
   
       /**
  +     * this is a string that uniquely describes the repository and can be 
used
  +     * for equality tests <i>across</i> instances.
  +     *
  +     * @return maven identifier
  +     */
  +    public String getRepositoryURI() {
  +        return "maven://" + getUrl();
  +    }
  +
  +    /**
        * fetch a library from the repository
        *
        * @param library
        *
  +     * @param useTimestamp
        * @return true if we retrieved
        *
        * @throws org.apache.tools.ant.BuildException
        *
        */
  -    public boolean fetch(Library library) throws IOException {
  -        boolean  fetched=super.fetch(library);
  +    public boolean fetch(Library library, boolean useTimestamp) throws 
IOException {
  +        boolean  fetched=super.fetch(library, useTimestamp);
           if(fetched && checkMD5) {
               //we got here if there was a fetch. so we now get the MD5 info 
from the file,
               boolean successful=false;
  @@ -140,5 +150,3 @@
       }
   
   }
  -
  -// e1b1720a761ca36eaa47e1c7d802e676
  \ No newline at end of file
  
  
  
  1.4       +19 -64    
ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/HttpRepository.java
  
  Index: HttpRepository.java
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/HttpRepository.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- HttpRepository.java       2 Nov 2004 23:37:21 -0000       1.3
  +++ HttpRepository.java       18 Nov 2004 16:00:17 -0000      1.4
  @@ -68,8 +68,6 @@
        * retry logic
        */
       public static final String ERROR_REENTRANT_USE = "Repository is already 
in use";
  -    private static final String IF_MODIFIED_SINCE = "If-Modified-Since";
  -    private static final int BLOCKSIZE = 8192;
   
       /**
        * get the base URL of the repository
  @@ -169,9 +167,9 @@
               url = url + '/';
           }
   
  -        //validate the URL
  -        URL repository;
           try {
  +            //validate the URL
  +            URL repository;
               repository = new URL(url);
           } catch (MalformedURLException e) {
               throw new BuildException(e);
  @@ -213,12 +211,13 @@
        *
        * @param library
        *
  +     * @param useTimestamp
        * @return true if we retrieved
        *
        * @throws org.apache.tools.ant.BuildException
        *
        */
  -    public boolean fetch(Library library) throws IOException {
  +    public boolean fetch(Library library, boolean useTimestamp) throws 
IOException {
   
           String path = getRemoteLibraryURL(library);
           logVerbose("Library URL=" + path);
  @@ -226,11 +225,9 @@
           logVerbose("destination =" + library.getAbsolutePath());
           long start, finish;
           start = System.currentTimeMillis();
  -        finish = System.currentTimeMillis();
  -        boolean useTimestamps = !getOwner().isForceDownload() &&
  -                !library.exists();
  -        boolean success=get(remoteURL, 
library.getLibraryFile(),useTimestamps,
  +        boolean success=get(remoteURL, library.getLibraryFile(),useTimestamp,
                   username, password);
  +        finish = System.currentTimeMillis();
           long diff = finish - start;
           logVerbose("downloaded in " + diff / 1000 + " seconds");
   
  @@ -246,9 +243,11 @@
        */
       public boolean get(URL url,File destFile,boolean useTimestamp,String 
user,String passwd)
               throws IOException {
  +        //create the destination dir
  +        destFile.getParentFile().mkdirs();
           Get getTask = new Get();
           getTask.setProject(getProject());
  -        getTask.setTaskName("dependencies");
  +        getTask.setTaskName(owner.getTaskName());
           getTask.setDest(destFile);
           getTask.setUsername(user);
           getTask.setPassword(passwd);
  @@ -287,65 +286,21 @@
       protected abstract String getRemoteLibraryURL(Library library);
   
       /**
  -     * save a stream from a connection to a library. prerequisite: connection
  -     * open and response=200.
  -     *
  -     * @param get
  -     * @param library
  -     *
  -     * @throws java.io.IOException on any trouble.
  +     * Returns a string representation of the repository
  +     * Used for scheduled updates.
  +     * @return the base URL
        */
  -    /*
  -    protected void saveStreamToLibrary(GetMethod get, Library library)
  -            throws IOException {
  -        //we only get here if we are happy
  -        //so save it to a temp file
  -        File tempDest = File.createTempFile("download", ".bin", getOwner()
  -                .getDestDir());
  -        logDebug("Saving file to " + tempDest);
  -        FileOutputStream fos = new FileOutputStream(tempDest);
  -        InputStream is = get.getResponseBodyAsStream();
  -        boolean finished = false;
  -        try {
  -            byte[] buffer = new byte[BLOCKSIZE];
  -            int length;
  -
  -            while ((length = is.read(buffer)) >= 0) {
  -                fos.write(buffer, 0, length);
  -            }
  -            finished = true;
  -        } finally {
  -            FileUtils.close(fos);
  -            FileUtils.close(is);
  -            // we have started to (over)write dest, but failed.
  -            // Try to delete the garbage we'd otherwise leave
  -            // behind.
  -            if (!finished) {
  -                logVerbose("Deleting temporary file after failed download");
  -                tempDest.delete();
  -            }
  -        }
  -        logDebug("download complete; renaming destination file");
  -        //then copy over the file
  -        File libraryFile = library.getLibraryFile();
  -        if (libraryFile.exists()) {
  -            libraryFile.delete();
  -        }
  -        // set the dest file
  -        if (!tempDest.renameTo(libraryFile)) {
  -            tempDest.delete();
  -            throw new IOException(
  -                    "Could not rename temp file to destination file");
  -        }
  +    public String toString() {
  +        return "Repository at " + getUrl();
       }
  -    */
   
       /**
  -     * Returns a string representation of the repository
  +     * this is a string that uniquely describes the repository and can be 
used
  +     * for equality tests <i>across</i> instances.
        *
  -     * @return the base URL
  +     * @return
        */
  -    public String toString() {
  -        return "Repository at " + getUrl();
  +    public String getRepositoryURI() {
  +        return "HttpRepository://"+getUrl();
       }
   }
  
  
  
  1.3       +11 -1     
ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/RepositoryRef.java
  
  Index: RepositoryRef.java
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/RepositoryRef.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- RepositoryRef.java        2 Nov 2004 23:37:21 -0000       1.2
  +++ RepositoryRef.java        18 Nov 2004 16:00:17 -0000      1.3
  @@ -70,10 +70,20 @@
        *
        * @param library
        *
  +     * @param useTimestamp
        * @return
        */
  -    public boolean fetch(Library library) throws IOException {
  +    public boolean fetch(Library library, boolean useTimestamp) throws 
IOException {
           throw new BuildException(E_NOTIMPL);
       }
   
  +    /**
  +     * this is a string that uniquely describes the repository and can be 
used
  +     * for equality tests <i>across</i> instances.
  +     *
  +     * @return
  +     */
  +    public String getRepositoryURI() {
  +        return "ref://"+getRefid();
  +    }
   }
  
  
  
  1.4       +293 -131  
ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/GetLibraries.java
  
  Index: GetLibraries.java
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/GetLibraries.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- GetLibraries.java 2 Nov 2004 23:37:21 -0000       1.3
  +++ GetLibraries.java 18 Nov 2004 16:00:17 -0000      1.4
  @@ -19,16 +19,23 @@
   import org.apache.tools.ant.BuildException;
   import org.apache.tools.ant.Project;
   import org.apache.tools.ant.Task;
  +import org.apache.tools.ant.taskdefs.repository.AbsentFilesPolicy;
  +import org.apache.tools.ant.taskdefs.repository.AssertDownloaded;
  +import org.apache.tools.ant.taskdefs.repository.EnabledLibraryElementList;
  +import org.apache.tools.ant.taskdefs.repository.ForceUpdatePolicy;
  +import org.apache.tools.ant.taskdefs.repository.LibraryPolicy;
  +import org.apache.tools.ant.taskdefs.repository.NoUpdatePolicy;
  +import org.apache.tools.ant.taskdefs.repository.ScheduledUpdatePolicy;
  +import org.apache.tools.ant.taskdefs.repository.TimestampPolicy;
   import org.apache.tools.ant.types.Path;
   import org.apache.tools.ant.types.Reference;
   
   import java.io.File;
   import java.io.IOException;
  -import java.util.Collection;
  +import java.util.ArrayList;
   import java.util.Iterator;
  -import java.util.LinkedList;
   import java.util.List;
  -import java.util.NoSuchElementException;
  +import java.util.ListIterator;
   
   /**
    * This task will retrieve one or more libraries from a repository. <ol>
  @@ -39,7 +46,7 @@
    * @ant.task
    * @since Ant 1.7
    */
  -public class GetLibraries extends Task {
  +public final class GetLibraries extends Task {
   
       /**
        * destination
  @@ -47,11 +54,6 @@
       private File destDir;
   
       /**
  -     * flag to force a download
  -     */
  -    private boolean forceDownload = false;
  -
  -    /**
        * flag to force offline
        */
       private boolean offline = false;
  @@ -59,7 +61,12 @@
       /**
        * list of libraries
        */
  -    private List libraries = new LinkedList();
  +    private EnabledLibraryElementList libraries = new 
EnabledLibraryElementList();
  +
  +    /**
  +     * helper list
  +     */
  +    private EnabledLibraryElementList policies=new 
EnabledLibraryElementList();
   
       /**
        * repository for retrieval
  @@ -72,16 +79,33 @@
        */
       private String pathid;
   
  -
  +    /**
  +     * should we be timestamp aware in downloads?
  +     */
  +    private boolean useTimestamp = false;
   
       public static final String ERROR_ONE_REPOSITORY_ONLY = "Only one 
repository is allowed";
       public static final String ERROR_NO_DEST_DIR = "No destination 
directory";
       public static final String ERROR_NO_REPOSITORY = "No repository defined";
  -    public static final String ERROR_NO_LIBRARIES = "No libraries to load";
  -    public static final String ERROR_REPO_PROBE_FAILED = "repository probe 
failed with ";
  -    public static final String ERROR_LIBRARY_FETCH_FAILED = "failed to 
retrieve ";
  -    public static final String ERROR_FORCED_DOWNLOAD_FAILED = "Failed to 
download every file on a forced download";
  -    public static final String ERROR_INCOMPLETE_RETRIEVAL = "Not all 
libraries could be retrieved";
  +    public static final String ERROR_NO_LIBRARIES = "No libraries declared";
  +    public static final String ERROR_REPO_PROBE_FAILED = "Repository probe 
failed with ";
  +    public static final String ERROR_LIBRARY_FETCH_FAILED = "Failed to 
retrieve ";
  +    public static final String ERROR_INCOMPLETE_RETRIEVAL = "Missing 
Libraries :";
  +    public static final String MSG_NO_RETRIEVE = "Connections disabled";
  +    public static final String MSG_NO_LIBRARIES_TO_FETCH = "No libraries 
marked for retrieval";
  +
  +
  +    /**
  +     * Init the task
  +     *
  +     * @throws org.apache.tools.ant.BuildException
  +     *          if something goes wrong with the build
  +     */
  +    public void init() throws BuildException {
  +        super.init();
  +        //set our default polocy
  +        add(new AbsentFilesPolicy());
  +    }
   
       /**
        * add a repository. Only one is (currently) supported
  @@ -115,6 +139,64 @@
           add(r);
       }
   
  +    /**
  +     * add anything that implements the library policy interface
  +     * @param policy
  +     */
  +    public void add(LibraryPolicy policy) {
  +        policies.add(policy);
  +    }
  +
  +    /**
  +     * add a schedule
  +     * @param update
  +     */
  +    public void addSchedule(ScheduledUpdatePolicy update) {
  +        add(update);
  +    }
  +
  +    /**
  +     * Declare that the update should be forced: everything
  +     * must be fetched; it will be a failure if any are not
  +     * @param policy
  +     */
  +    public void addForce(ForceUpdatePolicy policy) {
  +        add(policy);
  +    }
  +
  +    /**
  +     * Declare that no files should be fetched
  +     * @param policy
  +     */
  +    public void addNoupdate(NoUpdatePolicy policy) {
  +        add(policy);
  +    }
  +
  +    /**
  +     * declare that the update should be timestamp driven
  +     * @param policy
  +     */
  +    public void addTimestamp(TimestampPolicy policy) {
  +        add(policy);
  +    }
  +
  +    /**
  +     * declare that only absent files are to be fetched
  +     * @param policy
  +     */
  +    public void addAbsentfiles(AbsentFilesPolicy policy) {
  +        add(policy);
  +    }
  +
  +
  +    /**
  +     * make a declaration about the number of files to fetch
  +     *
  +     * @param policy
  +     */
  +    public void addAssertDownloaded(AssertDownloaded policy) {
  +        add(policy);
  +    }
   
       /**
        * add a library for retrieval
  @@ -134,14 +216,6 @@
           this.destDir = destDir;
       }
   
  -    /**
  -     * flag to force a download even if the clock indicates it aint needed.
  -     *
  -     * @param forceDownload
  -     */
  -    public void setForceDownload(boolean forceDownload) {
  -        this.forceDownload = forceDownload;
  -    }
   
       /**
        * test for being offline
  @@ -172,13 +246,6 @@
           return destDir;
       }
   
  -    /**
  -     * get force download flag
  -     * @return
  -     */
  -    public boolean isForceDownload() {
  -        return forceDownload;
  -    }
   
       /**
        * get the list of libraries
  @@ -214,12 +281,38 @@
       }
   
       /**
  +     * get the current timestamp flag
  +     * @return
  +     */
  +    public boolean isUseTimestamp() {
  +        return useTimestamp;
  +    }
  +
  +    /**
  +     * set the timestamp flag. Not for export into XML
  +     * @param useTimestamp
  +     */
  +    public void _setUseTimestamp(boolean useTimestamp) {
  +        this.useTimestamp = useTimestamp;
  +    }
  +
  +    /**
  +     * get the current policy list
  +     * @return
  +     */
  +    public List getPolicies() {
  +        return policies;
  +    }
  +
  +    /**
        * validate ourselves
        *
        * @throws BuildException
        */
       public void validate() {
  -        if (destDir == null || !destDir.isDirectory()) {
  +        if (destDir == null
  +        //        || !destDir.isDirectory()
  +        ) {
               throw new BuildException(ERROR_NO_DEST_DIR);
           }
           if (repository == null) {
  @@ -231,7 +324,6 @@
               library.validate();
           }
       }
  -
       /**
        * Called by the project to let the task do its work.
        *
  @@ -240,25 +332,90 @@
        */
       public void execute() throws BuildException {
           validate();
  +        if (isOffline()) {
  +            log("No retrieval, task is \"offline\"");
  +        } else {
  +            doExecute();
  +        }
  +        //validate the state
  +        verifyAllLibrariesPresent();
  +
  +        //create the path
  +        if (pathid != null) {
  +            createPath();
  +        }
  +    }
  +    /**
  +     * This is the real worker method
  +     *
  +     * @throws org.apache.tools.ant.BuildException
  +     *          if something goes wrong with the build
  +     */
  +    private void doExecute() throws BuildException {
           destDir.mkdirs();
           Repository repo = repository.resolve();
           repo.validate();
           if (libraries.size() == 0) {
               throw new BuildException(ERROR_NO_LIBRARIES);
           }
  -        int failures = 0;
           log("Getting libraries from " + repo.toString(), 
Project.MSG_VERBOSE);
           log("Saving libraries to " + destDir.toString(), 
Project.MSG_VERBOSE);
   
  +        //map libraries to files
           bindAllLibraries();
  -        if (isOffline()) {
  -            log("No retrieval, task is \"offline\"");
  -            //when offline, we just make sure everything is in place
  -            verifyAllLibrariesPresent();
  -            return;
  +
  +
  +        //flag to indicate whether the download should go ahead
  +        boolean retrieve = true;
  +        List processedPolicies = new ArrayList(policies.size());
  +        //iterate through all policies and execute their preload task
  +        Iterator policyIterator = policies.enabledIterator();
  +        while (retrieve && policyIterator.hasNext()) {
  +            LibraryPolicy libraryPolicy = (LibraryPolicy) 
policyIterator.next();
  +            retrieve=libraryPolicy.beforeConnect(this, libraryIterator());
  +            if(retrieve) {
  +                //add all processed properties to the list, 'cept for 
anything that
  +                //broke the chain
  +                processedPolicies.add(libraryPolicy);
  +            } else {
  +                log("Policy "+libraryPolicy.getClass().getName()
  +                        + " disabled retrieval",
  +                        Project.MSG_VERBOSE);
  +            }
  +        }
  +
  +        //see if we need to do a download
  +        if(!retrieve) {
  +            //if not, log it
  +            log(MSG_NO_RETRIEVE);
  +        } else {
  +            int downloads = calculateFetchCount();
  +            if(downloads>0) {
  +                //get the files
  +                connectAndRetrieve(repo, useTimestamp);
  +            } else {
  +                //nothing to fetch
  +                log(MSG_NO_LIBRARIES_TO_FETCH,Project.MSG_VERBOSE);
  +            }
  +        }
  +
  +        //now reverse iterate through all processed properties.
  +        for(int i=processedPolicies.size()-1;i>=0;i--) {
  +            LibraryPolicy libraryPolicy = 
(LibraryPolicy)processedPolicies.get(i);
  +            //and call their post-processor
  +            libraryPolicy.afterFetched(this,libraryIterator() );
           }
  +    }
   
  +    /**
  +     * connect to the remote system, retrieve files
  +     * @param repo
  +     * @param useTimestamp
  +     * @return number of failed retrievals.
  +     */
  +    private int connectAndRetrieve(Repository repo, boolean useTimestamp) {
           //connect the repository
  +        int failures = 0;
           repo.connect(this);
           try {
   
  @@ -274,82 +431,136 @@
                           Project.MSG_VERBOSE);
                   reachable = false;
               }
  -            if (!reachable) {
  -                if (forceDownload) {
  -                    throw new BuildException(repo.toString()
  -                            + " is unreachable and forceDownload is set");
  -                }
  -            } else {
  -                log("Repository is live", Project.MSG_DEBUG);
  +            if(!reachable) {
  +                log("repository is not reachable", Project.MSG_INFO);
  +                return 0;
               }
   
  -            //iterate through the libs we have
  -            Iterator it = filteredIterator();
  +            //iterate through the libs we have enabled
  +            Iterator it = enabledLibrariesIterator();
               while (it.hasNext()) {
                   Library library = (Library) it.next();
  -                try {
  -                    //fetch it
  -                    if (repo.fetch(library)) {
  +                //check to see if it is for fetching
  +                if(library.isToFetch()) {
  +                    log("Fetching "+library.getNormalFilename(), 
Project.MSG_VERBOSE);
  +                    try {
  +                        //fetch it
  +                        boolean fetched=repo.fetch(library, useTimestamp) ;
  +                        //record the fact in the library
  +                        log("success; marking as fetched",
  +                                Project.MSG_DEBUG);
  +                        library._setFetched(fetched);
  +                    } catch (IOException e) {
  +                        log(ERROR_LIBRARY_FETCH_FAILED + library);
  +                        log(e.getMessage());
  +                        //add failures
  +                        failures++;
                       }
  -                } catch (IOException e) {
  -                    //failures to fetch are logged at verbose level
  -                    log(ERROR_LIBRARY_FETCH_FAILED + library);
  -                    log(e.getMessage(), Project.MSG_VERBOSE);
  -                    //add failures
  -                    failures++;
  +                } else {
  +                    //no fetch
  +                    log("Skipping " + library.getNormalFilename(), 
Project.MSG_VERBOSE);
                   }
               }
           } finally {
  +
  +            log("disconnecting",Project.MSG_VERBOSE);
               repo.disconnect();
           }
  +        return failures;
  +    }
   
  -        //at this point downloads have finished.
  -        //we do still need to verify that everything worked.
  -        if ((failures>0 && forceDownload)) {
  -            throw new BuildException(ERROR_FORCED_DOWNLOAD_FAILED);
  +    /**
  +     * bind all libraries to our destination
  +     */
  +    public  void bindAllLibraries() {
  +        Iterator it = libraries.iterator();
  +        while (it.hasNext()) {
  +            Library library = (Library) it.next();
  +            library.bind(destDir);
           }
  +    }
   
  -        //validate the download
  -        verifyAllLibrariesPresent();
  -
  -        //create the path
  -        if(pathid!=null) {
  -            createPath();
  +    /**
  +     * set/clear the fetch flag on all libraries.
  +     * @param fetch
  +     */
  +    public void markAllLibrariesForFetch(boolean fetch) {
  +        Iterator it = libraryIterator();
  +        while (it.hasNext()) {
  +            Library library = (Library) it.next();
  +            library._setToFetch(fetch);
           }
  +    }
   
  +    /**
  +     * set the fetch flag on all libraries that are absent; clear
  +     * it from all those that exist
  +     *
  +     */
  +    public void markMissingLibrariesForFetch() {
  +        Iterator it = libraryIterator();
  +        while (it.hasNext()) {
  +            Library library = (Library) it.next();
  +            library._setToFetch(!library.exists());
  +        }
       }
   
       /**
  -     * bind all libraries to our destination
  +     * work out how many libraries to fetch
  +     * @return count of enabled libraries with the to fetch bit set
        */
  -    protected void bindAllLibraries() {
  -        Iterator it = libraries.iterator();
  +    public  int calculateFetchCount() {
  +        int count=0;
  +        Iterator it = enabledLibrariesIterator();
           while (it.hasNext()) {
               Library library = (Library) it.next();
  -            library.bind(destDir);
  +            if(library.isToFetch()) {
  +                count++;
  +            };
  +        }
  +        return count;
  +    }
  +
  +    /**
  +     * work out how many libraries were fetched
  +     * @return number of libraries that are enabled with the
  +     * [EMAIL PROTECTED] Library#wasFetched()} flag true.
  +     */
  +    public int calculateDownloadedCount() {
  +        int count = 0;
  +        //here verify that everything came in
  +        Iterator downloaded = enabledLibrariesIterator();
  +        while (downloaded.hasNext()) {
  +            Library library = (Library) downloaded.next();
  +            if (library.wasFetched()) {
  +                count++;
  +            }
           }
  +        return count;
       }
   
  +
       /**
        * verify that all libraries are present
        */
       protected void verifyAllLibrariesPresent() {
           //iterate through the libs we have
           boolean missing = false;
  -
  -        Iterator it = filteredIterator();
  +        StringBuffer buffer=new StringBuffer();
  +        Iterator it = enabledLibrariesIterator();
           while (it.hasNext()) {
               Library library = (Library) it.next();
               //check for the library existing
               if (!library.exists()) {
                   //and log if one is missing
  +                buffer.append(library.toString()+"; ");
                   log("Missing: " + library.toString(),
                           Project.MSG_ERR);
                   missing = true;
               }
           }
           if (missing) {
  -            throw new BuildException(ERROR_INCOMPLETE_RETRIEVAL);
  +            throw new BuildException(ERROR_INCOMPLETE_RETRIEVAL+buffer);
           }
       }
   
  @@ -358,7 +569,7 @@
        */
       private void createPath() {
           Path path = new Path(getProject());
  -        for (Iterator iterator = filteredIterator();
  +        for (Iterator iterator = enabledLibrariesIterator();
                iterator.hasNext();) {
               ((Library) iterator.next()).appendToPath(path);
           }
  @@ -369,66 +580,17 @@
        * get a filtered iterator of the dependencies
        * @return a new iterator that ignores disabled libraries
        */
  -    protected Iterator filteredIterator() {
  -        return new LibraryIterator(libraries,getProject());
  +    public Iterator enabledLibrariesIterator() {
  +        return libraries.enabledIterator();
       }
   
       /**
  -     * iterator through a list that skips everything that
  -     * is not enabled
  +     * get a list iterator for the files
  +     * This gives you more power
  +     * @return
        */
  -    private static class LibraryIterator implements Iterator {
  -        private Iterator _underlyingIterator;
  -        private Library _next;
  -        private Project _project;
  -
  -
  -        /**
  -         * constructor
  -         * @param collection
  -         * @param project
  -         */
  -        LibraryIterator(Collection collection, Project project) {
  -            _project = project;
  -            _underlyingIterator = collection.iterator();
  -        }
  -
  -
  -        /**
  -         * test for having another enabled component
  -         * @return
  -         */
  -        public boolean hasNext() {
  -            while (_next == null && _underlyingIterator.hasNext()) {
  -                Library candidate = (Library) _underlyingIterator.next();
  -                if (candidate.isEnabled(_project)) {
  -                    _next = candidate;
  -                }
  -            }
  -            return (_next != null);
  -        }
  -
  -        /**
  -         * get the next element
  -         * @return
  -         */
  -        public Object next() {
  -            if (!hasNext()) {
  -                throw new NoSuchElementException();
  -            }
  -            Library result = _next;
  -            _next = null;
  -            return result;
  -        }
  -
  -        /**
  -         * removal is not supported
  -         * @throws UnsupportedOperationException always
  -         */
  -        public void remove() {
  -            throw new UnsupportedOperationException();
  -        }
  +    public ListIterator libraryIterator() {
  +        return libraries.listIterator();
       }
  -
   
   }
  
  
  
  1.4       +104 -12   ant/src/etc/testcases/taskdefs/optional/getlibraries.xml
  
  Index: getlibraries.xml
  ===================================================================
  RCS file: /home/cvs/ant/src/etc/testcases/taskdefs/optional/getlibraries.xml,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- getlibraries.xml  2 Nov 2004 23:37:21 -0000       1.3
  +++ getlibraries.xml  18 Nov 2004 16:00:18 -0000      1.4
  @@ -7,8 +7,10 @@
   
     <target name="init">
       <property name="lib.dir" value="getlib"/>
  -    <mkdir dir="${lib.dir}"/>
  -    <property name="commons.logging" value="commons-logging-1.0.1.jar"/>
  +    
  +    <property name="commons.logging.project" value="commons-logging"/>
  +    <property name="commons.logging" 
  +      
value="${commons.logging.project}/jars/${commons.logging.project}-1.0.1.jar"/>
   
       <presetdef name="gl1">
         <getlibraries destDir="${lib.dir}">
  @@ -24,10 +26,11 @@
       <macrodef name="assert-downloaded">
         <attribute name="library" default="${commons.logging}"/>
         <sequential>
  +        <property name="@{library}.path" location="${lib.dir}/@{library}" />
           <available property="@{library}.exists"
  -          file="${lib.dir}/@{library}"/>
  +          file="[EMAIL PROTECTED]"/>
           <fail unless="@{library}.exists">
  -        Not found: [EMAIL PROTECTED]
  +          Not found: [EMAIL PROTECTED]
           </fail>
         </sequential>
       </macrodef>
  @@ -35,20 +38,23 @@
       <macrodef name="assert-not-downloaded">
         <attribute name="library" default="${commons.logging}"/>
         <sequential>
  +        <property name="@{library}.path" location="${lib.dir}/@{library}" />
           <available property="@{library}.exists"
  -          file="${lib.dir}/@{library}"/>
  +          file="[EMAIL PROTECTED]"/>
           <fail if="@{library}.exists">
  -        Found: [EMAIL PROTECTED]
  +          Found: [EMAIL PROTECTED]
           </fail>
         </sequential>
       </macrodef>
   
     </target>
   
  -  <target name="cleanup">
  +  <target name="cleanup"  depends="init">
       <delete dir="${lib.dir}"/>
     </target>
   
  +  <target name="teardown"  depends="cleanup"/>
  +  
     <target name="testEmpty" depends="init">
       <getlibraries/>
     </target>
  @@ -99,7 +105,7 @@
   
     <target name="testMavenInlineBadURL" depends="init">
       <getlib>
  -
  +      <mavenrepository url="http://invalid.example.org"/>
       </getlib>
     </target>
   
  @@ -118,19 +124,19 @@
     <target name="testOverwrite" depends="init">
       <getlib>
         <mavenrepository/>
  +      <assertdownloaded count="1" />
       </getlib>
  -    <assert-downloaded/>
       <getlib>
         <mavenrepository/>
  +      <assertdownloaded count="0" />
       </getlib>
     </target>
   
     <target name="testIf" depends="init">
  -    <property name="trueProp" value="true" />
       <gl1>
         <mavenrepository/>
         <library archive="commons-logging" project="commons-logging" 
version="1.0.1"
  -        if="trueProp"/>
  +        enabled="true"/>
       </gl1>
       <assert-downloaded/>
     </target>
  @@ -139,7 +145,7 @@
       <gl1>
         <mavenrepository/>
         <library archive="commons-logging" project="commons-logging" 
version="1.0.1"
  -        if="undefinedProp"/>
  +        enabled="false"/>
       </gl1>
       <assert-not-downloaded/>
     </target>
  @@ -164,5 +170,91 @@
       </getlib>
       <assert-downloaded/>
     </target>
  +  
  +  <target name="testSchedule" depends="init">
  +    <getlib >
  +      <mavenrepository/>
  +      <schedule days="1" markerFile="${lib.dir}/marker.txt"/>
  +      <assertdownloaded count="1" />
  +    </getlib>
  +    <getlib >
  +      <mavenrepository/>
  +      <schedule days="1" markerFile="${lib.dir}/marker.txt"/>
  +      <assertdownloaded count="0" />
  +    </getlib>
  +  </target>
  +
  +  <target name="testForceEnabled" depends="init">
  +    <getlib>
  +      <mavenrepository/>
  +      <force enabled="true" />
  +      <assertdownloaded count="1" />
  +    </getlib>
  +    <getlib>
  +      <mavenrepository/>
  +      <force enabled="true" />
  +      <assertdownloaded count="1" />
  +    </getlib>    
  +  </target>
  +
  +  <target name="testForceDisabled" depends="init">
  +    <getlib>
  +      <mavenrepository/>
  +      <force enabled="true" />
  +      <assertdownloaded count="1" />
  +    </getlib>
  +    <getlib >
  +      <mavenrepository/>
  +      <force enabled="false" />
  +      <assertdownloaded count="0" />
  +    </getlib>
  +  </target>
  +
  +  <target name="testAbsentFiles" depends="init">
  +    <getlib >
  +      <mavenrepository/>
  +      <absentfiles enabled="true" />
  +      <assertdownloaded count="1" />
  +    </getlib>
  +  </target>
  +
  +  <target name="testAbsentFilesTwice" depends="testAbsentFiles">
  +    <getlib >
  +      <mavenrepository/>
  +      <absentfiles enabled="true" />
  +      <assertdownloaded count="0" />
  +    </getlib>
  +  </target>
  +
  +  <target name="testNoUpdate" depends="init">
  +    <getlib >
  +      <mavenrepository/>
  +      <force />
  +      <noupdate />
  +      <assertdownloaded count="0" />
  +    </getlib>
  +  </target>
  +
  +  <target name="testTimestamp" depends="testAbsentFiles">
  +    <getlib >
  +      <mavenrepository/>
  +      <timestamp />
  +      <assertdownloaded count="0" />
  +    </getlib>
  +  </target>
  +
  +  <target name="testAssertDownloadedCountSet" depends="init">
  +    <getlib>
  +      <mavenrepository/>
  +      <assertdownloaded />
  +    </getlib>
  +  </target>
  +
  +  <target name="testAssertDownloadedCountTested" depends="init">
  +    <getlib>
  +      <mavenrepository/>
  +      <assertdownloaded count="152" />
  +    </getlib>
  +  </target>  
   </project>
   
  
  
  
  1.5       +63 -4     
ant/src/testcases/org/apache/tools/ant/taskdefs/optional/repository/GetLibrariesTest.java
  
  Index: GetLibrariesTest.java
  ===================================================================
  RCS file: 
/home/cvs/ant/src/testcases/org/apache/tools/ant/taskdefs/optional/repository/GetLibrariesTest.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- GetLibrariesTest.java     2 Nov 2004 23:37:21 -0000       1.4
  +++ GetLibrariesTest.java     18 Nov 2004 16:00:18 -0000      1.5
  @@ -17,6 +17,7 @@
   package org.apache.tools.ant.taskdefs.optional.repository;
   
   import org.apache.tools.ant.BuildFileTest;
  +import org.apache.tools.ant.taskdefs.repository.AssertDownloaded;
   
   /**
    * test the test libraries stuff.
  @@ -75,6 +76,10 @@
           execIfOnline(targetName);
       }
   
  +    /**
  +     * exec a target, but only if we are online
  +     * @param targetName
  +     */
       private void execIfOnline(String targetName) {
           if (offline()) {
               return;
  @@ -83,15 +88,28 @@
       }
   
       public void testTwoRepositories() {
  -        expectBuildException("testTwoRepositories", 
GetLibraries.ERROR_ONE_REPOSITORY_ONLY);
  +        expectBuildException("testTwoRepositories",
  +                GetLibraries.ERROR_ONE_REPOSITORY_ONLY);
       }
   
       public void testMavenInlineBadURL() {
  +        expectExceptionIfOnline("testMavenInlineBadURL",
  +                "testMavenInlineBadURL",
  +                GetLibraries.ERROR_INCOMPLETE_RETRIEVAL);
  +    }
  +
  +    /**
  +     * exec a target if we are online; expect an eception
  +     * @param target
  +     * @param cause caue of the faule
  +     * @param message
  +     */
  +    private void expectExceptionIfOnline(String target, String cause,String 
message) {
           if (offline()) {
               return;
           }
  -        expectBuildException("testTwoRepositories",
  -                GetLibraries.ERROR_INCOMPLETE_RETRIEVAL);
  +        expectBuildExceptionContaining(target,cause,
  +                message);
       }
   
       public void testRenaming() {
  @@ -119,4 +137,45 @@
           execIfOnline("testSecurity");
       }
   
  - }
  +    public void testSchedule() {
  +        execIfOnline("testSchedule");
  +    }
  +
  +    public void testForceEnabled() {
  +        execIfOnline("testForceEnabled");
  +    }
  +
  +    public void testForceDisabled() {
  +        execIfOnline("testForceDisabled");
  +    }
  +
  +    public void testAbsentFiles() {
  +        execIfOnline("testAbsentFiles");
  +    }
  +
  +    public void testAbsentFilesTwice() {
  +        execIfOnline("testAbsentFilesTwice");
  +    }
  +
  +    public void testNoUpdate() {
  +        expectExceptionIfOnline("testNoUpdate",
  +                "update disabled; dest file missing",
  +                GetLibraries.ERROR_INCOMPLETE_RETRIEVAL);
  +    }
  +
  +    public void testTimestamp() {
  +        execIfOnline("testTimestamp");
  +    }
  +
  +    public void testAssertDownloadedCountSet() {
  +        expectExceptionIfOnline("testAssertDownloadedCountSet",
  +                "No count in assertdownloaded",
  +                AssertDownloaded.ERROR_NO_COUNT);
  +    }
  +
  +    public void testAssertDownloadedCountTested() {
  +        expectExceptionIfOnline("testAssertDownloadedCountTested",
  +                "Wrong count in assertdownloaded",
  +                AssertDownloaded.ERROR_DOWNLOAD_FAILURE);
  +    }
  +}
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElement.java
  
  Index: EnabledLibraryElement.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.repository;
  
  /**
   * This is for any element that is enabled
   */
  public interface EnabledLibraryElement {
      /**
       * turn element on/off
       * @param enabled
       */
      void setEnabled(boolean enabled);
  
      /**
       * get the current enablement flag
       * @return
       */
      boolean getEnabled();
  }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/repository/ScheduledUpdatePolicy.java
  
  Index: ScheduledUpdatePolicy.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.repository;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.taskdefs.optional.repository.GetLibraries;
  import org.apache.tools.ant.taskdefs.optional.repository.Library;
  import org.apache.tools.ant.taskdefs.optional.repository.Repository;
  import org.apache.tools.ant.util.FileUtils;
  
  import java.io.BufferedInputStream;
  import java.io.BufferedOutputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.util.Iterator;
  import java.util.ListIterator;
  import java.util.Properties;
  
  /**
   * This [EMAIL PROTECTED] 
org.apache.tools.ant.taskdefs.repository.LibraryPolicy} updates the files only 
when the schedule
   * indicates that it should.
   * <p/>
   * The default interval is eleven hours; it's prime, it encourages
   * regular but not excessive days.
   * <p/>
   * It requires a marker file which is used to save a list of all files
   * that were saved. If anything in the list of files changes then the
   * update is triggered again.
   */
  public class ScheduledUpdatePolicy extends BaseLibraryPolicy  {
      private File markerFile;
      private int hours=17;
      private int days=0;
  
      /**
       * if not null, this means that we have a marker file to save
       */
      private Properties markerFileToSave;
  
      public static final String ERROR_NO_MARKER_FILE = "No marker file";
      public static final String MARKER_MISMATCH = "No match between last 
update and current one";
      public static final String INTERVAL_TRIGGERS_UPDATE = "Interval between 
updates is long; updating";
      public static final String INTERVAL_SHORT_NO_UPDATE = "Interval between 
updates is short; no update";
  
  
      public File getMarkerFile() {
          return markerFile;
      }
  
      /**
       * set a file that stores the history of the operation
       * @param markerFile
       */
      public void setMarkerFile(File markerFile) {
          this.markerFile = markerFile;
      }
  
      public int getHours() {
          return hours;
      }
  
      /**
       * set the interval between updates in hours
       * @param hours
       */
      public void setHours(int hours) {
          this.hours = hours;
      }
  
      public int getDays() {
          return days;
      }
  
      /**
       * set the interval between updates in days.
       * @param days
       */
      public void setDays(int days) {
          this.days = days;
      }
  
      /**
       * get the refresh interval in milliseconds
       * @return
       */
      public long getInterval() {
          return ((days*24)+hours)*60*60000;
      }
  
  
      /**
       * Method called before we connect
       *
       * @param owner
       *
       * @param libraries
       * @return true if the connection is to go ahead
       *
       * @throws org.apache.tools.ant.BuildException
       *          if needed
       */
      public boolean beforeConnect(GetLibraries owner, ListIterator libraries) {
  
          Repository repository=owner.getRepository();
          if(markerFile==null) {
              throw new BuildException(ERROR_NO_MARKER_FILE);
          }
          Properties now = makeProperties(owner.enabledLibrariesIterator(), 
repository);
          try {
              if(markerFile.exists()) {
                  long timestamp=markerFile.lastModified();
                  Properties then=loadMarkerFile();
                  long currentTime=System.currentTimeMillis();
                  long diff=currentTime-timestamp;
                  if(now.equals(then)) {
                      if(diff<getInterval()) {
                          owner.log(INTERVAL_SHORT_NO_UPDATE,
                                  Project.MSG_VERBOSE);
                          return false;
                      } else {
                          owner.log(INTERVAL_TRIGGERS_UPDATE,
                                  Project.MSG_VERBOSE);
                          return true;
                      }
                  } else {
                      owner.log(MARKER_MISMATCH,
                              Project.MSG_VERBOSE);
                  }
              } else {
                  owner.log("Marker file not found", Project.MSG_VERBOSE);
              }
              markerFileToSave = now;
              return true;
          } catch (IOException e) {
              throw new BuildException("Marker file 
"+markerFile.getAbsolutePath()+" access failed",e);
          }
      }
  
      /**
       * method called after a (nominally successful fetch)
       *
       * @param owner
       * @param libraries
       */
      public void afterFetched(GetLibraries owner, ListIterator libraries) {
  
          if(markerFileToSave!=null) {
              //if we get here, we need to save the file
              try {
                  saveMarkerFile(markerFileToSave);
              } catch (IOException e) {
                  throw new BuildException("Failed to save marker file "
                          +markerFile,
                          e);
              }
          } else {
              //touch the file anyway
              markerFile.setLastModified(System.currentTimeMillis());
          }
  
      }
  
      /**
       * make a properties file from the library list
       * @param libraries iterator of type Library.
       * @return a new properties file
       */
      protected Properties makeProperties(Iterator libraries, Repository 
repository) {
          Properties props=new Properties();
          int counter=1;
          while (libraries.hasNext()) {
              Library library = (Library) libraries.next();
              String name=makeEntry(library);
              props.put(Integer.toString(counter),name);
          }
          props.put("repository",repository.getRepositoryURI());
          return props;
      }
  
      /**
       * save a property file to disk.
       * @param props
       * @throws IOException
       */
      protected void saveMarkerFile(Properties props)
              throws IOException {
          markerFile.getParentFile().mkdirs();
          OutputStream out= new BufferedOutputStream(new 
FileOutputStream(markerFile));
          try {
              props.store(out,null);
          } finally {
              FileUtils.close(out);
          }
      }
  
      /**
       * Load an input stream
       * @return
       * @throws IOException
       */
      protected Properties loadMarkerFile() throws IOException {
          Properties props=new Properties();
          InputStream in=new BufferedInputStream(new 
FileInputStream(markerFile));
          try {
              props.load(in);
              return props;
          } finally {
              FileUtils.close(in);
          }
      }
  
  
  
  
      /**
       * make an entry for the properties file
       * @param lib
       * @return
       */
      protected String makeEntry(Library lib) {
          return lib.getMavenPath('/')+"//"+lib.getNormalFilename();
      }
  }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElementList.java
  
  Index: EnabledLibraryElementList.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.repository;
  
  import java.util.Collection;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.NoSuchElementException;
  
  /**
   * List with an enablement iterator.
   */
  public class EnabledLibraryElementList extends LinkedList {
  
      /**
       * Constructs an empty list.
       */
      public EnabledLibraryElementList() {
      }
  
      /**
       * return an iterator that only iterates over enabled stuff
       * @return
       */
      public Iterator enabledIterator() {
          return new EnabledIterator(this);
      }
  
      /**
       * iterator through a list that skips everything that is not enabled
       */
      private static class EnabledIterator implements Iterator {
          private Iterator _underlyingIterator;
          private EnabledLibraryElement _next;
  
  
          /**
           * constructor
           *
           * @param collection
           */
          EnabledIterator(Collection collection) {
              _underlyingIterator = collection.iterator();
          }
  
  
          /**
           * test for having another enabled component
           *
           * @return
           */
          public boolean hasNext() {
              while (_next == null && _underlyingIterator.hasNext()) {
                  EnabledLibraryElement candidate = (EnabledLibraryElement) 
_underlyingIterator.next();
                  if (candidate.getEnabled()) {
                      _next = candidate;
                  }
              }
              return (_next != null);
          }
  
          /**
           * get the next element
           *
           * @return
           */
          public Object next() {
              if (!hasNext()) {
                  throw new NoSuchElementException();
              }
              EnabledLibraryElement result = _next;
              _next = null;
              return result;
          }
  
          /**
           * removal is not supported
           *
           * @throws UnsupportedOperationException always
           */
          public void remove() {
              throw new UnsupportedOperationException();
          }
      }
  
  }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/repository/AbsentFilesPolicy.java
  
  Index: AbsentFilesPolicy.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.repository;
  
  import org.apache.tools.ant.taskdefs.optional.repository.GetLibraries;
  
  import java.util.ListIterator;
  
  /**
   * This policy only marks absent(enabled) files.
   */
  public class AbsentFilesPolicy extends BaseLibraryPolicy {
  
      /**
       * Tell owner to mark all missing libraries as fetchable
       *
       * @param owner
       * @param libraries
       *
       * @return true if the connection is to go ahead
       *
       * @throws org.apache.tools.ant.BuildException
       *          if needed
       */
      public boolean beforeConnect(GetLibraries owner, ListIterator libraries) {
          owner.markMissingLibrariesForFetch();
          return true;
      }
  }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/repository/TimestampPolicy.java
  
  Index: TimestampPolicy.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.repository;
  
  import org.apache.tools.ant.taskdefs.optional.repository.GetLibraries;
  
  import java.util.ListIterator;
  
  /**
   * Mark all files for fetching, but timestamp driven
   * This will only update changed files. Unlike [EMAIL PROTECTED] 
ForceUpdatePolicy},
   * there is no post-download verification that everything got fetched
   */
  public class TimestampPolicy extends BaseLibraryPolicy {
  
      /**
       * Method called before we connect. Caller can manipulate the list,
       *
       * @param owner
       * @param libraries
       *
       * @return true if the connection is to go ahead
       *
       * @throws org.apache.tools.ant.BuildException
       *          if needed
       */
      public boolean beforeConnect(GetLibraries owner, ListIterator libraries) {
          owner.markAllLibrariesForFetch(true);
          owner._setUseTimestamp(true);
          return true;
      }
  
  }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/repository/BaseLibraryPolicy.java
  
  Index: BaseLibraryPolicy.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.repository;
  
  import org.apache.tools.ant.taskdefs.optional.repository.GetLibraries;
  
  import java.util.ListIterator;
  
  /**
   */
  public abstract class BaseLibraryPolicy implements LibraryPolicy {
  
      /**
       * enabled flag
       */
      private boolean enabled=true;
  
      /**
       * turn policy on/off
       *
       * @param enabled
       */
      public void setEnabled(boolean enabled) {
          this.enabled = enabled;
      }
  
      /**
       * are we enabled
       * @return true if [EMAIL PROTECTED] #enabled} is set
       */
      public boolean getEnabled() {
          return enabled;
      }
  
      /**
       * Method called before we connect. Caller can manipulate the list,
       *
       * @param owner
       * @param libraries
       *
       * @return true if the connection is to go ahead
       *
       * @throws org.apache.tools.ant.BuildException
       *          if needed
       */
      public boolean beforeConnect(GetLibraries owner, ListIterator libraries) {
          return true;
      }
  
      /**
       * method called after a successful connection process.
       *
       * @param owner
       * @param libraries
       *
       * @throws org.apache.tools.ant.BuildException
       *
       */
      public void afterFetched(GetLibraries owner, ListIterator libraries) {
  
      }
  }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/repository/LibraryPolicy.java
  
  Index: LibraryPolicy.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  
  package org.apache.tools.ant.taskdefs.repository;
  
  import org.apache.tools.ant.taskdefs.optional.repository.GetLibraries;
  
  import java.util.ListIterator;
  
  /**
   * An interface that things can support to change the library behaviour.
   * Example uses could be: extra validation (signatures, etc), filename 
remapping
   * 
   *
   * Here is the use
   * <ol>
   * <li>Policies are executed in order of declaration.
   * <li>The [EMAIL PROTECTED] 
#beforeConnect(org.apache.tools.ant.taskdefs.optional.repository.GetLibraries, 
java.util.ListIterator)} call,
   * is called before any connection has been initiated; policies can manipulate
   * the library list, set/reset their toFetch list, rename destination files, 
etc.
   * <li>If any policy returns false from the method, the connection does not 
proceed.
   * This is not an error, provided the files are actually present.
   * <li>After running through the fetch of all files marked for download,
   * every policy implementation will again be called in order of declaration.
   * <li>The [EMAIL PROTECTED] 
#afterFetched(org.apache.tools.ant.taskdefs.optional.repository.GetLibraries, 
java.util.ListIterator)} method
   * does not return anything.
   * <li>Either method can throw a BuildException to indicate some kind of 
error.
   * </ol>
   *
   */
  public interface LibraryPolicy extends EnabledLibraryElement {
  
  
      /**
       * Method called before we connect. Caller can manipulate the list,
       * 
       *
       * @param owner
       *
       * @param libraries
       * @return true if the connection is to go ahead
       *
       * @throws org.apache.tools.ant.BuildException
       *          if needed
       */
      public boolean beforeConnect(GetLibraries owner, ListIterator libraries);
  
      /**
       * method called after a successful connection process.
       * @param owner
       * @param libraries
       * @throws org.apache.tools.ant.BuildException
       */
      public void afterFetched(GetLibraries owner,ListIterator libraries);
  
  
  }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/repository/ForceUpdatePolicy.java
  
  Index: ForceUpdatePolicy.java
  ===================================================================
  /*
  * Copyright  2004 The Apache Software Foundation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *  You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
  *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
  */
  package org.apache.tools.ant.taskdefs.repository;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.taskdefs.optional.repository.GetLibraries;
  import org.apache.tools.ant.taskdefs.optional.repository.Library;
  
  import java.util.Iterator;
  import java.util.ListIterator;
  
  /**
   * This update policy marks all libraries for download.
   * After downloading, it will raise an error if any one of the files was not
   * retrieved.
   */
  public class ForceUpdatePolicy extends BaseLibraryPolicy {
      public static final String ERROR_FORCED_DOWNLOAD_FAILED = "Failed to 
download file:";
  
  
      public String getName() {
          return "force";
      }
  
      /**
  
       *
       * @param owner
       * @param libraries
       *
       * @return true if the connection is to go ahead
       *
       * @throws org.apache.tools.ant.BuildException
       *          if needed
       */
      public boolean beforeConnect(GetLibraries owner, ListIterator libraries) {
          owner.markAllLibrariesForFetch(true);
          owner._setUseTimestamp(false);
          return true;
      }
  
      /**
       * method called after a successful connection process.
       *
       * @param owner
       * @param libraries
       *
       * @throws org.apache.tools.ant.BuildException
       *
       */
      public void afterFetched(GetLibraries owner, ListIterator libraries) {
          //here verify that everything came in
          Iterator downloaded = owner.enabledLibrariesIterator();
          while (downloaded.hasNext()) {
              Library library = (Library) downloaded.next();
              if (library.isToFetch() && !library.wasFetched()) {
                  throw new BuildException(ERROR_FORCED_DOWNLOAD_FAILED
                          + library.getDestFilename());
              }
          }
      }
  }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/repository/NoUpdatePolicy.java
  
  Index: NoUpdatePolicy.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.repository;
  
  import org.apache.tools.ant.taskdefs.optional.repository.GetLibraries;
  
  import java.util.ListIterator;
  
  /**
   * Reset the fetch bit on all libraries
   */
  public class NoUpdatePolicy extends BaseLibraryPolicy {
  
      /**
       * Method called before we connect. Caller can manipulate the list,
       *
       * @param owner
       * @param libraries
       *
       * @return true if the connection is to go ahead
       *
       * @throws org.apache.tools.ant.BuildException
       *          if needed
       */
      public boolean beforeConnect(GetLibraries owner, ListIterator libraries) {
              // mark all files as no Fetch
          owner.markAllLibrariesForFetch(false);
          return true;
      }
  }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/repository/AssertDownloaded.java
  
  Index: AssertDownloaded.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.repository;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.taskdefs.optional.repository.GetLibraries;
  
  import java.util.ListIterator;
  
  /**
   * This policy is really there for testing the tasks, but you can use
   * it for debugging your own logic.
   */
  public class AssertDownloaded extends BaseLibraryPolicy {
  
      /**
       * our count of files to fetch; null means undefined
       */
      Integer count;
      public static final String ERROR_NO_COUNT = "No count declared";
      public static final String ERROR_DOWNLOAD_FAILURE = "Download count 
mismatch: expected ";
  
      /**
       * set the number of files that must be fetched.
       * It is an error if the count does not match.
       * @param count
       */
      public void setCount(Integer count) {
          this.count = count;
      }
  
      /**
       * Method called before we connect. Caller can manipulate the list,
       *
       * @param owner
       * @param libraries
       *
       * @return true if the connection is to go ahead
       *
       * @throws org.apache.tools.ant.BuildException
       *          if needed
       */
      public boolean beforeConnect(GetLibraries owner, ListIterator libraries) {
          if(count==null) {
              throw new BuildException(ERROR_NO_COUNT);
          }
          return true;
      }
  
      /**
       * method called after a successful connection process.
       *
       * @param owner
       * @param libraries
       *
       * @throws org.apache.tools.ant.BuildException
       *
       */
      public void afterFetched(GetLibraries owner, ListIterator libraries) {
          int fetched=owner.calculateDownloadedCount();
          if(fetched!=count.intValue()) {
              throw new BuildException(ERROR_DOWNLOAD_FAILURE
                      +count
                      +" but fetched "+fetched);
          }
      }
  
  }
  
  
  
  1.45      +6 -5      ant/src/main/org/apache/tools/ant/taskdefs/Get.java
  
  Index: Get.java
  ===================================================================
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/Get.java,v
  retrieving revision 1.44
  retrieving revision 1.45
  diff -u -r1.44 -r1.45
  --- Get.java  2 Nov 2004 23:37:21 -0000       1.44
  +++ Get.java  18 Nov 2004 16:00:18 -0000      1.45
  @@ -17,6 +17,11 @@
   
   package org.apache.tools.ant.taskdefs;
   
  +import org.apache.tools.ant.BuildException;
  +import org.apache.tools.ant.Project;
  +import org.apache.tools.ant.Task;
  +import org.apache.tools.ant.util.FileUtils;
  +
   import java.io.File;
   import java.io.FileOutputStream;
   import java.io.IOException;
  @@ -26,11 +31,6 @@
   import java.net.URL;
   import java.net.URLConnection;
   import java.util.Date;
  -import org.apache.tools.ant.BuildException;
  -import org.apache.tools.ant.Project;
  -import org.apache.tools.ant.Task;
  -import org.apache.tools.ant.util.FileUtils;
  -import org.apache.tools.ant.util.JavaEnvUtils;
   
   /**
    * Gets a particular file from a URL source.
  @@ -115,6 +115,7 @@
               progress = new NullProgress();
           }
           log("Getting: " + source, logLevel);
  +        log("To: " + dest.getAbsolutePath(), logLevel);
   
           //set the timestamp to the file date.
           long timestamp = 0;
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to