View Javadoc

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 }