private void downloadSubmission(
      File formInstancesDir,
      DatabaseUtils formDatabase,
      BriefcaseFormDefinition lfd,
      FormStatus fs,
      String uri)
      throws Exception {

    if (formDatabase.hasRecordedInstance(uri) != null) {
      logger.info("already present - skipping fetch: " + uri);
      return;
    }

    String formId = lfd.getSubmissionKey(uri);

    if (isCancelled()) {
      fs.setStatusString("aborting fetch of submission...", true);
      EventBus.publish(new FormStatusEvent(fs));
      throw new SubmissionDownloadException("Transfer cancelled by user.");
    }

    String baseUrl = serverInfo.getUrl() + "/view/downloadSubmission";

    Map<String, String> params = new HashMap<String, String>();
    params.put("formId", formId);
    String fullUrl = WebUtils.createLinkWithProperties(baseUrl, params);
    AggregateUtils.DocumentFetchResult result;
    try {
      DocumentDescription submissionDescription =
          new DocumentDescription(
              "Fetch of a submission failed.  Detailed error: ",
              "Fetch of a submission failed.",
              "submission",
              terminationFuture);
      result =
          AggregateUtils.getXmlDocument(fullUrl, serverInfo, false, submissionDescription, null);
    } catch (XmlDocumentFetchException e) {
      throw new SubmissionDownloadException(e.getMessage());
    }

    // and parse the document...
    SubmissionManifest submissionManifest;
    try {
      submissionManifest = XmlManipulationUtils.parseDownloadSubmissionResponse(result.doc);
    } catch (ParsingException e) {
      throw new SubmissionDownloadException(e.getMessage());
    }

    String msg = "Fetched instanceID=" + submissionManifest.instanceID;
    logger.info(msg);

    if (FileSystemUtils.hasFormSubmissionDirectory(
        formInstancesDir, submissionManifest.instanceID)) {
      // create instance directory...
      File instanceDir =
          FileSystemUtils.assertFormSubmissionDirectory(
              formInstancesDir, submissionManifest.instanceID);

      // fetch attachments
      for (MediaFile m : submissionManifest.attachmentList) {
        downloadMediaFileIfChanged(instanceDir, m, fs);
      }

      // write submission file -- we rely on instanceId being unique...
      File submissionFile = new File(instanceDir, "submission.xml");
      OutputStreamWriter fo = new OutputStreamWriter(new FileOutputStream(submissionFile), "UTF-8");
      fo.write(submissionManifest.submissionXml);
      fo.close();

      // if we get here and it was a legacy server (0.9.x), we don't
      // actually know whether the submission was complete.  Otherwise,
      // if we get here, we know that this is a completed submission
      // (because it was in /view/submissionList) and that we safely
      // copied it into the storage area (because we didn't get any
      // exceptions).
      if (serverInfo.isOpenRosaServer()) {
        formDatabase.assertRecordedInstanceDirectory(uri, instanceDir);
      }
    } else {
      // create instance directory...
      File instanceDir =
          FileSystemUtils.assertFormSubmissionDirectory(
              formInstancesDir, submissionManifest.instanceID);

      // fetch attachments
      for (MediaFile m : submissionManifest.attachmentList) {
        downloadMediaFileIfChanged(instanceDir, m, fs);
      }

      // write submission file
      File submissionFile = new File(instanceDir, "submission.xml");
      OutputStreamWriter fo = new OutputStreamWriter(new FileOutputStream(submissionFile), "UTF-8");
      fo.write(submissionManifest.submissionXml);
      fo.close();

      // if we get here and it was a legacy server (0.9.x), we don't
      // actually know whether the submission was complete.  Otherwise,
      // if we get here, we know that this is a completed submission
      // (because it was in /view/submissionList) and that we safely
      // copied it into the storage area (because we didn't get any
      // exceptions).
      if (serverInfo.isOpenRosaServer()) {
        formDatabase.assertRecordedInstanceDirectory(uri, instanceDir);
      }
    }
  }
  public boolean downloadFormAndSubmissionFiles(List<FormStatus> formsToTransfer) {
    boolean allSuccessful = true;

    // boolean error = false;
    int total = formsToTransfer.size();

    for (int i = 0; i < total; i++) {
      FormStatus fs = formsToTransfer.get(i);

      if (isCancelled()) {
        fs.setStatusString("aborted. Skipping fetch of form and submissions...", true);
        EventBus.publish(new FormStatusEvent(fs));
        return false;
      }

      RemoteFormDefinition fd = (RemoteFormDefinition) fs.getFormDefinition();
      fs.setStatusString("Fetching form definition", true);
      EventBus.publish(new FormStatusEvent(fs));
      try {

        File tmpdl = FileSystemUtils.getTempFormDefinitionFile();
        AggregateUtils.commonDownloadFile(serverInfo, tmpdl, fd.getDownloadUrl());

        fs.setStatusString("resolving against briefcase form definitions", true);
        EventBus.publish(new FormStatusEvent(fs));

        boolean successful = false;
        BriefcaseFormDefinition briefcaseLfd;
        DatabaseUtils formDatabase = null;
        try {
          try {
            briefcaseLfd = BriefcaseFormDefinition.resolveAgainstBriefcaseDefn(tmpdl);
            if (briefcaseLfd.needsMediaUpdate()) {

              if (fd.getManifestUrl() != null) {
                File mediaDir = FileSystemUtils.getMediaDirectory(briefcaseLfd.getFormDirectory());
                String error = downloadManifestAndMediaFiles(mediaDir, fs);
                if (error != null) {
                  allSuccessful = false;
                  fs.setStatusString("Error fetching form definition: " + error, false);
                  EventBus.publish(new FormStatusEvent(fs));
                  continue;
                }
              }
            }
            formDatabase =
                new DatabaseUtils(FileSystemUtils.getFormDatabase(briefcaseLfd.getFormDirectory()));

          } catch (BadFormDefinition e) {
            e.printStackTrace();
            allSuccessful = false;
            fs.setStatusString("Error parsing form definition: " + e.getMessage(), false);
            EventBus.publish(new FormStatusEvent(fs));
            continue;
          }

          fs.setStatusString("preparing to retrieve instance data", true);
          EventBus.publish(new FormStatusEvent(fs));

          File formInstancesDir =
              FileSystemUtils.getFormInstancesDirectory(briefcaseLfd.getFormDirectory());

          // this will publish events
          successful =
              downloadAllSubmissionsForForm(formInstancesDir, formDatabase, briefcaseLfd, fs);
        } catch (FileSystemException e) {
          e.printStackTrace();
          allSuccessful = false;
          fs.setStatusString("unable to open form database: " + e.getMessage(), false);
          EventBus.publish(new FormStatusEvent(fs));
          continue;
        } finally {
          if (formDatabase != null) {
            try {
              formDatabase.close();
            } catch (SQLException e) {
              e.printStackTrace();
              allSuccessful = false;
              fs.setStatusString("unable to close form database: " + e.getMessage(), false);
              EventBus.publish(new FormStatusEvent(fs));
              continue;
            }
          }
        }

        allSuccessful = allSuccessful && successful;

        // on success, we haven't actually set a success event (because we don't know we're done)
        if (successful) {
          fs.setStatusString("SUCCESS!", true);
          EventBus.publish(new FormStatusEvent(fs));
        } else {
          fs.setStatusString("FAILED.", true);
          EventBus.publish(new FormStatusEvent(fs));
        }

      } catch (SocketTimeoutException se) {
        se.printStackTrace();
        allSuccessful = false;
        fs.setStatusString(
            "Communications to the server timed out. Detailed message: "
                + se.getLocalizedMessage()
                + " while accessing: "
                + fd.getDownloadUrl()
                + " A network login screen may be interfering with the transmission to the server.",
            false);
        EventBus.publish(new FormStatusEvent(fs));
        continue;
      } catch (IOException e) {
        e.printStackTrace();
        allSuccessful = false;
        fs.setStatusString(
            "Unexpected error: "
                + e.getLocalizedMessage()
                + " while accessing: "
                + fd.getDownloadUrl()
                + " A network login screen may be interfering with the transmission to the server.",
            false);
        EventBus.publish(new FormStatusEvent(fs));
        continue;
      } catch (FileSystemException e) {
        e.printStackTrace();
        allSuccessful = false;
        fs.setStatusString(
            "Unexpected error: "
                + e.getLocalizedMessage()
                + " while accessing: "
                + fd.getDownloadUrl(),
            false);
        EventBus.publish(new FormStatusEvent(fs));
        continue;
      } catch (URISyntaxException e) {
        e.printStackTrace();
        allSuccessful = false;
        fs.setStatusString(
            "Unexpected error: "
                + e.getLocalizedMessage()
                + " while accessing: "
                + fd.getDownloadUrl(),
            false);
        EventBus.publish(new FormStatusEvent(fs));
        continue;
      } catch (TransmissionException e) {
        e.printStackTrace();
        allSuccessful = false;
        fs.setStatusString(
            "Unexpected error: "
                + e.getLocalizedMessage()
                + " while accessing: "
                + fd.getDownloadUrl(),
            false);
        EventBus.publish(new FormStatusEvent(fs));
        continue;
      }
    }
    return allSuccessful;
  }