private boolean compareMD5(String expected, File file) {
   String actual = MD5Utils.getMD5(file);
   Launcher.debug(
       "Checking MD5 of "
           + file.getName()
           + ". Expected MD5: "
           + expected
           + " | Actual MD5: "
           + actual);
   if (expected == null || actual == null) {
     return false;
   }
   return expected.equals(actual);
 }
 public static Download downloadFile(
     String url, String output, String cacheName, String md5, DownloadListener listener)
     throws IOException {
   int tries = Settings.getLoginTries();
   File outputFile = null;
   Download download = null;
   while (tries > 0) {
     System.out.println("Starting download of " + url + ", with " + tries + " tries remaining");
     tries--;
     download = new Download(url, output);
     download.setListener(listener);
     download.run();
     if (!download.isSuccess()) {
       if (download.getOutFile() != null) {
         download.getOutFile().delete();
       }
       System.err.println("Download of " + url + " Failed!");
       if (listener != null)
         listener.stateChanged("Download Failed, retries remaining: " + tries, 0F);
     } else {
       if (md5 != null) {
         String resultMD5 = MD5Utils.getMD5(download.getOutFile());
         System.out.println("Expected MD5: " + md5 + " Calculated MD5: " + resultMD5);
         if (resultMD5.equals(md5)) {
           outputFile = download.getOutFile();
           break;
         }
       } else {
         outputFile = download.getOutFile();
         break;
       }
     }
   }
   if (outputFile == null) {
     throw new IOException("Failed to download " + url);
   }
   if (cacheName != null) {
     Utils.copy(outputFile, new File(Launcher.getGameUpdater().getBinCacheDir(), cacheName));
   }
   return download;
 }
  /**
   * Returns true if validation completed without errors, false if something went wrong deleting
   * files
   *
   * @return true on validation completion, false on failure
   * @throws RestfulAPIException
   */
  private boolean validate(SpoutcraftData build) throws RestfulAPIException {
    File minecraftJar = new File(Launcher.getGameUpdater().getBinDir(), "minecraft.jar");
    if (minecraftJar.exists()) {
      if (!compareMD5(build.getMinecraft().getMd5(), minecraftJar)) {
        // Launcher.err("Invalid minecraft.jar");
        return minecraftJar.delete();
      }
    } else {
      Launcher.err("There is no minecraft.jar!");
      return true;
    }

    File spoutcraft = new File(Launcher.getGameUpdater().getBinDir(), "spoutcraft.jar");
    if (spoutcraft.exists()) {
      if (!compareMD5(build.getMD5(), spoutcraft)) {
        Launcher.err("Invalid spoutcraft.jar");
        return spoutcraft.delete();
      }
    } else {
      Launcher.err("There is no spoutcraft.jar");
      return true;
    }

    final Minecraft minecraft = build.getMinecraft();
    final String jinputMD5 = UpdateThread.findMd5("jinput", null, minecraft.getLibraries());

    File jinputJar = new File(Launcher.getGameUpdater().getBinDir(), "jinput.jar");
    if (jinputJar.exists()) {
      if (!compareMD5(jinputMD5, jinputJar)) {
        Launcher.err("Invalid jinput.jar");
        return jinputJar.delete();
      }
    } else {
      Launcher.err("There is no jinput.jar");
      return true;
    }

    final String lwjglMD5 = UpdateThread.findMd5("lwjgl", null, minecraft.getLibraries());

    File lwjglJar = new File(Launcher.getGameUpdater().getBinDir(), "lwjgl.jar");
    if (lwjglJar.exists()) {
      if (!compareMD5(lwjglMD5, lwjglJar)) {
        Launcher.err("Invalid lwjgl.jar");
        return lwjglJar.delete();
      }
    } else {
      Launcher.err("There is no lwjgl.jar");
      return true;
    }

    final String lwjgl_utilMD5 = UpdateThread.findMd5("lwjgl_util", null, minecraft.getLibraries());

    File lwjgl_utilJar = new File(Launcher.getGameUpdater().getBinDir(), "lwjgl_util.jar");
    if (lwjgl_utilJar.exists()) {
      if (!compareMD5(lwjgl_utilMD5, lwjgl_utilJar)) {
        Launcher.err("Invalid lwjgl_util.jar");
        return lwjgl_utilJar.delete();
      }
    } else {
      Launcher.err("There is no lwjgl_util.jar");
      return true;
    }

    File libDir = new File(Launcher.getGameUpdater().getBinDir(), "lib");
    List<Library> libraries = build.getLibraries();
    for (Library lib : libraries) {
      File libraryFile = new File(libDir, lib.name() + ".jar");

      if (libraryFile.exists()) {
        String md5 = MD5Utils.getMD5(libraryFile);
        if (!lib.valid(md5)) {
          Launcher.err("Invalid " + libraryFile.getName());
          return libraryFile.delete();
        }
      } else {
        Launcher.err("There is no " + libraryFile.getName());
        return true;
      }
    }
    passed = true;
    return true;
  }