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

Last change on this file since 6388 was 6380, checked in by Don-vip, 10 years ago

update license/copyright information

  • Property svn:eol-style set to native
File size: 19.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6import gnu.getopt.Getopt;
7import gnu.getopt.LongOpt;
8
9import java.awt.Image;
10import java.awt.Toolkit;
11import java.awt.event.WindowAdapter;
12import java.awt.event.WindowEvent;
13import java.io.File;
14import java.net.Authenticator;
15import java.net.ProxySelector;
16import java.net.URL;
17import java.security.AllPermission;
18import java.security.CodeSource;
19import java.security.PermissionCollection;
20import java.security.Permissions;
21import java.security.Policy;
22import java.util.ArrayList;
23import java.util.Collection;
24import java.util.HashMap;
25import java.util.LinkedList;
26import java.util.List;
27import java.util.Map;
28
29import javax.swing.JFrame;
30import javax.swing.RepaintManager;
31import javax.swing.SwingUtilities;
32
33import org.jdesktop.swinghelper.debug.CheckThreadViolationRepaintManager;
34import org.openstreetmap.josm.Main;
35import org.openstreetmap.josm.data.AutosaveTask;
36import org.openstreetmap.josm.data.CustomConfigurator;
37import org.openstreetmap.josm.data.Preferences;
38import org.openstreetmap.josm.data.Version;
39import org.openstreetmap.josm.gui.download.DownloadDialog;
40import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
41import org.openstreetmap.josm.gui.progress.ProgressMonitor;
42import org.openstreetmap.josm.gui.util.GuiHelper;
43import org.openstreetmap.josm.io.DefaultProxySelector;
44import org.openstreetmap.josm.io.MessageNotifier;
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, 0);
87 }
88 });
89 mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
90 }
91
92 /**
93 * Displays help on the console
94 * @since 2748
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 /**
135 * JOSM command line options.
136 * @see <a href="http://josm.openstreetmap.de/wiki/Help/CommandLineOptions">Help/CommandLineOptions</a>
137 * @since 5279
138 */
139 public enum Option {
140 /** --help|-h Show this help */
141 HELP(false),
142 /** --version Displays the JOSM version and exits */
143 VERSION(false),
144 /** --language=<language> Set the language */
145 LANGUAGE(true),
146 /** --reset-preferences Reset the preferences to default */
147 RESET_PREFERENCES(false),
148 /** --load-preferences=<url-to-xml> Changes preferences according to the XML file */
149 LOAD_PREFERENCES(true),
150 /** --set=<key>=<value> Set preference key to value */
151 SET(true),
152 /** --geometry=widthxheight(+|-)x(+|-)y Standard unix geometry argument */
153 GEOMETRY(true),
154 /** --no-maximize Do not launch in maximized mode */
155 NO_MAXIMIZE(false),
156 /** --maximize Launch in maximized mode */
157 MAXIMIZE(false),
158 /** --download=minlat,minlon,maxlat,maxlon Download the bounding box <br>
159 * --download=<URL> Download the location at the URL (with lat=x&lon=y&zoom=z) <br>
160 * --download=<filename> Open a file (any file type that can be opened with File/Open) */
161 DOWNLOAD(true),
162 /** --downloadgps=minlat,minlon,maxlat,maxlon Download the bounding box as raw GPS <br>
163 * --downloadgps=<URL> Download the location at the URL (with lat=x&lon=y&zoom=z) as raw GPS */
164 DOWNLOADGPS(true),
165 /** --selection=<searchstring> Select with the given search */
166 SELECTION(true);
167
168 private String name;
169 private boolean requiresArgument;
170
171 private Option(boolean requiresArgument) {
172 this.name = name().toLowerCase().replace("_", "-");
173 this.requiresArgument = requiresArgument;
174 }
175
176 /**
177 * Replies the option name
178 * @return The option name, in lowercase
179 */
180 public String getName() {
181 return name;
182 }
183
184 /**
185 * Determines if this option requires an argument.
186 * @return {@code true} if this option requires an argument, {@code false} otherwise
187 */
188 public boolean requiresArgument() {
189 return requiresArgument;
190 }
191
192 public static Map<Option, Collection<String>> fromStringMap(Map<String, Collection<String>> opts) {
193 Map<Option, Collection<String>> res = new HashMap<Option, Collection<String>>();
194 for (Map.Entry<String, Collection<String>> e : opts.entrySet()) {
195 Option o = Option.valueOf(e.getKey().toUpperCase().replace("-", "_"));
196 if (o != null) {
197 res.put(o, e.getValue());
198 }
199 }
200 return res;
201 }
202 }
203
204 private static Map<Option, Collection<String>> buildCommandLineArgumentMap(String[] args) {
205
206 List<LongOpt> los = new ArrayList<LongOpt>();
207 for (Option o : Option.values()) {
208 los.add(new LongOpt(o.getName(), o.requiresArgument() ? LongOpt.REQUIRED_ARGUMENT : LongOpt.NO_ARGUMENT, null, 0));
209 }
210
211 Getopt g = new Getopt("JOSM", args, "hv", los.toArray(new LongOpt[los.size()]));
212
213 Map<Option, Collection<String>> argMap = new HashMap<Option, Collection<String>>();
214
215 int c;
216 while ((c = g.getopt()) != -1 ) {
217 Option opt = null;
218 switch (c) {
219 case 'h':
220 opt = Option.HELP;
221 break;
222 case 'v':
223 opt = Option.VERSION;
224 break;
225 case 0:
226 opt = Option.values()[g.getLongind()];
227 break;
228 }
229 if (opt != null) {
230 Collection<String> values = argMap.get(opt);
231 if (values == null) {
232 values = new ArrayList<String>();
233 argMap.put(opt, values);
234 }
235 values.add(g.getOptarg());
236 } else
237 throw new IllegalArgumentException();
238 }
239 // positional arguments are a shortcut for the --download ... option
240 for (int i = g.getOptind(); i < args.length; ++i) {
241 Collection<String> values = argMap.get(Option.DOWNLOAD);
242 if (values == null) {
243 values = new ArrayList<String>();
244 argMap.put(Option.DOWNLOAD, values);
245 }
246 values.add(args[i]);
247 }
248
249 return argMap;
250 }
251
252 /**
253 * Main application Startup
254 * @param argArray Command-line arguments
255 */
256 public static void main(final String[] argArray) {
257 I18n.init();
258 Main.checkJava6();
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 final boolean languageGiven = args.containsKey(Option.LANGUAGE);
269
270 if (languageGiven) {
271 I18n.set(args.get(Option.LANGUAGE).iterator().next());
272 }
273
274 Main.pref = new Preferences();
275
276 Policy.setPolicy(new Policy() {
277 // Permissions for plug-ins loaded when josm is started via webstart
278 private PermissionCollection pc;
279
280 {
281 pc = new Permissions();
282 pc.add(new AllPermission());
283 }
284
285 @Override
286 public void refresh() { }
287
288 @Override
289 public PermissionCollection getPermissions(CodeSource codesource) {
290 return pc;
291 }
292 });
293
294 Thread.setDefaultUncaughtExceptionHandler(new BugReportExceptionHandler());
295 // http://stuffthathappens.com/blog/2007/10/15/one-more-note-on-uncaught-exception-handlers/
296 System.setProperty("sun.awt.exception.handler", BugReportExceptionHandler.class.getName());
297
298 // initialize the platform hook, and
299 Main.determinePlatformHook();
300 // call the really early hook before we do anything else
301 Main.platform.preStartupHook();
302
303 Main.commandLineArgs = Utils.copyArray(argArray);
304
305 if (args.containsKey(Option.VERSION)) {
306 System.out.println(Version.getInstance().getAgentString());
307 System.exit(0);
308 }
309
310 Main.pref.init(args.containsKey(Option.RESET_PREFERENCES));
311
312 if (!languageGiven) {
313 I18n.set(Main.pref.get("language", null));
314 }
315 Main.pref.updateSystemProperties();
316
317 final JFrame mainFrame = new JFrame(tr("Java OpenStreetMap Editor"));
318 Main.parent = mainFrame;
319
320 if (args.containsKey(Option.LOAD_PREFERENCES)) {
321 CustomConfigurator.XMLCommandProcessor config = new CustomConfigurator.XMLCommandProcessor(Main.pref);
322 for (String i : args.get(Option.LOAD_PREFERENCES)) {
323 info("Reading preferences from " + i);
324 try {
325 config.openAndReadXML(Utils.openURL(new URL(i)));
326 } catch (Exception ex) {
327 throw new RuntimeException(ex);
328 }
329 }
330 }
331
332 if (args.containsKey(Option.SET)) {
333 for (String i : args.get(Option.SET)) {
334 String[] kv = i.split("=", 2);
335 Main.pref.put(kv[0], "null".equals(kv[1]) ? null : kv[1]);
336 }
337 }
338
339 DefaultAuthenticator.createInstance();
340 Authenticator.setDefault(DefaultAuthenticator.getInstance());
341 ProxySelector.setDefault(new DefaultProxySelector(ProxySelector.getDefault()));
342 OAuthAccessTokenHolder.getInstance().init(Main.pref, CredentialsManager.getInstance());
343
344 // asking for help? show help and exit
345 if (args.containsKey(Option.HELP)) {
346 showHelp();
347 System.exit(0);
348 }
349
350 final SplashScreen splash = new SplashScreen();
351 final ProgressMonitor monitor = splash.getProgressMonitor();
352 monitor.beginTask(tr("Initializing"));
353 splash.setVisible(Main.pref.getBoolean("draw.splashscreen", true));
354 Main.setInitStatusListener(new InitStatusListener() {
355
356 @Override
357 public void updateStatus(String event) {
358 monitor.indeterminateSubTask(event);
359 }
360 });
361
362 List<PluginInformation> pluginsToLoad = PluginHandler.buildListOfPluginsToLoad(splash,monitor.createSubTaskMonitor(1, false));
363 if (!pluginsToLoad.isEmpty() && PluginHandler.checkAndConfirmPluginUpdate(splash)) {
364 monitor.subTask(tr("Updating plugins"));
365 pluginsToLoad = PluginHandler.updatePlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false));
366 }
367
368 monitor.indeterminateSubTask(tr("Installing updated plugins"));
369 PluginHandler.installDownloadedPlugins(true);
370
371 monitor.indeterminateSubTask(tr("Loading early plugins"));
372 PluginHandler.loadEarlyPlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false));
373
374 monitor.indeterminateSubTask(tr("Setting defaults"));
375 preConstructorInit(args);
376
377 monitor.indeterminateSubTask(tr("Creating main GUI"));
378 final Main main = new MainApplication(mainFrame);
379
380 monitor.indeterminateSubTask(tr("Loading plugins"));
381 PluginHandler.loadLatePlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false));
382 toolbar.refreshToolbarControl();
383
384 GuiHelper.runInEDT(new Runnable() {
385 @Override
386 public void run() {
387 splash.setVisible(false);
388 splash.dispose();
389 mainFrame.setVisible(true);
390 }
391 });
392
393 Main.MasterWindowListener.setup();
394
395 boolean maximized = Boolean.parseBoolean(Main.pref.get("gui.maximized"));
396 if ((!args.containsKey(Option.NO_MAXIMIZE) && maximized) || args.containsKey(Option.MAXIMIZE)) {
397 if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH)) {
398 Main.windowState = JFrame.MAXIMIZED_BOTH;
399 mainFrame.setExtendedState(Main.windowState);
400 } else {
401 Main.debug("Main window: maximizing not supported");
402 }
403 }
404 if (main.menu.fullscreenToggleAction != null) {
405 main.menu.fullscreenToggleAction.initial();
406 }
407
408 final Map<Option, Collection<String>> args_final = args;
409
410 SwingUtilities.invokeLater(new Runnable() {
411 @Override
412 public void run() {
413 if (AutosaveTask.PROP_AUTOSAVE_ENABLED.get()) {
414 AutosaveTask autosaveTask = new AutosaveTask();
415 List<File> unsavedLayerFiles = autosaveTask.getUnsavedLayersFiles();
416 if (!unsavedLayerFiles.isEmpty()) {
417 ExtendedDialog dialog = new ExtendedDialog(
418 Main.parent,
419 tr("Unsaved osm data"),
420 new String[] {tr("Restore"), tr("Cancel"), tr("Discard")}
421 );
422 dialog.setContent(
423 trn("JOSM found {0} unsaved osm data layer. ",
424 "JOSM found {0} unsaved osm data layers. ", unsavedLayerFiles.size(), unsavedLayerFiles.size()) +
425 tr("It looks like JOSM crashed last time. Would you like to restore the data?"));
426 dialog.setButtonIcons(new String[] {"ok", "cancel", "dialogs/delete"});
427 int selection = dialog.showDialog().getValue();
428 if (selection == 1) {
429 autosaveTask.recoverUnsavedLayers();
430 } else if (selection == 3) {
431 autosaveTask.dicardUnsavedLayers();
432 }
433 }
434 autosaveTask.schedule();
435 }
436
437 postConstructorProcessCmdLine(args_final);
438
439 DownloadDialog.autostartIfNeeded();
440 }
441 });
442
443 if (RemoteControl.PROP_REMOTECONTROL_ENABLED.get()) {
444 RemoteControl.start();
445 }
446
447 if (MessageNotifier.PROP_NOTIFIER_ENABLED.get()) {
448 MessageNotifier.start();
449 }
450
451 if (Main.pref.getBoolean("debug.edt-checker.enable", Version.getInstance().isLocalBuild())) {
452 // 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
453 info("Enabled EDT checker, wrongful access to gui from non EDT thread will be printed to console");
454 RepaintManager.setCurrentManager(new CheckThreadViolationRepaintManager());
455 }
456 }
457}
Note: See TracBrowser for help on using the repository browser.