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

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

Checkstyle:

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