chiark / gitweb /
cd396c5cc36aef8d9db6cc2111bca2450878ed0a
[jarrg-owen.git] / src / com / tedpearson / util / update / Updater.java
1 package com.tedpearson.util.update;
2
3 import java.net.*;
4 import java.io.*;
5 import java.util.prefs.*;
6 import java.awt.Component;
7 import javax.swing.JOptionPane;
8 import javax.swing.*;
9
10 /*
11         TODO:
12         show update window with progress bar when updating (optionally)
13 */
14
15 public class Updater {
16         private int version = -1;
17         private URL downloadURL;
18         private static Updater updater = new Updater();
19         
20         public static Updater getUpdater() {
21                 return updater;
22         }
23         
24         public boolean checkForUpdate(
25                         Component parentComponent,
26                         String updateUrl,
27                         int currentVersion) {
28                 return checkForUpdate(parentComponent, updateUrl, "this program", currentVersion, true);
29         }
30         
31         
32         /**
33         * Just check to see if there is an update.
34         */
35         public boolean checkForUpdate(
36                         Component parentComponent,
37                         String updateUrl,
38                         String program,
39                         int currentVersion,
40                         boolean promptUser) {
41                 String node = "com/tedpearson/update";
42                 Preferences prefs = Preferences.userRoot().node(node);
43                 String update = prefs.get(updateUrl,"");
44                 if(update.equals("Never")) {
45                         return false;
46                 }
47                 if(!update.equals("Yes")) {
48                         if(!promptUser) {
49                                 return false;
50                         }
51                         // first, confirm user wants to allow updates
52                         int option = JOptionPane.showOptionDialog(parentComponent,
53                                 "Do you want to let " + program + " check for updates when it opens?",
54                                 "Check for Updates?",
55                                 0, JOptionPane.QUESTION_MESSAGE,
56                                 null, new String[] {"Yes","This Time","Not Now","Never"},"Yes");
57                         switch(option) {
58                                 case 2:
59                                         return false;
60                                 case 3:
61                                         prefs.put(updateUrl,"Never");
62                                         return false;
63                                 case 0:
64                                         prefs.put(updateUrl,"Yes");
65                                 case 1:
66                         }
67                 }
68                 // query the server to check the version number
69                 accessVersion(parentComponent, updateUrl);
70                 // System.out.println(version+","+currentVersion);
71                 if(version > currentVersion) {
72                         return true;
73                 } else {
74                         return false;
75                 }
76         }
77         
78         public void checkAndUpdate(
79                         Component parentComponent,
80                         String updateUrl,
81                         String program,
82                         int currentVersion,
83                         boolean promptUser,
84                         String jar) {
85                 if(checkForUpdate(parentComponent, updateUrl, program, currentVersion, promptUser)) {
86                         updateJar(parentComponent, updateUrl, currentVersion, promptUser, jar);
87                 }
88         }
89         
90         public void checkAndUpdate(
91                         Component parentComponent,
92                         String updateUrl,
93                         int currentVersion) {
94                 if(checkForUpdate(parentComponent, updateUrl, currentVersion)) {
95                         updateJar(parentComponent, updateUrl, currentVersion);
96                 }
97         }
98         
99         public void updateJar(
100                         Component parentComponent,
101                         String updateUrl,
102                         int currentVersion) {
103                 updateJar(parentComponent, updateUrl, currentVersion, true, null);
104         }
105         
106         public void updateJar(
107                         Component parentComponent,
108                         String updateUrl,
109                         int currentVersion,
110                         boolean promptUser,
111                         String jar) {
112                 try {
113                         accessVersion(parentComponent, updateUrl);
114                         // download new version
115                         File temp = File.createTempFile("com.tedpearson.updater.download",null);
116                         temp.deleteOnExit();
117                         URLConnection conn = downloadURL.openConnection();
118                         ProgressMonitorInputStream pmis = new ProgressMonitorInputStream(
119                                 parentComponent,
120                                 "Downloading program update",
121                                 conn.getInputStream()
122                         );
123                         ProgressMonitor pm = pmis.getProgressMonitor();
124                         pm.setMillisToDecideToPopup(0);
125                         pm.setMillisToPopup(0);
126                         if(!promptUser) {
127                                 pm.setMillisToDecideToPopup(Integer.MAX_VALUE);
128                                 pm.setMillisToPopup(Integer.MAX_VALUE);
129                         }
130                         pm.setMaximum(conn.getHeaderFieldInt("Content-Length",0));
131                         copyFile(pmis, new FileOutputStream(temp));
132                         // replace old with new.
133                         if(jar == null) {
134                                 jar = getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
135                         }       
136                         jar = jar.replaceAll("%20"," ");
137                         copyFile(new FileInputStream(temp), new FileOutputStream(new File(jar)));
138                         // remove temp file
139                         temp.delete();
140                         // launch new version and quit this one.
141                         ProcessBuilder pb = new ProcessBuilder("java","-jar",jar);
142                         pb.start();
143                         System.exit(0);
144                         // no new version
145                 } catch(Exception e) {
146                         // errors.
147                         e.printStackTrace();
148                         // show error here.
149                         if(promptUser) {
150                                 JOptionPane.showMessageDialog(parentComponent, "There was an error while trying to update.",
151                                         "Error", JOptionPane.ERROR_MESSAGE);
152                         }
153                 }
154         }
155         
156         private void accessVersion(Component parentComponent, String updateUrl) {
157                 if(version != -1) return;
158                 try {
159                         URL url = new URL(updateUrl);
160                         BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
161                         version = Integer.parseInt(br.readLine());
162                         downloadURL = new URL(br.readLine());
163                 } catch(Exception e) {
164                         // errors.
165                         e.printStackTrace();
166                         // show error here.
167                         JOptionPane.showMessageDialog(parentComponent, "There was an error while trying to update.",
168                                 "Error", JOptionPane.ERROR_MESSAGE);
169                 }
170         }
171         
172         /**
173         *       Utility method to copy a file. I can't believe java doesn't have anything
174         *       built-in to do something this simple with less code. Other than channels, that is.
175         *       
176         *       @param in stream to read file from
177         *       @param out stream to write file to
178         */
179         public static void copyFile(InputStream in, OutputStream out) throws IOException {
180                 byte[] buf = new byte[1024];
181                 int len;
182                 while ((len = in.read(buf)) > 0) {
183                         out.write(buf, 0, len);
184                         
185                 }
186                 in.close();
187                 out.close();
188         }
189 }