source: josm/trunk/src/org/openstreetmap/josm/gui/MainApplication.java@ 6040

Last change on this file since 6040 was 5868, checked in by stoecker, 11 years ago

see #8606 - use JOSM agent also for WebStart, join help browser and WikiReader

  • Property svn:eol-style set to native
File size: 17.7 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.Image;
8import java.awt.Toolkit;
9import java.awt.event.WindowAdapter;
10import java.awt.event.WindowEvent;
11import java.io.File;
12import java.net.Authenticator;
13import java.net.ProxySelector;
14import java.net.URL;
15import java.security.AllPermission;
16import java.security.CodeSource;
17import java.security.PermissionCollection;
18import java.security.Permissions;
19import java.security.Policy;
20import java.util.ArrayList;
21import java.util.Collection;
22import java.util.HashMap;
23import java.util.LinkedList;
24import java.util.List;
25import java.util.Map;
26
27import javax.swing.JFrame;
28import javax.swing.RepaintManager;
29import javax.swing.SwingUtilities;
30
31import gnu.getopt.Getopt;
32import gnu.getopt.LongOpt;
33
34import org.jdesktop.swinghelper.debug.CheckThreadViolationRepaintManager;
35import org.openstreetmap.josm.Main;
36import org.openstreetmap.josm.data.AutosaveTask;
37import org.openstreetmap.josm.data.CustomConfigurator;
38import org.openstreetmap.josm.data.Preferences;
39import org.openstreetmap.josm.data.Version;
40import org.openstreetmap.josm.gui.download.DownloadDialog;
41import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
42import org.openstreetmap.josm.gui.progress.ProgressMonitor;
43import org.openstreetmap.josm.gui.util.GuiHelper;
44import org.openstreetmap.josm.io.DefaultProxySelector;
45import org.openstreetmap.josm.io.auth.CredentialsManager;
46import org.openstreetmap.josm.io.auth.DefaultAuthenticator;
47import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
48import org.openstreetmap.josm.plugins.PluginHandler;
49import org.openstreetmap.josm.plugins.PluginInformation;
50import org.openstreetmap.josm.tools.BugReportExceptionHandler;
51import org.openstreetmap.josm.tools.I18n;
52import org.openstreetmap.josm.tools.ImageProvider;
53import org.openstreetmap.josm.tools.Utils;
54
55/**
56 * Main window class application.
57 *
58 * @author imi
59 */
60public class MainApplication extends Main {
61 /**
62 * Allow subclassing (see JOSM.java)
63 */
64 public MainApplication() {}
65
66 /**
67 * Constructs a main frame, ready sized and operating. Does not display the frame.
68 * @param mainFrame The main JFrame of the application
69 */
70 public MainApplication(JFrame mainFrame) {
71 addListener();
72 mainFrame.setContentPane(contentPanePrivate);
73 mainFrame.setJMenuBar(menu);
74 geometry.applySafe(mainFrame);
75 LinkedList<Image> l = new LinkedList<Image>();
76 l.add(ImageProvider.get("logo_16x16x32").getImage());
77 l.add(ImageProvider.get("logo_16x16x8").getImage());
78 l.add(ImageProvider.get("logo_32x32x32").getImage());
79 l.add(ImageProvider.get("logo_32x32x8").getImage());
80 l.add(ImageProvider.get("logo_48x48x32").getImage());
81 l.add(ImageProvider.get("logo_48x48x8").getImage());
82 l.add(ImageProvider.get("logo").getImage());
83 mainFrame.setIconImages(l);
84 mainFrame.addWindowListener(new WindowAdapter(){
85 @Override public void windowClosing(final WindowEvent arg0) {
86 Main.exitJosm(true);
87 }
88 });
89 mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
90 }
91
92 /**
93 * Displays help on the console
94 *
95 */
96 public static void showHelp() {
97 // TODO: put in a platformHook for system that have no console by default
98 System.out.println(tr("Java OpenStreetMap Editor")+" ["
99 +Version.getInstance().getAgentString()+"]\n\n"+
100 tr("usage")+":\n"+
101 "\tjava -jar josm.jar <options>...\n\n"+
102 tr("options")+":\n"+
103 "\t--help|-h "+tr("Show this help")+"\n"+
104 "\t--geometry=widthxheight(+|-)x(+|-)y "+tr("Standard unix geometry argument")+"\n"+
105 "\t[--download=]minlat,minlon,maxlat,maxlon "+tr("Download the bounding box")+"\n"+
106 "\t[--download=]<URL> "+tr("Download the location at the URL (with lat=x&lon=y&zoom=z)")+"\n"+
107 "\t[--download=]<filename> "+tr("Open a file (any file type that can be opened with File/Open)")+"\n"+
108 "\t--downloadgps=minlat,minlon,maxlat,maxlon "+tr("Download the bounding box as raw GPS")+"\n"+
109 "\t--downloadgps=<URL> "+tr("Download the location at the URL (with lat=x&lon=y&zoom=z) as raw GPS")+"\n"+
110 "\t--selection=<searchstring> "+tr("Select with the given search")+"\n"+
111 "\t--[no-]maximize "+tr("Launch in maximized mode")+"\n"+
112 "\t--reset-preferences "+tr("Reset the preferences to default")+"\n\n"+
113 "\t--load-preferences=<url-to-xml> "+tr("Changes preferences according to the XML file")+"\n\n"+
114 "\t--set=<key>=<value> "+tr("Set preference key to value")+"\n\n"+
115 "\t--language=<language> "+tr("Set the language")+"\n\n"+
116 "\t--version "+tr("Displays the JOSM version and exits")+"\n\n"+
117 tr("options provided as Java system properties")+":\n"+
118 "\t-Djosm.home="+tr("/PATH/TO/JOSM/FOLDER/ ")+tr("Change the folder for all user settings")+"\n\n"+
119 tr("note: For some tasks, JOSM needs a lot of memory. It can be necessary to add the following\n" +
120 " Java option to specify the maximum size of allocated memory in megabytes")+":\n"+
121 "\t-Xmx...m\n\n"+
122 tr("examples")+":\n"+
123 "\tjava -jar josm.jar track1.gpx track2.gpx london.osm\n"+
124 "\tjava -jar josm.jar http://www.openstreetmap.org/index.html?lat=43.2&lon=11.1&zoom=13\n"+
125 "\tjava -jar josm.jar london.osm --selection=http://www.ostertag.name/osm/OSM_errors_node-duplicate.xml\n"+
126 "\tjava -jar josm.jar 43.2,11.1,43.4,11.4\n"+
127 "\tjava -Djosm.home=/home/user/.josm_dev -jar josm.jar\n"+
128 "\tjava -Xmx400m -jar josm.jar\n\n"+
129 tr("Parameters --download, --downloadgps, and --selection are processed in this order.")+"\n"+
130 tr("Make sure you load some data if you use --selection.")+"\n"
131 );
132 }
133
134 public enum Option {
135 HELP(false),
136 VERSION(false),
137 LANGUAGE(true),
138 RESET_PREFERENCES(false),
139 LOAD_PREFERENCES(true),
140 SET(true),
141 GEOMETRY(true),
142 NO_MAXIMIZE(false),
143 MAXIMIZE(false),
144 DOWNLOAD(true),
145 DOWNLOADGPS(true),
146 SELECTION(true);
147
148 private String name;
149 private boolean requiresArgument;
150
151 private Option(boolean requiresArgument) {
152 this.name = name().toLowerCase().replace("_", "-");
153 this.requiresArgument = requiresArgument;
154 }
155
156 public String getName() {
157 return name;
158 }
159
160 public boolean requiresArgument() {
161 return requiresArgument;
162 }
163
164 public static Map<Option, Collection<String>> fromStringMap(Map<String, Collection<String>> opts) {
165 Map<Option, Collection<String>> res = new HashMap<Option, Collection<String>>();
166 for (Map.Entry<String, Collection<String>> e : opts.entrySet()) {
167 Option o = Option.valueOf(e.getKey().toUpperCase().replace("-", "_"));
168 if (o != null) {
169 res.put(o, e.getValue());
170 }
171 }
172 return res;
173 }
174 }
175
176 private static Map<Option, Collection<String>> buildCommandLineArgumentMap(String[] args) {
177
178 List<LongOpt> los = new ArrayList<LongOpt>();
179 for (Option o : Option.values()) {
180 los.add(new LongOpt(o.getName(), o.requiresArgument() ? LongOpt.REQUIRED_ARGUMENT : LongOpt.NO_ARGUMENT, null, 0));
181 }
182
183 Getopt g = new Getopt("JOSM", args, "hv", los.toArray(new LongOpt[0]));
184
185 Map<Option, Collection<String>> argMap = new HashMap<Option, Collection<String>>();
186
187 int c;
188 while ((c = g.getopt()) != -1 ) {
189 Option opt = null;
190 switch (c) {
191 case 'h':
192 opt = Option.HELP;
193 break;
194 case 'v':
195 opt = Option.VERSION;
196 break;
197 case 0:
198 opt = Option.values()[g.getLongind()];
199 break;
200 }
201 if (opt != null) {
202 Collection<String> values = argMap.get(opt);
203 if (values == null) {
204 values = new ArrayList<String>();
205 argMap.put(opt, values);
206 }
207 values.add(g.getOptarg());
208 } else
209 throw new IllegalArgumentException();
210 }
211 // positional arguments are a shortcut for the --download ... option
212 for (int i = g.getOptind(); i < args.length; ++i) {
213 Collection<String> values = argMap.get(Option.DOWNLOAD);
214 if (values == null) {
215 values = new ArrayList<String>();
216 argMap.put(Option.DOWNLOAD, values);
217 }
218 values.add(args[i]);
219 }
220
221 return argMap;
222 }
223
224 /**
225 * Main application Startup
226 * @param argArray Command-line arguments
227 */
228 public static void main(final String[] argArray) {
229 I18n.init();
230 Main.checkJava6();
231 Main.pref = new Preferences();
232
233 Policy.setPolicy(new Policy() {
234 // Permissions for plug-ins loaded when josm is started via webstart
235 private PermissionCollection pc;
236
237 {
238 pc = new Permissions();
239 pc.add(new AllPermission());
240 }
241
242 @Override
243 public void refresh() { }
244
245 @Override
246 public PermissionCollection getPermissions(CodeSource codesource) {
247 return pc;
248 }
249 });
250
251 Thread.setDefaultUncaughtExceptionHandler(new BugReportExceptionHandler());
252 // http://stuffthathappens.com/blog/2007/10/15/one-more-note-on-uncaught-exception-handlers/
253 System.setProperty("sun.awt.exception.handler", BugReportExceptionHandler.class.getName());
254
255 // initialize the platform hook, and
256 Main.determinePlatformHook();
257 // call the really early hook before we do anything else
258 Main.platform.preStartupHook();
259
260 // construct argument table
261 Map<Option, Collection<String>> args = null;
262 try {
263 args = buildCommandLineArgumentMap(argArray);
264 } catch (IllegalArgumentException e) {
265 System.exit(1);
266 }
267
268 Main.commandLineArgs = argArray;
269
270 if (args.containsKey(Option.VERSION)) {
271 System.out.println(Version.getInstance().getAgentString());
272 System.exit(0);
273 } //else {
274 // System.out.println(Version.getInstance().getReleaseAttributes());
275 //}
276
277 Main.pref.init(args.containsKey(Option.RESET_PREFERENCES));
278
279 // Check if passed as parameter
280 if (args.containsKey(Option.LANGUAGE)) {
281 I18n.set(args.get(Option.LANGUAGE).iterator().next());
282 } else {
283 I18n.set(Main.pref.get("language", null));
284 }
285 Main.pref.updateSystemProperties();
286
287 final JFrame mainFrame = new JFrame(tr("Java OpenStreetMap Editor"));
288 Main.parent = mainFrame;
289
290 if (args.containsKey(Option.LOAD_PREFERENCES)) {
291 CustomConfigurator.XMLCommandProcessor config = new CustomConfigurator.XMLCommandProcessor(Main.pref);
292 for (String i : args.get(Option.LOAD_PREFERENCES)) {
293 System.out.println("Reading preferences from " + i);
294 try {
295 config.openAndReadXML(Utils.openURL(new URL(i)));
296 } catch (Exception ex) {
297 throw new RuntimeException(ex);
298 }
299 }
300 }
301
302 if (args.containsKey(Option.SET)) {
303 for (String i : args.get(Option.SET)) {
304 String[] kv = i.split("=", 2);
305 Main.pref.put(kv[0], "null".equals(kv[1]) ? null : kv[1]);
306 }
307 }
308
309 DefaultAuthenticator.createInstance();
310 Authenticator.setDefault(DefaultAuthenticator.getInstance());
311 ProxySelector.setDefault(new DefaultProxySelector(ProxySelector.getDefault()));
312 OAuthAccessTokenHolder.getInstance().init(Main.pref, CredentialsManager.getInstance());
313
314 // asking for help? show help and exit
315 if (args.containsKey(Option.HELP)) {
316 showHelp();
317 System.exit(0);
318 }
319
320 final SplashScreen splash = new SplashScreen();
321 final ProgressMonitor monitor = splash.getProgressMonitor();
322 monitor.beginTask(tr("Initializing"));
323 splash.setVisible(Main.pref.getBoolean("draw.splashscreen", true));
324 Main.setInitStatusListener(new InitStatusListener() {
325
326 @Override
327 public void updateStatus(String event) {
328 monitor.indeterminateSubTask(event);
329 }
330 });
331
332 List<PluginInformation> pluginsToLoad = PluginHandler.buildListOfPluginsToLoad(splash,monitor.createSubTaskMonitor(1, false));
333 if (!pluginsToLoad.isEmpty() && PluginHandler.checkAndConfirmPluginUpdate(splash)) {
334 monitor.subTask(tr("Updating plugins"));
335 pluginsToLoad = PluginHandler.updatePlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false));
336 }
337
338 monitor.indeterminateSubTask(tr("Installing updated plugins"));
339 PluginHandler.installDownloadedPlugins(true);
340
341 monitor.indeterminateSubTask(tr("Loading early plugins"));
342 PluginHandler.loadEarlyPlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false));
343
344 monitor.indeterminateSubTask(tr("Setting defaults"));
345 preConstructorInit(args);
346
347 monitor.indeterminateSubTask(tr("Creating main GUI"));
348 final Main main = new MainApplication(mainFrame);
349
350 monitor.indeterminateSubTask(tr("Loading plugins"));
351 PluginHandler.loadLatePlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false));
352 toolbar.refreshToolbarControl();
353
354 GuiHelper.runInEDT(new Runnable() {
355 public void run() {
356 splash.setVisible(false);
357 splash.dispose();
358 mainFrame.setVisible(true);
359 }
360 });
361
362 Main.MasterWindowListener.setup();
363
364 boolean maximized = Boolean.parseBoolean(Main.pref.get("gui.maximized"));
365 if ((!args.containsKey(Option.NO_MAXIMIZE) && maximized) || args.containsKey(Option.MAXIMIZE)) {
366 if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH)) {
367 // Main.debug("Main window maximized");
368 Main.windowState = JFrame.MAXIMIZED_BOTH;
369 mainFrame.setExtendedState(Main.windowState);
370 } else {
371 Main.debug("Main window: maximizing not supported");
372 }
373 } else {
374 // Main.debug("Main window not maximized");
375 }
376 if(main.menu.fullscreenToggleAction != null) {
377 main.menu.fullscreenToggleAction.initial();
378 }
379
380 final Map<Option, Collection<String>> args_final = args;
381
382 SwingUtilities.invokeLater(new Runnable() {
383 public void run() {
384 if (AutosaveTask.PROP_AUTOSAVE_ENABLED.get()) {
385 AutosaveTask autosaveTask = new AutosaveTask();
386 List<File> unsavedLayerFiles = autosaveTask.getUnsavedLayersFiles();
387 if (!unsavedLayerFiles.isEmpty()) {
388 ExtendedDialog dialog = new ExtendedDialog(
389 Main.parent,
390 tr("Unsaved osm data"),
391 new String[] {tr("Restore"), tr("Cancel"), tr("Discard")}
392 );
393 dialog.setContent(
394 trn("JOSM found {0} unsaved osm data layer. ",
395 "JOSM found {0} unsaved osm data layers. ", unsavedLayerFiles.size(), unsavedLayerFiles.size()) +
396 tr("It looks like JOSM crashed last time. Would you like to restore the data?"));
397 dialog.setButtonIcons(new String[] {"ok", "cancel", "dialogs/delete"});
398 int selection = dialog.showDialog().getValue();
399 if (selection == 1) {
400 autosaveTask.recoverUnsavedLayers();
401 } else if (selection == 3) {
402 autosaveTask.dicardUnsavedLayers();
403 }
404 }
405 autosaveTask.schedule();
406 }
407
408 postConstructorProcessCmdLine(args_final);
409
410 DownloadDialog.autostartIfNeeded();
411 }
412 });
413
414 if (RemoteControl.PROP_REMOTECONTROL_ENABLED.get()) {
415 RemoteControl.start();
416 }
417
418 if (Main.pref.getBoolean("debug.edt-checker.enable", Version.getInstance().isLocalBuild())) {
419 // Repaint manager is registered so late for a reason - there is lots of violation during startup process but they don't seem to break anything and are difficult to fix
420 System.out.println("Enabled EDT checker, wrongful access to gui from non EDT thread will be printed to console");
421 RepaintManager.setCurrentManager(new CheckThreadViolationRepaintManager());
422 }
423 }
424}
Note: See TracBrowser for help on using the repository browser.