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

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

corrected the property name

File size: 16.2 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( "installed.startmenu.path", gs2InstallProps );
268 } catch ( Exception e ) {
269 System.err.println( e.getMessage() );
270 }
271 if ( smp != null ) {
272 startMenuPath = new File( smp );
273 }
274 } else if ( gs3InstallProps.exists() ) {
275 String smp = null;
276 try {
277 smp = getPropertyValue( "installed.startmenu.path", gs3InstallProps );
278 } catch ( Exception e ) {
279 System.err.println( e.getMessage() );
280 }
281 if ( smp != null ) {
282 startMenuPath = new File( smp );
283 }
284 }
285
286 if ( startMenuPath == null ) {
287
288 log( bundle.getString("uninstaller.info.no.startmenu") + "\n" );
289
290 } else {
291 log( "StartMenu Path: " + startMenuPath.getAbsolutePath() + "\n" );
292
293 try {
294 recursiveDelete( startMenuPath, null );
295 } catch ( CancelledException ce ) {
296 log( bundle.getString("uninstaller.cancelled") + "\n" );
297 changeToFinishToolbar();
298 JOptionPane.showMessageDialog(frame, bundle.getString("uninstaller.cancelled"), bundle.getString("uninstaller.complete"), 1);
299 return;
300 }
301 }
302
303 //delete the files
304 try {
305 ArrayList exceptions = new ArrayList();
306
307 //never delete the things we are currently running
308 exceptions.add( new File("bin/search4j.exe") );
309 exceptions.add( new File("bin/search4j") );
310
311 exceptions.add( new File("bin/windows/search4j.exe") );
312 exceptions.add( new File("bin/linux/search4j") );
313 exceptions.add( new File("bin/darwin/search4j") );
314
315 exceptions.add( new File("packages/jre") );
316 exceptions.add( new File("uninst.jar") );
317 exceptions.add( new File("Uninstall.bat") );
318 exceptions.add( new File("Uninstall.sh") );
319
320 if ( keepCollections ) {
321 exceptions.add( new File("web/sites/localsite/collect") );
322 exceptions.add( new File("collect") );
323 }
324
325
326 File cd = null;
327 try {
328 cd = new File( new File(".").getCanonicalPath() );
329 } catch ( Exception e ) {
330 JOptionPane.showMessageDialog(frame, bundle.getString("uninstaller.failed.to.figure.cd"), bundle.getString("uninstaller.error") , 0);
331 System.exit(0);
332 }
333
334 File[] ex = new File[exceptions.size()];
335 for ( int i=0; i<exceptions.size(); i++ ) {
336 ex[i] = (File)exceptions.get(i);
337 }
338
339 recursiveDelete( cd , ex );
340 } catch ( CancelledException ce ) {
341 log( bundle.getString("uninstaller.cancelled") + "\n" );
342 JOptionPane.showMessageDialog(frame, bundle.getString("uninstaller.cancelled"), bundle.getString("uninstaller.complete"), 1);
343 changeToFinishToolbar();
344 return;
345 }
346
347 //create the flag file to indicate the uninstaller wants jre and uninst.jar to be deleted
348 try {
349 (new File("uninst.flag")).createNewFile();
350 } catch (Exception e) {
351 log( bundle.getString("uninstaller.couldnt-create-flagfile") + "\n" );
352 }
353
354 changeToFinishToolbar();
355 log( bundle.getString("uninstaller.finished") );
356 JOptionPane.showMessageDialog(frame, bundle.getString("uninstaller.finished"), bundle.getString("uninstaller.complete"), 1);
357 }
358
359 class LogAppender implements Runnable {
360 String s;
361
362 public LogAppender( String s ) {
363 this.s = s;
364 }
365
366 public void run() {
367 log.append( s );
368 }
369
370 }
371
372 public String getPropertyValue( String propertyName, File file ) throws Exception {
373
374 String regex = "^" + propertyName.replaceAll("\\.","\\\\.") + "[:=]\\s*(.*)$";
375 Pattern wantedLine = Pattern.compile( regex );
376 BufferedReader in = null;
377 try {
378 in = new BufferedReader(new FileReader( file ));
379 } catch ( Exception e ) {
380 throw new Exception( "Error - couldn't open the properties file " + file );
381 }
382
383 String line, value = null;
384
385 try {
386 boolean found = false;
387 while ( (line = in.readLine()) != null && !found ) {
388
389 Matcher matcher = wantedLine.matcher( line );
390 if ( matcher.matches() ) {
391 //found the property
392 //System.err.println( "found the property" );
393 value = matcher.group(1);
394 value = value.replaceAll( "#.*", "" ).trim();
395 return value;
396 }
397
398 }
399
400 //close the input stream
401 //System.err.println( "close the input stream" );
402 in.close();
403
404 } catch ( Exception e ) {
405 throw new Exception( "Error - couldn't read from the properties file" );
406 }
407 return null;
408
409 }
410
411 public void recursiveDelete( File f, File[] exceptions ) throws CancelledException {
412
413 //log.append( "Processing: " + f.getAbsolutePath() + "\n" );
414
415 // Make sure the file or directory exists
416 if (!f.exists()) {
417 log( Strings.replaceAll( bundle.getString("uninstaller.warning.nonexistent"), "{file}", f.getAbsolutePath() ) + "\n" );
418 return;
419 }
420
421 // if this is an exception, return
422 if ( exceptions != null ) {
423 for ( int i=0; i<exceptions.length; i++ ) {
424 //System.out.println( "Comparing '" + f.getAbsolutePath() + "' with '" + exceptions[i].getAbsolutePath() + "'" );
425 try {
426 if ( f.equals( exceptions[i] ) || f.getCanonicalPath().equals(exceptions[i].getCanonicalPath()) ) {
427 log( Strings.replaceAll( bundle.getString("uninstaller.info.skipping"), "{file}", f.getAbsolutePath() ) + "\n" );
428 return;
429 }
430 } catch ( Exception e ) {
431 System.err.println("ERROR: Failed to resolve a path");
432 return;
433 }
434 }
435 }
436
437 //check existance
438 if ( !f.exists() ) {
439 log( Strings.replaceAll( bundle.getString("uninstaller.error.nonexistent"), "{file}", f.getAbsolutePath() ) + "\n" );
440 return;
441 }
442
443 //if it is a directory, recurse
444 if (f.isDirectory()) {
445 File[] files = f.listFiles();
446 if ( files != null && files.length > 0) {
447 for ( int i=0; i<files.length; i++ ) {
448 try {
449 recursiveDelete( files[i], exceptions );
450 } catch ( CancelledException ce ) {
451 throw new CancelledException();
452 }
453 }
454 }
455 }
456
457 //if this is now an empty directory, or a file, delete it
458 boolean doDelete = true;
459 if ( f.isDirectory() ) {
460 File[] files = f.listFiles();
461 doDelete = ( files == null || files.length == 0 );
462 }
463
464 if ( doDelete ) {
465
466 Object[] options = null;
467 int n = 0;
468 log( Strings.replaceAll( bundle.getString("uninstaller.deleting"), "{file}", f.getAbsolutePath() ) + "\n" );
469
470 if ( !f.delete() ) {
471 log( "*********\n" + Strings.replaceAll( bundle.getString("uninstaller.warning.couldnt.delete"), "{file}", f.getAbsolutePath() ) + "\n*********\n" );
472 return;
473 }
474 }
475
476 }
477
478 class CancelledException extends Exception {}
479
480 public void changeToFinishToolbar() {
481 initialToolbar.setVisible(false);
482 frame.getContentPane().remove(initialToolbar);
483 frame.getContentPane().add( BorderLayout.SOUTH, finishToolbar );
484 finishToolbar.setVisible(true);
485 }
486
487}
488
489class Strings {
490 static String replaceAll( String s, String nugget, String replacement ) {
491 StringBuffer string = new StringBuffer(s);
492 StringBuffer r = new StringBuffer();
493
494 int io = 0;
495 while ( (io=string.toString().indexOf(nugget)) != -1 ) {
496 r.append( string.toString().substring( 0, io ) );
497 r.append( replacement );
498 string.delete( 0, io + nugget.length() );
499 }
500 r.append( string.toString() );
501 return r.toString();
502 }
503}
504
505class FollowingJTextArea extends JTextArea {
506
507 private boolean follow = true;
508
509 public FollowingJTextArea() {
510 jInit();
511 }
512
513
514 private void jInit(){
515 final JPopupMenu popUp = getPopupMenu();
516 this.add(popUp);
517 this.addMouseListener(new MouseAdapter(){
518 public void mouseClicked(MouseEvent e) {
519 if (e.getButton() == e.BUTTON3) {
520 popUp.show(FollowingJTextArea.this,e.getX(),e.getY());
521 }
522 }
523 });
524 }
525
526 public boolean isFollow() {
527 return follow;
528 }
529 public void setFollow(boolean follow) {
530 this.follow = follow;
531 }
532
533 private void scrollToEnd(){
534 setCaretPosition(getDocument().getLength());
535 }
536 private void toggleFollow(){
537 setFollow(!isFollow());
538 }
539
540 /**
541 * Appends the given text to the end of the document.
542 *
543 * @param str the text to insert
544 * @todo Implement this javax.swing.JTextArea method
545 */
546 public void append(String str) {
547 super.append(str);
548 if(follow)scrollToEnd();
549 }
550 private JPopupMenu getPopupMenu() {
551 JPopupMenu contextMenu = new JPopupMenu("Options");
552
553 JMenuItem toggleFollowMenu = new JMenuItem("Toggle Follow");
554 toggleFollowMenu.addActionListener(new ActionListener() {
555 public void actionPerformed(ActionEvent e) {
556 toggleFollow();
557 }
558 });
559 contextMenu.add(toggleFollowMenu);
560
561 JMenuItem jumpToEndMenu = new JMenuItem("Jump To End");
562 jumpToEndMenu.addActionListener(new ActionListener() {
563 public void actionPerformed(ActionEvent e) {
564 setCaretPosition(getDocument().getLength());
565 }
566 });
567 contextMenu.add(toggleFollowMenu);
568
569 JMenuItem clearTextMenu = new JMenuItem("Clear Text");
570 clearTextMenu.addActionListener(new ActionListener() {
571 public void actionPerformed(ActionEvent e) {
572 setText("");
573 }
574 });
575 contextMenu.add(clearTextMenu);
576 return contextMenu;
577 }
578}
Note: See TracBrowser for help on using the repository browser.