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

Last change on this file since 17994 was 17333, checked in by Don-vip, 3 years ago

see #20129 - Fix typos and misspellings in the code (patch by gaben)

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