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,v 1.13 2004/04/18 23:51:35 jsdever Exp $
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 } catch (StringIndexOutOfBoundsException e) {
96 throw new HttpException("Status-Line '" + statusLine + "' is not valid");
97 }
98
99 at = statusLine.indexOf(" ", at);
100 if (at <= 0) {
101 throw new ProtocolException(
102 "Unable to parse HTTP-Version from the status line: '"
103 + statusLine + "'");
104 }
105 this.httpVersion = (statusLine.substring(start, at)).toUpperCase();
106
107
108 while (statusLine.charAt(at) == ' ') {
109 at++;
110 }
111
112
113 int to = statusLine.indexOf(" ", at);
114 if (to < 0) {
115 to = length;
116 }
117 try {
118 this.statusCode = Integer.parseInt(statusLine.substring(at, to));
119 } catch (NumberFormatException e) {
120 throw new ProtocolException(
121 "Unable to parse status code from status line: '"
122 + statusLine + "'");
123 }
124
125
126 at = to + 1;
127 try {
128 if (at < length) {
129 this.reasonPhrase = statusLine.substring(at).trim();
130 } else {
131 this.reasonPhrase = "";
132 }
133 } catch (StringIndexOutOfBoundsException e) {
134 throw new ProtocolException("Status text not specified: '"
135 + statusLine + "'");
136 }
137
138 this.statusLine = new String(statusLine);
139 }
140
141
142
143
144 /***
145 * @return the Status-Code
146 */
147 public final int getStatusCode() {
148 return statusCode;
149 }
150
151 /***
152 * @return the HTTP-Version
153 */
154 public final String getHttpVersion() {
155 return httpVersion;
156 }
157
158 /***
159 * @return the Reason-Phrase
160 */
161 public final String getReasonPhrase() {
162 return reasonPhrase;
163 }
164
165 /***
166 * Return a string representation of this object.
167 * @return a string represenation of this object.
168 */
169 public final String toString() {
170 return statusLine;
171 }
172
173 /***
174 * Tests if the string starts with 'HTTP' signature.
175 * @param s string to test
176 * @return <tt>true</tt> if the line starts with 'HTTP'
177 * signature, <tt>false</tt> otherwise.
178 */
179 public static boolean startsWithHTTP(final String s) {
180 try {
181 int at = 0;
182 while (Character.isWhitespace(s.charAt(at))) {
183 ++at;
184 }
185 return ("HTTP".equals(s.substring(at, at + 4)));
186 } catch (StringIndexOutOfBoundsException e) {
187 return false;
188 }
189 }
190 }