source: release-kits/shared/uninstaller/Uninstaller.java@ 17435

Last change on this file since 17435 was 17435, checked in by oranfry, 16 years ago

got the uninstaller working

File size: 13.1 KB
Line 
1import java.util.ResourceBundle;
2import java.awt.*;
3import java.awt.event.*;
4import javax.swing.JFrame;
5import javax.swing.JPanel;
6import javax.swing.JCheckBox;
7import javax.swing.JLabel;
8import javax.swing.JButton;
9import javax.swing.BoxLayout;
10import javax.swing.JTextArea;
11import javax.swing.JScrollPane;
12import javax.swing.border.EmptyBorder;
13import javax.swing.JOptionPane;
14import javax.swing.Box;
15import javax.swing.JDialog;
16import java.io.File;
17import java.io.BufferedReader;
18import java.io.FileReader;
19import java.io.File;
20import java.util.regex.Pattern;
21import java.util.regex.Matcher;
22import java.util.ArrayList;
23
24public class Uninstaller {
25
26 public static int SCREEN_WIDTH = 600;
27 public static int SCREEN_HEIGHT = 450;
28
29 public static final ResourceBundle bundle = ResourceBundle.getBundle("Uninstaller");
30
31 public static final File gs2InstallProps = new File("etc/installation.properties");
32 public static final File gs3InstallProps = new File("installation.properties");
33
34 boolean keepCollections = true;
35 //boolean keepModifiedFiles = false;
36 boolean ignoreReadOnlys = false;
37
38 JFrame frame;
39 JCheckBox keepCollectionsCheckbox;
40 //JCheckBox keepModifiedFilesCheckbox;
41 JPanel progressPanel;
42 JPanel introPanel;
43 JTextArea log;
44 JButton uninstallButton;
45 JPanel initialToolbar;
46 JPanel finishToolbar;
47
48
49 public static void main( String[] args ) {
50 (new Uninstaller()).go();
51 }
52
53 public void go() {
54
55 frame = new JFrame();
56 frame.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
57 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
58 frame.setLocation(screenSize.width/2 - frame.getWidth()/2, screenSize.height/2 - frame.getHeight()/2);
59
60 //The panel to be displayed while the uninstall is happening
61 progressPanel = new JPanel(new BorderLayout());
62 log = new JTextArea();
63 JScrollPane logPane = new JScrollPane(log);
64 logPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
65 logPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
66 progressPanel.add( BorderLayout.NORTH, new JLabel("Progress") );
67 progressPanel.add( BorderLayout.CENTER, logPane );
68
69 //The panel to introduce and ask for options
70 introPanel = new JPanel(new BorderLayout());
71 frame.getContentPane().add( BorderLayout.NORTH, introPanel );
72
73 JPanel innerPanel = new JPanel();
74 innerPanel.setLayout( new BoxLayout(innerPanel,BoxLayout.Y_AXIS) );
75 innerPanel.setBorder( new EmptyBorder(10, 10, 5, 10) );
76 introPanel.add( BorderLayout.WEST, innerPanel );
77
78 //initial toolbar
79 initialToolbar = new JPanel();
80 JButton cancelButton = new JButton(bundle.getString("cancel"));
81 cancelButton.addActionListener( new CancelListener() );
82
83 uninstallButton = new JButton(bundle.getString("uninstall"));
84 uninstallButton.addActionListener( new StartUninstallListener() );
85
86 initialToolbar.add(cancelButton);
87 initialToolbar.add(uninstallButton);
88 frame.getContentPane().add( BorderLayout.SOUTH, initialToolbar );
89
90 //finish toolbar
91 finishToolbar = new JPanel();
92 JButton finishButton = new JButton(bundle.getString("finish"));
93 finishButton.addActionListener( new FinishListener() );
94 finishToolbar.add( finishButton );
95
96 String pwd = (new File(".")).getAbsolutePath();
97 if ( pwd.endsWith("/.") ) {
98 pwd = pwd.substring( 0, pwd.length()-2 );
99 }
100
101 JLabel l;
102
103 l = new JLabel(bundle.getString("will.uninstall.from"));
104 innerPanel.add( l );
105 innerPanel.add( Box.createRigidArea(new Dimension(5,5)) );
106
107 l = new JLabel(" " + pwd);
108 l.setFont( new Font( "Monospaced", Font.BOLD, 14 ) );
109 innerPanel.add( l );
110 innerPanel.add( Box.createRigidArea(new Dimension(5,20)) );
111
112 l = new JLabel(bundle.getString("uninstall.options"));
113 innerPanel.add( l );
114
115 keepCollectionsCheckbox = new JCheckBox(bundle.getString("keep.collections"));
116 keepCollectionsCheckbox.setSelected(true);
117 innerPanel.add( keepCollectionsCheckbox );
118
119 //keepModifiedFilesCheckbox = new JCheckBox("Keep Modified Files");
120 //innerPanel.add( keepModifiedFilesCheckbox );
121
122 frame.setTitle( bundle.getString("greenstone.uninstaller") );
123 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
124 frame.setVisible(true);
125
126 boolean ready = precheck();
127 if ( !ready ) {
128 System.exit(0);
129 }
130
131 }
132
133 class CancelListener implements ActionListener {
134 public void actionPerformed( ActionEvent e ) {
135 System.exit(0);
136 }
137 }
138
139 class FinishListener implements ActionListener {
140 public void actionPerformed( ActionEvent e ) {
141 System.exit(0);
142 }
143 }
144
145 class StartUninstallListener implements ActionListener {
146 public void actionPerformed( ActionEvent e ) {
147
148 //The dialog to ask "are you sure"
149 Object[] options = { bundle.getString("cancel"), bundle.getString("uninstall") };
150 int n = JOptionPane.showOptionDialog(
151 frame,
152 bundle.getString("are.you.sure"),
153 bundle.getString("confirmation"),
154 JOptionPane.YES_NO_CANCEL_OPTION,
155 JOptionPane.QUESTION_MESSAGE,
156 null,
157 options,
158 options[0]
159 );
160 if ( n == 0 ) {
161 return;
162 }
163
164 keepCollections = keepCollectionsCheckbox.isSelected();
165 //keepModifiedFiles = keepModifiedFilesCheckbox.isSelected();
166
167 //confirm delete of collections
168 if ( !keepCollections ) {
169 options[0] = bundle.getString("cancel");
170 options[1] = bundle.getString("continue");
171 n = JOptionPane.showOptionDialog(
172 frame,
173 bundle.getString("are.you.sure.collections"),
174 bundle.getString("confirmation"),
175 JOptionPane.YES_NO_CANCEL_OPTION,
176 JOptionPane.WARNING_MESSAGE,
177 null,
178 options,
179 options[0]
180 );
181 if ( n == 0 ) {
182 return;
183 }
184 }
185
186 //swap to the progress panel
187 introPanel.setVisible(false);
188 frame.getContentPane().remove(introPanel);
189 frame.getContentPane().add( BorderLayout.CENTER, progressPanel);
190 frame.setVisible(true);
191
192 //disable the uninstall button
193 uninstallButton.setEnabled( false );
194
195
196 //start the unstinall
197 doUninstall();
198 }
199 }
200
201 /**
202 * Do some checks
203 */
204 public boolean precheck() {
205
206 if ( !gs2InstallProps.exists() && !gs3InstallProps.exists() ) {
207 log.append( bundle.getString("error.couldnt.find.install.props") + "\n" );
208 JOptionPane.showMessageDialog(frame, bundle.getString("error.couldnt.find.install.props"), bundle.getString("error"), 0);
209 return false;
210 }
211 return true;
212
213 }
214
215 /**
216 * Does the uninstall
217 */
218 public void doUninstall() {
219
220 File startMenuPath = null;
221
222 //delete the start menu group if present
223
224 if ( gs2InstallProps.exists() ) {
225 String smp = null;
226 try {
227 smp = getPropertyValue( "startmenu.path", gs2InstallProps );
228 } catch ( Exception e ) {}
229 if ( smp != null ) {
230 startMenuPath = new File( smp );
231 }
232 } else if ( gs3InstallProps.exists() ) {
233 String smp = null;
234 try {
235 smp = getPropertyValue( "startmenu.path", gs3InstallProps );
236 } catch ( Exception e ) {}
237 if ( smp != null ) {
238 startMenuPath = new File( smp );
239 }
240 }
241
242 if ( startMenuPath == null ) {
243 log.append( bundle.getString("info.no.startmenu") + "\n" );
244 } else {
245 log.append( "StartMenu Path: " + startMenuPath.getAbsolutePath() + "\n" );
246 try {
247 recursiveDelete( startMenuPath, null );
248 } catch ( CancelledException ce ) {
249 log.append( bundle.getString("cancelled") + "\n" );
250 changeToFinishToolbar();
251 JOptionPane.showMessageDialog(frame, bundle.getString("cancelled"), bundle.getString("complete"), 1);
252 return;
253 }
254 }
255
256 //delete the files
257 try {
258 ArrayList exceptions = new ArrayList();
259
260 //never delete the things we are currently running
261 exceptions.add( new File("bin/search4j.exe") );
262 exceptions.add( new File("packages/jre") );
263 exceptions.add( new File("uninst.jar") );
264 exceptions.add( new File("Uninstall.bat") );
265 exceptions.add( new File("Uninstall.sh") );
266
267 if ( keepCollections ) {
268 exceptions.add( new File("web/sites/localsite/collect") );
269 exceptions.add( new File("collect") );
270 }
271
272
273 File cd = null;
274 try {
275 cd = new File( new File(".").getCanonicalPath() );
276 } catch ( Exception e ) {
277 JOptionPane.showMessageDialog(frame, bundle.getString("failed.to.figure.cd"), bundle.getString("error") , 0);
278 System.exit(0);
279 }
280
281 File[] ex = new File[exceptions.size()];
282 for ( int i=0; i<exceptions.size(); i++ ) {
283 ex[i] = (File)exceptions.get(i);
284 }
285
286 recursiveDelete( cd , ex );
287 } catch ( CancelledException ce ) {
288 log.append( bundle.getString("cancelled") + "\n" );
289 JOptionPane.showMessageDialog(frame, bundle.getString("cancelled"), bundle.getString("complete"), 1);
290 changeToFinishToolbar();
291 return;
292 }
293
294 //create the flag file to indicate the uninstaller wants jre and uninst.jar to be deleted
295 try {
296 (new File("uninst.flag")).createNewFile();
297 } catch (Exception e) {
298 log.append( bundle.getString("couldnt-create-flagfile") + "\n" );
299 }
300
301 changeToFinishToolbar();
302 JOptionPane.showMessageDialog(frame, bundle.getString("finished"), bundle.getString("complete"), 1);
303 }
304
305 public String getPropertyValue( String propertyName, File file ) throws Exception {
306 String regex = "^" + propertyName.replaceAll("\\.","\\\\.") + "[:=]\\s*(.*)$";
307 Pattern wantedLine = Pattern.compile( regex );
308 BufferedReader in = null;
309 try {
310 in = new BufferedReader(new FileReader( file ));
311 } catch ( Exception e ) {
312 throw new Exception( "Error - couldn't open the properties file " + file );
313 }
314
315 String line, value = null;
316
317 try {
318 boolean found = false;
319 while ( (line = in.readLine()) != null && !found ) {
320
321 Matcher matcher = wantedLine.matcher( line );
322 if ( matcher.matches() ) {
323 //found the property
324 //System.err.println( "found the property" );
325 value = matcher.group(1);
326 value = value.replaceAll( "#.*", "" ).trim();
327 return value;
328 }
329
330 }
331
332 //close the input stream
333 //System.err.println( "close the input stream" );
334 in.close();
335
336 } catch ( Exception e ) {
337 throw new Exception( "Error - couldn't read from the properties file" );
338 }
339 return null;
340
341 }
342
343 public void recursiveDelete( File f, File[] exceptions ) throws CancelledException {
344
345 //log.append( "Processing: " + f.getAbsolutePath() + "\n" );
346
347 // Make sure the file or directory exists
348 if (!f.exists()) {
349 log.append( Strings.replaceAll( bundle.getString("warning.nonexistent"), "{file}", f.getAbsolutePath() ) + "\n" );
350 return;
351 }
352
353 // if this is an exception, return
354 if ( exceptions != null ) {
355 for ( int i=0; i<exceptions.length; i++ ) {
356 //System.out.println( "Comparing '" + f.getAbsolutePath() + "' with '" + exceptions[i].getAbsolutePath() + "'" );
357 try {
358 if ( f.equals( exceptions[i] ) || f.getCanonicalPath().equals(exceptions[i].getCanonicalPath()) ) {
359 log.append( Strings.replaceAll( bundle.getString("info.skipping"), "{file}", f.getAbsolutePath() ) + "\n" );
360 return;
361 }
362 } catch ( Exception e ) {
363 System.err.println("ERROR: Failed to resolve a path");
364 return;
365 }
366 }
367 }
368
369 //check existance
370 if ( !f.exists() ) {
371 log.append( Strings.replaceAll( bundle.getString("error.nonexistent"), "{file}", f.getAbsolutePath() ) + "\n" );
372 return;
373 }
374
375 //if it is a directory, recurse
376 if (f.isDirectory()) {
377 File[] files = f.listFiles();
378 if ( files != null && files.length > 0) {
379 for ( int i=0; i<files.length; i++ ) {
380 try {
381 recursiveDelete( files[i], exceptions );
382 } catch ( CancelledException ce ) {
383 throw new CancelledException();
384 }
385 }
386 }
387 }
388
389 //if this is now an empty directory, or a file, delete it
390 boolean doDelete = true;
391 if ( f.isDirectory() ) {
392 File[] files = f.listFiles();
393 doDelete = ( files == null || files.length == 0 );
394 }
395
396 if ( doDelete ) {
397
398 log.append( Strings.replaceAll( bundle.getString("deleting"), "{file}", f.getAbsolutePath() ) + "\n" );
399 while ( !f.delete() ) {
400 log.append( Strings.replaceAll( bundle.getString("warning.couldnt.delete"), "{file}", f.getAbsolutePath() ) + "\n" );
401
402 if ( ignoreReadOnlys ) {
403 return;
404 }
405
406 Object[] options = { bundle.getString("cancel"), bundle.getString("retry"), bundle.getString("skip"), bundle.getString("skip.all") };
407 int n = JOptionPane.showOptionDialog(
408 frame,
409 Strings.replaceAll( bundle.getString("warning.readonly"), "{file}", f.getAbsolutePath() ),
410 bundle.getString("readonly"),
411 JOptionPane.YES_NO_CANCEL_OPTION,
412 JOptionPane.QUESTION_MESSAGE,
413 null,
414 options,
415 options[2]
416 );
417
418 if ( n == 0 ) {
419 throw new CancelledException();
420 } else if ( n == 2 ) {
421 return;
422 } else if ( n == 3 ) {
423 ignoreReadOnlys = true;
424 return;
425 }
426
427 }
428 }
429
430 }
431
432 class CancelledException extends Exception {}
433
434 public void changeToFinishToolbar() {
435 initialToolbar.setVisible(false);
436 frame.getContentPane().remove(initialToolbar);
437 frame.getContentPane().add( BorderLayout.SOUTH, finishToolbar );
438 finishToolbar.setVisible(true);
439 }
440
441}
442
443class Strings {
444 static String replaceAll( String s, String nugget, String replacement ) {
445 StringBuffer string = new StringBuffer(s);
446 StringBuffer r = new StringBuffer();
447
448 int io = 0;
449 while ( (io=string.toString().indexOf(nugget)) != -1 ) {
450 r.append( string.toString().substring( 0, io ) );
451 r.append( replacement );
452 string.delete( 0, io + nugget.length() );
453 }
454 r.append( string.toString() );
455 return r.toString();
456 }
457}
458
Note: See TracBrowser for help on using the repository browser.