/*.................................................................................................................*/
 boolean checkUsernamePassword(boolean tellUserAboutCipres) {
   if (StringUtil.blank(username) || StringUtil.blank(password)) {
     MesquiteBoolean answer = new MesquiteBoolean(false);
     MesquiteString usernameString = new MesquiteString();
     if (username != null) usernameString.setValue(username);
     MesquiteString passwordString = new MesquiteString();
     if (password != null) passwordString.setValue(password);
     String help =
         "You will need an account on the CIPRes REST system to use this service.  To register, go to https://www.phylo.org/restusers/register.action";
     new UserNamePasswordDialog(
         ownerModule.containerOfModule(),
         "Sign in to CIPRes",
         help,
         "",
         "Username",
         "Password",
         answer,
         usernameString,
         passwordString);
     if (answer.getValue()) {
       username = usernameString.getValue();
       password = passwordString.getValue();
     }
     ownerModule.storePreferences();
   }
   boolean success = StringUtil.notEmpty(username) && StringUtil.notEmpty(password);
   if (!success && tellUserAboutCipres) {
     MesquiteMessage.discreetNotifyUser(
         "Use of the CIPRes service requires an account with CIPRes's REST service.  Go to https://www.phylo.org/restusers/register.action to register for an account");
   }
   return success;
 }
 /*.................................................................................................................*/
 public boolean downloadWorkingResults(
     HttpClient httpclient,
     String jobURL,
     String rootDir,
     String fileName,
     boolean onlyNewOrModified) {
   if (StringUtil.blank(fileName)) return false;
   String workingUri = getWorkingDirectory(jobURL);
   if (StringUtil.notEmpty(workingUri)) {
     Document cipresResponseDoc = cipresQuery(httpclient, workingUri, "workingdir");
     if (cipresResponseDoc != null) {
       CipresJobFile[] cipresJobFiles = processFilesDocument(cipresResponseDoc);
       if (cipresJobFiles == null || cipresJobFiles.length == 0) {
         return false;
       }
       for (int job = 0; job < cipresJobFiles.length; job++) {
         if (fileName.equalsIgnoreCase(cipresJobFiles[job].getFileName())
             && (!onlyNewOrModified
                 || fileNewOrModified(previousCipresJobFiles, cipresJobFiles, job)))
           cipresDownload(
               httpclient,
               cipresJobFiles[job].getDownloadURL(),
               rootDir + cipresJobFiles[job].getFileName());
       }
       previousCipresJobFiles = cipresJobFiles.clone();
       return true;
     }
   }
   return false;
 }
  /*.................................................................................................................*/
  public boolean downloadResults(
      HttpClient httpclient, String jobURL, String rootDir, boolean onlyNewOrModified) {

    String resultsUri = getResultsDirectory(jobURL);
    if (StringUtil.notEmpty(resultsUri)) {
      Document cipresResponseDoc = cipresQuery(httpclient, resultsUri, "results");
      if (cipresResponseDoc != null) {
        CipresJobFile[] cipresJobFiles = processFilesDocument(cipresResponseDoc);
        if (cipresJobFiles == null || cipresJobFiles.length == 0) {
          ownerModule.logln(cipresResponseDoc.toString());
          return false;
        }
        for (int job = 0; job < cipresJobFiles.length; job++) {
          if (!onlyNewOrModified || fileNewOrModified(previousCipresJobFiles, cipresJobFiles, job))
            cipresDownload(
                httpclient,
                cipresJobFiles[job].getDownloadURL(),
                rootDir + cipresJobFiles[job].getFileName());
        }
        previousCipresJobFiles = cipresJobFiles.clone();
        return true;
      }
    }
    return false;
  }
  public void reportError(Document doc, String noteToUser, boolean resetPassword) {
    if (doc == null) return;
    String displayMessage = doc.getRootElement().elementText("displayMessage");
    String message = doc.getRootElement().elementText("message");
    if (StringUtil.notEmpty(message)) {
      if ("Authentication Error".equalsIgnoreCase(displayMessage)) {
        if (resetPassword) password = "";
      } else {
        ownerModule.logln("\n******************");
        ownerModule.logln(noteToUser);
        ownerModule.logln(displayMessage);
        ownerModule.logln(message);
        List paramErrors = doc.getRootElement().elements("paramError");
        if (paramErrors != null)
          for (Iterator iter = paramErrors.iterator(); iter.hasNext(); ) {
            Element nextEntry = (Element) iter.next();
            String param = nextEntry.elementText("param");
            String error = nextEntry.elementText("error");
            ownerModule.logln("  " + param + ": " + error);
          }

        ownerModule.logln("\n******************\n");
      }
    }
  }
 /*.................................................................................................................*/
 public void prepareBuilder(MultipartEntityBuilder builder, String cipresTool, String jobID) {
   if (builder != null) {
     builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
     builder.addTextBody("tool", cipresTool);
     if (StringUtil.notEmpty(jobID)) builder.addTextBody("metadata.clientJobId", jobID);
     builder.addTextBody("metadata.statusEmail", "true");
     builder.addTextBody("vparam.runtime_", "0.50", ContentType.TEXT_PLAIN);
   }
 }
 /*.................................................................................................................*/
 boolean fileNewOrModified(
     CipresJobFile[] previousJobFiles, CipresJobFile[] jobFiles, int fileNumber) {
   if (previousJobFiles != null && jobFiles != null && fileNumber < jobFiles.length) {
     String fileName = jobFiles[fileNumber].getFileName();
     if (StringUtil.notEmpty(fileName)) {
       for (int i = 0; i < previousJobFiles.length; i++) {
         if (fileName.equalsIgnoreCase(
             previousJobFiles[i].getFileName())) { // we've found the file
           String lastMod = jobFiles[fileNumber].getLastModified();
           if (StringUtil.notEmpty(lastMod))
             return !lastMod.equals(
                 previousJobFiles[i].getLastModified()); // return true if the strings don't match
           else return true;
         }
       }
     }
   }
   return true;
 }
  /*.................................................................................................................*/
  public void getResults(HttpClient httpclient, String jobURL) {

    String resultsUri = getResultsDirectory(jobURL);
    if (StringUtil.notEmpty(resultsUri)) {
      Document cipresResponseDoc = cipresQuery(httpclient, resultsUri, "results");
      if (cipresResponseDoc != null) {
        CipresJobFile[] cipresJobFiles = processFilesDocument(cipresResponseDoc);
        for (int job = 0; job < cipresJobFiles.length; job++) {
          Debugg.println("fileName: " + cipresJobFiles[job].getFileName());
          Debugg.println("     downloadURL: " + cipresJobFiles[job].getDownloadURL());
          Debugg.println("     downloadTitle: " + cipresJobFiles[job].getDownloadTitle());
          Debugg.println("     length: " + cipresJobFiles[job].getLength());
        }
        previousCipresJobFiles = cipresJobFiles.clone();
      }
    }
  }
  /** The core method that initiates a job on CIPRes. */
  public boolean postJob(
      HttpClient httpclient, MultipartEntityBuilder builder, MesquiteString jobURL) {
    if (builder == null) return false;
    String URL = baseURL + "/job/" + username;
    HttpPost httppost = new HttpPost(URL);
    httppost.addHeader("cipres-appkey", CIPRESkey);

    // some of this from
    // http://stackoverflow.com/questions/18964288/upload-a-file-through-an-http-form-via-multipartentitybuilder-with-a-progress
    HttpEntity cipresEntity = builder.build();

    httppost.setEntity(cipresEntity);

    try {
      HttpResponse response = httpclient.execute(httppost);

      HttpEntity responseEntity = response.getEntity();
      InputStream instream = responseEntity.getContent();
      BufferedReader br = new BufferedReader(new InputStreamReader(instream));
      StringBuffer sb = new StringBuffer();
      String line = "";
      while ((line = br.readLine()) != null) {
        sb.append(line + StringUtil.lineEnding());
      }

      Document cipresResponseDoc = loadXMLFile("jobstatus", sb.toString()); // let's see how it went
      boolean success = false;
      if (cipresResponseDoc != null) {
        processJobSubmissionResponse(cipresResponseDoc, jobURL);
        if (verbose) ownerModule.logln(sb.toString());
        if (jobURL != null) success = StringUtil.notEmpty(jobURL.getValue());
        else success = true;
      } else {
        cipresResponseDoc = loadXMLFile(sb.toString());
        reportError(cipresResponseDoc, "Error with CIPRes run", false);
      }
      EntityUtils.consume(response.getEntity());
      return success;
    } catch (IOException e) {
      Debugg.printStackTrace(e);
    }
    return false;
  }