package forkk.multimc.update; import java.io.File; import java.io.IOException; import java.util.Arrays; import javax.swing.JOptionPane; import forkk.multimc.compat.OS; import forkk.multimc.compat.OSUtils; import forkk.multimc.util.FileUtils; public class UpdateFile { /** * Replaces the file specified by args[0] with this file and then quits. * This is used for updating, since files that are running cannot be modified. * @param args The first argument must specify the file to update. * The second one is a string of options that do the following:<br> * <ul> * <li>r: Runs the file after it is updated</li> * </ul> */ public static void main(String[] args) { File currentPath = null; File targetPath = null; try { if (args.length < 1) { System.out.println("Update file must have at least one argument!"); JOptionPane.showMessageDialog(null, "Error updating MultiMC: " + "Missing argument" + getCurrentFilePath(), "Update Failed", JOptionPane.ERROR_MESSAGE); return; } currentPath = new File(getCurrentFilePath()); targetPath = new File(args[0]); long waitStart = System.currentTimeMillis(); while (true) { try { FileUtils.copyFile(currentPath, targetPath, true); } catch (IOException e) { if (e.getMessage().contains("being used")) { if (System.currentTimeMillis() < waitStart + (3 * 1000)) { try { Thread.sleep(100); } catch (InterruptedException ie) { } continue; } else { JOptionPane.showMessageDialog(null, "Couldn't " + "update because the operation timed out " + "while waiting for MultiMC to close.\n" + "Path Replacing: " + targetPath + "\n" + "Current File: " + getCurrentFilePath() + "\n" + "Args: " + Arrays.toString(args) + "\n" + "Error Message: " + e.toString(), "Update Timed Out", JOptionPane.ERROR_MESSAGE); System.exit(0); } } else { throw e; } } break; } JOptionPane.showMessageDialog(null, "MultiMC updated successfully.", "Update Success", JOptionPane.INFORMATION_MESSAGE); } catch (IOException e) { e.printStackTrace(); System.err.println("Error occurred, update failed."); JOptionPane.showMessageDialog(null, "Error updating MultiMC: " + e.toString(), "Update Failed", JOptionPane.ERROR_MESSAGE); } finally { if (args.length >= 2) { if (args[1].lastIndexOf('r') > -1 && targetPath != null) { ProcessBuilder procBuilder = new ProcessBuilder( "java", "-jar", targetPath.toString()); try { System.out.println("Starting " + targetPath.toString()); procBuilder.start(); } catch (IOException e) { e.printStackTrace(); } } } } } /** * @return A path to the currently executing file */ public static String getCurrentFilePath() { File path = new File(UpdateFile.class.getClass(). getResource("/forkk/multimc/update/UpdateFile.class").getPath()); return path.toString().substring((OSUtils.getCurrentOS() == OS.WINDOWS? 6 : 5), path.toString().lastIndexOf('!')); } }