diff --git a/src/etc/testcases/taskdefs/optional/getlibraries.xml b/src/etc/testcases/taskdefs/optional/getlibraries.xml
index 105db852f..0e242be02 100644
--- a/src/etc/testcases/taskdefs/optional/getlibraries.xml
+++ b/src/etc/testcases/taskdefs/optional/getlibraries.xml
@@ -7,8 +7,10 @@
-
-
+
+
+
@@ -24,10 +26,11 @@
+
+ file="${@{library}.path}"/>
- Not found: ${lib.dir}@{library}
+ Not found: ${@{library}.path}
@@ -35,20 +38,23 @@
+
+ file="${@{library}.path}"/>
- Found: ${lib.dir}@{library}
+ Found: ${@{library}.path}
-
+
+
+
@@ -99,7 +105,7 @@
-
+
@@ -118,19 +124,19 @@
+
-
+
-
+ enabled="true"/>
@@ -139,7 +145,7 @@
+ enabled="false"/>
@@ -164,5 +170,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/org/apache/tools/ant/taskdefs/Get.java b/src/main/org/apache/tools/ant/taskdefs/Get.java
index 1ac4dc4f6..8e4a356b6 100644
--- a/src/main/org/apache/tools/ant/taskdefs/Get.java
+++ b/src/main/org/apache/tools/ant/taskdefs/Get.java
@@ -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.HttpURLConnection;
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 @@ public class Get extends Task {
progress = new NullProgress();
}
log("Getting: " + source, logLevel);
+ log("To: " + dest.getAbsolutePath(), logLevel);
//set the timestamp to the file date.
long timestamp = 0;
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/repository/GetLibraries.java b/src/main/org/apache/tools/ant/taskdefs/optional/repository/GetLibraries.java
index 031b351cf..05a499303 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/repository/GetLibraries.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/repository/GetLibraries.java
@@ -19,16 +19,23 @@ 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.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.
@@ -39,18 +46,13 @@ import java.util.NoSuchElementException;
* @ant.task
* @since Ant 1.7
*/
-public class GetLibraries extends Task {
+public final class GetLibraries extends Task {
/**
* destination
*/
private File destDir;
- /**
- * flag to force a download
- */
- private boolean forceDownload = false;
-
/**
* flag to force offline
*/
@@ -59,7 +61,12 @@ public class GetLibraries extends Task {
/**
* 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 @@ public class GetLibraries extends Task {
*/
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 @@ public class GetLibraries extends Task {
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 @@ public class GetLibraries extends Task {
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 @@ public class GetLibraries extends Task {
return destDir;
}
- /**
- * get force download flag
- * @return
- */
- public boolean isForceDownload() {
- return forceDownload;
- }
/**
* get the list of libraries
@@ -213,13 +280,39 @@ public class GetLibraries extends Task {
this.pathid = pathid;
}
+ /**
+ * 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 @@ public class GetLibraries extends Task {
library.validate();
}
}
-
/**
* Called by the project to let the task do its work.
*
@@ -240,25 +332,90 @@ public class GetLibraries extends Task {
*/
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 @@ public class GetLibraries extends Task {
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
+ * {@link 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 @@ public class GetLibraries extends Task {
*/
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 @@ public class GetLibraries extends Task {
* 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();
}
-
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/repository/HttpRepository.java b/src/main/org/apache/tools/ant/taskdefs/optional/repository/HttpRepository.java
index ac28c00e5..ca88acb26 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/repository/HttpRepository.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/repository/HttpRepository.java
@@ -68,8 +68,6 @@ public abstract class HttpRepository extends Repository {
* 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 @@ public abstract class HttpRepository extends Repository {
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 @@ public abstract class HttpRepository extends Repository {
*
* @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 @@ public abstract class HttpRepository extends Repository {
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 abstract class HttpRepository extends Repository {
*/
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 @@ public abstract class HttpRepository extends Repository {
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 across instances.
*
- * @return the base URL
+ * @return
*/
- public String toString() {
- return "Repository at " + getUrl();
+ public String getRepositoryURI() {
+ return "HttpRepository://"+getUrl();
}
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/repository/Library.java b/src/main/org/apache/tools/ant/taskdefs/optional/repository/Library.java
index da34ac033..30258431e 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/repository/Library.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/repository/Library.java
@@ -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 @@ import java.io.File;
*
* @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 {@link #enabled} is set
+ */
+ public boolean getEnabled() {
+ return enabled;
+ }
//project "ant"
private String project;
@@ -52,14 +76,12 @@ public class Library {
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 @@ public class Library {
* suffix
*/
private String suffix = "jar";
+ public static final String ERROR_FILE_IS_A_DIR = "Library file is a directory:";
/**
@@ -154,38 +177,6 @@ public class Library {
this.suffix = suffix;
}
- /**
- * 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)
@@ -195,6 +186,14 @@ public class Library {
return libraryFile;
}
+ /**
+ * set the library file.
+ * @param libraryFile
+ */
+ public void setLibraryFile(File libraryFile) {
+ this.libraryFile = libraryFile;
+ }
+
/**
* fault if the field is null or empty
*
@@ -241,10 +240,16 @@ public class Library {
*/
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 @@ public class Library {
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 @@ public class Library {
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 {@link #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;
+ }
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/repository/MavenRepository.java b/src/main/org/apache/tools/ant/taskdefs/optional/repository/MavenRepository.java
index ea0ff1531..288152e3d 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/repository/MavenRepository.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/repository/MavenRepository.java
@@ -19,10 +19,9 @@ package org.apache.tools.ant.taskdefs.optional.repository;
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;
@@ -90,18 +89,29 @@ public class MavenRepository extends HttpRepository {
return "Maven Repository at " + getUrl();
}
+ /**
+ * this is a string that uniquely describes the repository and can be used
+ * for equality tests across 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 @@ public class MavenRepository extends HttpRepository {
}
}
-
-// e1b1720a761ca36eaa47e1c7d802e676
\ No newline at end of file
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/repository/Repository.java b/src/main/org/apache/tools/ant/taskdefs/optional/repository/Repository.java
index edcf550f0..56b69b3a5 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/repository/Repository.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/repository/Repository.java
@@ -99,11 +99,18 @@ public abstract class Repository extends DataType {
/**
* 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 across instances.
+ * @return
+ */
+ public abstract String getRepositoryURI();
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/repository/RepositoryRef.java b/src/main/org/apache/tools/ant/taskdefs/optional/repository/RepositoryRef.java
index b1c4ef404..d2d750c33 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/repository/RepositoryRef.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/repository/RepositoryRef.java
@@ -70,10 +70,20 @@ public final class RepositoryRef extends Repository {
*
* @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 across instances.
+ *
+ * @return
+ */
+ public String getRepositoryURI() {
+ return "ref://"+getRefid();
+ }
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/repository/AbsentFilesPolicy.java b/src/main/org/apache/tools/ant/taskdefs/repository/AbsentFilesPolicy.java
new file mode 100644
index 000000000..4a7c8b539
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/repository/AbsentFilesPolicy.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/repository/AssertDownloaded.java b/src/main/org/apache/tools/ant/taskdefs/repository/AssertDownloaded.java
new file mode 100644
index 000000000..9fe5bae25
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/repository/AssertDownloaded.java
@@ -0,0 +1,82 @@
+/*
+ * 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);
+ }
+ }
+
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/repository/BaseLibraryPolicy.java b/src/main/org/apache/tools/ant/taskdefs/repository/BaseLibraryPolicy.java
new file mode 100644
index 000000000..bb70dbb3e
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/repository/BaseLibraryPolicy.java
@@ -0,0 +1,76 @@
+/*
+ * 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 {@link #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) {
+
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElement.java b/src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElement.java
new file mode 100644
index 000000000..1da661eeb
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElement.java
@@ -0,0 +1,34 @@
+/*
+ * 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();
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElementList.java b/src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElementList.java
new file mode 100644
index 000000000..ff5168018
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElementList.java
@@ -0,0 +1,100 @@
+/*
+ * 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();
+ }
+ }
+
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/repository/ForceUpdatePolicy.java b/src/main/org/apache/tools/ant/taskdefs/repository/ForceUpdatePolicy.java
new file mode 100644
index 000000000..38d677f2b
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/repository/ForceUpdatePolicy.java
@@ -0,0 +1,76 @@
+/*
+* 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());
+ }
+ }
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/repository/LibraryPolicy.java b/src/main/org/apache/tools/ant/taskdefs/repository/LibraryPolicy.java
new file mode 100644
index 000000000..b0facedb1
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/repository/LibraryPolicy.java
@@ -0,0 +1,71 @@
+/*
+ * 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
+ *
+ * - Policies are executed in order of declaration.
+ *
- The {@link #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.
+ *
- If any policy returns false from the method, the connection does not proceed.
+ * This is not an error, provided the files are actually present.
+ *
- After running through the fetch of all files marked for download,
+ * every policy implementation will again be called in order of declaration.
+ *
- The {@link #afterFetched(org.apache.tools.ant.taskdefs.optional.repository.GetLibraries, java.util.ListIterator)} method
+ * does not return anything.
+ *
- Either method can throw a BuildException to indicate some kind of error.
+ *
+ *
+ */
+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);
+
+
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/repository/NoUpdatePolicy.java b/src/main/org/apache/tools/ant/taskdefs/repository/NoUpdatePolicy.java
new file mode 100644
index 000000000..7c5d0adaf
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/repository/NoUpdatePolicy.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+ }
+}
diff --git a/src/main/org/apache/tools/ant/taskdefs/repository/ScheduledUpdatePolicy.java b/src/main/org/apache/tools/ant/taskdefs/repository/ScheduledUpdatePolicy.java
new file mode 100644
index 000000000..6fef41d5b
--- /dev/null
+++ b/src/main/org/apache/tools/ant/taskdefs/repository/ScheduledUpdatePolicy.java
@@ -0,0 +1,242 @@
+/*
+ * 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 {@link org.apache.tools.ant.taskdefs.repository.LibraryPolicy} updates the files only when the schedule
+ * indicates that it should.
+ *
+ * The default interval is eleven hours; it's prime, it encourages
+ * regular but not excessive days.
+ *
+ * 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