chiark / gitweb /
installer no longer phones home (!)
[jarrg-ian.git] / src / com / tedpearson / ypp / market / Installer.java
1 package com.tedpearson.ypp.market;
2
3 import javax.swing.*;
4 import java.awt.*;
5 import java.awt.event.*;
6 import javax.swing.border.*;
7 import java.io.*;
8 import com.tedpearson.util.update.*;
9 import java.util.Properties;
10 import java.net.URLDecoder;
11
12 /*
13         allow adding islands/oceans
14         implement uploads to YAARG
15 */
16
17 /**
18 *       An Installer for PCTB Java Client.
19 */
20 public class Installer extends JFrame {
21         private JLabel label;
22         private JProgressBar progress;
23         private JButton install, uninstall;
24         private static String os = System.getProperty("os.name");
25         private static String home = System.getProperty("java.home");
26         private static String user_home = System.getProperty("user.home");
27         private boolean installed = false;
28         private boolean uninstalled = false;
29         private static PrintWriter pw;
30         
31         public static void debug(String str) {
32                 try {
33                         pw.println(str);
34                         pw.flush();
35                 }catch(Exception e) {
36                         
37                 }
38         }
39         
40         public static void main(String[] args) {
41                 /*
42                 try{
43                         pw = new PrintWriter("C:/Users/Public/ERRORS");
44                 }catch(Exception e) {
45                         
46                 }
47                 */
48                 new Installer(args);
49         }
50         
51         /**
52         *       Checks if we have permission to write to the Java Home folder
53         *       that runs YPP. Pops up an error message and exits if we don't have access,
54         *       or on Mac OS X, re-runs the installer using applescript to authenticate.
55         */
56         private void checkPermission(String[] args) {
57                 File a11y = null;
58                 a11y = new File(getJavaHome(),"lib");
59                 if(os.equals("Mac OS X")) {
60                         if(!a11y.canWrite()) {
61                                 JOptionPane.showMessageDialog(null,"Please authenticate as an Administrator, when prompted, to continue installation.");
62                                 try {
63                                         String installer = URLDecoder.decode(getClass().getProtectionDomain().getCodeSource().getLocation()
64                                                 .getPath(), "URT-8");
65                                         Runtime.getRuntime().exec(new String[]{"osascript","-e","do shell script \"java -jar " +
66                                                 installer + "\" with administrator privileges"});
67                                 } catch(Exception e) {
68                                         e.printStackTrace();
69                                 }
70                                 System.exit(0);
71                         }
72                 } else {
73                         // clean up after myself
74                         if(os.contains("Vista")) {
75                                 File tempDir = new File(System.getProperty("java.io.tmpdir"));
76                                 for(File f : tempDir.listFiles()) {
77                                         if(f.getName().startsWith("PCTB-lib")) {
78                                                 for(File g : f.listFiles()) {
79                                                         g.delete();
80                                                 }
81                                                 f.delete();
82                                         }
83                                 }
84                         }
85                         // first check for YPP java
86                         boolean canWrite = true;
87                         File test = new File(a11y, "test_pctb");
88                         try {
89                                 test.createNewFile();
90                                 test.delete();
91                         } catch(IOException e) {
92                                 canWrite = false;
93                         }
94                         if(!canWrite || !a11y.canWrite()) {
95                                 if(os.contains("Vista")) {
96                                         if(args.length == 1 && args[0].equals("--elevate")) {
97                                                 JOptionPane.showMessageDialog(null,"Please run this installer while logged in as an Administrator.");
98                                                 System.exit(0);
99                                         }
100                                         try {
101                                                 String installer = URLDecoder.decode(getClass().getProtectionDomain().getCodeSource().getLocation()
102                                                         .getPath(), "UTF-8").replaceFirst("/","");
103                                                 ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/C", "elevate javaw -jar \"" + installer +
104                                                         "\" --elevate");
105                                                 // create temp lib directory
106                                                 File temp = File.createTempFile("PCTB-lib",null);
107                                                 temp.delete();
108                                                 temp.mkdir();
109                                                 File elevate = new File(temp, "elevate.cmd");
110                                                 OutputStream out = new FileOutputStream(elevate);
111                                                 InputStream in = getClass().getResourceAsStream("/lib/elevate.cmd");
112                                                 Updater.copyFile(in, out);
113                                                 
114                                                 elevate = new File(temp, "elevate.vbs");
115                                                 out = new FileOutputStream(elevate);
116                                                 in = getClass().getResourceAsStream("/lib/elevate.vbs");
117                                                 Updater.copyFile(in, out);
118                                                 
119                                                 pb.directory(temp);
120                                                 Process p = pb.start();
121                                         } catch(Exception e) {
122                                                 e.printStackTrace();
123                                         }
124                                         System.exit(0);
125                                 } else {
126                                         JOptionPane.showMessageDialog(null,"Please run this installer while logged in as an Administrator.");
127                                         System.exit(0);
128                                 }
129                         }
130                 }
131         }
132         
133         /**
134         *       Create the installer GUI
135         */
136         public Installer(String[] args) {
137                 super("PCTB Installer");
138                 
139                 // gui: simple window with status area and progress bar
140                 checkPermission(args);
141                 label = new JLabel("Ready to install!");
142                 add(label,BorderLayout.NORTH);
143                 progress = new JProgressBar();
144                 progress.setBorder(new EmptyBorder(10,0,10,0));
145                 add(progress,BorderLayout.CENTER);
146                 String buttonText = "Install";
147                 install = new JButton(buttonText);
148                 JPanel buttons = new JPanel();
149                 add(buttons,BorderLayout.SOUTH);
150                 install.addActionListener(new ActionListener() {
151                         public void actionPerformed(ActionEvent e) {
152                                 if(installed) {
153                                         System.exit(0);
154                                 }
155                                 try {
156                                         install.setEnabled(false);
157                                         uninstall.setEnabled(false);
158                                         install();
159                                 } catch(IOException err) {
160                                         err.printStackTrace();
161                                         JOptionPane.showMessageDialog(Installer.this, "Error during installation.");
162                                         setButtonStatus(false,false);
163                                         label.setText("Install failed!");
164                                 }
165                         }
166                 });
167                 uninstall = new JButton("Uninstall");
168                 buttons.add(uninstall);
169                 buttons.add(install);
170                 uninstall.addActionListener(new ActionListener() {
171                         public void actionPerformed(ActionEvent e) {
172                                 if(uninstalled) {
173                                         System.exit(0);
174                                 }
175                                 try {
176                                         install.setEnabled(false);
177                                         uninstall.setEnabled(false);
178                                         uninstall();
179                                 } catch(IOException err) {
180                                         err.printStackTrace();
181                                         JOptionPane.showMessageDialog(Installer.this, "Error during installation.");
182                                         setButtonStatus(false,false);
183                                         label.setText("Uninstall failed!");
184                                 }
185                         }
186                 });
187                 getRootPane().setBorder(new EmptyBorder(10,10,10,10));
188                 getRootPane().setDefaultButton(install);
189                 pack();
190                 setSize(300,getHeight());
191                 setLocationRelativeTo(null);
192                 setDefaultCloseOperation(EXIT_ON_CLOSE);
193                 setVisible(true);
194         }
195         
196         /**
197         *       Uninstalls the client. Throws an IOException ir errors occur.
198         *       (removes the PCTB class from assistive tech, deletes the jar)
199         */
200         private void uninstall() throws IOException {
201                 label.setText("Uninstalling...");
202                 progress.setIndeterminate(true);
203                 // remove from assistive tech
204                 File java_home = getJavaHome();
205                 File a11y = new File(java_home,"lib/accessibility.properties");
206                 if(a11y.exists()) {
207                         Properties p = new Properties();
208                         p.load(new FileInputStream(a11y));
209                         String tech = p.getProperty("assistive_technologies");
210                         tech = tech.replace("com.tedpearson.ypp.market.MarketUploader", "");
211                         p.setProperty("assistive_technologies", tech);
212                         p.store(new FileOutputStream(a11y),"Last Modified by PCTB-Installer");
213                 }
214                 // remove jar
215                 File jar = new File(java_home, "lib/ext/PCTB-Uploader.jar");
216                 jar.delete();
217                 setButtonStatus(false,true);
218         }
219         
220         /**
221         *       Utility method to find the Java Home folder that runs YPP. On Windows, it could be
222         *       inside the YPP folder.
223         */
224         private File getJavaHome() {
225                 File java_home = new File(home);
226                 if(os.contains("Windows")) {
227                         File defaultLocation = null;
228                         // check for javavm inside YPP folder, otherwise default location
229                         if(os.contains("Vista")) {
230                                 String user = System.getProperty("user.name");
231                                 defaultLocation = new File("C:\\Users\\" + user + "\\AppData\\Roaming\\Three Rings Design\\Puzzle Pirates\\");
232                         } else if(os.contains("XP")) {
233                                 defaultLocation = new File("C:\\Program Files\\Three Rings Design\\Puzzle Pirates\\");
234                         }
235                         if(defaultLocation != null && defaultLocation.exists()) {
236                                 File java_vm = new File(defaultLocation, "java_vm");
237                                 if(java_vm.exists()) {
238                                         // this is where we want to install instead
239                                         java_home = new File(defaultLocation, "java_vm");
240                                 }
241                         }
242                 }
243                 return java_home;
244         }
245         
246         /**
247         *       Installs the client.
248         */
249         private void install() throws IOException {
250                 label.setText("Installing...");
251                 progress.setIndeterminate(true);
252                 File java_home = getJavaHome();
253                 File controlPanel = new File(user_home);
254                 JFileChooser chooser = new JFileChooser(controlPanel);
255                 chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
256                 chooser.setDialogTitle("Choose location for Control Panel");
257                 chooser.setApproveButtonText("Install Control Panel here");
258                 int state = chooser.showOpenDialog(this);
259                 if(state == JFileChooser.APPROVE_OPTION) {
260                         controlPanel = chooser.getSelectedFile();
261                 } else {
262                         setButtonStatus(false,false);
263                         label.setText("Install failed!");
264                         return;
265                 }
266                 InputStream in = getClass().getResourceAsStream("/PCTB-ControlPanel.jar");
267                 File newFile = new File(controlPanel, "PCTB-ControlPanel.jar");
268                 newFile.createNewFile();
269                 OutputStream out = new FileOutputStream(newFile);
270                 Updater.copyFile(in, out);
271                 String search = "assistive_technologies";
272                 String value = "com.tedpearson.ypp.market.MarketUploader";
273                 File a11y = new File(java_home,"lib/accessibility.properties");
274                 boolean skipA11y = false;
275                 Properties p = new Properties();
276                 if(a11y.exists()) {
277                         // if already contains our modification, ignore
278                         // else add our modification
279                         p.load(new FileInputStream(a11y));
280                         String tech = p.getProperty(search);
281                         if(tech == null || tech.trim().equals("")) {
282                                 // add it!
283                                 p.setProperty(search, value);
284                                 p.store(new FileOutputStream(a11y),"Last Modified by PCTB-Installer");
285                         } else if(!tech.contains(value)) {
286                                 p.setProperty(search, tech+","+value);
287                                 p.store(new FileOutputStream(a11y),"Last Modified by PCTB-Installer");
288                         }
289                 } else {
290                         // create file with our modification
291                         a11y.createNewFile();
292                         p.setProperty(search, value);
293                         p.store(new FileOutputStream(a11y),"Last Modified by PCTB-Installer");
294                 }
295                 
296                 // install program
297                 // copy jar from resource to new file in ext
298                 //String installer = getClass().getProtectionDomain().getCodeSource().getLocation()
299                 //      .getPath().replaceAll("%20"," ");
300                 //new FileInputStream(installer);
301                 in = getClass().getResourceAsStream("/PCTB-Uploader.jar");
302                 newFile = new File(java_home, "lib/ext/PCTB-Uploader.jar");
303                 newFile.createNewFile();
304                 out = new FileOutputStream(newFile);
305                 Updater.copyFile(in, out);
306                 JOptionPane.showMessageDialog(this, "Install successful!\n\nWhen you open a new YPP client, you'll see\n" +
307                         "the upload client window alongside YPP.\n\n" +
308                         "To stop the window from appearing, use\n" +
309                         "the Control Panel to disable it, or uninstall.", "Success!", JOptionPane.INFORMATION_MESSAGE);
310                 setButtonStatus(true,false);
311         }
312         
313         /**
314         *       Cleanup after an install, uninstall, or error. Buttons, statuses, and such
315         */
316         private void setButtonStatus(boolean installQ, boolean uninstallQ) {
317                 progress.setIndeterminate(false);
318                 progress.setValue(100);
319                 install.setEnabled(true);
320                 uninstall.setEnabled(true);
321                 String q = "Quit";
322                 if(installQ) {
323                         install.setText(q);
324                         installed = true;
325                         label.setText("Install complete!");
326                 } else {
327                         install.setText("Install");
328                         installed = false;
329                 }
330                 
331                 if(uninstallQ) {
332                         uninstall.setText(q);
333                         uninstalled = true;
334                         label.setText("Uninstall successful.");
335                 } else {
336                         uninstall.setText("Uninstall");
337                         uninstalled = false;
338                 }
339         }
340 }