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}