/* * JLibs: Common Utilities for Java * Copyright (C) 2009 Santhosh Kumar T <santhosh.tekuri@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package jlibs.nio.http.msg; import jlibs.nio.http.expr.Bean; import jlibs.nio.http.expr.UnresolvedException; import jlibs.nio.http.util.USAscii; import java.nio.ByteBuffer; import static jlibs.nio.http.util.USAscii.*; /** * @author Santhosh Kumar Tekuri */ public final class Status extends RuntimeException implements Bean{ public final int code; public final String reason; public final boolean payloadNotAllowed; private final byte bytes10[]; private final byte bytes11[]; private final byte bytesxx[]; public Status(int code, String reason){ this(code, reason, false); } private Status(int code, String reason, boolean createBytes){ this.code = code; this.reason = reason; if(createBytes){ bytes10 = USAscii.toBytes("HTTP/1.0 "+code+" "+reason+"\r\n"); bytes11 = USAscii.toBytes("HTTP/1.1 "+code+" "+reason+"\r\n"); bytesxx = USAscii.toBytes(" "+code+" "+reason+"\r\n"); array[code-100] = this; }else bytes10 = bytes11 = bytesxx = null; payloadNotAllowed = (code/100)==1 // 1xx: Informational || code==204 // NO_CONTENT || code==205 // RESET_CONTENT || code==304; // NOT_MODIFIED } @Override public String getMessage(){ return reason; } @Override public Throwable fillInStackTrace(){ return this; } public Status with(String msg){ assert msg!=null; return new Status(code, msg, false); } public Status with(Throwable thr){ assert thr!=null; if(thr instanceof Status) return (Status)thr; String msg = thr.getMessage(); if(msg==null) msg = thr.getClass().getSimpleName(); Status status = new Status(code, msg, false); status.initCause(thr); return status; } public Status with(String msg, Throwable thr){ if(thr instanceof Status) return ((Status)thr).with(msg); Status status = new Status(code, msg, false); status.initCause(thr); return status; } public void putInto(ByteBuffer buffer, Version version){ if(version==Version.HTTP_1_1 && bytes11!=null) buffer.put(bytes11, 0, bytes11.length); else if(version==Version.HTTP_1_0 && bytes10!=null) buffer.put(bytes10, 0, bytes10.length); else if(bytesxx!=null){ version.putInto(buffer); buffer.put(bytesxx, 0, bytesxx.length); }else{ version.putInto(buffer); buffer.put(SP); buffer.put((byte)(code/100+'0')); buffer.put((byte)(code/10%10+'0')); buffer.put((byte)(code%10+'0')); buffer.put(SP); USAscii.append(buffer, reason); buffer.put(CR); buffer.put(LF); } } public boolean isInformational(){ return code/100==1; } public boolean isSuccessful(){ return code/100==2; } public boolean isRedirection(){ return code/100==3; } public boolean isClientError(){ return code/100==4; } public boolean isServerError(){ return code/100==5; } public boolean isError(){ return isClientError() || isServerError(); } @Override public int hashCode(){ return code; } @Override public boolean equals(Object obj){ return obj==this || (obj instanceof Status && this.code==(((Status)obj).code)); } @Override public String toString(){ return code+" "+reason; } @Override @SuppressWarnings("StringEquality") public Object getField(String name) throws UnresolvedException{ if(name=="code") return code; else if(name=="reason") return reason; else throw new UnresolvedException(name); } private static final Status array[] = new Status[900]; // 1xx: Informational public static final Status CONTINUE = new Status(100, "Continue", true); public static final Status SWITCHING_PROTOCOLS = new Status(101, "Switching Protocols", true); public static final Status PROCESSING = new Status(102, "Processing", true); // 2xx: Successful public static final Status OK = new Status(200, "OK", true); public static final Status CREATED = new Status(201, "Created", true); public static final Status ACCEPTED = new Status(202, "Accepted", true); public static final Status NON_AUTHORITATIVE_INFORMATION = new Status(203, "Non-Authoritative Information", true); public static final Status NO_CONTENT = new Status(204, "No Content", true); public static final Status RESET_CONTENT = new Status(205, "Reset Content", true); public static final Status PARTIAL_CONTENT = new Status(206, "Partial Content", true); public static final Status MULTI_STATUS = new Status(207, "Multi-Status", true); public static final Status ALREADY_REPORTED = new Status(208, "Already Reported", true); public static final Status IM_USED = new Status(226, "IM Used", true); // 3xx: Redirection public static final Status MULTIPLE_CHOICES = new Status(300, "Multiple Choices", true); public static final Status MOVED_PERMANENTLY = new Status(301, "Moved Permanently", true); public static final Status FOUND = new Status(302, "Found", true); public static final Status SEE_OTHER = new Status(303, "See Other", true); public static final Status NOT_MODIFIED = new Status(304, "Not Modified", true); public static final Status USE_PROXY = new Status(305, "Use Proxy", true); public static final Status SWITCH_PROXY = new Status(306, "Switch Proxy", true); public static final Status TEMPORARY_REDIRECT = new Status(307, "Temporary Redirect", true); public static final Status PERMANENT_REDIRECT = new Status(308, "Permanent Redirect", true); // 4xx: Client Error public static final Status BAD_REQUEST = new Status(400, "Bad Request", true); public static final Status UNAUTHORIZED = new Status(401, "Unauthorized", true); public static final Status PAYMENT_REQUIRED = new Status(402, "Payment Required", true); public static final Status FORBIDDEN = new Status(403, "Forbidden", true); public static final Status NOT_FOUND = new Status(404, "Not Found", true); public static final Status METHOD_NOT_ALLOWED = new Status(405, "Method Not Allowed", true); public static final Status NOT_ACCEPTABLE = new Status(406, "Not Acceptable", true); public static final Status PROXY_AUTHENTICATION_REQUIRED = new Status(407, "Proxy Authentication Required", true); public static final Status REQUEST_TIMEOUT = new Status(408, "Request Timeout", true); public static final Status CONFLICT = new Status(409, "Conflict", true); public static final Status GONE = new Status(410, "Gone", true); public static final Status LENGTH_REQUIRED = new Status(411, "Length Required", true); public static final Status PRECONDITION_FAILED = new Status(412, "Precondition Failed", true); public static final Status REQUEST_ENTITY_TOO_LARGE = new Status(413, "Request Entity Too Large", true); public static final Status REQUEST_URI_TOO_LONG = new Status(414, "Request-URI Too Long", true); public static final Status UNSUPPORTED_MEDIA_TYPE = new Status(415, "Unsupported Media Type", true); public static final Status REQUESTED_RANGE_NOT_SATISFIABLE = new Status(416, "Requested Range Not Satisfiable", true); public static final Status EXPECTATION_FAILED = new Status(417, "Expectation Failed", true); public static final Status IM_A_TEAPOT = new Status(418, "I'm a teapot", true); public static final Status AUTHENTICATION_TIMEOUT = new Status(419, "Authentication Timeout", true); public static final Status METHOD_FAILURE = new Status(420, "Method Failure", true); public static final Status UNPROCESSABLE_ENTITY = new Status(422, "Unprocessable Entity", true); public static final Status LOCKED = new Status(423, "Locked", true); public static final Status FAILED_DEPENDENCY = new Status(424, "Failed Dependency", true); public static final Status UPGRADE_REQUIRED = new Status(426, "Upgrade Required", true); public static final Status PRECONDITION_REQUIRED = new Status(428, "Precondition Required", true); public static final Status TOO_MANY_REQUESTS = new Status(429, "Too Many Requests", true); public static final Status REQUEST_HEADER_FIELDS_TOO_LARGE = new Status(431, "Request Header Fields Too Large", true); // 5xx: Server Error public static final Status INTERNAL_SERVER_ERROR = new Status(500, "Internal Server Error", true); public static final Status NOT_IMPLEMENTED = new Status(501, "Not Implemented", true); public static final Status BAD_GATEWAY = new Status(502, "Bad Gateway", true); public static final Status SERVICE_UNAVAILABLE = new Status(503, "Service Unavailable", true); public static final Status GATEWAY_TIMEOUT = new Status(504, "Gateway Timeout", true); public static final Status HTTP_VERSION_NOT_SUPPORTED = new Status(505, "HTTP Version Not Supported", true); public static final Status INSUFFICIENT_STORAGE = new Status(507, "Insufficient Storage", true); public static final Status LOOP_DETECTED = new Status(508, "Loop Detected", true); public static final Status NOT_EXTENDED = new Status(510, "Not Extended", true); public static final Status NETWORK_AUTHENTICATION_REQUIRED = new Status(511, "Network Authentication Required", true); public static Status valueOf(int code, CharSequence seq){ if(code<100 || code>999) throw new IllegalArgumentException("bad status code: "+code); Status status = array[code-100]; if(status==null || !status.reason.contentEquals(seq)) return new Status(code, seq.toString(), false); return status; } }