001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.http.classic.response; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020import static org.apache.juneau.http.classic.response.BadRequest.*; 021 022import java.util.*; 023 024import org.apache.http.*; 025import org.apache.http.Header; 026import org.apache.juneau.commons.*; 027import org.apache.juneau.http.*; 028import org.apache.juneau.http.classic.*; 029import org.apache.juneau.http.classic.header.*; 030 031/** 032 * Exception representing an HTTP 400 (Bad Request). 033 * 034 * <p> 035 * The server cannot or will not process the request due to an apparent client error (e.g., malformed request syntax, size too large, invalid request message framing, or deceptive request routing). 036 * 037 * <h5 class='section'>See Also:</h5><ul> 038 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauRestCommon">juneau-rest-common</a> 039 * </ul> 040 * 041 * @serial exclude 042 */ 043@Response 044@StatusCode(STATUS_CODE) 045@Schema(description = REASON_PHRASE) 046@SuppressWarnings({ 047 "java:S110" // Inheritance depth acceptable for HTTP exception hierarchy 048}) 049public class BadRequest extends BasicHttpException { 050 private static final long serialVersionUID = 1L; 051 052 /** HTTP status code */ 053 public static final int STATUS_CODE = 400; 054 055 /** Reason phrase */ 056 public static final String REASON_PHRASE = "Bad Request"; 057 058 /** Default status line */ 059 private static final BasicStatusLine STATUS_LINE = BasicStatusLine.create(STATUS_CODE, REASON_PHRASE); 060 061 /** Reusable unmodifiable instance */ 062 public static final BadRequest INSTANCE = new BadRequest().unmodifiable(); 063 064 /** 065 * Constructor. 066 */ 067 public BadRequest() { 068 this((Throwable)null, REASON_PHRASE); 069 } 070 071 /** 072 * Constructor. 073 * 074 * <p> 075 * This is the constructor used when parsing an HTTP response. 076 * 077 * @param response The HTTP response to copy from. Must not be <jk>null</jk>. 078 * @throws IllegalArgumentException If HTTP response status code does not match what was expected. 079 */ 080 public BadRequest(HttpResponse response) { 081 super(requireStatus(response, STATUS_CODE)); 082 } 083 084 /** 085 * Constructor. 086 * 087 * @param msg The message. Can be <jk>null</jk>, in which case the reason phrase is used as the message. 088 * @param args Optional {@link String#format(String, Object...) String.format}-style arguments in the message. 089 */ 090 public BadRequest(String msg, Object...args) { 091 this((Throwable)null, msg, args); 092 } 093 094 /** 095 * Constructor. 096 * 097 * @param cause The cause. Can be <jk>null</jk>, in which case the reason phrase is used as the message and no cause is chained. 098 */ 099 public BadRequest(Throwable cause) { 100 this(cause, cause == null ? REASON_PHRASE : cause.getMessage()); 101 } 102 103 /** 104 * Constructor. 105 * 106 * @param cause The caused-by exception. Can be <jk>null</jk> (no cause is chained). 107 * @param msg The message. Can be <jk>null</jk>, in which case the cause's message is used, or the reason phrase if the cause is also <jk>null</jk> or has no message. 108 * @param args The message arguments. 109 */ 110 public BadRequest(Throwable cause, String msg, Object...args) { 111 super(STATUS_CODE, cause, msg, args); 112 setStatusLine(STATUS_LINE.copy()); 113 } 114 115 /** 116 * Copy constructor. 117 * 118 * @param copyFrom The bean to copy. Must not be <jk>null</jk>. 119 */ 120 protected BadRequest(BadRequest copyFrom) { 121 super(copyFrom); 122 } 123 124 /** 125 * Creates a modifiable copy of this bean. 126 * 127 * @return A new modifiable bean. 128 */ 129 public BadRequest copy() { 130 return new BadRequest(this); 131 } 132 133 @Override /* Overridden from BasicHttpException */ 134 public BadRequest setContent(HttpEntity value) { 135 super.setContent(value); 136 return this; 137 } 138 139 @Override /* Overridden from BasicHttpException */ 140 public BadRequest setContent(String value) { 141 super.setContent(value); 142 return this; 143 } 144 145 @Override /* Overridden from BasicHttpException */ 146 public BadRequest setHeader2(String name, Object value) { 147 super.setHeader2(name, value); 148 return this; 149 } 150 151 @Override /* Overridden from BasicHttpException */ 152 public BadRequest setHeaders(HeaderList value) { 153 super.setHeaders(value); 154 return this; 155 } 156 157 @Override /* Overridden from BasicHttpException */ 158 public BadRequest setHeaders(List<Header> values) { 159 super.setHeaders(values); 160 return this; 161 } 162 163 @Override /* Overridden from BasicHttpException */ 164 public BadRequest setHeaders2(Header...values) { 165 super.setHeaders2(values); 166 return this; 167 } 168 169 @Override /* Overridden from BasicHttpException */ 170 public BadRequest setLocale2(Locale value) { 171 super.setLocale2(value); 172 return this; 173 } 174 175 @Override /* Overridden from BasicRuntimeException */ 176 public BadRequest setMessage(String message, Object...args) { 177 super.setMessage(message, args); 178 return this; 179 } 180 181 @Override /* Overridden from BasicHttpException */ 182 public BadRequest setProtocolVersion(ProtocolVersion value) { 183 super.setProtocolVersion(value); 184 return this; 185 } 186 187 @Override /* Overridden from BasicHttpException */ 188 public BadRequest setReasonPhrase2(String value) { 189 super.setReasonPhrase2(value); 190 return this; 191 } 192 193 @Override /* Overridden from BasicHttpException */ 194 public BadRequest setReasonPhraseCatalog(ReasonPhraseCatalog value) { 195 super.setReasonPhraseCatalog(value); 196 return this; 197 } 198 199 @Override /* Overridden from BasicHttpException */ 200 public BadRequest setStatusCode2(int code) throws IllegalStateException { 201 super.setStatusCode2(code); 202 return this; 203 } 204 205 @Override /* Overridden from BasicHttpException */ 206 public BadRequest setStatusLine(BasicStatusLine value) { 207 super.setStatusLine(value); 208 return this; 209 } 210 211 @Override /* Overridden from BasicHttpException */ 212 public BadRequest unmodifiable() { 213 return this instanceof UnmodifiableBean ? this : new Unmodifiable(this); 214 } 215 216 /** 217 * Unmodifiable point-in-time snapshot of the enclosing {@link BadRequest} exception. 218 * 219 * <p> 220 * Its only behavioral override is {@link #modify(Runnable)}, which throws — because all mutation is funneled through 221 * {@code modify(...)}, this single override freezes the entire mutation surface. 222 */ 223 public static class Unmodifiable extends BadRequest implements UnmodifiableBean { 224 225 private static final long serialVersionUID = 1L; 226 227 /** 228 * Constructor. 229 * 230 * @param copyFrom The exception to snapshot. Must not be <jk>null</jk>. 231 */ 232 @SuppressWarnings({ 233 "java:S1699" // Paradigm intentionally calls the overridable freeze() from the ctor to deep-freeze sub-beans. 234 }) 235 protected Unmodifiable(BadRequest copyFrom) { 236 super(copyFrom); 237 freeze(); 238 } 239 240 @Override /* Overridden from BasicHttpException */ 241 protected BasicHttpException modify(Runnable mutation) { 242 throw uoex("Bean is unmodifiable."); 243 } 244 } 245}