You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by st...@apache.org on 2004/10/26 01:13:39 UTC

cvs commit: ant/src/etc/testcases/taskdefs/optional getlibraries.xml

stevel      2004/10/25 16:13:39

  Modified:    src/main/org/apache/tools/ant/types defaults.properties
               src/main/org/apache/tools/ant/taskdefs defaults.properties
               .        build.xml WHATSNEW
  Added:       src/main/org/apache/tools/ant/taskdefs/optional/repository
                        GetLibraries.java HttpRepository.java Library.java
                        MavenRepository.java Repository.java
                        RepositoryRef.java
               src/testcases/org/apache/tools/ant/taskdefs/optional
                        GetLibrariesTest.java
               src/etc/testcases/taskdefs/optional getlibraries.xml
  Log:
  Repository support; needs http client 2.x and commons-logging.
  Broken: repository references (you'll see in the test results)
  not tested: authenticated access to the repository.
  Already had a feature request for multiple repository support;
  would be nice. That and better diagnostics on failure.
  Note that we dont currently probe ibiblio for availaibility; that was taking longer than the fetches themselves.
  
  Revision  Changes    Path
  1.1                  ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/GetLibraries.java
  
  Index: GetLibraries.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.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.types.Reference;
  
  import java.io.File;
  import java.io.IOException;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  
  /**
   * This task will retrieve one or more libraries from a repository. <ol>
   * <li>Users must declare a repository, either inline or by reference</li>
   * <li>Dependency checking is used (timestamps) unless forceDownload=true</li>
   * <li>It is an error if, at the end of the task, a library is missing.
   *
   * @ant.task
   * @since Ant 1.7
   */
  public class GetLibraries extends Task {
  
      /**
       * destination
       */
      private File destDir;
  
      /**
       * flag to force a download
       */
      private boolean forceDownload = false;
  
      /**
       * flag to force offline
       */
      private boolean offline = false;
  
      /**
       * list of libraries
       */
      private List libraries = new LinkedList();
  
      /**
       * repository for retrieval
       */
  
      private Repository repository;
  
      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";
  
      /**
       * add a repository. Only one is (currently) supported
       *
       * @param repo
       */
      public void add(Repository repo) {
          if (repository != null) {
              throw new BuildException(ERROR_ONE_REPOSITORY_ONLY);
          }
          repository = repo;
      }
  
  
      /**
       * add a repository. Unless there is explicit support for a subclass
       *
       * @param repo
       */
      public void addRepository(RepositoryRef repo) {
          add(repo);
      }
  
  
      /**
       * add a maven repository.
       */
  /*
      public void addMavenRepository(MavenRepository repo) {
          add(repo);
      }
  */
  
      /**
       * bind to a repository.
       */
      public void setRepositoryRef(final Reference ref) {
          //create a special repository that can only
          //resolve references.
          Repository r = new RepositoryRef(getProject(), ref);
          add(r);
      }
  
  
      /**
       * add a library for retrieval
       *
       * @param lib
       */
      public void addLibrary(Library lib) {
          libraries.add(lib);
      }
  
      /**
       * destination directory for all library files
       *
       * @param destDir
       */
      public void setDestDir(File 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
       *
       * @return true if the offline flag is set
       */
      public boolean isOffline() {
          return offline;
      }
  
      /**
       * declare the system offline. This disables any attempt to retrieve files.
       * In this mode, only the presence of files is verified. If forceDownload is
       * true, or there is a missing library, then an error will be raised.
       *
       * @param offline
       */
      public void setOffline(boolean offline) {
          this.offline = offline;
      }
  
      public File getDestDir() {
          return destDir;
      }
  
      public boolean isForceDownload() {
          return forceDownload;
      }
  
      public List getLibraries() {
          return libraries;
      }
  
      public Repository getRepository() {
          return repository;
      }
  
      /**
       * validate ourselves
       *
       * @throws BuildException
       */
      public void validate() {
          if (destDir == null || !destDir.exists() || !destDir.isDirectory()) {
              throw new BuildException(ERROR_NO_DEST_DIR);
          }
          if (repository == null) {
              throw new BuildException(ERROR_NO_REPOSITORY);
          }
          Iterator it = libraries.iterator();
          while (it.hasNext()) {
              Library library = (Library) it.next();
              library.validate();
          }
      }
  
      /**
       * Called by the project to let the task do its work.
       *
       * @throws org.apache.tools.ant.BuildException
       *          if something goes wrong with the build
       */
      public void execute() throws BuildException {
          validate();
          Repository repo = repository.resolve();
          repo.validate();
          int toFetch = libraries.size();
          if (toFetch == 0) {
              throw new BuildException(ERROR_NO_LIBRARIES);
          }
          int fetched = 0;
          log("Getting libraries from " + repo.toString(), Project.MSG_VERBOSE);
          log("Saving libraries to " + destDir.toString(), Project.MSG_VERBOSE);
  
          bindAllLibraries();
          if (isOffline()) {
              log("No retrieval, task is \"offline\"");
              verifyAllLibrariesPresent();
              return;
          }
  
  
          //connect the repository
          repo.connect(this);
          try {
  
              //check for reachability.
              //it is up to each repository to decide that.
              boolean reachable;
              try {
                  log("Checking repository for reachability", Project.MSG_DEBUG);
                  reachable = repo.checkRepositoryReachable();
              } catch (IOException e) {
  
                  log(ERROR_REPO_PROBE_FAILED + e.getMessage(),
                          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);
              }
  
              //iterate through the libs we have
              Iterator it = libraries.iterator();
              while (it.hasNext()) {
                  Library library = (Library) it.next();
                  library.bind(destDir);
                  try {
                      if (repo.fetch(library)) {
                          fetched++;
                      }
                  } catch (IOException e) {
                      //failures to fetch are logged at verbose level
                      log(ERROR_LIBRARY_FETCH_FAILED + library);
                      log(e.getMessage(), Project.MSG_VERBOSE);
                  }
              }
          } finally {
              repo.disconnect();
          }
  
          //at this point downloads have finished.
          //we do still need to verify that everything worked.
          if ((fetched < toFetch && forceDownload)) {
              throw new BuildException(ERROR_FORCED_DOWNLOAD_FAILED);
          }
  
          verifyAllLibrariesPresent();
  
      }
  
      /**
       * bind all libraries to our destination
       */
      protected void bindAllLibraries() {
          Iterator it = libraries.iterator();
          while (it.hasNext()) {
              Library library = (Library) it.next();
              library.bind(destDir);
          }
      }
  
      /**
       * verify that all libraries are present
       */
      protected void verifyAllLibrariesPresent() {
          //iterate through the libs we have
          boolean missing = false;
  
          Iterator it = libraries.iterator();
          while (it.hasNext()) {
              Library library = (Library) it.next();
              //check for the library existing
              if (!library.exists()) {
                  //and log if one is missing
                  log("Missing: " + library.toString(),
                          Project.MSG_ERR);
                  missing = true;
              }
          }
          if (missing) {
              throw new BuildException(ERROR_INCOMPLETE_RETRIEVAL);
          }
      }
  
  }
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/HttpRepository.java
  
  Index: HttpRepository.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.optional.repository;
  
  import org.apache.commons.httpclient.*;
  import org.apache.commons.httpclient.cookie.CookiePolicy;
  import org.apache.commons.httpclient.methods.GetMethod;
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.util.FileUtils;
  
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.Date;
  
  /**
   * This is a base class for repositories that are built on URLs. Although you
   * can share this datatype, it is *not* thread safe; you can only use it in one
   * thread at at time
   *
   * @since Ant1.7
   */
  public abstract class HttpRepository extends Repository {
      /**
       * repositoryURL of repository
       */
      private String url;
  
      /**
       * username
       */
      private String username;
  
      /**
       * password
       */
      private String password;
  
  
      /**
       * auth realm; can be null
       */
      private String realm;
  
      /**
       * this is our http client
       */
      private HttpClient client;
  
      /**
       * number of times to retry fetches
       */
      private int retries = 1;
  
      /**
       * no repository URL
       */
      public static final String ERROR_NO_REPOSITORY_URL = "No repository URL";
  
      /**
       * owner class
       */
      private GetLibraries owner;
  
      /**
       * retry logic
       */
      private DefaultMethodRetryHandler retryhandler;
      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
       *
       * @return
       */
      public String getUrl() {
          return url;
      }
  
      /**
       * Set the base URL of the repository
       *
       * @param url
       */
      public void setUrl(String url) {
          this.url = url;
      }
  
      public String getUsername() {
          return username;
      }
  
      /**
       * set the username for the remote repository
       *
       * @param username
       */
      public void setUsername(String username) {
          this.username = username;
      }
  
      public String getPassword() {
          return password;
      }
  
      /**
       * set the password for the remote repository
       *
       * @param password
       */
      public void setPassword(String password) {
          this.password = password;
      }
  
      public String getRealm() {
          return realm;
      }
  
      /**
       * set the realm for authentication; empty string is equivalent to "any
       * realm" (the default)
       *
       * @param realm
       */
      public void setRealm(String realm) {
          if (realm != null) {
              this.realm = realm;
          } else {
              this.realm = null;
          }
      }
  
  
      /**
       * @return number of times to retry fetches
       */
      public int getRetries() {
          return retries;
      }
  
      /**
       * number of times to retry fetches
       *
       * @param retries
       */
      public void setRetries(int retries) {
          this.retries = retries;
      }
  
      /**
       * get the client
       *
       * @return
       */
      public HttpClient getClient() {
          return client;
      }
  
      public GetLibraries getOwner() {
          return owner;
      }
  
      /**
       * validate yourself
       *
       * @throws org.apache.tools.ant.BuildException
       *          if unhappy
       */
      public void validate() {
          super.validate();
          checkChildrenAllowed();
          checkAttributesAllowed();
          if (url == null || url.length() == 0) {
              throw new BuildException(ERROR_NO_REPOSITORY_URL);
          }
      }
  
      /**
       * override point: connection is called at the start of the retrieval
       * process
       *
       * @param newOwner
       *
       * @throws org.apache.tools.ant.BuildException
       *
       */
      public void connect(GetLibraries newOwner) {
          this.owner = newOwner;
          if (client != null) {
              throw new BuildException(ERROR_REENTRANT_USE);
          }
          if (!url.endsWith("/")) {
              url = url + '/';
          }
          client = new HttpClient();
          //retry handler
          retryhandler = new DefaultMethodRetryHandler();
          retryhandler.setRequestSentRetryEnabled(false);
          retryhandler.setRetryCount(retries);
  
          //validate the URL
          URL repository;
          try {
              repository = new URL(url);
          } catch (MalformedURLException e) {
              throw new BuildException(e);
          }
          //authentication
          if (username != null) {
              Credentials defaultcreds =
                      new UsernamePasswordCredentials(username, password);
              client.getState().setCredentials(realm,
                      repository.getHost(),
                      defaultcreds);
              //turn auth on on first call
              client.getState().setAuthenticationPreemptive(true);
          }
          //cookies
          client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);
      }
  
      /**
       * override point: connection is called at the start of the retrieval
       * process
       *
       * @throws org.apache.tools.ant.BuildException
       *
       */
  
      public void disconnect() {
          client = null;
          retryhandler = null;
      }
  
      /**
       * Test for a repository being reachable. This method is called after {@link
       * #connect(org.apache.tools.ant.taskdefs.optional.repository.GetLibraries)}
       * is called, before any files are to be retrieved.
       * <p/>
       * If it returns false the repository considers itself offline. Similarly,
       * any ioexception is interpreted as being offline.
       * <p/>
       * The Http implementation probes for the base URL being reachable, and
       * returning a 200 status code.
       *
       * @return true if the repository is online.
       *
       * @throws java.io.IOException
       */
      public boolean checkRepositoryReachable() throws IOException {
          //return pingBaseURL();
          return true;
      }
  
      private boolean pingBaseURL() throws IOException {
          GetMethod get = createGet(getUrl());
          client.executeMethod(get);
          return get.getStatusCode() == HttpStatus.SC_OK;
      }
  
      /**
       * create a new getMethod against any URI
       *
       * @param url
       *
       * @return
       */
      public GetMethod createGet(String url) {
          GetMethod method = new GetMethod(url);
  
          method.setMethodRetryHandler(retryhandler);
          method.setDoAuthentication(true);
          method.setFollowRedirects(true);
  
          return method;
      }
  
      /**
       * @param method
       * @param timestamp
       *
       * @link http://www.w3.org/Protocols/HTTP/HTRQ_Headers.html#if-modified-since
       * @link http://www.w3.org/Protocols/rfc850/rfc850.html#z10
       */
      public void setIfModifiedSinceHeader(HttpMethod method, long timestamp) {
          Date date = new Date(timestamp);
          //ooh, naughty, deprecated. and like why is it deprecated?
          method.setRequestHeader(IF_MODIFIED_SINCE, date.toGMTString());
      }
  
      /**
       * fetch a library from the repository
       *
       * @param library
       *
       * @return true if we retrieved
       *
       * @throws org.apache.tools.ant.BuildException
       *
       */
      public boolean fetch(Library library) throws IOException {
  
          String path = getRemoteLibraryURL(library);
          logVerbose("Library URL=" + path);
          logVerbose("destination =" + library.getAbsolutePath());
          GetMethod get = createGet(path);
          boolean useTimestamps = !getOwner().isForceDownload() &&
                  !library.exists();
          if (useTimestamps) {
              setIfModifiedSinceHeader(get, library.getLastModified());
          }
          try {
              long start, finish;
              start = System.currentTimeMillis();
              client.executeMethod(get);
              if (useTimestamps && get.getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
                  logDebug("File is not modified");
                  //we get here if there is no change in timestamp
                  //so no fetch
                  return false;
              }
              if (get.getStatusCode() != HttpStatus.SC_OK) {
                  String message = "Request Failed:"
                          + get.getStatusCode()
                          + " from " + get.getPath();
                  logVerbose(message);
                  logVerbose(get.getStatusLine().toString());
                  logVerbose(get.getStatusText());
                  throw new BuildException(message);
              }
              saveStreamToLibrary(get, library);
              finish = System.currentTimeMillis();
              long diff = finish - start;
              logVerbose("downloaded in " + diff / 1000 + " seconds");
          } finally {
              // Release the connection.
              get.releaseConnection();
          }
  
          return true;
      }
  
      /**
       * log something at the verbose level
       *
       * @param message text to log
       */
      protected void logVerbose(String message) {
          getOwner().log(message,
                  Project.MSG_VERBOSE);
      }
  
      protected void logDebug(String message) {
          getOwner().log(message,
                  Project.MSG_DEBUG);
      }
  
      /**
       * Get the path to a remote library. This is the full URL
       *
       * @param library
       *
       * @return URL to 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.
       */
      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");
          }
      }
  
      /**
       * Returns a string representation of the repository
       *
       * @return the base URL
       */
      public String toString() {
          return "Repository at " + getUrl();
      }
  }
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/Library.java
  
  Index: Library.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  
  package org.apache.tools.ant.taskdefs.optional.repository;
  
  import org.apache.tools.ant.BuildException;
  
  import java.io.File;
  
  /**
   * How we represent libraries
   *
   * @since 20-Oct-2004
   */
  public class Library {
  
      //project "ant"
      private String project;
  
      //version "1.5"
      private String version;
  
      //archive prefix "ant-optional"
      private String archive;
  
      /**
       * very optional attribute; name of the destination. Autocalculated if not
       * set.
       */
  
      private String destinationName;
  
      private File libraryFile;
  
      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_VERSION = "No version defined";
      public static final String ERROR_NO_SUFFIX = "No version defined";
  
      /**
       * suffix
       */
      private String suffix = "jar";
  
  
      public String getProject() {
          return project;
      }
  
      public void setProject(String project) {
          this.project = project;
      }
  
      public String getVersion() {
          return version;
      }
  
      public void setVersion(String version) {
          this.version = version;
      }
  
      public String getArchive() {
          return archive;
      }
  
      public void setArchive(String archive) {
          this.archive = archive;
      }
  
      public String getDestinationName() {
          return destinationName;
      }
  
      public void setDestinationName(String destinationName) {
          this.destinationName = destinationName;
      }
  
      /**
       * get the suffix for this file.
       *
       * @return
       */
      public String getSuffix() {
          return suffix;
      }
  
      public void setSuffix(String suffix) {
          this.suffix = suffix;
      }
  
      public File getLibraryFile() {
          return libraryFile;
      }
  
      /**
       * fault if the field is null or empty
       *
       * @param field
       * @param message text for fault
       *
       * @throws BuildException if the field is not set up
       */
      private void faultIfEmpty(String field, String message) {
          if (field == null || field.length() == 0) {
              throw new BuildException(message);
          }
      }
  
      /**
       * validate;
       *
       * @throws BuildException if invalid
       */
      public void validate() {
          faultIfEmpty(archive, ERROR_NO_ARCHIVE);
          faultIfEmpty(project, ERROR_NO_PROJECT);
          faultIfEmpty(version, ERROR_NO_VERSION);
          faultIfEmpty(version, ERROR_NO_SUFFIX);
      }
  
      public String toString() {
          return "Library " + getNormalFilename()
                  + " from project " + project
                  + " to " + getDestinationName();
      }
  
      /**
       * calculare the destination file of a library
       *
       * @param baseDir
       *
       * @throws BuildException if invalid
       */
      public void bind(File baseDir) {
          validate();
          if (destinationName == null) {
              destinationName = getNormalFilename();
          }
          libraryFile = new File(baseDir, destinationName);
      }
  
      /**
       * a test that is only valid after binding
       *
       * @return
       */
      public boolean exists() {
          return libraryFile.exists();
      }
  
      /**
       * get the last modified date
       *
       * @return
       */
      public long getLastModified() {
          return libraryFile.lastModified();
      }
  
      /**
       * get the filename from the rule of archive+version+'.'+suffix. Clearly
       * only valid if all fields are defined.
       *
       * @return a string representing the expected name of the file at the
       *         source
       */
      public String getNormalFilename() {
          return archive + "-" + version + "." + suffix;
      }
  
      /**
       * get the filename of the destination; no path.
       *
       * @return
       */
      public String getDestFilename() {
          if (destinationName == null) {
              return getNormalFilename();
          } else {
              return destinationName;
          }
      }
  
      /**
       * get a maven path (project/filename)
       *
       * @param separator directory separator
       *
       * @return
       */
      public String getMavenPath(char separator) {
          return project + separator + "jars" + separator + getNormalFilename();
      }
  
      /**
       * get the absolute path of this library
       *
       * @return
       */
      public String getAbsolutePath() {
          return libraryFile.getAbsolutePath();
      }
  
  }
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/MavenRepository.java
  
  Index: MavenRepository.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  
  package org.apache.tools.ant.taskdefs.optional.repository;
  
  
  /**
   * A Maven repository knows about maven repository layout rules It also defaults
   * to http://www.ibiblio.org/maven/
   *
   * @link http://maven.apache.org/reference/user-guide.html#Remote_Repository_Layout
   * @link
   * @since Ant1.7
   */
  public class MavenRepository extends HttpRepository {
      public static final String MAVEN_URL = "http://www.ibiblio.org/maven/";
  
  
      /**
       * bind to the main maven repository
       */
      public MavenRepository() {
          setUrl(MAVEN_URL);
      }
  
      /**
       * Get the path to a remote library. This is the full URL
       *
       * @param library
       *
       * @return URL to library
       */
      protected String getRemoteLibraryURL(Library library) {
          String base = getUrl();
          if (!base.endsWith("/")) {
              base = base + '/';
          }
  
          return base + library.getMavenPath('/');
      }
  
      /**
       * Returns a string representation of the repository
       *
       * @return the base URL
       */
      public String toString() {
          return "Maven Repository at " + getUrl();
      }
  
  }
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/Repository.java
  
  Index: Repository.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  
  package org.apache.tools.ant.taskdefs.optional.repository;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.types.DataType;
  
  import java.io.IOException;
  
  /**
   * This type represents a repository; a place that stores libraries for
   * retrieval. To use this type, you must use a non-abstract class, either one
   * that ships with Ant, or one you implement and declare yourself.
   * <p/>
   * The &lt;getlibraries&gt; task lets you supply a repository by reference
   * inline {@link GetLibraries#add(Repository)} or on the command line {@link
   * GetLibraries#setRepositoryRef(org.apache.tools.ant.types.Reference)}
   *
   * @since Ant1.7
   */
  public abstract class Repository extends DataType {
  
  
      /**
       * validate yourself
       *
       * @throws BuildException if unhappy
       */
      public void validate() {
      }
  
      /**
       * recursively resolve any references to get the real repository
       *
       * @return
       */
      public final Repository resolve() {
          if (getRefid() == null) {
              return this;
          } else {
              Repository repository = (Repository) getCheckedRef(this.getClass(),
                      "Repository");
              return repository;
          }
      }
  
      /**
       * override point: connection is called at the start of the retrieval
       * process
       *
       * @param owner owner of the libraries
       *
       * @throws BuildException
       */
      public void connect(GetLibraries owner) {
  
      }
  
      /**
       * override point: connection is called at the start of the retrieval
       * process
       *
       * @throws BuildException
       */
  
      public void disconnect() {
  
      }
  
  
      /**
       * Test for a repository being reachable. This method is called after {@link
       * #connect(GetLibraries)} is called, before any files are to be retrieved.
       * <p/>
       * If it returns false the repository considers itself offline. Similarly,
       * any ioexception is interpreted as being offline.
       *
       * @return true if the repository is online.
       *
       * @throws IOException
       */
      public abstract boolean checkRepositoryReachable() throws IOException;
  
      /**
       * fetch a library from the repository
       *
       * @param library
       *
       * @return
       */
      public abstract boolean fetch(Library library) throws IOException;
  
  
  }
  
  
  
  1.1                  ant/src/main/org/apache/tools/ant/taskdefs/optional/repository/RepositoryRef.java
  
  Index: RepositoryRef.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.optional.repository;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.types.Reference;
  
  import java.io.IOException;
  
  /**
   * not a real repository; one to paste a reference into the chain for
   * resolution.
   *
   * @since Ant1.7
   */
  public final class RepositoryRef extends Repository {
  
  
      /**
       * create a repository reference
       *
       * @param reference
       */
      public RepositoryRef(Project project, Reference reference) {
          setRefid(reference);
          setProject(project);
      }
  
      /**
       * empty constructor
       */
      public RepositoryRef() {
      }
  
      /**
       * Test for a repository being reachable. This method is called after {@link
       * #connect(GetLibraries)} is called, before any files are to be retrieved.
       * <p/>
       * If it returns false the repository considers itself offline. Similarly,
       * any ioexception is interpreted as being offline.
       *
       * @return true if the repository is online.
       *
       * @throws java.io.IOException
       */
      public boolean checkRepositoryReachable() throws IOException {
          return false;
      }
  
      /**
       * fetch a library from the repository
       *
       * @param library
       *
       * @return
       */
      public boolean fetch(Library library) throws IOException {
          throw new BuildException("Not Implemented");
      }
  
  }
  
  
  
  1.1                  ant/src/testcases/org/apache/tools/ant/taskdefs/optional/GetLibrariesTest.java
  
  Index: GetLibrariesTest.java
  ===================================================================
  /*
   * Copyright  2004 The Apache Software Foundation
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  package org.apache.tools.ant.taskdefs.optional;
  
  import org.apache.tools.ant.BuildFileTest;
  import org.apache.tools.ant.taskdefs.optional.repository.GetLibraries;
  
  /**
   * test the test libraries stuff.
   * skip all the tests if we are offline
   */
  public class GetLibrariesTest extends BuildFileTest {
      private final static String TASKDEFS_DIR = "src/etc/testcases/taskdefs/optional/";
  
  
      public GetLibrariesTest(String name) {
          super(name);
      }
  
      public void setUp() {
          configureProject(TASKDEFS_DIR + "getlibraries.xml");
      }
  
  
      protected boolean offline() {
          return "true".equals(System.getProperty("offline"));
      }
  
      public void tearDown() {
          executeTarget("cleanup");
      }
  
      public void testEmpty() {
          expectBuildException("testEmpty",GetLibraries.ERROR_NO_DEST_DIR);
      }
  
      public void testEmpty2() {
          expectBuildException("testEmpty2", GetLibraries.ERROR_NO_REPOSITORY);
      }
  
      public void testEmpty3() {
          expectBuildException("testEmpty3", GetLibraries.ERROR_NO_LIBRARIES);
      }
  
      public void testNoRepo() {
          expectBuildException("testNoRepo", GetLibraries.ERROR_NO_REPOSITORY);
      }
  
      public void testUnknownReference() {
          expectBuildException("testUnknownReference", "Reference unknown not found.");
      }
  
      /**
       * refs are  broken
       * */
      public void testFunctionalInline() {
          if(offline()) {
              return;
          }
          executeTarget("testFunctionalInline");
      }
      
      public void testMavenInline() {
          if (offline()) {
              return;
          }
          executeTarget("testMavenInline");
      }
  
      public void testTwoRepositories() {
          expectBuildException("testTwoRepositories", GetLibraries.ERROR_ONE_REPOSITORY_ONLY);
      }
  
      public void testMavenInlineBadURL() {
          if (offline()) {
              return;
          }
          expectBuildException("testTwoRepositories",
                  GetLibraries.ERROR_INCOMPLETE_RETRIEVAL);
      }
  
      public void testRenaming() {
          if (offline()) {
              return;
          }
          executeTarget("testRenaming");
      }
  
      public void testOverwrite() {
          if (offline()) {
              return;
          }
          executeTarget("testOverwrite");
      }
   }
  
  
  
  1.27      +2 -1      ant/src/main/org/apache/tools/ant/types/defaults.properties
  
  Index: defaults.properties
  ===================================================================
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/types/defaults.properties,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- defaults.properties	13 Oct 2004 05:53:52 -0000	1.26
  +++ defaults.properties	25 Oct 2004 23:13:38 -0000	1.27
  @@ -33,4 +33,5 @@
   propertyset=org.apache.tools.ant.types.PropertySet
   assertions=org.apache.tools.ant.types.Assertions
   concatfilter=org.apache.tools.ant.filters.ConcatFilter
  -ispingable=org.apache.tools.ant.taskdefs.optional.condition.IsPingable
  \ No newline at end of file
  +ispingable=org.apache.tools.ant.taskdefs.optional.condition.IsPingable
  +mavenrepository=org.apache.tools.ant.taskdefs.optional.repository.MavenRepository
  \ No newline at end of file
  
  
  
  1.159     +1 -0      ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties
  
  Index: defaults.properties
  ===================================================================
  RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/defaults.properties,v
  retrieving revision 1.158
  retrieving revision 1.159
  diff -u -r1.158 -r1.159
  --- defaults.properties	8 Oct 2004 16:40:07 -0000	1.158
  +++ defaults.properties	25 Oct 2004 23:13:38 -0000	1.159
  @@ -203,6 +203,7 @@
   scriptdef=org.apache.tools.ant.taskdefs.optional.script.ScriptDef
   ildasm=org.apache.tools.ant.taskdefs.optional.dotnet.Ildasm
   apt=org.apache.tools.ant.taskdefs.Apt
  +getlibraries=org.apache.tools.ant.taskdefs.optional.repository.GetLibraries
   
   # deprecated ant tasks (kept for back compatibility)
   starteam=org.apache.tools.ant.taskdefs.optional.scm.AntStarTeamCheckOut
  
  
  
  1.434     +21 -0     ant/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/ant/build.xml,v
  retrieving revision 1.433
  retrieving revision 1.434
  diff -u -r1.433 -r1.434
  --- build.xml	19 Oct 2004 14:29:21 -0000	1.433
  +++ build.xml	25 Oct 2004 23:13:38 -0000	1.434
  @@ -328,6 +328,11 @@
       <filename name="${ant.package}/launch/**/*"/>
     </selector>
   
  +  <selector id="needs.commons.httpclient">
  +    <filename name="${optional.package}/repository/**/*"/>
  +  </selector>
  +
  +
     <patternset id="onlinetests">
       <exclude name="**/GetTest.java" if="offline"/>
       <exclude name="**/SignJarTest.java" if="offline"/>
  @@ -561,6 +566,17 @@
                      classpathref="classpath"/>
         </or>
       </condition>
  +
  +    <!-- http client needs commons logging -->
  +    <condition property="commons.httpclient.present">
  +      <and>
  +        <available
  +          classname="org.apache.commons.httpclient.HttpClient"
  +          classpathref="classpath"/>
  +        <isset property="commons.logging.present"/>
  +      </and>
  +    </condition>
  +
       <condition property="wsdl.found">
         <or>
           <available file="wsdl"     filepath="${env.PATH}"/>
  @@ -679,6 +695,7 @@
               <selector refid="needs.jdepend" unless="jdepend.present"/>
               <selector refid="needs.swing"  unless="swing.present"/>
               <selector refid="needs.jsch" unless="jsch.present"/>
  +            <selector refid="needs.commons.httpclient" unless="commons.httpclient.present"/>
             </or>
           </not>
         </selector>
  @@ -853,6 +870,7 @@
               <selector refid="needs.jdepend"/>
               <selector refid="needs.swing"/>
               <selector refid="needs.jsch"/>
  +            <selector refid="needs.commons.httpclient"/>
             </or>
           </not>
         </and>
  @@ -897,6 +915,7 @@
       <optional-jar dep="swing"/>
       <optional-jar dep="jsch"/>
       <optional-jar dep="jdepend"/>
  +    <optional-jar dep="commons.httpclient"/>
   
       <jar destfile="${build.lib}/${optional.jars.prefix}-weblogic.jar"
            basedir="${build.classes}"
  @@ -1471,6 +1490,7 @@
   
         <sysproperty key="ant.home" value="${ant.home}"/>
         <sysproperty key="build.tests" file="${build.tests}"/>
  +      <sysproperty key="offline" value="${offline}"/>
         <sysproperty key="build.tests.value" value="${build.tests.value}"/>
         <sysproperty key="tests-classpath.value"
                      value="${tests-classpath.value}"/>
  @@ -1624,6 +1644,7 @@
         <sysproperty key="ant.home" value="${ant.home}"/>
         <sysproperty key="build.tests" file="${build.tests}"/>
         <sysproperty key="build.tests.value" value="${build.tests.value}"/>
  +      <sysproperty key="offline" value="${offline}"/>      
         <sysproperty key="tests-classpath.value"
                      value="${tests-classpath.value}"/>
         <classpath refid="tests-classpath"/>
  
  
  
  1.676     +2 -0      ant/WHATSNEW
  
  Index: WHATSNEW
  ===================================================================
  RCS file: /home/cvs/ant/WHATSNEW,v
  retrieving revision 1.675
  retrieving revision 1.676
  diff -u -r1.675 -r1.676
  --- WHATSNEW	21 Oct 2004 13:54:25 -0000	1.675
  +++ WHATSNEW	25 Oct 2004 23:13:39 -0000	1.676
  @@ -68,6 +68,8 @@
   * Added a new "failall" value for the onerror attribute of <typedef>.
     Bugzilla report 31685.
   
  +* New task <getlibraries> can retrieve library files from a maven repository.  
  +
   Changes from Ant 1.6.2 to current Ant 1.6 CVS version
   =====================================================
   
  
  
  
  1.1                  ant/src/etc/testcases/taskdefs/optional/getlibraries.xml
  
  Index: getlibraries.xml
  ===================================================================
  <?xml version="1.0"?>
  <project name="getlibraries" basedir="." default="all">
  
  
    <!-- use the normal one at ibiblio-->
    <mavenrepository id="maven"/>
  
    <target name="init">
      <property name="lib.dir" value="getlib"/>
      <mkdir dir="${lib.dir}"/>
      <property name="commons.logging" value="commons-logging-1.0.1.jar"/>
  
      <presetdef name="getlib">
        <getlibraries destDir="${lib.dir}">
          <library archive="commons-logging" project="commons-logging" version="1.0.1"/>
        </getlibraries>
      </presetdef>
  
      <macrodef name="assert-downloaded">
        <attribute name="library" default="${commons.logging}"/>
        <sequential>
          <available property="@{library}.exists"
            file="${lib.dir}/@{library}"/>
          <fail unless="@{library}.exists">
          Not found: ${lib.dir}@{library}
          </fail>
        </sequential>
      </macrodef>
    </target>
  
    <target name="cleanup">
      <delete dir="${lib.dir}"/>
    </target>
  
    <target name="testEmpty" depends="init">
      <getlibraries/>
    </target>
  
    <target name="testEmpty2" depends="init">
      <getlibraries destDir="${lib.dir}">
  
      </getlibraries>
    </target>
  
    <target name="testEmpty3" depends="init">
      <getlibraries destDir="${lib.dir}">
        <repository/>
      </getlibraries>
    </target>
  
    <target name="testNoRepo" depends="init">
      <getlib/>
    </target>
  
    <target name="testUnknownReference" depends="init">
      <getlib>
        <repository refid="unknown"/>
      </getlib>
    </target>
  
  
    <target name="testFunctionalInline" depends="init">
      <getlib repositoryref="maven">
      </getlib>
      <assert-downloaded/>
    </target>
  
    <target name="testMavenInline" depends="init">
      <getlib>
        <mavenrepository/>
      </getlib>
      <assert-downloaded/>
    </target>
  
    <target name="testTwoRepositories" depends="init">
      <getlib>
        <mavenrepository/>
        <mavenrepository/>
      </getlib>
    </target>
  
  
    <target name="testMavenInlineBadURL" depends="init">
      <getlib>
  
      </getlib>
    </target>
  
    <target name="testRenaming" depends="init">
      <getlib>
        <mavenrepository/>
        <library archive="commons-logging" project="commons-logging" version="1.0.1"
          destinationName="renamed.jar"
          />
      </getlib>
      <assert-downloaded/>
      <assert-downloaded library="renamed.jar"/>
    </target>
  
  
    <target name="testOverwrite" depends="init">
      <getlib>
        <mavenrepository/>
      </getlib>
      <assert-downloaded/>
      <getlib>
        <mavenrepository/>
      </getlib>
    </target>
  
  </project>
  
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org