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