boolean (String patch, Path dest, UpdaterUI ui, boolean doBackup) { try { PatchFileCreator.PreparationResult preparationResult; File backupDir = null; PatchFileCreator.ApplicationResult applicationResult; try { File patchFile = Utils.getTempFile("patch"); LOG.info("Extracting patch file..."); ui.startProcess(UpdaterUI.message("extracting.patch.file")); ui.setProgressIndeterminate(); try (ZipFile zipFile = new ZipFile(patch); InputStream in = Utils.getEntryInputStream(zipFile, PATCH_FILE_NAME); OutputStream out = new BufferedOutputStream(Files.newOutputStream(patchFile.toPath()))) { Utils.copyStream(in, out); } ui.checkCancelled(); File destDir = dest.toFile(); preparationResult = PatchFileCreator.prepareAndValidate(patchFile, destDir, ui); Map<String, ValidationResult.Option> resolutions = askForResolutions(preparationResult.validationResults, ui); if (doBackup) { backupDir = Utils.getTempFile("backup"); if (!backupDir.mkdir()) throw new IOException("Cannot create a backup directory: " + backupDir); } applicationResult = PatchFileCreator.apply(preparationResult, resolutions, backupDir, ui); } catch (OperationCancelledException e) { LOG.log(Level.WARNING, "cancelled", e); return false; } catch (Throwable t) { LOG.log(Level.SEVERE, "prepare failed", t); String message = UpdaterUI.message("prepare.failed", t.getClass().getSimpleName(), t.getMessage()) + "\n\n" + ui.bold(UpdaterUI.message("nothing.changed.retry")) + "\n\n" + UpdaterUI.message("see.log", logPath); ui.showError(message); return false; } if (!applicationResult.applied) { List<PatchAction> appliedActions = applicationResult.appliedActions; Throwable error = applicationResult.error; if (error != null) { String message = UpdaterUI.message("apply.failed", error.getClass().getSimpleName(), error.getMessage()) + "\n\n"; if (appliedActions.isEmpty()) { message += ui.bold(UpdaterUI.message("nothing.changed.retry")); } else if (backupDir == null) { message += ui.bold(UpdaterUI.message("corrupted.reinstall")); } else { message += ui.bold(UpdaterUI.message("corrupted.reverting")); } message += "\n\n" + UpdaterUI.message("see.log", logPath); ui.showError(message); } if (!appliedActions.isEmpty() && backupDir != null) { try { PatchFileCreator.revert(preparationResult, appliedActions, backupDir, ui); } catch (Throwable t) { LOG.log(Level.SEVERE, "revert failed", t); String message = UpdaterUI.message("revert.failed", t.getClass().getSimpleName(), t.getMessage()) + "\n\n" + ui.bold(UpdaterUI.message("corrupted.reinstall")) + "\n\n" + UpdaterUI.message("see.log", logPath); ui.showError(message); } } } return applicationResult.applied; } finally { try { cleanup(ui); refreshApplicationIcon(dest.toString()); } catch (Throwable t) { LOG.log(Level.WARNING, "cleanup failed", t); } } }