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

Last change on this file since 5508 was 5275, checked in by bastiK, 12 years ago

doc improvements

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