001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005import static org.openstreetmap.josm.tools.I18n.trn; 006import gnu.getopt.Getopt; 007import gnu.getopt.LongOpt; 008 009import java.awt.Dimension; 010import java.awt.Image; 011import java.awt.Toolkit; 012import java.awt.event.WindowAdapter; 013import java.awt.event.WindowEvent; 014import java.io.File; 015import java.io.IOException; 016import java.io.InputStream; 017import java.net.Authenticator; 018import java.net.ProxySelector; 019import java.net.URL; 020import java.security.AllPermission; 021import java.security.CodeSource; 022import java.security.KeyStoreException; 023import java.security.NoSuchAlgorithmException; 024import java.security.PermissionCollection; 025import java.security.Permissions; 026import java.security.Policy; 027import java.security.cert.CertificateException; 028import java.util.ArrayList; 029import java.util.Arrays; 030import java.util.Collection; 031import java.util.HashMap; 032import java.util.LinkedList; 033import java.util.List; 034import java.util.Map; 035import java.util.Set; 036import java.util.TreeSet; 037 038import javax.swing.JFrame; 039import javax.swing.JOptionPane; 040import javax.swing.RepaintManager; 041import javax.swing.SwingUtilities; 042 043import org.jdesktop.swinghelper.debug.CheckThreadViolationRepaintManager; 044import org.openstreetmap.josm.Main; 045import org.openstreetmap.josm.actions.PreferencesAction; 046import org.openstreetmap.josm.data.AutosaveTask; 047import org.openstreetmap.josm.data.CustomConfigurator; 048import org.openstreetmap.josm.data.Preferences; 049import org.openstreetmap.josm.data.Version; 050import org.openstreetmap.josm.gui.download.DownloadDialog; 051import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder; 052import org.openstreetmap.josm.gui.preferences.server.ProxyPreference; 053import org.openstreetmap.josm.gui.progress.ProgressMonitor; 054import org.openstreetmap.josm.gui.util.GuiHelper; 055import org.openstreetmap.josm.io.DefaultProxySelector; 056import org.openstreetmap.josm.io.MessageNotifier; 057import org.openstreetmap.josm.io.OnlineResource; 058import org.openstreetmap.josm.io.auth.CredentialsManager; 059import org.openstreetmap.josm.io.auth.DefaultAuthenticator; 060import org.openstreetmap.josm.io.remotecontrol.RemoteControl; 061import org.openstreetmap.josm.plugins.PluginHandler; 062import org.openstreetmap.josm.plugins.PluginInformation; 063import org.openstreetmap.josm.tools.BugReportExceptionHandler; 064import org.openstreetmap.josm.tools.FontsManager; 065import org.openstreetmap.josm.tools.I18n; 066import org.openstreetmap.josm.tools.ImageProvider; 067import org.openstreetmap.josm.tools.OsmUrlToBounds; 068import org.openstreetmap.josm.tools.PlatformHookWindows; 069import org.openstreetmap.josm.tools.Utils; 070 071/** 072 * Main window class application. 073 * 074 * @author imi 075 */ 076public class MainApplication extends Main { 077 /** 078 * Allow subclassing (see JOSM.java) 079 */ 080 public MainApplication() {} 081 082 /** 083 * Constructs a main frame, ready sized and operating. Does not display the frame. 084 * @param mainFrame The main JFrame of the application 085 */ 086 public MainApplication(JFrame mainFrame) { 087 addListener(); 088 mainFrame.setContentPane(contentPanePrivate); 089 mainFrame.setJMenuBar(menu); 090 geometry.applySafe(mainFrame); 091 List<Image> l = new LinkedList<>(); 092 l.add(ImageProvider.get("logo_16x16x32").getImage()); 093 l.add(ImageProvider.get("logo_16x16x8").getImage()); 094 l.add(ImageProvider.get("logo_32x32x32").getImage()); 095 l.add(ImageProvider.get("logo_32x32x8").getImage()); 096 l.add(ImageProvider.get("logo_48x48x32").getImage()); 097 l.add(ImageProvider.get("logo_48x48x8").getImage()); 098 l.add(ImageProvider.get("logo").getImage()); 099 mainFrame.setIconImages(l); 100 mainFrame.addWindowListener(new WindowAdapter(){ 101 @Override 102 public void windowClosing(final WindowEvent arg0) { 103 Main.exitJosm(true, 0); 104 } 105 }); 106 mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); 107 } 108 109 /** 110 * Displays help on the console 111 * @since 2748 112 */ 113 public static void showHelp() { 114 // TODO: put in a platformHook for system that have no console by default 115 System.out.println(tr("Java OpenStreetMap Editor")+" [" 116 +Version.getInstance().getAgentString()+"]\n\n"+ 117 tr("usage")+":\n"+ 118 "\tjava -jar josm.jar <options>...\n\n"+ 119 tr("options")+":\n"+ 120 "\t--help|-h "+tr("Show this help")+"\n"+ 121 "\t--geometry=widthxheight(+|-)x(+|-)y "+tr("Standard unix geometry argument")+"\n"+ 122 "\t[--download=]minlat,minlon,maxlat,maxlon "+tr("Download the bounding box")+"\n"+ 123 "\t[--download=]<URL> "+tr("Download the location at the URL (with lat=x&lon=y&zoom=z)")+"\n"+ 124 "\t[--download=]<filename> "+tr("Open a file (any file type that can be opened with File/Open)")+"\n"+ 125 "\t--downloadgps=minlat,minlon,maxlat,maxlon "+tr("Download the bounding box as raw GPS")+"\n"+ 126 "\t--downloadgps=<URL> "+tr("Download the location at the URL (with lat=x&lon=y&zoom=z) as raw GPS")+"\n"+ 127 "\t--selection=<searchstring> "+tr("Select with the given search")+"\n"+ 128 "\t--[no-]maximize "+tr("Launch in maximized mode")+"\n"+ 129 "\t--reset-preferences "+tr("Reset the preferences to default")+"\n\n"+ 130 "\t--load-preferences=<url-to-xml> "+tr("Changes preferences according to the XML file")+"\n\n"+ 131 "\t--set=<key>=<value> "+tr("Set preference key to value")+"\n\n"+ 132 "\t--language=<language> "+tr("Set the language")+"\n\n"+ 133 "\t--version "+tr("Displays the JOSM version and exits")+"\n\n"+ 134 "\t--debug "+tr("Print debugging messages to console")+"\n\n"+ 135 "\t--offline=<osm_api|josm_website|all> "+tr("Disable access to the given resource(s), separated by comma")+"\n\n"+ 136 tr("options provided as Java system properties")+":\n"+ 137 "\t-Djosm.home="+tr("/PATH/TO/JOSM/FOLDER/ ")+tr("Change the folder for all user settings")+"\n\n"+ 138 tr("note: For some tasks, JOSM needs a lot of memory. It can be necessary to add the following\n" + 139 " Java option to specify the maximum size of allocated memory in megabytes")+":\n"+ 140 "\t-Xmx...m\n\n"+ 141 tr("examples")+":\n"+ 142 "\tjava -jar josm.jar track1.gpx track2.gpx london.osm\n"+ 143 "\tjava -jar josm.jar "+OsmUrlToBounds.getURL(43.2, 11.1, 13)+"\n"+ 144 "\tjava -jar josm.jar london.osm --selection=http://www.ostertag.name/osm/OSM_errors_node-duplicate.xml\n"+ 145 "\tjava -jar josm.jar 43.2,11.1,43.4,11.4\n"+ 146 "\tjava -Djosm.home=/home/user/.josm_dev -jar josm.jar\n"+ 147 "\tjava -Xmx1024m -jar josm.jar\n\n"+ 148 tr("Parameters --download, --downloadgps, and --selection are processed in this order.")+"\n"+ 149 tr("Make sure you load some data if you use --selection.")+"\n" 150 ); 151 } 152 153 /** 154 * JOSM command line options. 155 * @see <a href="https://josm.openstreetmap.de/wiki/Help/CommandLineOptions">Help/CommandLineOptions</a> 156 * @since 5279 157 */ 158 public enum Option { 159 /** --help|-h Show this help */ 160 HELP(false), 161 /** --version Displays the JOSM version and exits */ 162 VERSION(false), 163 /** --debug Print debugging messages to console */ 164 DEBUG(false), 165 /** --trace Print detailed debugging messages to console */ 166 TRACE(false), 167 /** --language=<language> Set the language */ 168 LANGUAGE(true), 169 /** --reset-preferences Reset the preferences to default */ 170 RESET_PREFERENCES(false), 171 /** --load-preferences=<url-to-xml> Changes preferences according to the XML file */ 172 LOAD_PREFERENCES(true), 173 /** --set=<key>=<value> Set preference key to value */ 174 SET(true), 175 /** --geometry=widthxheight(+|-)x(+|-)y Standard unix geometry argument */ 176 GEOMETRY(true), 177 /** --no-maximize Do not launch in maximized mode */ 178 NO_MAXIMIZE(false), 179 /** --maximize Launch in maximized mode */ 180 MAXIMIZE(false), 181 /** --download=minlat,minlon,maxlat,maxlon Download the bounding box <br> 182 * --download=<URL> Download the location at the URL (with lat=x&lon=y&zoom=z) <br> 183 * --download=<filename> Open a file (any file type that can be opened with File/Open) */ 184 DOWNLOAD(true), 185 /** --downloadgps=minlat,minlon,maxlat,maxlon Download the bounding box as raw GPS <br> 186 * --downloadgps=<URL> Download the location at the URL (with lat=x&lon=y&zoom=z) as raw GPS */ 187 DOWNLOADGPS(true), 188 /** --selection=<searchstring> Select with the given search */ 189 SELECTION(true), 190 /** --offline=<osm_api|josm_website|all> Disable access to the given resource(s), delimited by comma */ 191 OFFLINE(true); 192 193 private String name; 194 private boolean requiresArgument; 195 196 private Option(boolean requiresArgument) { 197 this.name = name().toLowerCase().replace("_", "-"); 198 this.requiresArgument = requiresArgument; 199 } 200 201 /** 202 * Replies the option name 203 * @return The option name, in lowercase 204 */ 205 public String getName() { 206 return name; 207 } 208 209 /** 210 * Determines if this option requires an argument. 211 * @return {@code true} if this option requires an argument, {@code false} otherwise 212 */ 213 public boolean requiresArgument() { 214 return requiresArgument; 215 } 216 217 public static Map<Option, Collection<String>> fromStringMap(Map<String, Collection<String>> opts) { 218 Map<Option, Collection<String>> res = new HashMap<>(); 219 for (Map.Entry<String, Collection<String>> e : opts.entrySet()) { 220 Option o = Option.valueOf(e.getKey().toUpperCase().replace("-", "_")); 221 if (o != null) { 222 res.put(o, e.getValue()); 223 } 224 } 225 return res; 226 } 227 } 228 229 private static Map<Option, Collection<String>> buildCommandLineArgumentMap(String[] args) { 230 231 List<LongOpt> los = new ArrayList<>(); 232 for (Option o : Option.values()) { 233 los.add(new LongOpt(o.getName(), o.requiresArgument() ? LongOpt.REQUIRED_ARGUMENT : LongOpt.NO_ARGUMENT, null, 0)); 234 } 235 236 Getopt g = new Getopt("JOSM", args, "hv", los.toArray(new LongOpt[los.size()])); 237 238 Map<Option, Collection<String>> argMap = new HashMap<>(); 239 240 int c; 241 while ((c = g.getopt()) != -1 ) { 242 Option opt = null; 243 switch (c) { 244 case 'h': 245 opt = Option.HELP; 246 break; 247 case 'v': 248 opt = Option.VERSION; 249 break; 250 case 0: 251 opt = Option.values()[g.getLongind()]; 252 break; 253 } 254 if (opt != null) { 255 Collection<String> values = argMap.get(opt); 256 if (values == null) { 257 values = new ArrayList<>(); 258 argMap.put(opt, values); 259 } 260 values.add(g.getOptarg()); 261 } else 262 throw new IllegalArgumentException(); 263 } 264 // positional arguments are a shortcut for the --download ... option 265 for (int i = g.getOptind(); i < args.length; ++i) { 266 Collection<String> values = argMap.get(Option.DOWNLOAD); 267 if (values == null) { 268 values = new ArrayList<>(); 269 argMap.put(Option.DOWNLOAD, values); 270 } 271 values.add(args[i]); 272 } 273 274 return argMap; 275 } 276 277 /** 278 * Main application Startup 279 * @param argArray Command-line arguments 280 */ 281 public static void main(final String[] argArray) { 282 I18n.init(); 283 Main.checkJavaVersion(); 284 285 // construct argument table 286 Map<Option, Collection<String>> args = null; 287 try { 288 args = buildCommandLineArgumentMap(argArray); 289 } catch (IllegalArgumentException e) { 290 System.exit(1); 291 return; 292 } 293 294 final boolean languageGiven = args.containsKey(Option.LANGUAGE); 295 296 if (languageGiven) { 297 I18n.set(args.get(Option.LANGUAGE).iterator().next()); 298 } 299 300 initApplicationPreferences(); 301 302 Policy.setPolicy(new Policy() { 303 // Permissions for plug-ins loaded when josm is started via webstart 304 private PermissionCollection pc; 305 306 { 307 pc = new Permissions(); 308 pc.add(new AllPermission()); 309 } 310 311 @Override 312 public void refresh() { } 313 314 @Override 315 public PermissionCollection getPermissions(CodeSource codesource) { 316 return pc; 317 } 318 }); 319 320 Thread.setDefaultUncaughtExceptionHandler(new BugReportExceptionHandler()); 321 322 // initialize the platform hook, and 323 Main.determinePlatformHook(); 324 // call the really early hook before we do anything else 325 Main.platform.preStartupHook(); 326 327 Main.commandLineArgs = Utils.copyArray(argArray); 328 329 if (args.containsKey(Option.VERSION)) { 330 System.out.println(Version.getInstance().getAgentString()); 331 System.exit(0); 332 } 333 334 if (args.containsKey(Option.DEBUG) || args.containsKey(Option.TRACE)) { 335 // Enable JOSM debug level 336 logLevel = 4; 337 Main.info(tr("Printing debugging messages to console")); 338 } 339 340 if (args.containsKey(Option.TRACE)) { 341 // Enable JOSM debug level 342 logLevel = 5; 343 // Enable debug in OAuth signpost via system preference, but only at trace level 344 Preferences.updateSystemProperty("debug", "true"); 345 Main.info(tr("Enabled detailed debug level (trace)")); 346 } 347 348 Main.pref.init(args.containsKey(Option.RESET_PREFERENCES)); 349 350 if (!languageGiven) { 351 I18n.set(Main.pref.get("language", null)); 352 } 353 Main.pref.updateSystemProperties(); 354 355 // asking for help? show help and exit 356 if (args.containsKey(Option.HELP)) { 357 showHelp(); 358 System.exit(0); 359 } 360 361 processOffline(args); 362 363 FontsManager.initialize(); 364 365 final JFrame mainFrame = new JFrame(tr("Java OpenStreetMap Editor")); 366 Main.parent = mainFrame; 367 368 if (args.containsKey(Option.LOAD_PREFERENCES)) { 369 CustomConfigurator.XMLCommandProcessor config = new CustomConfigurator.XMLCommandProcessor(Main.pref); 370 for (String i : args.get(Option.LOAD_PREFERENCES)) { 371 info("Reading preferences from " + i); 372 try (InputStream is = Utils.openURL(new URL(i))) { 373 config.openAndReadXML(is); 374 } catch (Exception ex) { 375 throw new RuntimeException(ex); 376 } 377 } 378 } 379 380 if (args.containsKey(Option.SET)) { 381 for (String i : args.get(Option.SET)) { 382 String[] kv = i.split("=", 2); 383 Main.pref.put(kv[0], "null".equals(kv[1]) ? null : kv[1]); 384 } 385 } 386 387 DefaultAuthenticator.createInstance(); 388 Authenticator.setDefault(DefaultAuthenticator.getInstance()); 389 DefaultProxySelector proxySelector = new DefaultProxySelector(ProxySelector.getDefault()); 390 ProxySelector.setDefault(proxySelector); 391 OAuthAccessTokenHolder.getInstance().init(Main.pref, CredentialsManager.getInstance()); 392 393 final SplashScreen splash = new SplashScreen(); 394 final ProgressMonitor monitor = splash.getProgressMonitor(); 395 monitor.beginTask(tr("Initializing")); 396 splash.setVisible(Main.pref.getBoolean("draw.splashscreen", true)); 397 Main.setInitStatusListener(new InitStatusListener() { 398 399 @Override 400 public void updateStatus(String event) { 401 monitor.indeterminateSubTask(event); 402 } 403 }); 404 405 Collection<PluginInformation> pluginsToLoad = PluginHandler.buildListOfPluginsToLoad(splash,monitor.createSubTaskMonitor(1, false)); 406 if (!pluginsToLoad.isEmpty() && PluginHandler.checkAndConfirmPluginUpdate(splash)) { 407 monitor.subTask(tr("Updating plugins")); 408 pluginsToLoad = PluginHandler.updatePlugins(splash, null, monitor.createSubTaskMonitor(1, false), false); 409 } 410 411 monitor.indeterminateSubTask(tr("Installing updated plugins")); 412 PluginHandler.installDownloadedPlugins(true); 413 414 monitor.indeterminateSubTask(tr("Loading early plugins")); 415 PluginHandler.loadEarlyPlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false)); 416 417 monitor.indeterminateSubTask(tr("Setting defaults")); 418 preConstructorInit(args); 419 420 monitor.indeterminateSubTask(tr("Creating main GUI")); 421 final Main main = new MainApplication(mainFrame); 422 423 monitor.indeterminateSubTask(tr("Loading plugins")); 424 PluginHandler.loadLatePlugins(splash,pluginsToLoad, monitor.createSubTaskMonitor(1, false)); 425 toolbar.refreshToolbarControl(); 426 427 // Wait for splash disappearance (fix #9714) 428 GuiHelper.runInEDTAndWait(new Runnable() { 429 @Override 430 public void run() { 431 splash.setVisible(false); 432 splash.dispose(); 433 mainFrame.setVisible(true); 434 } 435 }); 436 437 Main.MasterWindowListener.setup(); 438 439 boolean maximized = Main.pref.getBoolean("gui.maximized", false); 440 if ((!args.containsKey(Option.NO_MAXIMIZE) && maximized) || args.containsKey(Option.MAXIMIZE)) { 441 if (Toolkit.getDefaultToolkit().isFrameStateSupported(JFrame.MAXIMIZED_BOTH)) { 442 Main.windowState = JFrame.MAXIMIZED_BOTH; 443 mainFrame.setExtendedState(Main.windowState); 444 } else { 445 Main.debug("Main window: maximizing not supported"); 446 } 447 } 448 if (main.menu.fullscreenToggleAction != null) { 449 main.menu.fullscreenToggleAction.initial(); 450 } 451 452 SwingUtilities.invokeLater(new GuiFinalizationWorker(args, proxySelector)); 453 454 if (Main.isPlatformWindows()) { 455 try { 456 // Check for insecure certificates to remove. 457 // This is Windows-dependant code but it can't go to preStartupHook (need i18n) neither startupHook (need to be called before remote control) 458 PlatformHookWindows.removeInsecureCertificates(); 459 } catch (NoSuchAlgorithmException | CertificateException | KeyStoreException | IOException e) { 460 error(e); 461 } 462 } 463 464 if (RemoteControl.PROP_REMOTECONTROL_ENABLED.get()) { 465 RemoteControl.start(); 466 } 467 468 if (MessageNotifier.PROP_NOTIFIER_ENABLED.get()) { 469 MessageNotifier.start(); 470 } 471 472 if (Main.pref.getBoolean("debug.edt-checker.enable", Version.getInstance().isLocalBuild())) { 473 // 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 474 info("Enabled EDT checker, wrongful access to gui from non EDT thread will be printed to console"); 475 RepaintManager.setCurrentManager(new CheckThreadViolationRepaintManager()); 476 } 477 } 478 479 private static void processOffline(Map<Option, Collection<String>> args) { 480 if (args.containsKey(Option.OFFLINE)) { 481 for (String s : args.get(Option.OFFLINE).iterator().next().split(",")) { 482 try { 483 Main.setOffline(OnlineResource.valueOf(s.toUpperCase())); 484 } catch (IllegalArgumentException e) { 485 Main.error(tr("''{0}'' is not a valid value for argument ''{1}''. Possible values are {2}, possibly delimited by commas.", 486 s.toUpperCase(), Option.OFFLINE.getName(), Arrays.toString(OnlineResource.values()))); 487 System.exit(1); 488 return; 489 } 490 } 491 Set<OnlineResource> offline = Main.getOfflineResources(); 492 if (!offline.isEmpty()) { 493 Main.warn(trn("JOSM is running in offline mode. This resource will not be available: {0}", 494 "JOSM is running in offline mode. These resources will not be available: {0}", 495 offline.size(), offline.size() == 1 ? offline.iterator().next() : Arrays.toString(offline.toArray()))); 496 } 497 } 498 } 499 500 private static class GuiFinalizationWorker implements Runnable { 501 502 private final Map<Option, Collection<String>> args; 503 private final DefaultProxySelector proxySelector; 504 505 public GuiFinalizationWorker(Map<Option, Collection<String>> args, DefaultProxySelector proxySelector) { 506 this.args = args; 507 this.proxySelector = proxySelector; 508 } 509 510 @Override 511 public void run() { 512 513 // Handle proxy/network errors early to inform user he should change settings to be able to use JOSM correctly 514 if (!handleProxyErrors()) { 515 handleNetworkErrors(); 516 } 517 518 // Restore autosave layers after crash and start autosave thread 519 handleAutosave(); 520 521 // Handle command line instructions 522 postConstructorProcessCmdLine(args); 523 524 // Show download dialog if autostart is enabled 525 DownloadDialog.autostartIfNeeded(); 526 } 527 528 private void handleAutosave() { 529 if (AutosaveTask.PROP_AUTOSAVE_ENABLED.get()) { 530 AutosaveTask autosaveTask = new AutosaveTask(); 531 List<File> unsavedLayerFiles = autosaveTask.getUnsavedLayersFiles(); 532 if (!unsavedLayerFiles.isEmpty()) { 533 ExtendedDialog dialog = new ExtendedDialog( 534 Main.parent, 535 tr("Unsaved osm data"), 536 new String[] {tr("Restore"), tr("Cancel"), tr("Discard")} 537 ); 538 dialog.setContent( 539 trn("JOSM found {0} unsaved osm data layer. ", 540 "JOSM found {0} unsaved osm data layers. ", unsavedLayerFiles.size(), unsavedLayerFiles.size()) + 541 tr("It looks like JOSM crashed last time. Would you like to restore the data?")); 542 dialog.setButtonIcons(new String[] {"ok", "cancel", "dialogs/delete"}); 543 int selection = dialog.showDialog().getValue(); 544 if (selection == 1) { 545 autosaveTask.recoverUnsavedLayers(); 546 } else if (selection == 3) { 547 autosaveTask.discardUnsavedLayers(); 548 } 549 } 550 autosaveTask.schedule(); 551 } 552 } 553 554 private boolean handleNetworkOrProxyErrors(boolean hasErrors, String title, String message) { 555 if (hasErrors) { 556 ExtendedDialog ed = new ExtendedDialog( 557 Main.parent, title, 558 new String[]{tr("Change proxy settings"), tr("Cancel")}); 559 ed.setButtonIcons(new String[]{"dialogs/settings.png", "cancel.png"}).setCancelButton(2); 560 ed.setMinimumSize(new Dimension(460, 260)); 561 ed.setIcon(JOptionPane.WARNING_MESSAGE); 562 ed.setContent(message); 563 564 if (ed.showDialog().getValue() == 1) { 565 PreferencesAction.forPreferenceSubTab(null, null, ProxyPreference.class).run(); 566 } 567 } 568 return hasErrors; 569 } 570 571 private boolean handleProxyErrors() { 572 return handleNetworkOrProxyErrors(proxySelector.hasErrors(), tr("Proxy errors occurred"), 573 tr("JOSM tried to access the following resources:<br>" + 574 "{0}" + 575 "but <b>failed</b> to do so, because of the following proxy errors:<br>" + 576 "{1}" + 577 "Would you like to change your proxy settings now?", 578 Utils.joinAsHtmlUnorderedList(proxySelector.getErrorResources()), 579 Utils.joinAsHtmlUnorderedList(proxySelector.getErrorMessages()) 580 )); 581 } 582 583 private boolean handleNetworkErrors() { 584 boolean condition = !NETWORK_ERRORS.isEmpty(); 585 if (condition) { 586 Set<String> errors = new TreeSet<>(); 587 for (Throwable t : NETWORK_ERRORS.values()) { 588 errors.add(t.toString()); 589 } 590 return handleNetworkOrProxyErrors(condition, tr("Network errors occurred"), 591 tr("JOSM tried to access the following resources:<br>" + 592 "{0}" + 593 "but <b>failed</b> to do so, because of the following network errors:<br>" + 594 "{1}" + 595 "It may be due to a missing proxy configuration.<br>" + 596 "Would you like to change your proxy settings now?", 597 Utils.joinAsHtmlUnorderedList(NETWORK_ERRORS.keySet()), 598 Utils.joinAsHtmlUnorderedList(errors) 599 )); 600 } 601 return false; 602 } 603 } 604}