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 }