/**
   * Locates and if necessary downloads the artifact.
   *
   * @param artifact the Artifact to download and locate in the cache.
   * @return the File pointing to the artifact. The file may not exist if the download has failed.
   */
  private File getResourceFile(Artifact artifact) throws TransitException, IOException {
    CacheMonitorRouter monitor = Transit.getInstance().getCacheMonitorRouter();
    if (monitor != null) {
      monitor.resourceRequested(artifact);
    }
    if (null == artifact) {
      throw new NullArgumentException("artifact");
    }
    String path = m_resolver.resolvePath(artifact);
    File destination = new File(m_cacheDir, path);
    File parentDir = destination.getParentFile();
    parentDir.mkdirs();
    boolean exist = destination.exists();
    boolean success;
    if (exist) {
      success = true;
    } else {
      ResourceHost known = findKnownGroupHost(artifact);
      success = download(known, artifact, destination);
      if (!success) {
        ResourceHost any = findAnyPresence(artifact);
        success = download(any, artifact, destination);
      }
    }
    if (success) {
      checkInternalConsistency(artifact, destination);
      endNotifyMonitor(monitor, exist, artifact, destination);
    }

    if (!destination.exists() && monitor != null) {
      monitor.failedDownload(artifact);
    }

    return destination;
  }
  /**
   * Download an artifact from a host to the cache.
   *
   * @param host the remote host
   * @param artifact the artifact being retrieved
   * @param destination the cached destination
   * @return TRUE if downloaded
   * @exception IOException if an IO error occurs
   * @exception TransitException if a transit system error occurs
   */
  private boolean download(ResourceHost host, Artifact artifact, File destination)
      throws IOException, TransitException {
    if (host == null) {
      return false;
    }

    CacheMonitorRouter monitor = Transit.getInstance().getCacheMonitorRouter();

    File parentDir = destination.getParentFile();
    File tempFile = File.createTempFile("~dpml", ".tmp", parentDir);
    tempFile.deleteOnExit(); // safety harness in case we abort abnormally
    FileOutputStream tempOut = new FileOutputStream(tempFile);

    try {
      Date lastModified = host.download(artifact, tempOut);
      // An atomic operation and no risk of a corrupted
      // artifact content.
      tempFile.renameTo(destination);
      destination.setLastModified(lastModified.getTime());
      return true;
    } catch (Throwable e) {
      tempFile.delete();
      if (monitor != null) {
        monitor.failedDownloadFromHost(host.toString(), artifact, e);
      }
      return false;
    }
  }