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

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

uninstaller now uses the unified language bundle strings, has the buttons in the right order, and repaints using a dialog box which will be replaced with a call to repaint() or similar

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