source: josm/trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java@ 12204

Last change on this file since 12204 was 11984, checked in by stoecker, 7 years ago

improve overpass API rate limit message, fix wrong timeout error message

  • Property svn:eol-style set to native
File size: 17.8 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.io.IOException;
8import java.lang.reflect.InvocationTargetException;
9import java.net.HttpURLConnection;
10import java.net.SocketException;
11import java.net.UnknownHostException;
12import java.util.regex.Matcher;
13import java.util.regex.Pattern;
14
15import javax.swing.JOptionPane;
16
17import org.openstreetmap.josm.Main;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.io.ChangesetClosedException;
20import org.openstreetmap.josm.io.IllegalDataException;
21import org.openstreetmap.josm.io.MissingOAuthAccessTokenException;
22import org.openstreetmap.josm.io.OfflineAccessException;
23import org.openstreetmap.josm.io.OsmApi;
24import org.openstreetmap.josm.io.OsmApiException;
25import org.openstreetmap.josm.io.OsmApiInitializationException;
26import org.openstreetmap.josm.io.OsmTransferException;
27import org.openstreetmap.josm.tools.ExceptionUtil;
28import org.openstreetmap.josm.tools.bugreport.BugReportExceptionHandler;
29
30/**
31 * This utility class provides static methods which explain various exceptions to the user.
32 *
33 */
34public final class ExceptionDialogUtil {
35
36 /**
37 * just static utility functions. no constructor
38 */
39 private ExceptionDialogUtil() {
40 // Hide default constructor for utility classes
41 }
42
43 /**
44 * handles an exception caught during OSM API initialization
45 *
46 * @param e the exception
47 */
48 public static void explainOsmApiInitializationException(OsmApiInitializationException e) {
49 HelpAwareOptionPane.showOptionDialog(
50 Main.parent,
51 ExceptionUtil.explainOsmApiInitializationException(e),
52 tr("Error"),
53 JOptionPane.ERROR_MESSAGE,
54 ht("/ErrorMessages#OsmApiInitializationException")
55 );
56 }
57
58 /**
59 * handles a ChangesetClosedException
60 *
61 * @param e the exception
62 */
63 public static void explainChangesetClosedException(ChangesetClosedException e) {
64 HelpAwareOptionPane.showOptionDialog(
65 Main.parent,
66 ExceptionUtil.explainChangesetClosedException(e),
67 tr("Error"),
68 JOptionPane.ERROR_MESSAGE,
69 ht("/Action/Upload#ChangesetClosed")
70 );
71 }
72
73 /**
74 * Explains an upload error due to a violated precondition, i.e. a HTTP return code 412
75 *
76 * @param e the exception
77 */
78 public static void explainPreconditionFailed(OsmApiException e) {
79 HelpAwareOptionPane.showOptionDialog(
80 Main.parent,
81 ExceptionUtil.explainPreconditionFailed(e),
82 tr("Precondition violation"),
83 JOptionPane.ERROR_MESSAGE,
84 ht("/ErrorMessages#OsmApiException")
85 );
86 }
87
88 /**
89 * Explains an exception with a generic message dialog
90 *
91 * @param e the exception
92 */
93 public static void explainGeneric(Exception e) {
94 Main.error(e);
95 BugReportExceptionHandler.handleException(e);
96 }
97
98 /**
99 * Explains a {@link SecurityException} which has caused an {@link OsmTransferException}.
100 * This is most likely happening when user tries to access the OSM API from within an
101 * applet which wasn't loaded from the API server.
102 *
103 * @param e the exception
104 */
105
106 public static void explainSecurityException(OsmTransferException e) {
107 HelpAwareOptionPane.showOptionDialog(
108 Main.parent,
109 ExceptionUtil.explainSecurityException(e),
110 tr("Security exception"),
111 JOptionPane.ERROR_MESSAGE,
112 ht("/ErrorMessages#SecurityException")
113 );
114 }
115
116 /**
117 * Explains a {@link SocketException} which has caused an {@link OsmTransferException}.
118 * This is most likely because there's not connection to the Internet or because
119 * the remote server is not reachable.
120 *
121 * @param e the exception
122 */
123
124 public static void explainNestedSocketException(OsmTransferException e) {
125 HelpAwareOptionPane.showOptionDialog(
126 Main.parent,
127 ExceptionUtil.explainNestedSocketException(e),
128 tr("Network exception"),
129 JOptionPane.ERROR_MESSAGE,
130 ht("/ErrorMessages#NestedSocketException")
131 );
132 }
133
134 /**
135 * Explains a {@link IOException} which has caused an {@link OsmTransferException}.
136 * This is most likely happening when the communication with the remote server is
137 * interrupted for any reason.
138 *
139 * @param e the exception
140 */
141
142 public static void explainNestedIOException(OsmTransferException e) {
143 HelpAwareOptionPane.showOptionDialog(
144 Main.parent,
145 ExceptionUtil.explainNestedIOException(e),
146 tr("IO Exception"),
147 JOptionPane.ERROR_MESSAGE,
148 ht("/ErrorMessages#NestedIOException")
149 );
150 }
151
152 /**
153 * Explains a {@link IllegalDataException} which has caused an {@link OsmTransferException}.
154 * This is most likely happening when JOSM tries to load data in an unsupported format.
155 *
156 * @param e the exception
157 */
158 public static void explainNestedIllegalDataException(OsmTransferException e) {
159 HelpAwareOptionPane.showOptionDialog(
160 Main.parent,
161 ExceptionUtil.explainNestedIllegalDataException(e),
162 tr("Illegal Data"),
163 JOptionPane.ERROR_MESSAGE,
164 ht("/ErrorMessages#IllegalDataException")
165 );
166 }
167
168 /**
169 * Explains a {@link OfflineAccessException} which has caused an {@link OsmTransferException}.
170 * This is most likely happening when JOSM tries to access OSM API or JOSM website while in offline mode.
171 *
172 * @param e the exception
173 * @since 7434
174 */
175 public static void explainNestedOfflineAccessException(OsmTransferException e) {
176 HelpAwareOptionPane.showOptionDialog(
177 Main.parent,
178 ExceptionUtil.explainOfflineAccessException(e),
179 tr("Offline mode"),
180 JOptionPane.ERROR_MESSAGE,
181 ht("/ErrorMessages#OfflineAccessException")
182 );
183 }
184
185 /**
186 * Explains a {@link InvocationTargetException }
187 *
188 * @param e the exception
189 */
190 public static void explainNestedInvocationTargetException(Exception e) {
191 InvocationTargetException ex = ExceptionUtil.getNestedException(e, InvocationTargetException.class);
192 if (ex != null) {
193 // Users should be able to submit a bug report for an invocation target exception
194 //
195 BugReportExceptionHandler.handleException(ex);
196 return;
197 }
198 }
199
200 /**
201 * Explains a {@link OsmApiException} which was thrown because of an internal server
202 * error in the OSM API server.
203 *
204 * @param e the exception
205 */
206
207 public static void explainInternalServerError(OsmTransferException e) {
208 HelpAwareOptionPane.showOptionDialog(
209 Main.parent,
210 ExceptionUtil.explainInternalServerError(e),
211 tr("Internal Server Error"),
212 JOptionPane.ERROR_MESSAGE,
213 ht("/ErrorMessages#InternalServerError")
214 );
215 }
216
217 /**
218 * Explains a {@link OsmApiException} which was thrown because of a bad
219 * request
220 *
221 * @param e the exception
222 */
223 public static void explainBadRequest(OsmApiException e) {
224 HelpAwareOptionPane.showOptionDialog(
225 Main.parent,
226 ExceptionUtil.explainBadRequest(e),
227 tr("Bad Request"),
228 JOptionPane.ERROR_MESSAGE,
229 ht("/ErrorMessages#BadRequest")
230 );
231 }
232
233 /**
234 * Explains a {@link OsmApiException} which was thrown because a resource wasn't found
235 * on the server
236 *
237 * @param e the exception
238 */
239 public static void explainNotFound(OsmApiException e) {
240 HelpAwareOptionPane.showOptionDialog(
241 Main.parent,
242 ExceptionUtil.explainNotFound(e),
243 tr("Not Found"),
244 JOptionPane.ERROR_MESSAGE,
245 ht("/ErrorMessages#NotFound")
246 );
247 }
248
249 /**
250 * Explains a {@link OsmApiException} which was thrown because of a conflict
251 *
252 * @param e the exception
253 */
254 public static void explainConflict(OsmApiException e) {
255 HelpAwareOptionPane.showOptionDialog(
256 Main.parent,
257 ExceptionUtil.explainConflict(e),
258 tr("Conflict"),
259 JOptionPane.ERROR_MESSAGE,
260 ht("/ErrorMessages#Conflict")
261 );
262 }
263
264 /**
265 * Explains a {@link OsmApiException} which was thrown because the authentication at
266 * the OSM server failed
267 *
268 * @param e the exception
269 */
270 public static void explainAuthenticationFailed(OsmApiException e) {
271 String msg;
272 if (OsmApi.isUsingOAuth()) {
273 msg = ExceptionUtil.explainFailedOAuthAuthentication(e);
274 } else {
275 msg = ExceptionUtil.explainFailedBasicAuthentication(e);
276 }
277
278 HelpAwareOptionPane.showOptionDialog(
279 Main.parent,
280 msg,
281 tr("Authentication Failed"),
282 JOptionPane.ERROR_MESSAGE,
283 ht("/ErrorMessages#AuthenticationFailed")
284 );
285 }
286
287 /**
288 * Explains a {@link OsmApiException} which was thrown because accessing a protected
289 * resource was forbidden (HTTP 403).
290 *
291 * @param e the exception
292 */
293 public static void explainAuthorizationFailed(OsmApiException e) {
294
295 Matcher m;
296 String msg;
297 String url = e.getAccessedUrl();
298 Pattern p = Pattern.compile("https?://.*/api/0.6/(node|way|relation)/(\\d+)/(\\d+)");
299
300 // Special case for individual access to redacted versions
301 // See http://wiki.openstreetmap.org/wiki/Open_Database_License/Changes_in_the_API
302 if (url != null && (m = p.matcher(url)).matches()) {
303 String type = m.group(1);
304 String id = m.group(2);
305 String version = m.group(3);
306 // {1} is the translation of "node", "way" or "relation"
307 msg = tr("Access to redacted version ''{0}'' of {1} {2} is forbidden.",
308 version, tr(type), id);
309 } else if (OsmApi.isUsingOAuth()) {
310 msg = ExceptionUtil.explainFailedOAuthAuthorisation(e);
311 } else {
312 msg = ExceptionUtil.explainFailedAuthorisation(e);
313 }
314
315 HelpAwareOptionPane.showOptionDialog(
316 Main.parent,
317 msg,
318 tr("Authorisation Failed"),
319 JOptionPane.ERROR_MESSAGE,
320 ht("/ErrorMessages#AuthorizationFailed")
321 );
322 }
323
324 /**
325 * Explains a {@link OsmApiException} which was thrown because of a
326 * client timeout (HTTP 408)
327 *
328 * @param e the exception
329 */
330 public static void explainClientTimeout(OsmApiException e) {
331 HelpAwareOptionPane.showOptionDialog(
332 Main.parent,
333 ExceptionUtil.explainClientTimeout(e),
334 tr("Client Time Out"),
335 JOptionPane.ERROR_MESSAGE,
336 ht("/ErrorMessages#ClientTimeOut")
337 );
338 }
339
340 /**
341 * Explains a {@link OsmApiException} which was thrown because of a
342 * bandwidth limit (HTTP 509)
343 *
344 * @param e the exception
345 */
346 public static void explainBandwidthLimitExceeded(OsmApiException e) {
347 HelpAwareOptionPane.showOptionDialog(
348 Main.parent,
349 ExceptionUtil.explainBandwidthLimitExceeded(e),
350 tr("Bandwidth Limit Exceeded"),
351 JOptionPane.ERROR_MESSAGE,
352 ht("/ErrorMessages#BandwidthLimit")
353 );
354 }
355
356 /**
357 * Explains a {@link OsmApiException} with a generic error message.
358 *
359 * @param e the exception
360 */
361 public static void explainGenericHttpException(OsmApiException e) {
362 HelpAwareOptionPane.showOptionDialog(
363 Main.parent,
364 ExceptionUtil.explainGeneric(e),
365 tr("Communication with OSM server failed"),
366 JOptionPane.ERROR_MESSAGE,
367 ht("/ErrorMessages#GenericCommunicationError")
368 );
369 }
370
371 /**
372 * Explains a {@link OsmApiException} which was thrown because accessing a protected
373 * resource was forbidden.
374 *
375 * @param e the exception
376 */
377 public static void explainMissingOAuthAccessTokenException(MissingOAuthAccessTokenException e) {
378 HelpAwareOptionPane.showOptionDialog(
379 Main.parent,
380 ExceptionUtil.explainMissingOAuthAccessTokenException(e),
381 tr("Authentication failed"),
382 JOptionPane.ERROR_MESSAGE,
383 ht("/ErrorMessages#MissingOAuthAccessToken")
384 );
385 }
386
387 /**
388 * Explains a {@link UnknownHostException} which has caused an {@link OsmTransferException}.
389 * This is most likely happening when there is an error in the API URL or when
390 * local DNS services are not working.
391 *
392 * @param e the exception
393 */
394 public static void explainNestedUnkonwnHostException(OsmTransferException e) {
395 HelpAwareOptionPane.showOptionDialog(
396 Main.parent,
397 ExceptionUtil.explainNestedUnknownHostException(e),
398 tr("Unknown host"),
399 JOptionPane.ERROR_MESSAGE,
400 ht("/ErrorMessages#UnknownHost")
401 );
402 }
403
404 /**
405 * Explains an {@link OsmTransferException} to the user.
406 *
407 * @param e the {@link OsmTransferException}
408 */
409 public static void explainOsmTransferException(OsmTransferException e) {
410 if (ExceptionUtil.getNestedException(e, SecurityException.class) != null) {
411 explainSecurityException(e);
412 return;
413 }
414 if (ExceptionUtil.getNestedException(e, SocketException.class) != null) {
415 explainNestedSocketException(e);
416 return;
417 }
418 if (ExceptionUtil.getNestedException(e, UnknownHostException.class) != null) {
419 explainNestedUnkonwnHostException(e);
420 return;
421 }
422 if (ExceptionUtil.getNestedException(e, IOException.class) != null) {
423 explainNestedIOException(e);
424 return;
425 }
426 if (ExceptionUtil.getNestedException(e, IllegalDataException.class) != null) {
427 explainNestedIllegalDataException(e);
428 return;
429 }
430 if (ExceptionUtil.getNestedException(e, OfflineAccessException.class) != null) {
431 explainNestedOfflineAccessException(e);
432 return;
433 }
434 if (e instanceof OsmApiInitializationException) {
435 explainOsmApiInitializationException((OsmApiInitializationException) e);
436 return;
437 }
438
439 if (e instanceof ChangesetClosedException) {
440 explainChangesetClosedException((ChangesetClosedException) e);
441 return;
442 }
443
444 if (e instanceof MissingOAuthAccessTokenException) {
445 explainMissingOAuthAccessTokenException((MissingOAuthAccessTokenException) e);
446 return;
447 }
448
449 if (e instanceof OsmApiException) {
450 OsmApiException oae = (OsmApiException) e;
451 switch(oae.getResponseCode()) {
452 case HttpURLConnection.HTTP_PRECON_FAILED:
453 explainPreconditionFailed(oae);
454 return;
455 case HttpURLConnection.HTTP_GONE:
456 explainGoneForUnknownPrimitive(oae);
457 return;
458 case HttpURLConnection.HTTP_INTERNAL_ERROR:
459 explainInternalServerError(oae);
460 return;
461 case HttpURLConnection.HTTP_BAD_REQUEST:
462 explainBadRequest(oae);
463 return;
464 case HttpURLConnection.HTTP_NOT_FOUND:
465 explainNotFound(oae);
466 return;
467 case HttpURLConnection.HTTP_CONFLICT:
468 explainConflict(oae);
469 return;
470 case HttpURLConnection.HTTP_UNAUTHORIZED:
471 explainAuthenticationFailed(oae);
472 return;
473 case HttpURLConnection.HTTP_FORBIDDEN:
474 explainAuthorizationFailed(oae);
475 return;
476 case HttpURLConnection.HTTP_CLIENT_TIMEOUT:
477 explainClientTimeout(oae);
478 return;
479 case 509: case 429:
480 explainBandwidthLimitExceeded(oae);
481 return;
482 default:
483 explainGenericHttpException(oae);
484 return;
485 }
486 }
487 explainGeneric(e);
488 }
489
490 /**
491 * explains the case of an error due to a delete request on an already deleted
492 * {@link OsmPrimitive}, i.e. a HTTP response code 410, where we don't know which
493 * {@link OsmPrimitive} is causing the error.
494 *
495 * @param e the exception
496 */
497 public static void explainGoneForUnknownPrimitive(OsmApiException e) {
498 HelpAwareOptionPane.showOptionDialog(
499 Main.parent,
500 ExceptionUtil.explainGoneForUnknownPrimitive(e),
501 tr("Object deleted"),
502 JOptionPane.ERROR_MESSAGE,
503 ht("/ErrorMessages#GoneForUnknownPrimitive")
504 );
505 }
506
507 /**
508 * Explains an {@link Exception} to the user.
509 *
510 * @param e the {@link Exception}
511 */
512 public static void explainException(Exception e) {
513 if (ExceptionUtil.getNestedException(e, InvocationTargetException.class) != null) {
514 explainNestedInvocationTargetException(e);
515 return;
516 }
517 if (e instanceof OsmTransferException) {
518 explainOsmTransferException((OsmTransferException) e);
519 return;
520 }
521 explainGeneric(e);
522 }
523}
Note: See TracBrowser for help on using the repository browser.