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

Last change on this file since 17828 was 17828, checked in by oranfry, 15 years ago

finish button to stay disabled until install finished

File size: 16.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 javax.swing.JMenuItem;
17import javax.swing.JPopupMenu;
18
19import java.io.File;
20import java.io.BufferedReader;
21import java.io.FileReader;
22import java.io.FileNotFoundException;
23import java.io.FileWriter;
24import java.io.IOException;
25
26import java.util.regex.Pattern;
27import java.util.regex.Matcher;
28import java.util.ArrayList;
29
30import javax.swing.SwingUtilities;
31
32
33public class Uninstaller {
34
35 public static int SCREEN_WIDTH = 600;
36 public static int SCREEN_HEIGHT = 450;
37
38 public static final ResourceBundle bundle = ResourceBundle.getBundle("resources.LanguagePack");
39
40 public static final File gs2InstallProps = new File("etc/installation.properties");
41 public static final File gs3InstallProps = new File("installation.properties");
42
43 boolean keepCollections = true;
44 //boolean keepModifiedFiles = false;
45 boolean ignoreReadOnlys = false;
46
47 JFrame frame;
48 JCheckBox keepCollectionsCheckbox;
49 //JCheckBox keepModifiedFilesCheckbox;
50
51 //panels
52 JPanel progressPanel;
53 JPanel introPanel;
54
55 //toolbars
56 JPanel initialToolbar;
57 JPanel finishToolbar;
58
59
60 JScrollPane logPane;
61 FollowingJTextArea log;
62 JButton uninstallButton;
63 JButton finishButton;
64
65 boolean confirmationGiven = false;
66 Thread mainThread = null;
67
68 public static void main( String[] args ) {
69 (new Uninstaller()).go();
70 }
71
72 public void go() {
73
74 mainThread = Thread.currentThread();
75
76 frame = new JFrame();
77 frame.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
78 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
79 frame.setLocation(screenSize.width/2 - frame.getWidth()/2, screenSize.height/2 - frame.getHeight()/2);
80
81 //The panel to introduce and ask for options
82 introPanel = new JPanel(new BorderLayout());
83 JPanel innerPanel = new JPanel();
84 innerPanel.setLayout( new BoxLayout(innerPanel,BoxLayout.Y_AXIS) );
85 innerPanel.setBorder( new EmptyBorder(10, 10, 5, 10) );
86 introPanel.add( BorderLayout.WEST, innerPanel );
87
88 //The panel to be displayed while the uninstall is happening
89 progressPanel = new JPanel(new BorderLayout());
90 log = new FollowingJTextArea();
91 log.setEditable(false);
92 logPane = new JScrollPane(log);
93 logPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
94 logPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
95 progressPanel.add( BorderLayout.NORTH, new JLabel("Progress") );
96 progressPanel.add( BorderLayout.CENTER, logPane );
97
98 //initial toolbar
99 initialToolbar = new JPanel();
100 uninstallButton = new JButton(bundle.getString("uninstaller.uninstall"));
101 uninstallButton.addActionListener( new StartUninstallListener() );
102 JButton cancelButton = new JButton(bundle.getString("uninstaller.cancel"));
103 cancelButton.addActionListener( new CancelListener() );
104 initialToolbar.add(uninstallButton);
105 initialToolbar.add(cancelButton);
106
107 //finish toolbar
108 finishToolbar = new JPanel();
109 finishButton = new JButton(bundle.getString("uninstaller.finish"));
110 finishButton.addActionListener( new FinishListener() );
111 finishButton.setEnabled( false );
112 finishToolbar.add( finishButton );
113
114
115 String pwd = (new File(".")).getAbsolutePath();
116 if ( pwd.endsWith("/.") ) {
117 pwd = pwd.substring( 0, pwd.length()-2 );
118 }
119
120 JLabel l;
121
122 l = new JLabel(bundle.getString("uninstaller.will.uninstall.from"));
123 innerPanel.add( l );
124 innerPanel.add( Box.createRigidArea(new Dimension(5,5)) );
125
126 l = new JLabel(" " + pwd);
127 l.setFont( new Font( "Monospaced", Font.BOLD, 14 ) );
128 innerPanel.add( l );
129 innerPanel.add( Box.createRigidArea(new Dimension(5,20)) );
130
131 l = new JLabel(bundle.getString("uninstaller.uninstall.options"));
132 innerPanel.add( l );
133
134 keepCollectionsCheckbox = new JCheckBox(bundle.getString("uninstaller.keep.collections"));
135 keepCollectionsCheckbox.setSelected(true);
136 innerPanel.add( keepCollectionsCheckbox );
137
138 //keepModifiedFilesCheckbox = new JCheckBox("Keep Modified Files");
139 //innerPanel.add( keepModifiedFilesCheckbox );
140
141 frame.setTitle( bundle.getString("uninstaller.greenstone.uninstaller") );
142 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
143
144 //the initial screen
145 frame.getContentPane().add( BorderLayout.CENTER, introPanel );
146 frame.getContentPane().add( BorderLayout.SOUTH, initialToolbar );
147
148 frame.setVisible(true);
149
150 boolean ready = precheck();
151 if ( !ready ) {
152 System.exit(0);
153 }
154
155 //block and wait for signal to do the uninstall
156 do {
157 try {
158 Thread.sleep( Long.MAX_VALUE );
159 } catch ( InterruptedException ie ) {
160 }
161 } while ( !confirmationGiven );
162
163 doUninstall();
164 finishButton.setEnabled( true );
165
166 }
167
168 class CancelListener implements ActionListener {
169 public void actionPerformed( ActionEvent e ) {
170 System.exit(0);
171 }
172 }
173
174 class FinishListener implements ActionListener {
175 public void actionPerformed( ActionEvent e ) {
176 System.exit(0);
177 }
178 }
179
180 class StartUninstallListener implements ActionListener {
181 public void actionPerformed( ActionEvent e ) {
182
183 //The dialog to ask "are you sure"
184 Object[] options = { bundle.getString("uninstaller.uninstall"), bundle.getString("uninstaller.cancel") };
185 int n = JOptionPane.showOptionDialog(
186 frame,
187 bundle.getString("uninstaller.are.you.sure"),
188 bundle.getString("uninstaller.confirmation"),
189 JOptionPane.YES_NO_CANCEL_OPTION,
190 JOptionPane.QUESTION_MESSAGE,
191 null,
192 options,
193 options[0]
194 );
195 if ( n == 1 ) {
196 return;
197 }
198
199 keepCollections = keepCollectionsCheckbox.isSelected();
200 //keepModifiedFiles = keepModifiedFilesCheckbox.isSelected();
201
202 //confirm delete of collections
203 if ( !keepCollections ) {
204 options[0] = bundle.getString("uninstaller.continue");
205 options[1] = bundle.getString("uninstaller.cancel");
206 n = JOptionPane.showOptionDialog(
207 frame,
208 bundle.getString("uninstaller.are.you.sure.collections"),
209 bundle.getString("uninstaller.confirmation"),
210 JOptionPane.YES_NO_CANCEL_OPTION,
211 JOptionPane.WARNING_MESSAGE,
212 null,
213 options,
214 options[0]
215 );
216 if ( n == 1 ) {
217 return;
218 }
219 }
220
221
222 introPanel.setVisible( false );
223 frame.getContentPane().remove(introPanel);
224 frame.getContentPane().add( BorderLayout.CENTER, progressPanel );
225
226 initialToolbar.setVisible( false );
227 frame.getContentPane().remove( initialToolbar );
228 frame.getContentPane().add( BorderLayout.SOUTH, finishToolbar);
229
230 confirmationGiven = true;
231 mainThread.interrupt();
232 }
233 }
234
235 /**
236 * Do some checks
237 */
238 public boolean precheck() {
239
240 if ( !gs2InstallProps.exists() && !gs3InstallProps.exists() ) {
241 log( bundle.getString("uninstaller.error.couldnt.find.install.props") + "\n" );
242 JOptionPane.showMessageDialog(frame, bundle.getString("uninstaller.error.couldnt.find.install.props"), bundle.getString("uninstaller.error"), 0);
243 return false;
244 }
245 return true;
246
247 }
248
249 public void log( String s ) {
250 SwingUtilities.invokeLater( new LogAppender( s ) );
251 //log.append( s );
252
253 }
254
255 /**
256 * Does the uninstall
257 */
258 public void doUninstall() {
259
260 File startMenuPath = null;
261
262 //delete the start menu group if present
263
264 if ( gs2InstallProps.exists() ) {
265 String smp = null;
266 try {
267 smp = getPropertyValue( "startmenu.path", gs2InstallProps );
268 } catch ( Exception e ) {}
269 if ( smp != null ) {
270 startMenuPath = new File( smp );
271 }
272 } else if ( gs3InstallProps.exists() ) {
273 String smp = null;
274 try {
275 smp = getPropertyValue( "startmenu.path", gs3InstallProps );
276 } catch ( Exception e ) {}
277 if ( smp != null ) {
278 startMenuPath = new File( smp );
279 }
280 }
281
282 if ( startMenuPath == null ) {
283
284 log( bundle.getString("uninstaller.info.no.startmenu") + "\n" );
285
286 } else {
287 log( "StartMenu Path: " + startMenuPath.getAbsolutePath() + "\n" );
288
289 try {
290 recursiveDelete( startMenuPath, null );
291 } catch ( CancelledException ce ) {
292 log( bundle.getString("uninstaller.cancelled") + "\n" );
293 changeToFinishToolbar();
294 JOptionPane.showMessageDialog(frame, bundle.getString("uninstaller.cancelled"), bundle.getString("uninstaller.complete"), 1);
295 return;
296 }
297 }
298
299 //delete the files
300 try {
301 ArrayList exceptions = new ArrayList();
302
303 //never delete the things we are currently running
304 exceptions.add( new File("bin/search4j.exe") );
305 exceptions.add( new File("bin/search4j") );
306
307 exceptions.add( new File("bin/windows/search4j.exe") );
308 exceptions.add( new File("bin/linux/search4j") );
309 exceptions.add( new File("bin/darwin/search4j") );
310
311 exceptions.add( new File("packages/jre") );
312 exceptions.add( new File("uninst.jar") );
313 exceptions.add( new File("Uninstall.bat") );
314 exceptions.add( new File("Uninstall.sh") );
315
316 if ( keepCollections ) {
317 exceptions.add( new File("web/sites/localsite/collect") );
318 exceptions.add( new File("collect") );
319 }
320
321
322 File cd = null;
323 try {
324 cd = new File( new File(".").getCanonicalPath() );
325 } catch ( Exception e ) {
326 JOptionPane.showMessageDialog(frame, bundle.getString("uninstaller.failed.to.figure.cd"), bundle.getString("uninstaller.error") , 0);
327 System.exit(0);
328 }
329
330 File[] ex = new File[exceptions.size()];
331 for ( int i=0; i<exceptions.size(); i++ ) {
332 ex[i] = (File)exceptions.get(i);
333 }
334
335 recursiveDelete( cd , ex );
336 } catch ( CancelledException ce ) {
337 log( bundle.getString("uninstaller.cancelled") + "\n" );
338 JOptionPane.showMessageDialog(frame, bundle.getString("uninstaller.cancelled"), bundle.getString("uninstaller.complete"), 1);
339 changeToFinishToolbar();
340 return;
341 }
342
343 //create the flag file to indicate the uninstaller wants jre and uninst.jar to be deleted
344 try {
345 (new File("uninst.flag")).createNewFile();
346 } catch (Exception e) {
347 log( bundle.getString("uninstaller.couldnt-create-flagfile") + "\n" );
348 }
349
350 changeToFinishToolbar();
351 log( bundle.getString("uninstaller.finished") );
352 JOptionPane.showMessageDialog(frame, bundle.getString("uninstaller.finished"), bundle.getString("uninstaller.complete"), 1);
353 }
354
355 class LogAppender implements Runnable {
356 String s;
357
358 public LogAppender( String s ) {
359 this.s = s;
360 }
361
362 public void run() {
363 log.append( s );
364 }
365
366 }
367
368 public String getPropertyValue( String propertyName, File file ) throws Exception {
369 String regex = "^" + propertyName.replaceAll("\\.","\\\\.") + "[:=]\\s*(.*)$";
370 Pattern wantedLine = Pattern.compile( regex );
371 BufferedReader in = null;
372 try {
373 in = new BufferedReader(new FileReader( file ));
374 } catch ( Exception e ) {
375 throw new Exception( "Error - couldn't open the properties file " + file );
376 }
377
378 String line, value = null;
379
380 try {
381 boolean found = false;
382 while ( (line = in.readLine()) != null && !found ) {
383
384 Matcher matcher = wantedLine.matcher( line );
385 if ( matcher.matches() ) {
386 //found the property
387 //System.err.println( "found the property" );
388 value = matcher.group(1);
389 value = value.replaceAll( "#.*", "" ).trim();
390 return value;
391 }
392
393 }
394
395 //close the input stream
396 //System.err.println( "close the input stream" );
397 in.close();
398
399 } catch ( Exception e ) {
400 throw new Exception( "Error - couldn't read from the properties file" );
401 }
402 return null;
403
404 }
405
406 public void recursiveDelete( File f, File[] exceptions ) throws CancelledException {
407
408 //log.append( "Processing: " + f.getAbsolutePath() + "\n" );
409
410 // Make sure the file or directory exists
411 if (!f.exists()) {
412 log( Strings.replaceAll( bundle.getString("uninstaller.warning.nonexistent"), "{file}", f.getAbsolutePath() ) + "\n" );
413 return;
414 }
415
416 // if this is an exception, return
417 if ( exceptions != null ) {
418 for ( int i=0; i<exceptions.length; i++ ) {
419 //System.out.println( "Comparing '" + f.getAbsolutePath() + "' with '" + exceptions[i].getAbsolutePath() + "'" );
420 try {
421 if ( f.equals( exceptions[i] ) || f.getCanonicalPath().equals(exceptions[i].getCanonicalPath()) ) {
422 log( Strings.replaceAll( bundle.getString("uninstaller.info.skipping"), "{file}", f.getAbsolutePath() ) + "\n" );
423 return;
424 }
425 } catch ( Exception e ) {
426 System.err.println("ERROR: Failed to resolve a path");
427 return;
428 }
429 }
430 }
431
432 //check existance
433 if ( !f.exists() ) {
434 log( Strings.replaceAll( bundle.getString("uninstaller.error.nonexistent"), "{file}", f.getAbsolutePath() ) + "\n" );
435 return;
436 }
437
438 //if it is a directory, recurse
439 if (f.isDirectory()) {
440 File[] files = f.listFiles();
441 if ( files != null && files.length > 0) {
442 for ( int i=0; i<files.length; i++ ) {
443 try {
444 recursiveDelete( files[i], exceptions );
445 } catch ( CancelledException ce ) {
446 throw new CancelledException();
447 }
448 }
449 }
450 }
451
452 //if this is now an empty directory, or a file, delete it
453 boolean doDelete = true;
454 if ( f.isDirectory() ) {
455 File[] files = f.listFiles();
456 doDelete = ( files == null || files.length == 0 );
457 }
458
459 if ( doDelete ) {
460
461 Object[] options = null;
462 int n = 0;
463 log( Strings.replaceAll( bundle.getString("uninstaller.deleting"), "{file}", f.getAbsolutePath() ) + "\n" );
464
465 if ( !f.delete() ) {
466 log( "*********\n" + Strings.replaceAll( bundle.getString("uninstaller.warning.couldnt.delete"), "{file}", f.getAbsolutePath() ) + "\n*********\n" );
467 return;
468 }
469 }
470
471 }
472
473 class CancelledException extends Exception {}
474
475 public void changeToFinishToolbar() {
476 initialToolbar.setVisible(false);
477 frame.getContentPane().remove(initialToolbar);
478 frame.getContentPane().add( BorderLayout.SOUTH, finishToolbar );
479 finishToolbar.setVisible(true);
480 }
481
482}
483
484class Strings {
485 static String replaceAll( String s, String nugget, String replacement ) {
486 StringBuffer string = new StringBuffer(s);
487 StringBuffer r = new StringBuffer();
488
489 int io = 0;
490 while ( (io=string.toString().indexOf(nugget)) != -1 ) {
491 r.append( string.toString().substring( 0, io ) );
492 r.append( replacement );
493 string.delete( 0, io + nugget.length() );
494 }
495 r.append( string.toString() );
496 return r.toString();
497 }
498}
499
500class FollowingJTextArea extends JTextArea {
501
502 private boolean follow = true;
503
504 public FollowingJTextArea() {
505 jInit();
506 }
507
508
509 private void jInit(){
510 final JPopupMenu popUp = getPopupMenu();
511 this.add(popUp);
512 this.addMouseListener(new MouseAdapter(){
513 public void mouseClicked(MouseEvent e) {
514 if (e.getButton() == e.BUTTON3) {
515 popUp.show(FollowingJTextArea.this,e.getX(),e.getY());
516 }
517 }
518 });
519 }
520
521 public boolean isFollow() {
522 return follow;
523 }
524 public void setFollow(boolean follow) {
525 this.follow = follow;
526 }
527
528 private void scrollToEnd(){
529 setCaretPosition(getDocument().getLength());
530 }
531 private void toggleFollow(){
532 setFollow(!isFollow());
533 }
534
535 /**
536 * Appends the given text to the end of the document.
537 *
538 * @param str the text to insert
539 * @todo Implement this javax.swing.JTextArea method
540 */
541 public void append(String str) {
542 super.append(str);
543 if(follow)scrollToEnd();
544 }
545 private JPopupMenu getPopupMenu() {
546 JPopupMenu contextMenu = new JPopupMenu("Options");
547
548 JMenuItem toggleFollowMenu = new JMenuItem("Toggle Follow");
549 toggleFollowMenu.addActionListener(new ActionListener() {
550 public void actionPerformed(ActionEvent e) {
551 toggleFollow();
552 }
553 });
554 contextMenu.add(toggleFollowMenu);
555
556 JMenuItem jumpToEndMenu = new JMenuItem("Jump To End");
557 jumpToEndMenu.addActionListener(new ActionListener() {
558 public void actionPerformed(ActionEvent e) {
559 setCaretPosition(getDocument().getLength());
560 }
561 });
562 contextMenu.add(toggleFollowMenu);
563
564 JMenuItem clearTextMenu = new JMenuItem("Clear Text");
565 clearTextMenu.addActionListener(new ActionListener() {
566 public void actionPerformed(ActionEvent e) {
567 setText("");
568 }
569 });
570 contextMenu.add(clearTextMenu);
571 return contextMenu;
572 }
573}
Note: See TracBrowser for help on using the repository browser.