KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > coyote > Request


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.coyote;
19
20 import java.io.IOException JavaDoc;
21 import java.util.HashMap JavaDoc;
22
23 import org.apache.tomcat.util.buf.ByteChunk;
24 import org.apache.tomcat.util.buf.MessageBytes;
25 import org.apache.tomcat.util.buf.UDecoder;
26
27 import org.apache.tomcat.util.http.MimeHeaders;
28 import org.apache.tomcat.util.http.Parameters;
29 import org.apache.tomcat.util.http.ContentType;
30 import org.apache.tomcat.util.http.Cookies;
31
32 /**
33  * This is a low-level, efficient representation of a server request. Most
34  * fields are GC-free, expensive operations are delayed until the user code
35  * needs the information.
36  *
37  * Processing is delegated to modules, using a hook mechanism.
38  *
39  * This class is not intended for user code - it is used internally by tomcat
40  * for processing the request in the most efficient way. Users ( servlets ) can
41  * access the information using a facade, which provides the high-level view
42  * of the request.
43  *
44  * For lazy evaluation, the request uses the getInfo() hook. The following ids
45  * are defined:
46  * <ul>
47  * <li>req.encoding - returns the request encoding
48  * <li>req.attribute - returns a module-specific attribute ( like SSL keys, etc ).
49  * </ul>
50  *
51  * Tomcat defines a number of attributes:
52  * <ul>
53  * <li>"org.apache.tomcat.request" - allows access to the low-level
54  * request object in trusted applications
55  * </ul>
56  *
57  * @author James Duncan Davidson [duncan@eng.sun.com]
58  * @author James Todd [gonzo@eng.sun.com]
59  * @author Jason Hunter [jch@eng.sun.com]
60  * @author Harish Prabandham
61  * @author Alex Cruikshank [alex@epitonic.com]
62  * @author Hans Bergsten [hans@gefionsoftware.com]
63  * @author Costin Manolache
64  * @author Remy Maucherat
65  */

66 public final class Request {
67
68
69     // ----------------------------------------------------------- Constructors
70

71
72     public Request() {
73
74         parameters.setQuery(queryMB);
75         parameters.setURLDecoder(urlDecoder);
76         parameters.setHeaders(headers);
77
78     }
79
80
81     // ----------------------------------------------------- Instance Variables
82

83
84     private int serverPort = -1;
85     private MessageBytes serverNameMB = MessageBytes.newInstance();
86
87     private int remotePort;
88     private int localPort;
89
90     private MessageBytes schemeMB = MessageBytes.newInstance();
91
92     private MessageBytes methodMB = MessageBytes.newInstance();
93     private MessageBytes unparsedURIMB = MessageBytes.newInstance();
94     private MessageBytes uriMB = MessageBytes.newInstance();
95     private MessageBytes decodedUriMB = MessageBytes.newInstance();
96     private MessageBytes queryMB = MessageBytes.newInstance();
97     private MessageBytes protoMB = MessageBytes.newInstance();
98
99     // remote address/host
100
private MessageBytes remoteAddrMB = MessageBytes.newInstance();
101     private MessageBytes localNameMB = MessageBytes.newInstance();
102     private MessageBytes remoteHostMB = MessageBytes.newInstance();
103     private MessageBytes localAddrMB = MessageBytes.newInstance();
104      
105     private MimeHeaders headers = new MimeHeaders();
106
107     private MessageBytes instanceId = MessageBytes.newInstance();
108
109     /**
110      * Notes.
111      */

112     private Object JavaDoc notes[] = new Object JavaDoc[Constants.MAX_NOTES];
113
114
115     /**
116      * Associated input buffer.
117      */

118     private InputBuffer inputBuffer = null;
119
120
121     /**
122      * URL decoder.
123      */

124     private UDecoder urlDecoder = new UDecoder();
125
126
127     /**
128      * HTTP specific fields. (remove them ?)
129      */

130     private long contentLength = -1;
131     private MessageBytes contentTypeMB = null;
132     private String JavaDoc charEncoding = null;
133     private Cookies cookies = new Cookies(headers);
134     private Parameters parameters = new Parameters();
135
136     private MessageBytes remoteUser=MessageBytes.newInstance();
137     private MessageBytes authType=MessageBytes.newInstance();
138     private HashMap JavaDoc attributes=new HashMap JavaDoc();
139
140     private Response response;
141     private ActionHook hook;
142
143     private int bytesRead=0;
144     // Time of the request - usefull to avoid repeated calls to System.currentTime
145
private long startTime = 0L;
146
147     private RequestInfo reqProcessorMX=new RequestInfo(this);
148     // ------------------------------------------------------------- Properties
149

150
151     /**
152      * Get the instance id (or JVM route). Curently Ajp is sending it with each
153      * request. In future this should be fixed, and sent only once ( or
154      * 'negociated' at config time so both tomcat and apache share the same name.
155      *
156      * @return the instance id
157      */

158     public MessageBytes instanceId() {
159         return instanceId;
160     }
161
162
163     public MimeHeaders getMimeHeaders() {
164         return headers;
165     }
166
167
168     public UDecoder getURLDecoder() {
169         return urlDecoder;
170     }
171
172     // -------------------- Request data --------------------
173

174
175     public MessageBytes scheme() {
176         return schemeMB;
177     }
178     
179     public MessageBytes method() {
180         return methodMB;
181     }
182     
183     public MessageBytes unparsedURI() {
184         return unparsedURIMB;
185     }
186
187     public MessageBytes requestURI() {
188         return uriMB;
189     }
190
191     public MessageBytes decodedURI() {
192         return decodedUriMB;
193     }
194
195     public MessageBytes query() {
196         return queryMB;
197     }
198
199     public MessageBytes queryString() {
200         return queryMB;
201     }
202
203     public MessageBytes protocol() {
204         return protoMB;
205     }
206     
207     /**
208      * Return the buffer holding the server name, if
209      * any. Use isNull() to check if there is no value
210      * set.
211      * This is the "virtual host", derived from the
212      * Host: header.
213      */

214     public MessageBytes serverName() {
215         return serverNameMB;
216     }
217
218     public int getServerPort() {
219         return serverPort;
220     }
221     
222     public void setServerPort(int serverPort ) {
223         this.serverPort=serverPort;
224     }
225
226     public MessageBytes remoteAddr() {
227         return remoteAddrMB;
228     }
229
230     public MessageBytes remoteHost() {
231         return remoteHostMB;
232     }
233
234     public MessageBytes localName() {
235         return localNameMB;
236     }
237
238     public MessageBytes localAddr() {
239         return localAddrMB;
240     }
241     
242     public int getRemotePort(){
243         return remotePort;
244     }
245         
246     public void setRemotePort(int port){
247         this.remotePort = port;
248     }
249     
250     public int getLocalPort(){
251         return localPort;
252     }
253         
254     public void setLocalPort(int port){
255         this.localPort = port;
256     }
257
258     // -------------------- encoding/type --------------------
259

260
261     /**
262      * Get the character encoding used for this request.
263      */

264     public String JavaDoc getCharacterEncoding() {
265
266         if (charEncoding != null)
267             return charEncoding;
268
269         charEncoding = ContentType.getCharsetFromContentType(getContentType());
270         return charEncoding;
271
272     }
273
274
275     public void setCharacterEncoding(String JavaDoc enc) {
276         this.charEncoding = enc;
277     }
278
279
280     public void setContentLength(int len) {
281         this.contentLength = len;
282     }
283
284
285     public int getContentLength() {
286         long length = getContentLengthLong();
287
288         if (length < Integer.MAX_VALUE) {
289             return (int) length;
290         }
291         return -1;
292     }
293
294     public long getContentLengthLong() {
295         if( contentLength > -1 ) return contentLength;
296
297         MessageBytes clB = headers.getValue("content-length");
298         contentLength = (clB == null || clB.isNull()) ? -1 : clB.getLong();
299
300         return contentLength;
301     }
302
303     public String JavaDoc getContentType() {
304         contentType();
305         if ((contentTypeMB == null) || contentTypeMB.isNull())
306             return null;
307         return contentTypeMB.toString();
308     }
309
310
311     public void setContentType(String JavaDoc type) {
312         contentTypeMB.setString(type);
313     }
314
315
316     public MessageBytes contentType() {
317         if (contentTypeMB == null)
318             contentTypeMB = headers.getValue("content-type");
319         return contentTypeMB;
320     }
321
322
323     public void setContentType(MessageBytes mb) {
324         contentTypeMB=mb;
325     }
326
327
328     public String JavaDoc getHeader(String JavaDoc name) {
329         return headers.getHeader(name);
330     }
331
332     // -------------------- Associated response --------------------
333

334     public Response getResponse() {
335         return response;
336     }
337
338     public void setResponse( Response response ) {
339         this.response=response;
340         response.setRequest( this );
341     }
342     
343     public void action(ActionCode actionCode, Object JavaDoc param) {
344         if( hook==null && response!=null )
345             hook=response.getHook();
346         
347         if (hook != null) {
348             if( param==null )
349                 hook.action(actionCode, this);
350             else
351                 hook.action(actionCode, param);
352         }
353     }
354
355
356     // -------------------- Cookies --------------------
357

358
359     public Cookies getCookies() {
360         return cookies;
361     }
362
363
364     // -------------------- Parameters --------------------
365

366
367     public Parameters getParameters() {
368         return parameters;
369     }
370
371
372     // -------------------- Other attributes --------------------
373
// We can use notes for most - need to discuss what is of general interest
374

375     public void setAttribute( String JavaDoc name, Object JavaDoc o ) {
376         attributes.put( name, o );
377     }
378
379     public HashMap JavaDoc getAttributes() {
380         return attributes;
381     }
382
383     public Object JavaDoc getAttribute(String JavaDoc name ) {
384         return attributes.get(name);
385     }
386     
387     public MessageBytes getRemoteUser() {
388         return remoteUser;
389     }
390
391     public MessageBytes getAuthType() {
392         return authType;
393     }
394
395     // -------------------- Input Buffer --------------------
396

397
398     public InputBuffer getInputBuffer() {
399         return inputBuffer;
400     }
401
402
403     public void setInputBuffer(InputBuffer inputBuffer) {
404         this.inputBuffer = inputBuffer;
405     }
406
407
408     /**
409      * Read data from the input buffer and put it into a byte chunk.
410      *
411      * The buffer is owned by the protocol implementation - it will be reused on the next read.
412      * The Adapter must either process the data in place or copy it to a separate buffer if it needs
413      * to hold it. In most cases this is done during byte->char conversions or via InputStream. Unlike
414      * InputStream, this interface allows the app to process data in place, without copy.
415      *
416      */

417     public int doRead(ByteChunk chunk)
418         throws IOException JavaDoc {
419         int n = inputBuffer.doRead(chunk, this);
420         if (n > 0) {
421             bytesRead+=n;
422         }
423         return n;
424     }
425
426
427     // -------------------- debug --------------------
428

429     public String JavaDoc toString() {
430         return "R( " + requestURI().toString() + ")";
431     }
432
433     public long getStartTime() {
434         return startTime;
435     }
436
437     public void setStartTime(long startTime) {
438         this.startTime = startTime;
439     }
440
441     // -------------------- Per-Request "notes" --------------------
442

443
444     /**
445      * Used to store private data. Thread data could be used instead - but
446      * if you have the req, getting/setting a note is just a array access, may
447      * be faster than ThreadLocal for very frequent operations.
448      *
449      * Example use:
450      * Jk:
451      * HandlerRequest.HOSTBUFFER = 10 CharChunk, buffer for Host decoding
452      * WorkerEnv: SSL_CERT_NOTE=16 - MessageBytes containing the cert
453      *
454      * Catalina CoyoteAdapter:
455      * ADAPTER_NOTES = 1 - stores the HttpServletRequest object ( req/res)
456      *
457      * To avoid conflicts, note in the range 0 - 8 are reserved for the
458      * servlet container ( catalina connector, etc ), and values in 9 - 16
459      * for connector use.
460      *
461      * 17-31 range is not allocated or used.
462      */

463     public final void setNote(int pos, Object JavaDoc value) {
464         notes[pos] = value;
465     }
466
467
468     public final Object JavaDoc getNote(int pos) {
469         return notes[pos];
470     }
471
472
473     // -------------------- Recycling --------------------
474

475
476     public void recycle() {
477         bytesRead=0;
478
479         contentLength = -1;
480         contentTypeMB = null;
481         charEncoding = null;
482         headers.recycle();
483         serverNameMB.recycle();
484         serverPort=-1;
485         localPort = -1;
486         remotePort = -1;
487
488         cookies.recycle();
489         parameters.recycle();
490
491         unparsedURIMB.recycle();
492         uriMB.recycle();
493         decodedUriMB.recycle();
494         queryMB.recycle();
495         methodMB.recycle();
496         protoMB.recycle();
497
498         schemeMB.recycle();
499
500         instanceId.recycle();
501         remoteUser.recycle();
502         authType.recycle();
503         attributes.clear();
504     }
505
506     // -------------------- Info --------------------
507
public void updateCounters() {
508         reqProcessorMX.updateCounters();
509     }
510
511     public RequestInfo getRequestProcessor() {
512         return reqProcessorMX;
513     }
514
515     public int getBytesRead() {
516         return bytesRead;
517     }
518
519     public void setBytesRead(int bytesRead) {
520         this.bytesRead = bytesRead;
521     }
522 }
523
Popular Tags