1 /*
2 * @(#)Request.java 0.3-3 06/05/2001
3 *
4 * This file is part of the HTTPClient package
5 * Copyright (C) 1996-2001 Ronald Tschalär
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307, USA
21 *
22 * For questions, suggestions, bug-reports, enhancement-requests etc.
23 * I may be contacted at:
24 *
25 * ronald@innovation.ch
26 *
27 * The HTTPClient's home page is located at:
28 *
29 * http://www.innovation.ch/java/HTTPClient/
30 *
31 */
32
33 package HTTPClient;
34
35
36 /**
37 * This class represents an http request. It's used by classes which
38 * implement the HTTPClientModule interface.
39 *
40 * @version 0.3-3 06/05/2001
41 * @author Ronald Tschalär
42 */
43 public final class Request implements RoRequest, Cloneable
44 {
45 /** null headers */
46 private static final NVPair[] empty = new NVPair[0];
47
48 /** the current HTTPConnection */
49 private HTTPConnection connection;
50
51 /** the request method to be used (e.g. GET, POST, etc) */
52 private String method;
53
54 /** the request-uri */
55 private String req_uri;
56
57 /** the headers to be used */
58 private NVPair[] headers;
59
60 /** the entity (if any) */
61 private byte[] data;
62
63 /** or an output stream on which the entity will be written */
64 private HttpOutputStream stream;
65
66 /** are modules allowed to popup windows or otherwise prompt user? */
67 private boolean allow_ui;
68
69 /** number of millisecs to wait for an error from the server before sending
70 the entity (used when retrying requests) */
71 long delay_entity = 0;
72
73 /** number of retries so far */
74 int num_retries = 0;
75
76 /** disable pipelining of following request */
77 boolean dont_pipeline = false;
78
79 /** was this request aborted by the user? */
80 boolean aborted = false;
81
82 /** is this an internally generated subrequest? */
83 boolean internal_subrequest = false;
84
85
86 // Constructors
87
88 /**
89 * Creates a new request structure.
90 *
91 * @param con the current HTTPConnection
92 * @param method the request method
93 * @param req_uri the request-uri
94 * @param headers the request headers
95 * @param data the entity as a byte[]
96 * @param stream the entity as a stream
97 * @param allow_ui allow user interaction
98 */
99 public Request(HTTPConnection con, String method, String req_uri,
100 NVPair[] headers, byte[] data, HttpOutputStream stream,
101 boolean allow_ui)
102 {
103 this.connection = con;
104 this.method = method;
105 setRequestURI(req_uri);
106 setHeaders(headers);
107 this.data = data;
108 this.stream = stream;
109 this.allow_ui = allow_ui;
110 }
111
112
113 // Methods
114
115 /**
116 * @return the HTTPConnection this request is associated with
117 */
118 public HTTPConnection getConnection()
119 {
120 return connection;
121 }
122
123 /**
124 * @param con the HTTPConnection this request is associated with
125 */
126 public void setConnection(HTTPConnection con)
127 {
128 this.connection = con;
129 }
130
131
132 /**
133 * @return the request method
134 */
135 public String getMethod()
136 {
137 return method;
138 }
139
140 /**
141 * @param method the request method (e.g. GET, POST, etc)
142 */
143 public void setMethod(String method)
144 {
145 this.method = method;
146 }
147
148
149 /**
150 * @return the request-uri
151 */
152 public String getRequestURI()
153 {
154 return req_uri;
155 }
156
157 /**
158 * @param req_uri the request-uri
159 */
160 public void setRequestURI(String req_uri)
161 {
162 if (req_uri != null && req_uri.trim().length() > 0)
163 {
164 req_uri = req_uri.trim();
165 if (req_uri.charAt(0) != '/' && !req_uri.equals("*") &&
166 !method.equals("CONNECT") && !isAbsolute(req_uri))
167 req_uri = "/" + req_uri;
168 this.req_uri = req_uri;
169 }
170 else
171 this.req_uri = "/";
172 }
173
174 private static final boolean isAbsolute(String uri)
175 {
176 char ch = '\0';
177 int pos = 0, len = uri.length();
178 while (pos < len && (ch = uri.charAt(pos)) != ':' &&
179 ch != '/' && ch != '?' && ch != '#')
180 pos++;
181
182 return (ch == ':');
183 }
184
185
186 /**
187 * @return the headers making up this request
188 */
189 public NVPair[] getHeaders()
190 {
191 return headers;
192 }
193
194 /**
195 * @param headers the headers for this request
196 */
197 public void setHeaders(NVPair[] headers)
198 {
199 if (headers != null)
200 this.headers = headers;
201 else
202 this.headers = empty;
203 }
204
205
206 /**
207 * @return the body of this request
208 */
209 public byte[] getData()
210 {
211 return data;
212 }
213
214 /**
215 * @param data the entity for this request
216 */
217 public void setData(byte[] data)
218 {
219 this.data = data;
220 }
221
222
223 /**
224 * @return the output stream on which the body is written
225 */
226 public HttpOutputStream getStream()
227 {
228 return stream;
229 }
230
231 /**
232 * @param stream an output stream on which the entity is written
233 */
234 public void setStream(HttpOutputStream stream)
235 {
236 this.stream = stream;
237 }
238
239
240 /**
241 * @return true if the modules or handlers for this request may popup
242 * windows or otherwise interact with the user
243 */
244 public boolean allowUI()
245 {
246 return allow_ui;
247 }
248
249 /**
250 * @param allow_ui are modules and handlers allowed to popup windows or
251 * otherwise interact with the user?
252 */
253 public void setAllowUI(boolean allow_ui)
254 {
255 this.allow_ui = allow_ui;
256 }
257
258
259 /**
260 * @return a clone of this request object
261 */
262 public Object clone()
263 {
264 Request cl;
265 try
266 { cl = (Request) super.clone(); }
267 catch (CloneNotSupportedException cnse)
268 { throw new InternalError(cnse.toString()); /* shouldn't happen */ }
269
270 cl.headers = new NVPair[headers.length];
271 System.arraycopy(headers, 0, cl.headers, 0, headers.length);
272
273 return cl;
274 }
275
276
277 /**
278 * Copy all the fields from <var>other</var> to this request.
279 *
280 * @param other the Request to copy from
281 */
282 public void copyFrom(Request other)
283 {
284 this.connection = other.connection;
285 this.method = other.method;
286 this.req_uri = other.req_uri;
287 this.headers = other.headers;
288 this.data = other.data;
289 this.stream = other.stream;
290 this.allow_ui = other.allow_ui;
291 this.delay_entity = other.delay_entity;
292 this.num_retries = other.num_retries;
293 this.dont_pipeline = other.dont_pipeline;
294 this.aborted = other.aborted;
295 this.internal_subrequest = other.internal_subrequest;
296 }
297
298
299 /**
300 * @return a string containing the method and request-uri
301 */
302 public String toString()
303 {
304 return getClass().getName() + ": " + method + " " + req_uri;
305 }
306 }