+package com.tedpearson.util.update;
+
+import java.net.*;
+import java.io.*;
+import java.util.prefs.*;
+import java.awt.Component;
+import javax.swing.JOptionPane;
+import javax.swing.*;
+
+/*
+ TODO:
+ show update window with progress bar when updating (optionally)
+*/
+
+public class Updater {
+ private int version = -1;
+ private URL downloadURL;
+ private static Updater updater = new Updater();
+
+ public static Updater getUpdater() {
+ return updater;
+ }
+
+ public boolean checkForUpdate(
+ Component parentComponent,
+ String updateUrl,
+ int currentVersion) {
+ return checkForUpdate(parentComponent, updateUrl, "this program", currentVersion, true);
+ }
+
+
+ /**
+ * Just check to see if there is an update.
+ */
+ public boolean checkForUpdate(
+ Component parentComponent,
+ String updateUrl,
+ String program,
+ int currentVersion,
+ boolean promptUser) {
+ String node = "com/tedpearson/update";
+ Preferences prefs = Preferences.userRoot().node(node);
+ String update = prefs.get(updateUrl,"");
+ if(update.equals("Never")) {
+ return false;
+ }
+ if(!update.equals("Yes")) {
+ if(!promptUser) {
+ return false;
+ }
+ // first, confirm user wants to allow updates
+ int option = JOptionPane.showOptionDialog(parentComponent,
+ "Do you want to let " + program + " check for updates when it opens?",
+ "Check for Updates?",
+ 0, JOptionPane.QUESTION_MESSAGE,
+ null, new String[] {"Yes","This Time","Not Now","Never"},"Yes");
+ switch(option) {
+ case 2:
+ return false;
+ case 3:
+ prefs.put(updateUrl,"Never");
+ return false;
+ case 0:
+ prefs.put(updateUrl,"Yes");
+ case 1:
+ }
+ }
+ // query the server to check the version number
+ accessVersion(parentComponent, updateUrl);
+ // System.out.println(version+","+currentVersion);
+ if(version > currentVersion) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void checkAndUpdate(
+ Component parentComponent,
+ String updateUrl,
+ String program,
+ int currentVersion,
+ boolean promptUser,
+ String jar) {
+ if(checkForUpdate(parentComponent, updateUrl, program, currentVersion, promptUser)) {
+ updateJar(parentComponent, updateUrl, currentVersion, promptUser, jar);
+ }
+ }
+
+ public void checkAndUpdate(
+ Component parentComponent,
+ String updateUrl,
+ int currentVersion) {
+ if(checkForUpdate(parentComponent, updateUrl, currentVersion)) {
+ updateJar(parentComponent, updateUrl, currentVersion);
+ }
+ }
+
+ public void updateJar(
+ Component parentComponent,
+ String updateUrl,
+ int currentVersion) {
+ updateJar(parentComponent, updateUrl, currentVersion, true, null);
+ }
+
+ public void updateJar(
+ Component parentComponent,
+ String updateUrl,
+ int currentVersion,
+ boolean promptUser,
+ String jar) {
+ try {
+ accessVersion(parentComponent, updateUrl);
+ // download new version
+ File temp = File.createTempFile("com.tedpearson.updater.download",null);
+ temp.deleteOnExit();
+ URLConnection conn = downloadURL.openConnection();
+ ProgressMonitorInputStream pmis = new ProgressMonitorInputStream(
+ parentComponent,
+ "Downloading program update",
+ conn.getInputStream()
+ );
+ ProgressMonitor pm = pmis.getProgressMonitor();
+ pm.setMillisToDecideToPopup(0);
+ pm.setMillisToPopup(0);
+ if(!promptUser) {
+ pm.setMillisToDecideToPopup(Integer.MAX_VALUE);
+ pm.setMillisToPopup(Integer.MAX_VALUE);
+ }
+ pm.setMaximum(conn.getHeaderFieldInt("Content-Length",0));
+ copyFile(pmis, new FileOutputStream(temp));
+ // replace old with new.
+ if(jar == null) {
+ jar = getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
+ }
+ jar = jar.replaceAll("%20"," ");
+ copyFile(new FileInputStream(temp), new FileOutputStream(new File(jar)));
+ // remove temp file
+ temp.delete();
+ // launch new version and quit this one.
+ ProcessBuilder pb = new ProcessBuilder("java","-jar",jar);
+ pb.start();
+ System.exit(0);
+ // no new version
+ } catch(Exception e) {
+ // errors.
+ e.printStackTrace();
+ // show error here.
+ if(promptUser) {
+ JOptionPane.showMessageDialog(parentComponent, "There was an error while trying to update.",
+ "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ private void accessVersion(Component parentComponent, String updateUrl) {
+ if(version != -1) return;
+ try {
+ URL url = new URL(updateUrl);
+ BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
+ version = Integer.parseInt(br.readLine());
+ downloadURL = new URL(br.readLine());
+ } catch(Exception e) {
+ // errors.
+ e.printStackTrace();
+ // show error here.
+ JOptionPane.showMessageDialog(parentComponent, "There was an error while trying to update.",
+ "Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ /**
+ * Utility method to copy a file. I can't believe java doesn't have anything
+ * built-in to do something this simple with less code. Other than channels, that is.
+ *
+ * @param in stream to read file from
+ * @param out stream to write file to
+ */
+ public static void copyFile(InputStream in, OutputStream out) throws IOException {
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = in.read(buf)) > 0) {
+ out.write(buf, 0, len);
+
+ }
+ in.close();
+ out.close();
+ }
+}
\ No newline at end of file