1 /***
2 * Ambient - A music player for the Android platform
3 Copyright (C) 2007 Martin Vysny
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 package sk.baka.ambient.commons;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 /***
27 * The server-side HTTP exception.
28 *
29 * @author Martin Vysny
30 */
31 public final class ServerHttpException extends Exception {
32 private static final long serialVersionUID = -582260129800748510L;
33 private final static Map<Integer, String> STATUS_CODES = new HashMap<Integer, String>();
34 static {
35 STATUS_CODES.put(100, "Continue");
36 STATUS_CODES.put(101, "Switching Protocols");
37 STATUS_CODES.put(200, "OK");
38 STATUS_CODES.put(201, "Created");
39 STATUS_CODES.put(202, "Accepted");
40 STATUS_CODES.put(203, "Non-Authoritative Information");
41 STATUS_CODES.put(204, "No Content");
42 STATUS_CODES.put(205, "Reset Content");
43 STATUS_CODES.put(206, "Partial Content");
44 STATUS_CODES.put(400, "Bad Request");
45 STATUS_CODES.put(401, "Unauthorized");
46 STATUS_CODES.put(402, "Payment Required");
47 STATUS_CODES.put(403, "Forbidden");
48 STATUS_CODES.put(404, "Not Found");
49 STATUS_CODES.put(405, "Method Not Allowed");
50 STATUS_CODES.put(406, "Not Acceptable");
51 STATUS_CODES.put(407, "Proxy Authentication Required");
52 STATUS_CODES.put(408, "Request Timeout");
53 STATUS_CODES.put(409, "Conflict");
54 STATUS_CODES.put(410, "Gone");
55 STATUS_CODES.put(411, "Length Required");
56 STATUS_CODES.put(412, "Precondition Failed");
57 STATUS_CODES.put(413, "Request Entity Too Large");
58 STATUS_CODES.put(414, "Request-URI Too Long");
59 STATUS_CODES.put(415, "Unsupported Media Type");
60 STATUS_CODES.put(416, "Requested Range Not Satisfiable");
61 STATUS_CODES.put(417, "Expectation Failed");
62 STATUS_CODES.put(500, "Internal Server Error");
63 STATUS_CODES.put(501, "Not Implemented");
64 STATUS_CODES.put(502, "Bad Gateway");
65 STATUS_CODES.put(503, "Service Unavailable");
66 STATUS_CODES.put(504, "Gateway Timeout");
67 STATUS_CODES.put(505, "HTTP Version Not Supported");
68 }
69
70 /***
71 * The error code.
72 */
73 public final int errorCode;
74 private final String message;
75
76 /***
77 * Returns status name for given error code.
78 *
79 * @param errorCode
80 * the error code. See <a
81 * href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"
82 * >error codes list</a> for details.
83 * @return the status name.
84 */
85 public static String getStatus(final int errorCode) {
86 final String result = STATUS_CODES.get(errorCode);
87 if (result == null) {
88 return "Unknown status";
89 }
90 return result;
91 }
92
93 /***
94 * Creates new exception.
95 *
96 * @param errorCode
97 * the error code.
98 */
99 public ServerHttpException(final int errorCode) {
100 super(errorCode + " " + getStatus(errorCode));
101 this.errorCode = errorCode;
102 message = null;
103 }
104
105 /***
106 * Creates new exception.
107 *
108 * @param errorCode
109 * the error code.
110 * @param message
111 * optional additional error info.
112 */
113 public ServerHttpException(final int errorCode, final String message) {
114 super(errorCode + " " + getStatus(errorCode) + ": " + message);
115 this.errorCode = errorCode;
116 this.message = message;
117 }
118
119 /***
120 * Creates new exception.
121 *
122 * @param errorCode
123 * the error code.
124 * @param cause
125 * the cause.
126 */
127 public ServerHttpException(final int errorCode, final Throwable cause) {
128 super(errorCode + " " + getStatus(errorCode), cause);
129 this.errorCode = errorCode;
130 this.message = MiscUtils.getStackTrace(cause);
131 }
132
133 /***
134 * Returns the response line, for example
135 * "HTTP/1.1 501 Not Implemented\r\nPUT Not implemented\r\n\r\n".
136 *
137 * @param httpVersion
138 * the http version, 0 or 1.
139 * @param out
140 * write the response here.
141 * @throws IOException
142 * if i/o error occurs.
143 */
144 public void writeResponse(byte httpVersion, final OutputStream out)
145 throws IOException {
146 writeResponse(httpVersion, errorCode, message, out);
147 }
148
149 /***
150 * Returns the response line, for example "HTTP/1.1 501 Not Implemented".
151 *
152 * @param httpVersion
153 * the http version, 0 or 1.
154 * @return the response line.
155 */
156 public String getResponseLine(byte httpVersion) {
157 return getResponseLine(httpVersion, errorCode);
158 }
159
160 /***
161 * Returns the response line, for example "HTTP/1.1 501 Not Implemented".
162 *
163 * @param httpVersion
164 * the http version, 0 or 1.
165 * @param errorCode
166 * the HTTP error code.
167 * @return the response line.
168 */
169 public static String getResponseLine(byte httpVersion, final int errorCode) {
170 final StringBuilder b = new StringBuilder();
171 b.append("HTTP/1.");
172 b.append((char) (httpVersion + '0'));
173 b.append(' ');
174 b.append(errorCode);
175 b.append(' ');
176 b.append(getStatus(errorCode));
177 return b.toString();
178 }
179
180 /***
181 * Returns the entire response, for example
182 * "HTTP/1.1 501 Not Implemented\r\nPUT Not implemented\r\n\r\n".
183 *
184 * @param httpVersion
185 * the http version, 0 or 1.
186 * @param errorCode
187 * the HTTP error code.
188 * @param message
189 * optional additional error info.
190 * @param out
191 * write the result here.
192 * @throws IOException
193 * if i/o error occurs.
194 */
195 public static void writeResponse(byte httpVersion, final int errorCode,
196 final String message, OutputStream out) throws IOException {
197 final byte[] msg = message == null ? null : message.getBytes("UTF-8");
198 IOUtils
199 .writeHttpResponse(httpVersion, errorCode, true,
200 msg == null ? -1 : msg.length,
201 "text/plain; charset=UTF-8", out);
202 IOUtils.writeLine(out);
203 if (msg != null) {
204 out.write(msg);
205 }
206 }
207 }