View Javadoc

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 }