1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.apache.commons.httpclient;
31
32 /***
33 * Represents a Status-Line as returned from a HTTP server.
34 *
35 * <a href="http://www.ietf.org/rfc/rfc2616.txt">RFC2616</a> states
36 * the following regarding the Status-Line:
37 * <pre>
38 * 6.1 Status-Line
39 *
40 * The first line of a Response message is the Status-Line, consisting
41 * of the protocol version followed by a numeric status code and its
42 * associated textual phrase, with each element separated by SP
43 * characters. No CR or LF is allowed except in the final CRLF sequence.
44 *
45 * Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
46 * </pre>
47 * <p>
48 * This class is immutable and is inherently thread safe.
49 *
50 * @see HttpStatus
51 * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a>
52 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
53 * @version $Id: StatusLine.java 354155 2005-12-05 20:18:10Z olegk $
54 * @since 2.0
55 */
56 public class StatusLine {
57
58
59
60 /*** The original Status-Line. */
61 private final String statusLine;
62
63 /*** The HTTP-Version. */
64 private final String httpVersion;
65
66 /*** The Status-Code. */
67 private final int statusCode;
68
69 /*** The Reason-Phrase. */
70 private final String reasonPhrase;
71
72
73
74
75 /***
76 * Default constructor.
77 *
78 * @param statusLine the status line returned from the HTTP server
79 * @throws HttpException if the status line is invalid
80 */
81 public StatusLine(final String statusLine) throws HttpException {
82
83 int length = statusLine.length();
84 int at = 0;
85 int start = 0;
86 try {
87 while (Character.isWhitespace(statusLine.charAt(at))) {
88 ++at;
89 ++start;
90 }
91 if (!"HTTP".equals(statusLine.substring(at, at += 4))) {
92 throw new HttpException("Status-Line '" + statusLine
93 + "' does not start with HTTP");
94 }
95
96 at = statusLine.indexOf(" ", at);
97 if (at <= 0) {
98 throw new ProtocolException(
99 "Unable to parse HTTP-Version from the status line: '"
100 + statusLine + "'");
101 }
102 this.httpVersion = (statusLine.substring(start, at)).toUpperCase();
103
104
105 while (statusLine.charAt(at) == ' ') {
106 at++;
107 }
108
109
110 int to = statusLine.indexOf(" ", at);
111 if (to < 0) {
112 to = length;
113 }
114 try {
115 this.statusCode = Integer.parseInt(statusLine.substring(at, to));
116 } catch (NumberFormatException e) {
117 throw new ProtocolException(
118 "Unable to parse status code from status line: '"
119 + statusLine + "'");
120 }
121
122 at = to + 1;
123 if (at < length) {
124 this.reasonPhrase = statusLine.substring(at).trim();
125 } else {
126 this.reasonPhrase = "";
127 }
128 } catch (StringIndexOutOfBoundsException e) {
129 throw new HttpException("Status-Line '" + statusLine + "' is not valid");
130 }
131
132 this.statusLine = statusLine;
133 }
134
135
136
137
138 /***
139 * @return the Status-Code
140 */
141 public final int getStatusCode() {
142 return statusCode;
143 }
144
145 /***
146 * @return the HTTP-Version
147 */
148 public final String getHttpVersion() {
149 return httpVersion;
150 }
151
152 /***
153 * @return the Reason-Phrase
154 */
155 public final String getReasonPhrase() {
156 return reasonPhrase;
157 }
158
159 /***
160 * Return a string representation of this object.
161 * @return a string represenation of this object.
162 */
163 public final String toString() {
164 return statusLine;
165 }
166
167 /***
168 * Tests if the string starts with 'HTTP' signature.
169 * @param s string to test
170 * @return <tt>true</tt> if the line starts with 'HTTP'
171 * signature, <tt>false</tt> otherwise.
172 */
173 public static boolean startsWithHTTP(final String s) {
174 try {
175 int at = 0;
176 while (Character.isWhitespace(s.charAt(at))) {
177 ++at;
178 }
179 return ("HTTP".equals(s.substring(at, at + 4)));
180 } catch (StringIndexOutOfBoundsException e) {
181 return false;
182 }
183 }
184 }