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

Last change on this file since 2984 was 2984, checked in by jttt, 14 years ago

Fix #4524 Exception handling in PleaseWaitRunnable

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