001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io;
003import static org.openstreetmap.josm.tools.I18n.tr;
004
005import org.openstreetmap.josm.Main;
006
007/**
008 * Exception thrown when a communication error occurs when accessing the <a href="http://wiki.openstreetmap.org/wiki/API_v0.6">OSM API</a>.
009 * @see OsmApi
010 */
011public class OsmApiException extends OsmTransferException {
012
013    private int responseCode;
014    private String errorHeader;
015    private String errorBody;
016    private String accessedUrl;
017
018    /**
019     * Constructs an {@code OsmApiException} with the specified response code, error header and error body
020     * @param responseCode The HTTP response code replied by the OSM server.
021     * See {@link java.net.HttpURLConnection HttpURLConnection} for predefined HTTP response code values
022     * @param errorHeader The error header, as transmitted in the {@code Error} field of the HTTP response header
023     * @param errorBody The error body, as transmitted in the HTTP response body
024     * @param accessedUrl The complete URL accessed when this error occured
025     * @since 5584
026     */
027    public OsmApiException(int responseCode, String errorHeader, String errorBody, String accessedUrl) {
028        this.responseCode = responseCode;
029        this.errorHeader = errorHeader;
030        this.errorBody = errorBody;
031        this.accessedUrl = accessedUrl;
032    }
033
034    /**
035     * Constructs an {@code OsmApiException} with the specified response code, error header and error body
036     * @param responseCode The HTTP response code replied by the OSM server.
037     * See {@link java.net.HttpURLConnection HttpURLConnection} for predefined HTTP response code values
038     * @param errorHeader The error header, as transmitted in the {@code Error} field of the HTTP response header
039     * @param errorBody The error body, as transmitted in the HTTP response body
040     */
041    public OsmApiException(int responseCode, String errorHeader, String errorBody) {
042        this(responseCode, errorHeader, errorBody, null);
043    }
044
045    /**
046     * Constructs an {@code OsmApiException} with the specified detail message.
047     * The cause is not initialized, and may subsequently be initialized by a call to {@link #initCause}.
048     *
049     * @param message The detail message (which is saved for later retrieval by the {@link #getMessage} method)
050     */
051    public OsmApiException(String message) {
052        super(message);
053    }
054
055    /**
056     * Constructs an {@code OsmApiException} with the specified cause and a detail message of
057     * <tt>(cause==null ? null : cause.toString())</tt>
058     * (which typically contains the class and detail message of <tt>cause</tt>).
059     *
060     * @param cause the cause (which is saved for later retrieval by the {@link #getCause} method).
061     *              A <tt>null</tt> value is permitted, and indicates that the cause is nonexistent or unknown.
062     */
063    public OsmApiException(Throwable cause) {
064        super(cause);
065    }
066
067    /**
068     * Constructs an {@code OsmApiException} with the specified detail message and cause.
069     *
070     * <p> Note that the detail message associated with {@code cause} is <i>not</i> automatically incorporated
071     * into this exception's detail message.
072     *
073     * @param message The detail message (which is saved for later retrieval by the {@link #getMessage} method)
074     * @param cause   The cause (which is saved for later retrieval by the {@link #getCause} method).
075     *                A null value is permitted, and indicates that the cause is nonexistent or unknown.
076     *
077     */
078    public OsmApiException(String message, Throwable cause) {
079        super(message, cause);
080    }
081
082    /**
083     * Replies the HTTP response code.
084     * @return The HTTP response code replied by the OSM server. Refer to
085     * <a href="http://wiki.openstreetmap.org/wiki/API_v0.6">OSM API</a> to see the list of response codes returned by the API for each call.
086     */
087    public int getResponseCode() {
088        return responseCode;
089    }
090
091    /**
092     * Sets the HTTP response code.
093     * @param responseCode The HTTP response code replied by the OSM server.
094     * See {@link java.net.HttpURLConnection HttpURLConnection} for predefined HTTP response code values
095     */
096    public void setResponseCode(int responseCode) {
097        this.responseCode = responseCode;
098    }
099
100    /**
101     * Replies the error header.
102     * @return the error header, as transmitted in the {@code Error} field of the HTTP response header
103     */
104    public String getErrorHeader() {
105        return errorHeader;
106    }
107
108    /**
109     * Sets the error header.
110     * @param errorHeader the error header, as transmitted in the {@code Error} field of the HTTP response header
111     */
112    public void setErrorHeader(String errorHeader) {
113        this.errorHeader = errorHeader;
114    }
115
116    /**
117     * Replies the error body.
118     * @return The error body, as transmitted in the HTTP response body
119     */
120    public String getErrorBody() {
121        return errorBody;
122    }
123
124    /**
125     * Sets the error body.
126     * @param errorBody The error body, as transmitted in the HTTP response body
127     */
128    public void setErrorBody(String errorBody) {
129        this.errorBody = errorBody;
130    }
131
132    @Override
133    public String getMessage() {
134        StringBuilder sb = new StringBuilder();
135        sb.append("ResponseCode=")
136        .append(responseCode);
137        String eh = "";
138        try {
139            if (errorHeader != null)
140                eh = tr(errorHeader.trim());
141            if (!eh.isEmpty()) {
142                sb.append(", Error Header=<")
143                .append(eh)
144                .append('>');
145            }
146        } catch (Exception e) {
147            // Ignored
148            if (Main.isTraceEnabled()) {
149                Main.trace(e.getMessage());
150            }
151        }
152        try {
153            String eb = errorBody != null ? tr(errorBody.trim()) : "";
154            if (!eb.isEmpty() && !eb.equals(eh)) {
155                sb.append(", Error Body=<")
156                .append(eb)
157                .append('>');
158            }
159        } catch (Exception e) {
160            // Ignored
161            if (Main.isTraceEnabled()) {
162                Main.trace(e.getMessage());
163            }
164        }
165        return sb.toString();
166    }
167
168    /**
169     * Replies a message suitable to be displayed in a message dialog
170     *
171     * @return a message which is suitable to be displayed in a message dialog
172     */
173    public String getDisplayMessage() {
174        StringBuilder sb = new StringBuilder();
175        if (errorHeader != null) {
176            sb.append(tr(errorHeader));
177            sb.append(tr("(Code={0})", responseCode));
178        } else if (errorBody != null && !errorBody.trim().isEmpty()) {
179            errorBody = errorBody.trim();
180            sb.append(tr(errorBody));
181            sb.append(tr("(Code={0})", responseCode));
182        } else {
183            sb.append(tr("The server replied an error with code {0}.", responseCode));
184        }
185        return sb.toString();
186    }
187
188    /**
189     * Sets the complete URL accessed when this error occured.
190     * This is distinct from the one set with {@link #setUrl}, which is generally only the base URL of the server.
191     * @param url the complete URL accessed when this error occured.
192     */
193    public void setAccessedUrl(String url) {
194        this.accessedUrl = url;
195    }
196
197    /**
198     * Replies the complete URL accessed when this error occured.
199     * This is distinct from the one returned by {@link #getUrl}, which is generally only the base URL of the server.
200     * @return the complete URL accessed when this error occured.
201     */
202    public String getAccessedUrl() {
203        return accessedUrl;
204    }
205}