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

Last change on this file since 12851 was 12620, checked in by Don-vip, 7 years ago

see #15182 - deprecate all Main logging methods and introduce suitable replacements in Logging for most of them

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