KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > ide > IDEApplication


1 /*******************************************************************************
2  * Copyright (c) 2003, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.ui.internal.ide;
12
13 import java.io.File JavaDoc;
14 import java.io.FileInputStream JavaDoc;
15 import java.io.FileOutputStream JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.io.OutputStream JavaDoc;
18 import java.net.MalformedURLException JavaDoc;
19 import java.net.URL JavaDoc;
20 import java.util.Properties JavaDoc;
21
22 import org.eclipse.core.runtime.CoreException;
23 import org.eclipse.core.runtime.IConfigurationElement;
24 import org.eclipse.core.runtime.IExecutableExtension;
25 import org.eclipse.core.runtime.IPlatformRunnable;
26 import org.eclipse.core.runtime.IStatus;
27 import org.eclipse.core.runtime.Platform;
28 import org.eclipse.core.runtime.Status;
29 import org.eclipse.jface.dialogs.MessageDialog;
30 import org.eclipse.osgi.service.datalocation.Location;
31 import org.eclipse.osgi.util.NLS;
32 import org.eclipse.swt.SWT;
33 import org.eclipse.swt.widgets.Display;
34 import org.eclipse.swt.widgets.MessageBox;
35 import org.eclipse.swt.widgets.Shell;
36 import org.eclipse.ui.PlatformUI;
37
38 /**
39  * The "main program" for the Eclipse IDE.
40  *
41  * @since 3.0
42  */

43 public class IDEApplication implements IPlatformRunnable, IExecutableExtension {
44
45     /**
46      * The name of the folder containing metadata information for the workspace.
47      */

48     public static final String JavaDoc METADATA_FOLDER = ".metadata"; //$NON-NLS-1$
49

50     private static final String JavaDoc VERSION_FILENAME = "version.ini"; //$NON-NLS-1$
51

52     private static final String JavaDoc WORKSPACE_VERSION_KEY = "org.eclipse.core.runtime"; //$NON-NLS-1$
53

54     private static final String JavaDoc WORKSPACE_VERSION_VALUE = "1"; //$NON-NLS-1$
55

56     private static final String JavaDoc PROP_EXIT_CODE = "eclipse.exitcode"; //$NON-NLS-1$
57

58     /**
59      * A special return code that will be recognized by the launcher and used to
60      * restart the workbench.
61      */

62     private static final Integer JavaDoc EXIT_RELAUNCH = new Integer JavaDoc(24);
63
64     /**
65      * Creates a new IDE application.
66      */

67     public IDEApplication() {
68         // There is nothing to do for IDEApplication
69
}
70
71     /* (non-Javadoc)
72      * @see org.eclipse.core.boot.IPlatformRunnable#run(java.lang.Object)
73      */

74     public Object JavaDoc run(Object JavaDoc args) throws Exception JavaDoc {
75         Display display = createDisplay();
76
77         try {
78             Shell shell = new Shell(display, SWT.ON_TOP);
79
80             try {
81                 if (!checkInstanceLocation(shell)) {
82                     Platform.endSplash();
83                     return EXIT_OK;
84                 }
85             } finally {
86                 if (shell != null) {
87                     shell.dispose();
88                 }
89             }
90
91             // create the workbench with this advisor and run it until it exits
92
// N.B. createWorkbench remembers the advisor, and also registers
93
// the workbench globally so that all UI plug-ins can find it using
94
// PlatformUI.getWorkbench() or AbstractUIPlugin.getWorkbench()
95
int returnCode = PlatformUI.createAndRunWorkbench(display,
96                     new IDEWorkbenchAdvisor());
97
98             // the workbench doesn't support relaunch yet (bug 61809) so
99
// for now restart is used, and exit data properties are checked
100
// here to substitute in the relaunch return code if needed
101
if (returnCode != PlatformUI.RETURN_RESTART) {
102                 return EXIT_OK;
103             }
104
105             // if the exit code property has been set to the relaunch code, then
106
// return that code now, otherwise this is a normal restart
107
return EXIT_RELAUNCH.equals(Integer.getInteger(PROP_EXIT_CODE)) ? EXIT_RELAUNCH
108                     : EXIT_RESTART;
109         } finally {
110             if (display != null) {
111                 display.dispose();
112             }
113         }
114     }
115
116     /**
117      * Creates the display used by the application.
118      *
119      * @return the display used by the application
120      */

121     protected Display createDisplay() {
122         return PlatformUI.createDisplay();
123     }
124
125     /* (non-Javadoc)
126      * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
127      */

128     public void setInitializationData(IConfigurationElement config,
129             String JavaDoc propertyName, Object JavaDoc data) throws CoreException {
130         // There is nothing to do for IDEApplication
131
}
132
133     /**
134      * Return true if a valid workspace path has been set and false otherwise.
135      * Prompt for and set the path if possible and required.
136      *
137      * @return true if a valid instance location has been set and false
138      * otherwise
139      */

140     private boolean checkInstanceLocation(Shell shell) {
141         // -data @none was specified but an ide requires workspace
142
Location instanceLoc = Platform.getInstanceLocation();
143         if (instanceLoc == null) {
144             MessageDialog
145                     .openError(
146                             shell,
147                             IDEWorkbenchMessages.IDEApplication_workspaceMandatoryTitle,
148                             IDEWorkbenchMessages.IDEApplication_workspaceMandatoryMessage);
149             return false;
150         }
151
152         // -data "/valid/path", workspace already set
153
if (instanceLoc.isSet()) {
154             // make sure the meta data version is compatible (or the user has
155
// chosen to overwrite it).
156
if (!checkValidWorkspace(shell, instanceLoc.getURL())) {
157                 return false;
158             }
159
160             // at this point its valid, so try to lock it and update the
161
// metadata version information if successful
162
try {
163                 if (instanceLoc.lock()) {
164                     writeWorkspaceVersion();
165                     return true;
166                 }
167                 MessageDialog
168                 .openError(
169                         shell,
170                         IDEWorkbenchMessages.IDEApplication_workspaceCannotLockTitle,
171                         IDEWorkbenchMessages.IDEApplication_workspaceCannotLockMessage);
172             } catch (IOException JavaDoc e) {
173                 IDEWorkbenchPlugin.log("Could not obtain lock for workspace location", //$NON-NLS-1$
174
e);
175                 MessageDialog
176                 .openError(
177                         shell,
178                         IDEWorkbenchMessages.InternalError,
179                         e.getMessage());
180             }
181             return false;
182         }
183
184         // -data @noDefault or -data not specified, prompt and set
185
ChooseWorkspaceData launchData = new ChooseWorkspaceData(instanceLoc
186                 .getDefault());
187
188         boolean force = false;
189         while (true) {
190             URL JavaDoc workspaceUrl = promptForWorkspace(shell, launchData, force);
191             if (workspaceUrl == null) {
192                 return false;
193             }
194
195             // if there is an error with the first selection, then force the
196
// dialog to open to give the user a chance to correct
197
force = true;
198
199             try {
200                 // the operation will fail if the url is not a valid
201
// instance data area, so other checking is unneeded
202
if (instanceLoc.setURL(workspaceUrl, true)) {
203                     launchData.writePersistedData();
204                     writeWorkspaceVersion();
205                     return true;
206                 }
207             } catch (IllegalStateException JavaDoc e) {
208                 MessageDialog
209                         .openError(
210                                 shell,
211                                 IDEWorkbenchMessages.IDEApplication_workspaceCannotBeSetTitle,
212                                 IDEWorkbenchMessages.IDEApplication_workspaceCannotBeSetMessage);
213                 return false;
214             }
215
216             // by this point it has been determined that the workspace is
217
// already in use -- force the user to choose again
218
MessageDialog.openError(shell, IDEWorkbenchMessages.IDEApplication_workspaceInUseTitle,
219                     IDEWorkbenchMessages.IDEApplication_workspaceInUseMessage);
220         }
221     }
222
223     /**
224      * Open a workspace selection dialog on the argument shell, populating the
225      * argument data with the user's selection. Perform first level validation
226      * on the selection by comparing the version information. This method does
227      * not examine the runtime state (e.g., is the workspace already locked?).
228      *
229      * @param shell
230      * @param launchData
231      * @param force
232      * setting to true makes the dialog open regardless of the
233      * showDialog value
234      * @return An URL storing the selected workspace or null if the user has
235      * canceled the launch operation.
236      */

237     private URL JavaDoc promptForWorkspace(Shell shell, ChooseWorkspaceData launchData,
238             boolean force) {
239         URL JavaDoc url = null;
240         do {
241             // don't use the parent shell to make the dialog a top-level
242
// shell. See bug 84881.
243
new ChooseWorkspaceDialog(null, launchData, false, true).prompt(force);
244             String JavaDoc instancePath = launchData.getSelection();
245             if (instancePath == null) {
246                 return null;
247             }
248
249             // the dialog is not forced on the first iteration, but is on every
250
// subsequent one -- if there was an error then the user needs to be
251
// allowed to fix it
252
force = true;
253
254             // 70576: don't accept empty input
255
if (instancePath.length() <= 0) {
256                 MessageDialog
257                 .openError(
258                         shell,
259                         IDEWorkbenchMessages.IDEApplication_workspaceEmptyTitle,
260                         IDEWorkbenchMessages.IDEApplication_workspaceEmptyMessage);
261                 continue;
262             }
263
264             // create the workspace if it does not already exist
265
File JavaDoc workspace = new File JavaDoc(instancePath);
266             if (!workspace.exists()) {
267                 workspace.mkdir();
268             }
269
270             try {
271                 // Don't use File.toURL() since it adds a leading slash that Platform does not
272
// handle properly. See bug 54081 for more details.
273
String JavaDoc path = workspace.getAbsolutePath().replace(
274                         File.separatorChar, '/');
275                 url = new URL JavaDoc("file", null, path); //$NON-NLS-1$
276
} catch (MalformedURLException JavaDoc e) {
277                 MessageDialog
278                         .openError(
279                                 shell,
280                                 IDEWorkbenchMessages.IDEApplication_workspaceInvalidTitle,
281                                 IDEWorkbenchMessages.IDEApplication_workspaceInvalidMessage);
282                 continue;
283             }
284         } while (!checkValidWorkspace(shell, url));
285
286         return url;
287     }
288
289     /**
290      * Return true if the argument directory is ok to use as a workspace and
291      * false otherwise. A version check will be performed, and a confirmation
292      * box may be displayed on the argument shell if an older version is
293      * detected.
294      *
295      * @return true if the argument URL is ok to use as a workspace and false
296      * otherwise.
297      */

298     private boolean checkValidWorkspace(Shell shell, URL JavaDoc url) {
299         // a null url is not a valid workspace
300
if (url == null) {
301             return false;
302         }
303
304         String JavaDoc version = readWorkspaceVersion(url);
305
306         // if the version could not be read, then there is not any existing
307
// workspace data to trample, e.g., perhaps its a new directory that
308
// is just starting to be used as a workspace
309
if (version == null) {
310             return true;
311         }
312
313         final int ide_version = Integer.parseInt(WORKSPACE_VERSION_VALUE);
314         int workspace_version = Integer.parseInt(version);
315
316         // equality test is required since any version difference (newer
317
// or older) may result in data being trampled
318
if (workspace_version == ide_version) {
319             return true;
320         }
321
322         // At this point workspace has been detected to be from a version
323
// other than the current ide version -- find out if the user wants
324
// to use it anyhow.
325
String JavaDoc title = IDEWorkbenchMessages.IDEApplication_versionTitle;
326         String JavaDoc message = NLS.bind(IDEWorkbenchMessages.IDEApplication_versionMessage, url.getFile());
327
328         MessageBox mbox = new MessageBox(shell, SWT.OK | SWT.CANCEL
329                 | SWT.ICON_WARNING | SWT.APPLICATION_MODAL);
330         mbox.setText(title);
331         mbox.setMessage(message);
332         return mbox.open() == SWT.OK;
333     }
334
335     /**
336      * Look at the argument URL for the workspace's version information. Return
337      * that version if found and null otherwise.
338      */

339     private static String JavaDoc readWorkspaceVersion(URL JavaDoc workspace) {
340         File JavaDoc versionFile = getVersionFile(workspace, false);
341         if (versionFile == null || !versionFile.exists()) {
342             return null;
343         }
344
345         try {
346             // Although the version file is not spec'ed to be a Java properties
347
// file, it happens to follow the same format currently, so using
348
// Properties to read it is convenient.
349
Properties JavaDoc props = new Properties JavaDoc();
350             FileInputStream JavaDoc is = new FileInputStream JavaDoc(versionFile);
351             try {
352                 props.load(is);
353             } finally {
354                 is.close();
355             }
356
357             return props.getProperty(WORKSPACE_VERSION_KEY);
358         } catch (IOException JavaDoc e) {
359             IDEWorkbenchPlugin.log("Could not read version file", new Status( //$NON-NLS-1$
360
IStatus.ERROR, IDEWorkbenchPlugin.IDE_WORKBENCH,
361                     IStatus.ERROR,
362                     e.getMessage() == null ? "" : e.getMessage(), //$NON-NLS-1$,
363
e));
364             return null;
365         }
366     }
367
368     /**
369      * Write the version of the metadata into a known file overwriting any
370      * existing file contents. Writing the version file isn't really crucial,
371      * so the function is silent about failure
372      */

373     private static void writeWorkspaceVersion() {
374         Location instanceLoc = Platform.getInstanceLocation();
375         if (instanceLoc == null || instanceLoc.isReadOnly()) {
376             return;
377         }
378
379         File JavaDoc versionFile = getVersionFile(instanceLoc.getURL(), true);
380         if (versionFile == null) {
381             return;
382         }
383
384         OutputStream JavaDoc output = null;
385         try {
386             String JavaDoc versionLine = WORKSPACE_VERSION_KEY + '='
387                     + WORKSPACE_VERSION_VALUE;
388
389             output = new FileOutputStream JavaDoc(versionFile);
390             output.write(versionLine.getBytes("UTF-8")); //$NON-NLS-1$
391
} catch (IOException JavaDoc e) {
392             IDEWorkbenchPlugin.log("Could not write version file", //$NON-NLS-1$
393
StatusUtil.newStatus(IStatus.ERROR, e.getMessage(), e));
394         } finally {
395             try {
396                 if (output != null) {
397                     output.close();
398                 }
399             } catch (IOException JavaDoc e) {
400                 // do nothing
401
}
402         }
403     }
404
405     /**
406      * The version file is stored in the metadata area of the workspace. This
407      * method returns an URL to the file or null if the directory or file does
408      * not exist (and the create parameter is false).
409      *
410      * @param create
411      * If the directory and file does not exist this parameter
412      * controls whether it will be created.
413      * @return An url to the file or null if the version file does not exist or
414      * could not be created.
415      */

416     private static File JavaDoc getVersionFile(URL JavaDoc workspaceUrl, boolean create) {
417         if (workspaceUrl == null) {
418             return null;
419         }
420
421         try {
422             // make sure the directory exists
423
File JavaDoc metaDir = new File JavaDoc(workspaceUrl.getPath(), METADATA_FOLDER);
424             if (!metaDir.exists() && (!create || !metaDir.mkdir())) {
425                 return null;
426             }
427
428             // make sure the file exists
429
File JavaDoc versionFile = new File JavaDoc(metaDir, VERSION_FILENAME);
430             if (!versionFile.exists()
431                     && (!create || !versionFile.createNewFile())) {
432                 return null;
433             }
434
435             return versionFile;
436         } catch (IOException JavaDoc e) {
437             // cannot log because instance area has not been set
438
return null;
439         }
440     }
441 }
442
Popular Tags