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

Last change on this file since 1922 was 1885, checked in by Gubaer, 15 years ago

Improved exception handling

File size: 10.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.net.HttpURLConnection;
7import java.net.MalformedURLException;
8import java.net.SocketException;
9import java.net.URL;
10import java.net.UnknownHostException;
11
12import javax.swing.JOptionPane;
13
14import org.openstreetmap.josm.Main;
15import org.openstreetmap.josm.io.OsmApi;
16import org.openstreetmap.josm.io.OsmApiException;
17import org.openstreetmap.josm.io.OsmApiInitializationException;
18import org.openstreetmap.josm.io.OsmTransferException;
19
20/**
21 * This utility class provides static methods which explain various exceptions to the user.
22 *
23 */
24public class ExceptionDialogUtil {
25
26 /**
27 * just static utility functions. no constructor
28 */
29 private ExceptionDialogUtil() {}
30
31 /**
32 * handles an exception caught during OSM API initialization
33 *
34 * @param e the exception
35 */
36 public static void explainOsmApiInitializationException(OsmApiInitializationException e) {
37 e.printStackTrace();
38 OptionPaneUtil.showMessageDialog(
39 Main.parent,
40 tr( "Failed to initialize communication with the OSM server {0}.\n"
41 + "Check the server URL in your preferences and your internet connection.",
42 Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api")
43 ),
44 tr("Error"),
45 JOptionPane.ERROR_MESSAGE
46 );
47 }
48
49
50 /**
51 * Explains an upload error due to a violated precondition, i.e. a HTTP return code 412
52 *
53 * @param e the exception
54 */
55 public static void explainPreconditionFailed(OsmApiException e) {
56 e.printStackTrace();
57 OptionPaneUtil.showMessageDialog(
58 Main.parent,
59 tr("<html>Uploading to the server <strong>failed</strong> because your current<br>"
60 +"dataset violates a precondition.<br>"
61 +"The error message is:<br>"
62 + "{0}"
63 + "</html>",
64 e.getMessage().replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
65 ),
66 tr("Precondition violation"),
67 JOptionPane.ERROR_MESSAGE
68 );
69 }
70
71
72 /**
73 * Explains an exception with a generic message dialog
74 *
75 * @param e the exception
76 */
77 public static void explainGeneric(Exception e) {
78 String msg = e.getMessage();
79 if (msg == null) {
80 msg = e.toString();
81 }
82 e.printStackTrace();
83 OptionPaneUtil.showMessageDialog(
84 Main.parent,
85 msg,
86 tr("Error"),
87 JOptionPane.ERROR_MESSAGE
88 );
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 whitin 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 String apiUrl = OsmApi.getOsmApi().getBaseUrl();
101 String host = tr("unknown");
102 try {
103 host = new URL(apiUrl).getHost();
104 } catch(MalformedURLException ex) {
105 // shouldn't happen
106 }
107
108 String message = tr("<html>Failed to open a connection to the remote server<br>"
109 + "''{0}''<br>"
110 + "for security reasons. This is most likely because you are running<br>"
111 + "in an applet and because you didn''t load your applet from ''{1}''.</html>",
112 apiUrl, host
113 );
114 OptionPaneUtil.showMessageDialog(
115 Main.parent,
116 message,
117 tr("Security exception"),
118 JOptionPane.ERROR_MESSAGE
119 );
120 }
121
122 /**
123 * Explains a {@see SecurityException} which has caused an {@see OsmTransferException}.
124 * This is most likely happening when user tries to access the OSM API from whitin an
125 * applet which wasn't loaded from the API server.
126 *
127 * @param e the exception
128 */
129
130 public static void explainNestedSocketException(OsmTransferException e) {
131 String apiUrl = OsmApi.getOsmApi().getBaseUrl();
132 String message = tr("<html>Failed to open a connection to the remote server<br>"
133 + "''{0}''.<br>"
134 + "Please check your internet connection.</html>",
135 apiUrl
136 );
137 e.printStackTrace();
138 OptionPaneUtil.showMessageDialog(
139 Main.parent,
140 message,
141 tr("Network exception"),
142 JOptionPane.ERROR_MESSAGE
143 );
144 }
145
146 /**
147 * Explains a {@see SecurityException} which has caused an {@see OsmTransferException}.
148 * This is most likely happening when user tries to access the OSM API from whitin an
149 * applet which wasn't loaded from the API server.
150 *
151 * @param e the exception
152 */
153
154 public static void explainNestedUnkonwnHostException(OsmTransferException e) {
155 String apiUrl = OsmApi.getOsmApi().getBaseUrl();
156 String host = tr("unknown");
157 try {
158 host = new URL(apiUrl).getHost();
159 } catch(MalformedURLException ex) {
160 // shouldn't happen
161 }
162
163 String message = tr("<html>Failed to open a connection to the remote server<br>"
164 + "''{0}''.<br>"
165 + "Host name ''{1}'' couldn''t be resolved. <br>"
166 + "Please check the API URL in your preferences and your internet connection.</html>",
167 apiUrl, host
168 );
169 e.printStackTrace();
170 OptionPaneUtil.showMessageDialog(
171 Main.parent,
172 message,
173 tr("Unknown host"),
174 JOptionPane.ERROR_MESSAGE
175 );
176 }
177
178 protected static <T> T getNestedException(Exception e, Class<T> nested) {
179 Throwable t = e;
180 while (t != null && !(t.getClass().isAssignableFrom(nested))) {
181 t = t.getCause();
182 }
183 return nested.cast(t);
184 }
185
186 /**
187 * Replies the first {@see SecurityException} in a chain of nested exceptions.
188 * null, if no {@see SecurityException} is in this chain.
189 *
190 * @param e the root exception
191 * @return the first {@see SecurityException} in a chain of nested exceptions
192 */
193 protected static SecurityException getNestedSecurityException(Exception e) {
194 return getNestedException(e, SecurityException.class);
195 }
196
197
198 /**
199 * Replies the first {@see SocketException} in a chain of nested exceptions.
200 * null, if no {@see SocketException} is in this chain.
201 *
202 * @param e the root exception
203 * @return the first {@see SocketException} in a chain of nested exceptions
204 */
205 protected static SocketException getNestedSocketException(Exception e) {
206 return getNestedException(e, SocketException.class);
207 }
208
209 /**
210 * Replies the first {@see UnknownHostException} in a chain of nested exceptions.
211 * null, if no {@see UnknownHostException} is in this chain.
212 *
213 * @param e the root exception
214 * @return the first {@see UnknownHostException} in a chain of nested exceptions
215 */
216 protected static UnknownHostException getNestedUnknownHostException(Exception e) {
217 return getNestedException(e, UnknownHostException.class);
218 }
219
220
221 /**
222 * Explains an {@see OsmTransferException} to the user.
223 *
224 * @param e the {@see OsmTransferException}
225 */
226 public static void explainOsmTransferException(OsmTransferException e) {
227 if (getNestedSecurityException(e) != null) {
228 explainSecurityException(e);
229 return;
230 }
231 if (getNestedSocketException(e) != null) {
232 explainNestedSocketException(e);
233 return;
234 }
235 if (getNestedUnknownHostException(e) != null) {
236 explainNestedUnkonwnHostException(e);
237 return;
238 }
239 if (e instanceof OsmApiInitializationException){
240 explainOsmApiInitializationException((OsmApiInitializationException)e);
241 return;
242 }
243 if (e instanceof OsmApiException) {
244 OsmApiException oae = (OsmApiException)e;
245 if (oae.getResponseCode() == HttpURLConnection.HTTP_PRECON_FAILED) {
246 explainPreconditionFailed(oae);
247 return;
248 }
249 if (oae.getResponseCode() == HttpURLConnection.HTTP_GONE) {
250 explainGoneForUnknownPrimitive(oae);
251 return;
252 }
253 }
254
255 explainGeneric(e);
256 }
257
258 /**
259 * explains the case of an error due to a delete request on an already deleted
260 * {@see OsmPrimitive}, i.e. a HTTP response code 410, where we don't know which
261 * {@see OsmPrimitive} is causing the error.
262 *
263 * @param e the exception
264 */
265 public static void explainGoneForUnknownPrimitive(OsmApiException e) {
266 String msg = tr("<html>Uploading <strong>failed</strong> because a primitive you tried to<br>"
267 + "delete on the server is already deleted.<br>"
268 + "<br>"
269 + "The error message is:<br>"
270 + "{0}"
271 + "</html>",
272 e.getMessage().replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
273 );
274 OptionPaneUtil.showMessageDialog(
275 Main.parent,
276 msg,
277 tr("Primitive already deleted"),
278 JOptionPane.ERROR_MESSAGE
279 );
280
281 }
282
283 /**
284 * Explains an {@see Exception} to the user.
285 *
286 * @param e the {@see Exception}
287 */
288 public static void explainException(Exception e) {
289 if (e instanceof OsmTransferException) {
290 explainOsmTransferException((OsmTransferException)e);
291 return;
292 }
293 explainGeneric(e);
294 }
295}
Note: See TracBrowser for help on using the repository browser.