private ReplicationState download(
      ReplicationDownloaderConfiguration configuration,
      ReplicationState serverState,
      ReplicationState initialLocalState) {
    URL baseUrl;
    ReplicationState localState;
    Date maximumDownloadTimestamp;

    localState = initialLocalState;

    // Determine the location of download files.
    baseUrl = configuration.getBaseUrl();

    // Determine the maximum timestamp that can be downloaded.
    maximumDownloadTimestamp =
        calculateMaximumTimestamp(
            configuration, serverState.getTimestamp(), localState.getTimestamp());
    LOG.fine("The maximum timestamp to be downloaded is " + maximumDownloadTimestamp + ".");

    // Download all files and send their contents to the sink.
    while (localState.getSequenceNumber() < serverState.getSequenceNumber()) {
      File replicationFile;
      long sequenceNumber;
      ReplicationState fileReplicationState;

      // Ensure that our current state is within the allowable timestamp range.
      if (localState.getTimestamp().compareTo(maximumDownloadTimestamp) >= 0) {
        break;
      }

      // Calculate the next sequence number.
      sequenceNumber = localState.getSequenceNumber() + 1;
      LOG.finer("Processing replication sequence " + sequenceNumber + ".");

      // Get the state associated with the next file.
      fileReplicationState = serverStateReader.getServerState(baseUrl, sequenceNumber);

      // Download the next replication file to a temporary file.
      replicationFile =
          downloadReplicationFile(
              sequenceFormatter.getFormattedName(sequenceNumber, ".osc.gz"), baseUrl);

      // Process the file and send its contents to the sink.
      processReplicationFile(replicationFile, fileReplicationState);

      // Update the local state to reflect the file state just processed.
      localState = fileReplicationState;
    }

    return localState;
  }
  private void runImpl() {
    try {
      ReplicationDownloaderConfiguration configuration;
      ReplicationState serverState;
      ReplicationState localState;
      PropertiesPersister localStatePersistor;

      // Instantiate utility objects.
      configuration =
          new ReplicationDownloaderConfiguration(new File(workingDirectory, CONFIG_FILE));

      // Obtain the server state.
      LOG.fine("Reading current server state.");
      serverState = serverStateReader.getServerState(configuration.getBaseUrl());

      // Build the local state persister which is used for both loading and storing local state.
      localStatePersistor = new PropertiesPersister(new File(workingDirectory, LOCAL_STATE_FILE));

      // Begin processing.
      processInitialize(Collections.<String, Object>emptyMap());

      // If local state isn't available we need to copy server state to be the initial local state
      // then exit.
      if (localStatePersistor.exists()) {
        localState = new ReplicationState(localStatePersistor.loadMap());

        // Download and process the replication files.
        localState = download(configuration, serverState, localState);

      } else {
        localState = serverState;

        processInitializeState(localState);
      }

      // Commit downstream changes.
      processComplete();

      // Persist the local state.
      localStatePersistor.store(localState.store());

    } finally {
      processRelease();
    }
  }