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