Browse Source

Updated <getlibraries> code, plus new classes. After this

checkin I'm about to move and rename some of the existing stuff.


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@277053 13f79535-47bb-0310-9956-ffa450edef68
master
Steve Loughran 20 years ago
parent
commit
f630ef56ed
19 changed files with 1460 additions and 277 deletions
  1. +104
    -12
      src/etc/testcases/taskdefs/optional/getlibraries.xml
  2. +6
    -5
      src/main/org/apache/tools/ant/taskdefs/Get.java
  3. +293
    -131
      src/main/org/apache/tools/ant/taskdefs/optional/repository/GetLibraries.java
  4. +19
    -64
      src/main/org/apache/tools/ant/taskdefs/optional/repository/HttpRepository.java
  5. +126
    -52
      src/main/org/apache/tools/ant/taskdefs/optional/repository/Library.java
  6. +14
    -6
      src/main/org/apache/tools/ant/taskdefs/optional/repository/MavenRepository.java
  7. +9
    -2
      src/main/org/apache/tools/ant/taskdefs/optional/repository/Repository.java
  8. +11
    -1
      src/main/org/apache/tools/ant/taskdefs/optional/repository/RepositoryRef.java
  9. +43
    -0
      src/main/org/apache/tools/ant/taskdefs/repository/AbsentFilesPolicy.java
  10. +82
    -0
      src/main/org/apache/tools/ant/taskdefs/repository/AssertDownloaded.java
  11. +76
    -0
      src/main/org/apache/tools/ant/taskdefs/repository/BaseLibraryPolicy.java
  12. +34
    -0
      src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElement.java
  13. +100
    -0
      src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElementList.java
  14. +76
    -0
      src/main/org/apache/tools/ant/taskdefs/repository/ForceUpdatePolicy.java
  15. +71
    -0
      src/main/org/apache/tools/ant/taskdefs/repository/LibraryPolicy.java
  16. +44
    -0
      src/main/org/apache/tools/ant/taskdefs/repository/NoUpdatePolicy.java
  17. +242
    -0
      src/main/org/apache/tools/ant/taskdefs/repository/ScheduledUpdatePolicy.java
  18. +47
    -0
      src/main/org/apache/tools/ant/taskdefs/repository/TimestampPolicy.java
  19. +63
    -4
      src/testcases/org/apache/tools/ant/taskdefs/optional/repository/GetLibrariesTest.java

+ 104
- 12
src/etc/testcases/taskdefs/optional/getlibraries.xml View File

@@ -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="${@{library}.path}"/>
<fail unless="@{library}.exists">
Not found: ${lib.dir}@{library}
Not found: ${@{library}.path}
</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="${@{library}.path}"/>
<fail if="@{library}.exists">
Found: ${lib.dir}@{library}
Found: ${@{library}.path}
</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>


+ 6
- 5
src/main/org/apache/tools/ant/taskdefs/Get.java View File

@@ -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;


+ 293
- 131
src/main/org/apache/tools/ant/taskdefs/optional/repository/GetLibraries.java View File

@@ -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. <ol>
@@ -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();
}


}

+ 19
- 64
src/main/org/apache/tools/ant/taskdefs/optional/repository/HttpRepository.java View File

@@ -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 <i>across</i> instances.
*
* @return the base URL
* @return
*/
public String toString() {
return "Repository at " + getUrl();
public String getRepositoryURI() {
return "HttpRepository://"+getUrl();
}
}

+ 126
- 52
src/main/org/apache/tools/ant/taskdefs/optional/repository/Library.java View File

@@ -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;
}

}

+ 14
- 6
src/main/org/apache/tools/ant/taskdefs/optional/repository/MavenRepository.java View File

@@ -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 <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 @@ public class MavenRepository extends HttpRepository {
}

}

// e1b1720a761ca36eaa47e1c7d802e676

+ 9
- 2
src/main/org/apache/tools/ant/taskdefs/optional/repository/Repository.java View File

@@ -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 <i>across</i> instances.
* @return
*/
public abstract String getRepositoryURI();
}

+ 11
- 1
src/main/org/apache/tools/ant/taskdefs/optional/repository/RepositoryRef.java View File

@@ -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 <i>across</i> instances.
*
* @return
*/
public String getRepositoryURI() {
return "ref://"+getRefid();
}
}

+ 43
- 0
src/main/org/apache/tools/ant/taskdefs/repository/AbsentFilesPolicy.java View File

@@ -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;
}
}

+ 82
- 0
src/main/org/apache/tools/ant/taskdefs/repository/AssertDownloaded.java View File

@@ -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);
}
}

}

+ 76
- 0
src/main/org/apache/tools/ant/taskdefs/repository/BaseLibraryPolicy.java View File

@@ -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) {

}
}

+ 34
- 0
src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElement.java View File

@@ -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();
}

+ 100
- 0
src/main/org/apache/tools/ant/taskdefs/repository/EnabledLibraryElementList.java View File

@@ -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();
}
}

}

+ 76
- 0
src/main/org/apache/tools/ant/taskdefs/repository/ForceUpdatePolicy.java View File

@@ -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());
}
}
}
}

+ 71
- 0
src/main/org/apache/tools/ant/taskdefs/repository/LibraryPolicy.java View File

@@ -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
* <ol>
* <li>Policies are executed in order of declaration.
* <li>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.
* <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 {@link #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);


}

+ 44
- 0
src/main/org/apache/tools/ant/taskdefs/repository/NoUpdatePolicy.java View File

@@ -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;
}
}

+ 242
- 0
src/main/org/apache/tools/ant/taskdefs/repository/ScheduledUpdatePolicy.java View File

@@ -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.
* <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();
}
}

+ 47
- 0
src/main/org/apache/tools/ant/taskdefs/repository/TimestampPolicy.java View File

@@ -0,0 +1,47 @@
/*
* 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 {@link 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;
}

}

+ 63
- 4
src/testcases/org/apache/tools/ant/taskdefs/optional/repository/GetLibrariesTest.java View File

@@ -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 @@ public class GetLibrariesTest extends BuildFileTest {
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 class GetLibrariesTest extends BuildFileTest {
}

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 @@ public class GetLibrariesTest extends BuildFileTest {
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);
}
}

Loading…
Cancel
Save