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-ffa450edef68master
| @@ -7,8 +7,10 @@ | |||||
| <target name="init"> | <target name="init"> | ||||
| <property name="lib.dir" value="getlib"/> | <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"> | <presetdef name="gl1"> | ||||
| <getlibraries destDir="${lib.dir}"> | <getlibraries destDir="${lib.dir}"> | ||||
| @@ -24,10 +26,11 @@ | |||||
| <macrodef name="assert-downloaded"> | <macrodef name="assert-downloaded"> | ||||
| <attribute name="library" default="${commons.logging}"/> | <attribute name="library" default="${commons.logging}"/> | ||||
| <sequential> | <sequential> | ||||
| <property name="@{library}.path" location="${lib.dir}/@{library}" /> | |||||
| <available property="@{library}.exists" | <available property="@{library}.exists" | ||||
| file="${lib.dir}/@{library}"/> | |||||
| file="${@{library}.path}"/> | |||||
| <fail unless="@{library}.exists"> | <fail unless="@{library}.exists"> | ||||
| Not found: ${lib.dir}@{library} | |||||
| Not found: ${@{library}.path} | |||||
| </fail> | </fail> | ||||
| </sequential> | </sequential> | ||||
| </macrodef> | </macrodef> | ||||
| @@ -35,20 +38,23 @@ | |||||
| <macrodef name="assert-not-downloaded"> | <macrodef name="assert-not-downloaded"> | ||||
| <attribute name="library" default="${commons.logging}"/> | <attribute name="library" default="${commons.logging}"/> | ||||
| <sequential> | <sequential> | ||||
| <property name="@{library}.path" location="${lib.dir}/@{library}" /> | |||||
| <available property="@{library}.exists" | <available property="@{library}.exists" | ||||
| file="${lib.dir}/@{library}"/> | |||||
| file="${@{library}.path}"/> | |||||
| <fail if="@{library}.exists"> | <fail if="@{library}.exists"> | ||||
| Found: ${lib.dir}@{library} | |||||
| Found: ${@{library}.path} | |||||
| </fail> | </fail> | ||||
| </sequential> | </sequential> | ||||
| </macrodef> | </macrodef> | ||||
| </target> | </target> | ||||
| <target name="cleanup"> | |||||
| <target name="cleanup" depends="init"> | |||||
| <delete dir="${lib.dir}"/> | <delete dir="${lib.dir}"/> | ||||
| </target> | </target> | ||||
| <target name="teardown" depends="cleanup"/> | |||||
| <target name="testEmpty" depends="init"> | <target name="testEmpty" depends="init"> | ||||
| <getlibraries/> | <getlibraries/> | ||||
| </target> | </target> | ||||
| @@ -99,7 +105,7 @@ | |||||
| <target name="testMavenInlineBadURL" depends="init"> | <target name="testMavenInlineBadURL" depends="init"> | ||||
| <getlib> | <getlib> | ||||
| <mavenrepository url="http://invalid.example.org"/> | |||||
| </getlib> | </getlib> | ||||
| </target> | </target> | ||||
| @@ -118,19 +124,19 @@ | |||||
| <target name="testOverwrite" depends="init"> | <target name="testOverwrite" depends="init"> | ||||
| <getlib> | <getlib> | ||||
| <mavenrepository/> | <mavenrepository/> | ||||
| <assertdownloaded count="1" /> | |||||
| </getlib> | </getlib> | ||||
| <assert-downloaded/> | |||||
| <getlib> | <getlib> | ||||
| <mavenrepository/> | <mavenrepository/> | ||||
| <assertdownloaded count="0" /> | |||||
| </getlib> | </getlib> | ||||
| </target> | </target> | ||||
| <target name="testIf" depends="init"> | <target name="testIf" depends="init"> | ||||
| <property name="trueProp" value="true" /> | |||||
| <gl1> | <gl1> | ||||
| <mavenrepository/> | <mavenrepository/> | ||||
| <library archive="commons-logging" project="commons-logging" version="1.0.1" | <library archive="commons-logging" project="commons-logging" version="1.0.1" | ||||
| if="trueProp"/> | |||||
| enabled="true"/> | |||||
| </gl1> | </gl1> | ||||
| <assert-downloaded/> | <assert-downloaded/> | ||||
| </target> | </target> | ||||
| @@ -139,7 +145,7 @@ | |||||
| <gl1> | <gl1> | ||||
| <mavenrepository/> | <mavenrepository/> | ||||
| <library archive="commons-logging" project="commons-logging" version="1.0.1" | <library archive="commons-logging" project="commons-logging" version="1.0.1" | ||||
| if="undefinedProp"/> | |||||
| enabled="false"/> | |||||
| </gl1> | </gl1> | ||||
| <assert-not-downloaded/> | <assert-not-downloaded/> | ||||
| </target> | </target> | ||||
| @@ -164,5 +170,91 @@ | |||||
| </getlib> | </getlib> | ||||
| <assert-downloaded/> | <assert-downloaded/> | ||||
| </target> | </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> | </project> | ||||
| @@ -17,6 +17,11 @@ | |||||
| package org.apache.tools.ant.taskdefs; | 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.File; | ||||
| import java.io.FileOutputStream; | import java.io.FileOutputStream; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| @@ -26,11 +31,6 @@ import java.net.HttpURLConnection; | |||||
| import java.net.URL; | import java.net.URL; | ||||
| import java.net.URLConnection; | import java.net.URLConnection; | ||||
| import java.util.Date; | 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. | * Gets a particular file from a URL source. | ||||
| @@ -115,6 +115,7 @@ public class Get extends Task { | |||||
| progress = new NullProgress(); | progress = new NullProgress(); | ||||
| } | } | ||||
| log("Getting: " + source, logLevel); | log("Getting: " + source, logLevel); | ||||
| log("To: " + dest.getAbsolutePath(), logLevel); | |||||
| //set the timestamp to the file date. | //set the timestamp to the file date. | ||||
| long timestamp = 0; | long timestamp = 0; | ||||
| @@ -19,16 +19,23 @@ package org.apache.tools.ant.taskdefs.optional.repository; | |||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| import org.apache.tools.ant.Task; | 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.Path; | ||||
| import org.apache.tools.ant.types.Reference; | import org.apache.tools.ant.types.Reference; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.util.Collection; | |||||
| import java.util.ArrayList; | |||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import java.util.LinkedList; | |||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.NoSuchElementException; | |||||
| import java.util.ListIterator; | |||||
| /** | /** | ||||
| * This task will retrieve one or more libraries from a repository. <ol> | * This task will retrieve one or more libraries from a repository. <ol> | ||||
| @@ -39,18 +46,13 @@ import java.util.NoSuchElementException; | |||||
| * @ant.task | * @ant.task | ||||
| * @since Ant 1.7 | * @since Ant 1.7 | ||||
| */ | */ | ||||
| public class GetLibraries extends Task { | |||||
| public final class GetLibraries extends Task { | |||||
| /** | /** | ||||
| * destination | * destination | ||||
| */ | */ | ||||
| private File destDir; | private File destDir; | ||||
| /** | |||||
| * flag to force a download | |||||
| */ | |||||
| private boolean forceDownload = false; | |||||
| /** | /** | ||||
| * flag to force offline | * flag to force offline | ||||
| */ | */ | ||||
| @@ -59,7 +61,12 @@ public class GetLibraries extends Task { | |||||
| /** | /** | ||||
| * list of libraries | * list of libraries | ||||
| */ | */ | ||||
| private List libraries = new LinkedList(); | |||||
| private EnabledLibraryElementList libraries = new EnabledLibraryElementList(); | |||||
| /** | |||||
| * helper list | |||||
| */ | |||||
| private EnabledLibraryElementList policies=new EnabledLibraryElementList(); | |||||
| /** | /** | ||||
| * repository for retrieval | * repository for retrieval | ||||
| @@ -72,16 +79,33 @@ public class GetLibraries extends Task { | |||||
| */ | */ | ||||
| private String pathid; | 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_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_DEST_DIR = "No destination directory"; | ||||
| public static final String ERROR_NO_REPOSITORY = "No repository defined"; | 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 | * add a repository. Only one is (currently) supported | ||||
| @@ -115,6 +139,64 @@ public class GetLibraries extends Task { | |||||
| add(r); | 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 | * add a library for retrieval | ||||
| @@ -134,14 +216,6 @@ public class GetLibraries extends Task { | |||||
| this.destDir = destDir; | 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 | * test for being offline | ||||
| @@ -172,13 +246,6 @@ public class GetLibraries extends Task { | |||||
| return destDir; | return destDir; | ||||
| } | } | ||||
| /** | |||||
| * get force download flag | |||||
| * @return | |||||
| */ | |||||
| public boolean isForceDownload() { | |||||
| return forceDownload; | |||||
| } | |||||
| /** | /** | ||||
| * get the list of libraries | * get the list of libraries | ||||
| @@ -213,13 +280,39 @@ public class GetLibraries extends Task { | |||||
| this.pathid = pathid; | 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 | * validate ourselves | ||||
| * | * | ||||
| * @throws BuildException | * @throws BuildException | ||||
| */ | */ | ||||
| public void validate() { | public void validate() { | ||||
| if (destDir == null || !destDir.isDirectory()) { | |||||
| if (destDir == null | |||||
| // || !destDir.isDirectory() | |||||
| ) { | |||||
| throw new BuildException(ERROR_NO_DEST_DIR); | throw new BuildException(ERROR_NO_DEST_DIR); | ||||
| } | } | ||||
| if (repository == null) { | if (repository == null) { | ||||
| @@ -231,7 +324,6 @@ public class GetLibraries extends Task { | |||||
| library.validate(); | library.validate(); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Called by the project to let the task do its work. | * 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 { | public void execute() throws BuildException { | ||||
| validate(); | 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(); | destDir.mkdirs(); | ||||
| Repository repo = repository.resolve(); | Repository repo = repository.resolve(); | ||||
| repo.validate(); | repo.validate(); | ||||
| if (libraries.size() == 0) { | if (libraries.size() == 0) { | ||||
| throw new BuildException(ERROR_NO_LIBRARIES); | throw new BuildException(ERROR_NO_LIBRARIES); | ||||
| } | } | ||||
| int failures = 0; | |||||
| log("Getting libraries from " + repo.toString(), Project.MSG_VERBOSE); | log("Getting libraries from " + repo.toString(), Project.MSG_VERBOSE); | ||||
| log("Saving libraries to " + destDir.toString(), Project.MSG_VERBOSE); | log("Saving libraries to " + destDir.toString(), Project.MSG_VERBOSE); | ||||
| //map libraries to files | |||||
| bindAllLibraries(); | 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 | //connect the repository | ||||
| int failures = 0; | |||||
| repo.connect(this); | repo.connect(this); | ||||
| try { | try { | ||||
| @@ -274,82 +431,136 @@ public class GetLibraries extends Task { | |||||
| Project.MSG_VERBOSE); | Project.MSG_VERBOSE); | ||||
| reachable = false; | 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()) { | while (it.hasNext()) { | ||||
| Library library = (Library) it.next(); | 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 { | } finally { | ||||
| log("disconnecting",Project.MSG_VERBOSE); | |||||
| repo.disconnect(); | 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()) { | while (it.hasNext()) { | ||||
| Library library = (Library) it.next(); | 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 | * verify that all libraries are present | ||||
| */ | */ | ||||
| protected void verifyAllLibrariesPresent() { | protected void verifyAllLibrariesPresent() { | ||||
| //iterate through the libs we have | //iterate through the libs we have | ||||
| boolean missing = false; | boolean missing = false; | ||||
| Iterator it = filteredIterator(); | |||||
| StringBuffer buffer=new StringBuffer(); | |||||
| Iterator it = enabledLibrariesIterator(); | |||||
| while (it.hasNext()) { | while (it.hasNext()) { | ||||
| Library library = (Library) it.next(); | Library library = (Library) it.next(); | ||||
| //check for the library existing | //check for the library existing | ||||
| if (!library.exists()) { | if (!library.exists()) { | ||||
| //and log if one is missing | //and log if one is missing | ||||
| buffer.append(library.toString()+"; "); | |||||
| log("Missing: " + library.toString(), | log("Missing: " + library.toString(), | ||||
| Project.MSG_ERR); | Project.MSG_ERR); | ||||
| missing = true; | missing = true; | ||||
| } | } | ||||
| } | } | ||||
| if (missing) { | 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() { | private void createPath() { | ||||
| Path path = new Path(getProject()); | Path path = new Path(getProject()); | ||||
| for (Iterator iterator = filteredIterator(); | |||||
| for (Iterator iterator = enabledLibrariesIterator(); | |||||
| iterator.hasNext();) { | iterator.hasNext();) { | ||||
| ((Library) iterator.next()).appendToPath(path); | ((Library) iterator.next()).appendToPath(path); | ||||
| } | } | ||||
| @@ -369,66 +580,17 @@ public class GetLibraries extends Task { | |||||
| * get a filtered iterator of the dependencies | * get a filtered iterator of the dependencies | ||||
| * @return a new iterator that ignores disabled libraries | * @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(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -68,8 +68,6 @@ public abstract class HttpRepository extends Repository { | |||||
| * retry logic | * retry logic | ||||
| */ | */ | ||||
| public static final String ERROR_REENTRANT_USE = "Repository is already in use"; | 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 | * get the base URL of the repository | ||||
| @@ -169,9 +167,9 @@ public abstract class HttpRepository extends Repository { | |||||
| url = url + '/'; | url = url + '/'; | ||||
| } | } | ||||
| //validate the URL | |||||
| URL repository; | |||||
| try { | try { | ||||
| //validate the URL | |||||
| URL repository; | |||||
| repository = new URL(url); | repository = new URL(url); | ||||
| } catch (MalformedURLException e) { | } catch (MalformedURLException e) { | ||||
| throw new BuildException(e); | throw new BuildException(e); | ||||
| @@ -213,12 +211,13 @@ public abstract class HttpRepository extends Repository { | |||||
| * | * | ||||
| * @param library | * @param library | ||||
| * | * | ||||
| * @param useTimestamp | |||||
| * @return true if we retrieved | * @return true if we retrieved | ||||
| * | * | ||||
| * @throws org.apache.tools.ant.BuildException | * @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); | String path = getRemoteLibraryURL(library); | ||||
| logVerbose("Library URL=" + path); | logVerbose("Library URL=" + path); | ||||
| @@ -226,11 +225,9 @@ public abstract class HttpRepository extends Repository { | |||||
| logVerbose("destination =" + library.getAbsolutePath()); | logVerbose("destination =" + library.getAbsolutePath()); | ||||
| long start, finish; | long start, finish; | ||||
| start = System.currentTimeMillis(); | 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); | username, password); | ||||
| finish = System.currentTimeMillis(); | |||||
| long diff = finish - start; | long diff = finish - start; | ||||
| logVerbose("downloaded in " + diff / 1000 + " seconds"); | 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) | public boolean get(URL url,File destFile,boolean useTimestamp,String user,String passwd) | ||||
| throws IOException { | throws IOException { | ||||
| //create the destination dir | |||||
| destFile.getParentFile().mkdirs(); | |||||
| Get getTask = new Get(); | Get getTask = new Get(); | ||||
| getTask.setProject(getProject()); | getTask.setProject(getProject()); | ||||
| getTask.setTaskName("dependencies"); | |||||
| getTask.setTaskName(owner.getTaskName()); | |||||
| getTask.setDest(destFile); | getTask.setDest(destFile); | ||||
| getTask.setUsername(user); | getTask.setUsername(user); | ||||
| getTask.setPassword(passwd); | getTask.setPassword(passwd); | ||||
| @@ -287,65 +286,21 @@ public abstract class HttpRepository extends Repository { | |||||
| protected abstract String getRemoteLibraryURL(Library library); | 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(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -18,8 +18,9 @@ | |||||
| package org.apache.tools.ant.taskdefs.optional.repository; | package org.apache.tools.ant.taskdefs.optional.repository; | ||||
| import org.apache.tools.ant.BuildException; | 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.types.Path; | ||||
| import org.apache.tools.ant.util.FileUtils; | |||||
| import java.io.File; | import java.io.File; | ||||
| @@ -28,7 +29,30 @@ import java.io.File; | |||||
| * | * | ||||
| * @since Ant1.7 | * @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" | //project "ant" | ||||
| private String project; | private String project; | ||||
| @@ -52,14 +76,12 @@ public class Library { | |||||
| private File libraryFile; | 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_ARCHIVE = "No archive defined"; | ||||
| public static final String ERROR_NO_PROJECT = "No project defined"; | public static final String ERROR_NO_PROJECT = "No project defined"; | ||||
| @@ -70,6 +92,7 @@ public class Library { | |||||
| * suffix | * suffix | ||||
| */ | */ | ||||
| private String suffix = "jar"; | 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; | 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 | * get the library file | ||||
| * (only non-null after binding) | * (only non-null after binding) | ||||
| @@ -195,6 +186,14 @@ public class Library { | |||||
| return libraryFile; | return libraryFile; | ||||
| } | } | ||||
| /** | |||||
| * set the library file. | |||||
| * @param libraryFile | |||||
| */ | |||||
| public void setLibraryFile(File libraryFile) { | |||||
| this.libraryFile = libraryFile; | |||||
| } | |||||
| /** | /** | ||||
| * fault if the field is null or empty | * fault if the field is null or empty | ||||
| * | * | ||||
| @@ -241,10 +240,16 @@ public class Library { | |||||
| */ | */ | ||||
| public void bind(File baseDir) { | public void bind(File baseDir) { | ||||
| validate(); | validate(); | ||||
| FileUtils fileUtils=FileUtils.newFileUtils(); | |||||
| if (destinationName == null) { | 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(); | 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 | * @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 | * add our location to a filepath | ||||
| @@ -335,5 +359,55 @@ public class Library { | |||||
| pathElement.setLocation(getLibraryFile()); | 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; | |||||
| } | |||||
| } | } | ||||
| @@ -19,10 +19,9 @@ package org.apache.tools.ant.taskdefs.optional.repository; | |||||
| import org.apache.tools.ant.util.FileUtils; | import org.apache.tools.ant.util.FileUtils; | ||||
| import java.io.IOException; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.FileInputStream; | import java.io.FileInputStream; | ||||
| import java.io.FileReader; | |||||
| import java.io.IOException; | |||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||
| import java.io.Reader; | import java.io.Reader; | ||||
| import java.net.URL; | import java.net.URL; | ||||
| @@ -90,18 +89,29 @@ public class MavenRepository extends HttpRepository { | |||||
| return "Maven Repository at " + getUrl(); | 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 | * fetch a library from the repository | ||||
| * | * | ||||
| * @param library | * @param library | ||||
| * | * | ||||
| * @param useTimestamp | |||||
| * @return true if we retrieved | * @return true if we retrieved | ||||
| * | * | ||||
| * @throws org.apache.tools.ant.BuildException | * @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) { | if(fetched && checkMD5) { | ||||
| //we got here if there was a fetch. so we now get the MD5 info from the file, | //we got here if there was a fetch. so we now get the MD5 info from the file, | ||||
| boolean successful=false; | boolean successful=false; | ||||
| @@ -140,5 +150,3 @@ public class MavenRepository extends HttpRepository { | |||||
| } | } | ||||
| } | } | ||||
| // e1b1720a761ca36eaa47e1c7d802e676 | |||||
| @@ -99,11 +99,18 @@ public abstract class Repository extends DataType { | |||||
| /** | /** | ||||
| * fetch a library from the repository | * 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 | * @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(); | |||||
| } | } | ||||
| @@ -70,10 +70,20 @@ public final class RepositoryRef extends Repository { | |||||
| * | * | ||||
| * @param library | * @param library | ||||
| * | * | ||||
| * @param useTimestamp | |||||
| * @return | * @return | ||||
| */ | */ | ||||
| public boolean fetch(Library library) throws IOException { | |||||
| public boolean fetch(Library library, boolean useTimestamp) throws IOException { | |||||
| throw new BuildException(E_NOTIMPL); | 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(); | |||||
| } | |||||
| } | } | ||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| @@ -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); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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) { | |||||
| } | |||||
| } | |||||
| @@ -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(); | |||||
| } | |||||
| @@ -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(); | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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()); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| @@ -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); | |||||
| } | |||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| @@ -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(); | |||||
| } | |||||
| } | |||||
| @@ -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; | |||||
| } | |||||
| } | |||||
| @@ -17,6 +17,7 @@ | |||||
| package org.apache.tools.ant.taskdefs.optional.repository; | package org.apache.tools.ant.taskdefs.optional.repository; | ||||
| import org.apache.tools.ant.BuildFileTest; | import org.apache.tools.ant.BuildFileTest; | ||||
| import org.apache.tools.ant.taskdefs.repository.AssertDownloaded; | |||||
| /** | /** | ||||
| * test the test libraries stuff. | * test the test libraries stuff. | ||||
| @@ -75,6 +76,10 @@ public class GetLibrariesTest extends BuildFileTest { | |||||
| execIfOnline(targetName); | execIfOnline(targetName); | ||||
| } | } | ||||
| /** | |||||
| * exec a target, but only if we are online | |||||
| * @param targetName | |||||
| */ | |||||
| private void execIfOnline(String targetName) { | private void execIfOnline(String targetName) { | ||||
| if (offline()) { | if (offline()) { | ||||
| return; | return; | ||||
| @@ -83,15 +88,28 @@ public class GetLibrariesTest extends BuildFileTest { | |||||
| } | } | ||||
| public void testTwoRepositories() { | public void testTwoRepositories() { | ||||
| expectBuildException("testTwoRepositories", GetLibraries.ERROR_ONE_REPOSITORY_ONLY); | |||||
| expectBuildException("testTwoRepositories", | |||||
| GetLibraries.ERROR_ONE_REPOSITORY_ONLY); | |||||
| } | } | ||||
| public void testMavenInlineBadURL() { | 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()) { | if (offline()) { | ||||
| return; | return; | ||||
| } | } | ||||
| expectBuildException("testTwoRepositories", | |||||
| GetLibraries.ERROR_INCOMPLETE_RETRIEVAL); | |||||
| expectBuildExceptionContaining(target,cause, | |||||
| message); | |||||
| } | } | ||||
| public void testRenaming() { | public void testRenaming() { | ||||
| @@ -119,4 +137,45 @@ public class GetLibrariesTest extends BuildFileTest { | |||||
| execIfOnline("testSecurity"); | 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); | |||||
| } | |||||
| } | |||||