View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.http.message;
29  
30  import java.io.Serializable;
31  
32  import org.apache.hc.core5.annotation.Contract;
33  import org.apache.hc.core5.annotation.ThreadingBehavior;
34  import org.apache.hc.core5.http.HttpResponse;
35  import org.apache.hc.core5.http.HttpVersion;
36  import org.apache.hc.core5.http.ProtocolVersion;
37  import org.apache.hc.core5.util.Args;
38  
39  /**
40   * HTTP/1.1 status line.
41   *
42   * @since 4.0
43   */
44  @Contract(threading = ThreadingBehavior.IMMUTABLE)
45  public final class StatusLine implements Serializable {
46  
47      private static final long serialVersionUID = -2443303766890459269L;
48  
49      /**
50       * The protocol version.
51       */
52      private final ProtocolVersion protoVersion;
53  
54      /**
55       * The status code.
56       */
57      private final int statusCode;
58  
59      /**
60       * The status code class.
61       */
62      private final StatusClass statusClass;
63  
64      /**
65       * The reason phrase.
66       */
67      private final String reasonPhrase;
68  
69      public StatusLine(final HttpResponse response) {
70          super();
71          Args.notNull(response, "Response");
72          this.protoVersion = response.getVersion() != null ? response.getVersion() : HttpVersion.HTTP_1_1;
73          this.statusCode = response.getCode();
74          this.statusClass = StatusClass.from(this.statusCode);
75          this.reasonPhrase = response.getReasonPhrase();
76      }
77  
78      /**
79       * Creates a new status line with the given version, status, and reason.
80       *
81       * @param version      the protocol version of the response
82       * @param statusCode   the status code of the response
83       * @param reasonPhrase the reason phrase to the status code, or
84       *                     {@code null}
85       */
86      public StatusLine(final ProtocolVersion version, final int statusCode, final String reasonPhrase) {
87          super();
88          this.statusCode = Args.notNegative(statusCode, "Status code");
89          this.statusClass = StatusClass.from(this.statusCode);
90          this.protoVersion = version != null ? version : HttpVersion.HTTP_1_1;
91          this.reasonPhrase = reasonPhrase;
92      }
93  
94      public int getStatusCode() {
95          return this.statusCode;
96      }
97  
98      public StatusClass getStatusClass() {
99          return this.statusClass;
100     }
101 
102     /**
103      * Whether this status code is in the HTTP series {@link StatusClass#INFORMATIONAL}.
104      *
105      * @since 5.1
106      */
107     public boolean isInformational() {
108         return getStatusClass() == StatusClass.INFORMATIONAL;
109     }
110 
111     /**
112      * Whether this status code is in the HTTP series {@link StatusClass#SUCCESSFUL}.
113      *
114      * @since 5.1
115      */
116     public boolean isSuccessful() {
117         return getStatusClass() == StatusClass.SUCCESSFUL;
118     }
119 
120     /**
121      * Whether this status code is in the HTTP series {@link StatusClass#REDIRECTION}.
122      *
123      * @since 5.1
124      */
125     public boolean isRedirection() {
126         return getStatusClass() == StatusClass.REDIRECTION;
127     }
128 
129     /**
130      * Whether this status code is in the HTTP series {@link StatusClass#CLIENT_ERROR}.
131      *
132      * @since 5.1
133      */
134     public boolean isClientError() {
135         return getStatusClass() == StatusClass.CLIENT_ERROR;
136     }
137 
138     /**
139      * Whether this status code is in the HTTP series {@link StatusClass#SERVER_ERROR}.
140      *
141      * @since 5.1
142      */
143     public boolean isServerError() {
144         return getStatusClass() == StatusClass.SERVER_ERROR;
145     }
146 
147     /**
148      * Whether this status code is in the HTTP series {@link StatusClass#CLIENT_ERROR}
149      * or {@link StatusClass#SERVER_ERROR}.
150      *
151      * @since 5.1
152      */
153     public boolean isError() {
154         return isClientError() || isServerError();
155     }
156 
157     public ProtocolVersion getProtocolVersion() {
158         return this.protoVersion;
159     }
160 
161     public String getReasonPhrase() {
162         return this.reasonPhrase;
163     }
164 
165     @Override
166     public String toString() {
167         final StringBuilder buf = new StringBuilder();
168         buf.append(this.protoVersion).append(" ").append(this.statusCode).append(" ");
169         if (this.reasonPhrase != null) {
170             buf.append(this.reasonPhrase);
171         }
172         return buf.toString();
173     }
174 
175     /**
176      * Standard classes of HTTP status codes, plus {@code OTHER} for non-standard codes.
177      */
178     public enum StatusClass {
179 
180         /**
181          * Informational {@code 1xx} HTTP status codes.
182          */
183         INFORMATIONAL,
184 
185         /**
186          * Successful {@code 2xx} HTTP status codes.
187          */
188         SUCCESSFUL,
189 
190         /**
191          * Redirection {@code 3xx} HTTP status codes.
192          */
193         REDIRECTION,
194 
195         /**
196          * Client Error {@code 4xx} HTTP status codes.
197          */
198         CLIENT_ERROR,
199 
200         /**
201          * {@code 5xx} HTTP status codes.
202          */
203         SERVER_ERROR,
204 
205         /**
206          * Any other HTTP status codes (e.g. non-standard status codes).
207          */
208         OTHER;
209 
210         /**
211          * Gets the response status class for the given status code.
212          *
213          * @param statusCode response status code to get the class for.
214          * @return class of the response status code.
215          */
216         public static StatusClass from(final int statusCode) {
217             final StatusClass statusClass;
218 
219             switch (statusCode / 100) {
220                 case 1:
221                     statusClass = INFORMATIONAL;
222                     break;
223                 case 2:
224                     statusClass = SUCCESSFUL;
225                     break;
226                 case 3:
227                     statusClass = REDIRECTION;
228                     break;
229                 case 4:
230                     statusClass = CLIENT_ERROR;
231                     break;
232                 case 5:
233                     statusClass = SERVER_ERROR;
234                     break;
235                 default:
236                     statusClass = OTHER;
237                     break;
238             }
239 
240             return statusClass;
241         }
242     }
243 }