Annotation of java/classes/org/w3c/jigsaw/servlet/JigsawHttpServletRequest.java, revision 1.58
1.1 abaird 1: // JigsawHttpServletRequest.java
1.58 ! ylafon 2: // $Id: JigsawHttpServletRequest.java,v 1.57 2000/08/16 21:37:44 ylafon Exp $
1.1 abaird 3: // (c) COPYRIGHT MIT and INRIA, 1996.
4: // Please first read the full copyright statement in file COPYRIGHT.html
5:
1.16 bmahe 6: package org.w3c.jigsaw.servlet;
1.1 abaird 7:
1.57 ylafon 8: import java.io.BufferedReader;
9: import java.io.IOException;
10: import java.io.InputStream;
11: import java.io.InputStreamReader;
12: import java.io.Reader;
13: import java.io.StringReader;
14: import java.io.UnsupportedEncodingException;
15:
16: import java.util.Enumeration;
17: import java.util.Hashtable;
18: import java.util.Locale;
19: import java.util.Vector;
20:
1.47 bmahe 21: import java.security.Principal;
1.1 abaird 22:
1.57 ylafon 23: import javax.servlet.RequestDispatcher;
24: import javax.servlet.Servlet;
25: import javax.servlet.ServletInputStream;
26:
27: import javax.servlet.http.Cookie;
28: import javax.servlet.http.HttpServletRequest;
29: import javax.servlet.http.HttpSession;
30:
31: import org.w3c.util.ArrayEnumeration;
32: import org.w3c.util.EmptyEnumeration;
33: import org.w3c.util.ObservableProperties;
34:
35: import org.w3c.jigsaw.http.Client;
36: import org.w3c.jigsaw.http.Request;
37: import org.w3c.jigsaw.http.httpd;
1.1 abaird 38:
1.16 bmahe 39: import org.w3c.jigsaw.forms.URLDecoder;
40: import org.w3c.jigsaw.forms.URLDecoderException;
1.46 bmahe 41: import org.w3c.jigsaw.resources.VirtualHostResource;
1.57 ylafon 42:
43: import org.w3c.www.http.ContentLengthInputStream;
44: import org.w3c.www.http.HeaderDescription;
45: import org.w3c.www.http.HeaderValue;
46: import org.w3c.www.http.HttpAcceptLanguage;
47: import org.w3c.www.http.HttpCookie;
48: import org.w3c.www.http.HttpCookieList;
49: import org.w3c.www.http.HttpEntityMessage;
50: import org.w3c.www.http.HttpMessage;
51: import org.w3c.www.http.HttpRequestMessage;
52:
53: import org.w3c.www.mime.MimeType;
54:
1.16 bmahe 55: import org.w3c.jigsaw.auth.AuthFilter; // for auth infos access
1.2 abaird 56:
1.57 ylafon 57: import org.w3c.tools.resources.InvalidResourceException;
58: import org.w3c.tools.resources.Resource;
59: import org.w3c.tools.resources.ResourceReference;
1.14 bmahe 60:
1.6 abaird 61: class HeaderNames implements Enumeration {
1.18 bmahe 62: // The HeaderDescription enumeration
63: Enumeration e = null;
1.6 abaird 64:
1.18 bmahe 65: public boolean hasMoreElements() {
66: return e.hasMoreElements();
67: }
68:
69: public Object nextElement() {
70: HeaderDescription d = (HeaderDescription) e.nextElement();
71: return d.getName();
72: }
73:
74: HeaderNames(Enumeration e) {
75: this.e = e ;
76: }
1.6 abaird 77:
78: }
79:
1.2 abaird 80: /**
81: * @author Alexandre Rafalovitch <alex@access.com.au>
82: * @author Anselm Baird-Smith <abaird@w3.org>
1.12 bmahe 83: * @author Benoit Mahe <bmahe@sophia.inria.fr>
1.2 abaird 84: */
1.1 abaird 85:
86: public class JigsawHttpServletRequest implements HttpServletRequest {
1.9 bmahe 87:
1.25 bmahe 88: /**
89: * The InputStream state codes.
90: */
91:
92: /**
93: * The initial state of the request InputStream
94: */
1.18 bmahe 95: private final static int STREAM_STATE_INITIAL = 0;
1.25 bmahe 96:
97: /**
98: * One reader has been created and is probably used.
99: */
1.18 bmahe 100: private final static int STREAM_READER_USED = 1;
1.25 bmahe 101:
102: /**
103: * The input stream is used
104: */
1.18 bmahe 105: private final static int INPUT_STREAM_USED = 2;
106:
1.25 bmahe 107: /**
108: * The inputstream state
109: */
1.18 bmahe 110: private int stream_state = STREAM_STATE_INITIAL;
111:
112: public final static
113: String STATE_PARAMETERS = "org.w3c.jigsaw.servlet.stateParam";
114:
115: private static MimeType type = MimeType.APPLICATION_X_WWW_FORM_URLENCODED ;
116: /**
117: * The initial request.
118: */
119: private Request request = null;
120: /**
121: * The attached servlet.
122: */
123: private Servlet servlet = null;
124: /**
125: * The lazyly computed queryParameters hashtable.
126: */
127: private Hashtable queryParameters = null;
128:
1.25 bmahe 129: protected JigsawHttpServletResponse response = null;
130:
131: protected JigsawHttpSession httpSession = null;
132:
1.29 bmahe 133: protected JigsawHttpSessionContext sessionContext = null;
1.25 bmahe 134:
135: protected String requestedSessionID = null;
136:
1.45 bmahe 137: private Hashtable mergeParameters(Hashtable source, Hashtable dest) {
138: if (source == null)
139: return dest;
140: if (dest != null) {
141: Enumeration e = source.keys();
142: while (e.hasMoreElements()) {
143: String name = (String)e.nextElement();
144: Object value = dest.get(name);
145: if (value == null)
146: dest.put(name, source.get(name));
147: else if (value instanceof String[]) {
148: String oldValues [] = (String[])value;
149: String newValues [] = new String[oldValues.length+1];
150: System.arraycopy(oldValues,0,newValues,0,
151: oldValues.length);
152: newValues[oldValues.length] = (String)source.get(name);
153: dest.put(name,newValues);
154: } else {
155: String newValues [] = new String[2];
156: newValues[0] = (String)source.get(name);
157: newValues[1] = (String)value;
158: dest.put(name,newValues);
159: }
160: }
161: return dest;
162: } else {
163: return source;
164: }
165: }
166:
167: private synchronized void prepareQueryParameters() {
1.18 bmahe 168: if( queryParameters != null )
169: return;
1.45 bmahe 170: Hashtable postParameters = null;
1.18 bmahe 171: // What kinf of parameters are we expecting ?
172: if ( request.getMethod().equals("POST") ) {
173: // POSTed parameters, check content type:
174: if ((! request.hasContentType())
175: || (type.match(request.getContentType()) < 0) )
176: return;
1.58 ! ylafon 177: postParameters = new Hashtable(2);
1.18 bmahe 178: // Get and decode the request entity:
179: URLDecoder dec = null;
180: try {
181: InputStream in = request.getInputStream() ;
182: // Notify the client that we are willing to continue
1.58 ! ylafon 183: String exp = request.getExpect();
! 184: if (exp != null && (exp.equalsIgnoreCase("100-continue"))) {
! 185: Client client = request.getClient();
! 186: // FIXME send only if needed
! 187: if ( client != null ) {
! 188: client.sendContinue();
! 189: }
! 190: }
1.18 bmahe 191: dec = new URLDecoder (in, false);
1.45 bmahe 192: postParameters = dec.parse () ;
1.18 bmahe 193: } catch (URLDecoderException e) {
1.45 bmahe 194: postParameters = null;
1.18 bmahe 195: } catch (IOException ex) {
1.45 bmahe 196: postParameters = null;
1.18 bmahe 197: }
1.45 bmahe 198: }
199: // URL encoded parameters:
1.52 bmahe 200: String query = getQueryString();
1.45 bmahe 201: if (query != null) {
202: Reader qis = new StringReader(query);
203: try {
204: queryParameters = new URLDecoder(qis, false).parse();
205: } catch (Exception ex) {
206: throw new RuntimeException("Java implementation bug.");
1.18 bmahe 207: }
208: }
1.45 bmahe 209: queryParameters = mergeParameters(postParameters, queryParameters);
1.18 bmahe 210: // state parameters
211: Hashtable param = (Hashtable)request.getState(STATE_PARAMETERS);
1.45 bmahe 212: queryParameters = mergeParameters(param, queryParameters);
1.18 bmahe 213: }
214:
1.31 bmahe 215: protected String getURLParameter(String name) {
216: Hashtable urlParameters = null;
1.52 bmahe 217: String query = getQueryString();
1.31 bmahe 218: if (query != null) {
1.42 bmahe 219: Reader qis = new StringReader(query);
1.31 bmahe 220: try {
221: urlParameters = new URLDecoder(qis, false).parse();
222: return (String) urlParameters.get(name);
223: } catch (Exception ex) {
224: throw new RuntimeException("Java implementation bug.");
225: }
226: }
227: return null;
228: }
1.18 bmahe 229:
230: /**
231: * Return the Charset parameter of content type
232: * @return A String instance
233: */
234: public String getCharacterEncoding() {
235: org.w3c.www.mime.MimeType type = request.getContentType();
236: if ((type != null) && (type.hasParameter("charset"))) {
237: return type.getParameterValue("charset");
238: }
1.19 bmahe 239: return "ISO-8859-1";
1.18 bmahe 240: }
241:
242: /**
243: * ServletRequest implementation - Get the length of request data.
244: * @return An int, or <strong>-1</strong>.
245: */
246:
1.52 bmahe 247: public int getContentLength() {
1.18 bmahe 248: return request.getContentLength();
249: }
250:
251: /**
252: * ServletRequest implementation - Get the type of the request's body.
253: * @return A String encoded mime type, or <strong>null</strong>.
254: */
255:
1.52 bmahe 256: public String getContentType() {
1.18 bmahe 257: org.w3c.www.mime.MimeType t = request.getContentType();
258: return (t == null) ? null : t.toString();
259: }
1.57 ylafon 260:
1.18 bmahe 261: /**
262: * ServletRequest implementation - Get the protocol of that request.
263: * @return A String encoded version of the protocol.
264: */
265:
1.52 bmahe 266: public String getProtocol() {
1.18 bmahe 267: return request.getVersion();
268: }
1.57 ylafon 269:
1.47 bmahe 270: protected httpd getServer() {
271: return request.getClient().getServer();
272: }
273:
1.18 bmahe 274: /**
275: * ServletRequest implementation - Get the name of queried server.
276: * @return Name of server, as a String.
277: */
278:
1.52 bmahe 279: public String getServerName() {
280: String host = request.getHost();
1.53 bmahe 281: if (host != null) {
282: int idx = host.lastIndexOf(':');
283: if (idx != -1) {
284: return host.substring(0, host.lastIndexOf(':'));
285: } else {
286: return host;
287: }
288: } else {
1.52 bmahe 289: return getServer().getHost();
1.53 bmahe 290: }
1.18 bmahe 291: }
292:
293: /**
294: * ServletRequest implementation - Get the port of queried server.
295: * @return A port number (int).
296: */
297:
1.52 bmahe 298: public int getServerPort() {
1.39 bmahe 299: if (request.isProxy()) {
300: String host = request.getHost();
301: if (host != null) {
302: int idx = host.lastIndexOf(':');
303: if (idx == -1)
304: return 80;
305: return Integer.parseInt(host.substring(idx+1));
306: }
307: }
1.47 bmahe 308: return getServer().getLocalPort();
1.18 bmahe 309: }
310:
311: /**
312: * ServletRequest implementation - Get the IP address of requests's sender.
313: * @return Numeric IP address, as a String.
314: */
315:
1.52 bmahe 316: public String getRemoteAddr() {
1.18 bmahe 317: return request.getClient().getInetAddress().getHostAddress();
318: }
319:
320: /**
321: * ServletRequest implementation - FQDN of request's sender.
322: * @return Name of client's machine (FQDN).
323: */
324:
1.52 bmahe 325: public String getRemoteHost() {
1.18 bmahe 326: return request.getClient().getInetAddress().getHostName();
327: }
328:
329: /**
330: * ServletRequest implementation - Get real path.
331: * Jigsaw realy has no notion of <em>translation</em> stricto
332: * sensu (it has much better in fact ;-). This is a pain here.
1.46 bmahe 333: * @return the real path.
1.42 bmahe 334: * @deprecated since jsdk1.2
1.18 bmahe 335: */
336:
337: public String getRealPath(String name) {
1.47 bmahe 338: httpd server = getServer();
1.46 bmahe 339: ResourceReference rr_root = server.getRootReference();
1.50 bmahe 340: return JigsawServletContext.getRealPath(name,
341: rr_root,
342: request.getTargetResource());
1.18 bmahe 343: }
344:
1.32 bmahe 345: protected ServletInputStream is = null;
346:
1.18 bmahe 347: /**
1.32 bmahe 348: * Returns an input stream for reading binary data in the request body.
349: * @exception IllegalStateException if getReader has been called on
350: * this same request.
351: * @exception IOException on other I/O related errors.
1.41 ylafon 352: * @see JigsawHttpServletRequest#getReader
1.32 bmahe 353: */
1.18 bmahe 354: public ServletInputStream getInputStream()
355: throws IOException
356: {
357: if (stream_state == STREAM_READER_USED)
358: throw new IllegalStateException("Reader used");
359: stream_state = INPUT_STREAM_USED;
360: return getJigsawInputStream();
361: }
1.57 ylafon 362:
1.37 bmahe 363: /**
1.38 bmahe 364: * @exception IOException if an IO error occurs
1.37 bmahe 365: */
1.18 bmahe 366: protected ServletInputStream getJigsawInputStream()
367: throws IOException
368: {
369: // If alredy computed return:
370: if ( is != null )
371: return is;
372: // Built it:
373: InputStream stream = null;
374: if ((stream = request.getInputStream()) == null)
375: stream = new ContentLengthInputStream(null, 0);
376: return is = new JigsawServletInputStream(stream);
377: }
378:
379: /**
380: * ServletRequest implementation - Get a parameter value.
381: * @return The String encoded value for the parameter.
382: */
383:
1.52 bmahe 384: public String getParameter(String name) {
1.18 bmahe 385: prepareQueryParameters();
386: if ( queryParameters != null ) {
387: Object value = queryParameters.get(name);
388: if (value instanceof String[])
389: return ((String[])value)[0];
390: else return (String)value;
391: }
392: else
393: return null;
394: }
395:
396: /**
397: * ServletRequest implementation - Get the parameters value.
398: * @return The String array encoded value for the parameter.
399: */
1.57 ylafon 400:
1.18 bmahe 401: public String[] getParameterValues(String parameter) {
402: Vector V = new Vector(23);
403: prepareQueryParameters();
404: if (queryParameters == null)
405: return null;
406: Object value = queryParameters.get(parameter);
407: if (value == null) return null;
408: if (value instanceof String[])
409: return (String[])value;
410: else {
411: String [] parameterValues = new String[1];
412: parameterValues[0] = (String)value;
413: return parameterValues;
414: }
415: }
416:
417: /**
418: * ServletRequest implementation - List available parameters.
419: * @return An enumeration of parameter names.
420: */
1.57 ylafon 421:
1.52 bmahe 422: public Enumeration getParameterNames() {
1.18 bmahe 423: prepareQueryParameters();
424: return ((queryParameters == null)
425: ? new EmptyEnumeration()
426: : queryParameters.keys());
427: }
428:
429: /**
430: * ServletRequest implementation - Get an attribute of the request.
431: * This closely match Jigsaw's notion of request state.
432: * @param name The name of the attribute.
433: * @return An object that gives the value of the attribute.
434: */
435:
436: public Object getAttribute(String name) {
437: return request.getState(name);
438: }
439:
1.42 bmahe 440: public void setAttribute(String name, Object object) {
441: request.setState(name, object);
442: }
443:
1.47 bmahe 444: /**
445: * Removes an attribute from this request. This method is not
446: * generally needed as attributes only persist as long as the request
447: * is being handled.
448: *
449: * <p>Attribute names should follow the same conventions as
450: * package names. Names beginning with <code>java.*</code>,
451: * <code>javax.*</code>, and <code>com.sun.*</code>, are
452: * reserved for use by Sun Microsystems.
453: *
454: * @param name a <code>String</code> specifying
455: * the name of the attribute to remove
456: */
457: public void removeAttribute(String name) {
458: request.delState(name);
459: }
460:
1.42 bmahe 461: public Enumeration getAttributeNames() {
462: return request.getStateNames();
463: }
464:
1.18 bmahe 465: /**
1.47 bmahe 466: * Returns the preferred <code>Locale</code> that the client will
467: * accept content in, based on the Accept-Language header.
468: * If the client request doesn't provide an Accept-Language header,
469: * this method returns the default locale for the server.
470: *
471: * @return the preferred <code>Locale</code> for the client
472: */
473: public Locale getLocale() {
474: return (Locale)getLocales().nextElement();
475: }
1.57 ylafon 476:
1.47 bmahe 477: /**
478: * Returns an <code>Enumeration</code> of <code>Locale</code> objects
479: * indicating, in decreasing order starting with the preferred locale, the
480: * locales that are acceptable to the client based on the Accept-Language
481: * header.
482: * If the client request doesn't provide an Accept-Language header,
483: * this method returns an <code>Enumeration</code> containing one
484: * <code>Locale</code>, the default locale for the server.
485: *
486: * @return an <code>Enumeration</code> of preferred
487: * <code>Locale</code> objects for the client
488: */
489: public Enumeration getLocales() {
490: HttpAcceptLanguage languages[] = request.getAcceptLanguage();
491: if (languages == null) {
492: Vector def = new Vector();
493: def.addElement(Locale.getDefault());
494: return def.elements();
495: }
496:
1.48 bmahe 497: //LinkedList is better, but we must be JDK1.1 compliant
498: Vector locales = new Vector();
1.47 bmahe 499:
500: for (int i = 0 ; i < languages.length ; i++) {
501: HttpAcceptLanguage language = languages[i];
502: double quality = language.getQuality();
503: String lang = language.getLanguage();
504: String country = "";
505: int idx = lang.indexOf('-');
506: if (idx > -1) {
507: country = lang.substring(idx + 1).trim();
508: lang = lang.substring(0, idx).trim();
509: }
510: // insert the Locale in ordered list
1.48 bmahe 511: int qidx = 0;
512: int size = locales.size();
513: if (size > 0) {
514: QLocale ql = (QLocale) locales.firstElement();
515: while ((qidx < size) && (ql.getLanguageQuality() >= quality)) {
516: try {
517: ql = (QLocale) locales.elementAt(++qidx);
518: } catch (ArrayIndexOutOfBoundsException ex) {
519: //end of vector, so append
520: }
521: }
522: locales.insertElementAt(new QLocale(lang, country, quality),
523: qidx);
524: } else {
525: locales.addElement(new QLocale(lang, country, quality));
1.47 bmahe 526: }
527: }
528: // because Locale is final :(
529: int size = locales.size();
530: Vector vlocale = new Vector(size);
531: for (int i = 0 ; i < size ; i ++) {
1.48 bmahe 532: vlocale.addElement(((QLocale)locales.elementAt(i)).getLocale());
1.47 bmahe 533: }
534: return vlocale.elements();
535: }
536:
537: /**
538: * Returns a boolean indicating whether this request was made using a
539: * secure channel, such as HTTPS.
540: *
541: * @return a boolean indicating if the request was made using a
542: * secure channel
543: */
544:
545: public boolean isSecure() {
546: // only https secure?
547: return (request.getURL().getProtocol().equalsIgnoreCase("https"));
548: }
1.57 ylafon 549:
1.47 bmahe 550: /**
1.18 bmahe 551: * HttpServletRequest implementation - Get the request's method.
552: * @return A String instance.
553: */
554:
1.52 bmahe 555: public String getMethod() {
1.18 bmahe 556: return request.getMethod();
557: }
558:
559: /**
560: * HttpServletRequest implementation - Get the request's path info.
561: * @return A String instance or <strong>null</strong>.
562: */
563:
1.52 bmahe 564: public String getPathInfo() {
565: if (request.hasState(JigsawRequestDispatcher.PATH_INFO_P)) {
566: String pathinfo =
567: (String) request.getState(JigsawRequestDispatcher.PATH_INFO_P);
568: return (pathinfo.equals("/")) ? null : pathinfo;
1.50 bmahe 569: }
1.52 bmahe 570: return null;
1.18 bmahe 571: }
1.57 ylafon 572:
1.18 bmahe 573: /**
574: * HttpServletRequest implementation - Get the request's path translated.
575: * @return A String instance or <strong>null</strong>.
576: */
1.57 ylafon 577:
1.52 bmahe 578: public String getPathTranslated() {
1.18 bmahe 579: String pathinfo = getPathInfo();
1.46 bmahe 580: if ( pathinfo != null )
581: return getRealPath(pathinfo);
1.18 bmahe 582: return null;
583: }
584:
585: /**
1.47 bmahe 586: * Returns the portion of the request URI that indicates the context
587: * of the request. The context path always comes first in a request
588: * URI. The path starts with a "/" character but does not end with a "/"
589: * character. For servlets in the default (root) context, this method
590: * returns "".
591: * @return a <code>String</code> specifying the portion of the request
592: * URI that indicates the context of the request
593: */
594: public String getContextPath() {
1.56 bmahe 595: return "";
1.47 bmahe 596: }
597:
1.52 bmahe 598: public boolean hasQueryString() {
1.54 bmahe 599: if (request.hasQueryString()) {
1.52 bmahe 600: return true;
601: } else {
1.54 bmahe 602: return request.hasState(JigsawRequestDispatcher.QUERY_STRING_P);
1.52 bmahe 603: }
604: }
605:
1.47 bmahe 606: /**
1.18 bmahe 607: * HttpServletRequest implementation - Get the request's query string.
608: * @return A String instance or <strong>null</strong>.
609: */
1.52 bmahe 610: public String getQueryString() {
1.54 bmahe 611: if (request.hasQueryString()) {
612: return request.getQueryString();
613: } else if (request.hasState(JigsawRequestDispatcher.QUERY_STRING_P)) {
1.52 bmahe 614: return (String)
615: request.getState(JigsawRequestDispatcher.QUERY_STRING_P);
616: }
1.54 bmahe 617: return null;
1.18 bmahe 618: }
1.57 ylafon 619:
1.18 bmahe 620: /**
621: * HttpServletRequest implementation - Get the request's user (if any).
622: * @return A String instance or <strong>null</strong>.
623: */
624:
1.52 bmahe 625: public String getRemoteUser() {
1.18 bmahe 626: return (String) request.getState(AuthFilter.STATE_AUTHUSER);
627: }
1.57 ylafon 628:
1.18 bmahe 629: /**
1.47 bmahe 630: * Returns a boolean indicating whether the authenticated user is included
631: * in the specified logical "role". Roles and role membership can be
632: * defined using deployment descriptors. If the user has not been
633: * authenticated, the method returns <code>false</code>.
634: *
635: * @param role a <code>String</code> specifying the name of the role
636: * @return a <code>boolean</code> indicating whether the user making this
637: * request belongs to a given role; <code>false</code> if the user has not
638: * been authenticated
639: */
640:
641: public boolean isUserInRole(String role) {
642: throw new RuntimeException("Not Yet Implemented");
643: }
644:
645: /**
646: * Returns a <code>java.security.Principal</code> object containing
647: * the name of the current authenticated user. If the user has not been
648: * authenticated, the method returns <code>null</code>.
649: *
650: * @return a <code>java.security.Principal</code> containing
651: * the name of the user making this request; <code>null</code> if the
652: * user has not been authenticated
653: */
654: public Principal getUserPrincipal() {
655: return new PrincipalImpl(getRemoteUser());
656: }
657:
658: /**
1.18 bmahe 659: * HttpServletRequest implementation - Get the request's auth method.
660: * @return A String instance or <strong>null</strong>.
661: */
662:
663: public String getAuthType() {
664: return (String) request.getState(AuthFilter.STATE_AUTHTYPE);
665: }
666:
667: /**
668: * HttpServletRequest implementation - Get a request header as a String.
669: * @return A String instance or <strong>null</strong>.
670: */
671:
672: public String getHeader(String name) {
673: return request.getValue(name);
674: }
675:
676: /**
1.47 bmahe 677: * Returns all the values of the specified request header
678: * as an <code>Enumeration</code> of <code>String</code> objects.
679: *
680: * <p>Some headers, such as <code>Accept-Language</code> can be sent
681: * by clients as several headers each with a different value rather than
682: * sending the header as a comma separated list.
683: *
684: * <p>WARNING, this can't happen with Jigsaw, all multiple values are
685: * grouped in one, and only one, header. So, this method always return
686: * ONE header value.
687: *
688: * <p>If the request did not include any headers
689: * of the specified name, this method returns an empty
690: * <code>Enumeration</code>.
691: * The header name is case insensitive. You can use
692: * this method with any request header.
693: *
694: * @param name a <code>String</code> specifying the header name
695: * @return a <code>Enumeration</code> containing the values of the
696: * requested header, or <code>null</code> if the request does not
697: * have any headers of that name
698: */
699:
700: public Enumeration getHeaders(String name) {
701: String value = getHeader(name);
702: String array[] = { value };
703: return new ArrayEnumeration(array);
704: }
705:
706: /**
1.18 bmahe 707: * HttpServletRequest implementation - Get a request header as an int.
708: * @return An int, or <strong>-1</strong>.
709: */
710:
711: public int getIntHeader(String name) {
712: HeaderValue v = request.getHeaderValue(name);
713: if ( v != null ) {
714: Object o = v.getValue();
715: if ((o != null) && (o instanceof Integer))
716: return ((Integer) o).intValue();
1.1 abaird 717: }
1.18 bmahe 718: return -1;
1.1 abaird 719: }
1.18 bmahe 720:
721: /**
722: * HttpServletRequest implementation - Get a request header as an date.
723: * @return An long (as a number of milliseconds), or <strong>-1</strong>.
724: */
725:
726: public long getDateHeader(String name) {
727: HeaderValue v = request.getHeaderValue(name, null);
728: if ( v != null ) {
729: Object o = v.getValue();
730: if ((o != null) && (o instanceof Long))
731: return ((Long) o).longValue();
1.10 bmahe 732: }
1.18 bmahe 733: return (long) -1;
1.1 abaird 734: }
1.8 bmahe 735:
1.18 bmahe 736: /**
737: * HttpServletRequest implementation - Get a all header names.
738: * @return An enumeration.
739: */
740:
741: public Enumeration getHeaderNames() {
742: return new HeaderNames(request.enumerateHeaderDescriptions());
743: }
1.16 bmahe 744:
1.25 bmahe 745: /**
746: * Gets, from the first line of the HTTP request,
747: * the part of this request's URI that is to the left of any query string.
748: */
1.55 bmahe 749: public String getRequestURI() {
1.39 bmahe 750: String uri = null;
1.52 bmahe 751: if (request.hasState(JigsawRequestDispatcher.REQUEST_URI_P)) {
752: uri = (String)
753: request.getState(JigsawRequestDispatcher.REQUEST_URI_P);
1.39 bmahe 754: } else {
1.52 bmahe 755: //fixme test
756: if (request.isProxy()) {
757: uri = request.getURL().toExternalForm();
758: } else {
759: uri = request.getURLPath();
760: }
761: if (hasQueryString()) {
762: String query = getQueryString();
763: int idx = uri.lastIndexOf(query);
764: uri = uri.substring(0, idx-1);
765: }
1.39 bmahe 766: }
767: return uri;
1.18 bmahe 768: }
1.57 ylafon 769:
1.25 bmahe 770: /**
1.47 bmahe 771: * Returns a {@link RequestDispatcher} object that acts as a wrapper for
772: * the resource located at the given path.
773: * A <code>RequestDispatcher</code> object can be used to forward
774: * a request to the resource or to include the resource in a response.
775: * The resource can be dynamic or static.
776: *
777: * <p>The pathname specified may be relative, although it cannot extend
778: * outside the current servlet context. If the path begins with
779: * a "/" it is interpreted as relative to the current context root.
780: * This method returns <code>null</code> if the servlet container
781: * cannot return a <code>RequestDispatcher</code>.
782: *
783: * <p>The difference between this method and {@link
784: * ServletContext#getRequestDispatcher} is that this method can take a
785: * relative path.
786: *
787: * @param path a <code>String</code> specifying the pathname
788: * to the resource
789: * @return a <code>RequestDispatcher</code> object that acts as a
790: * wrapper for the resource at the specified path
791: * @see RequestDispatcher
792: * @see ServletContext#getRequestDispatcher
793: */
794: public RequestDispatcher getRequestDispatcher(String path) {
795: if (path == null) {
796: throw new IllegalArgumentException("null");
797: }
1.52 bmahe 798: String urlpath = null;
799: ResourceReference rr = request.getTargetResource();
800: if (! path.startsWith("/")) {
801: String uri = null;
1.47 bmahe 802: try {
1.52 bmahe 803: ResourceReference rrp = rr.lock().getParent();
804: try {
805: Resource r = rrp.lock();
806: uri = r.getURLPath();
807: } catch (InvalidResourceException irex) {
808: return null;
809: } finally {
810: rrp.unlock();
811: }
812: } catch (InvalidResourceException ex) {
1.47 bmahe 813: return null;
814: } finally {
1.52 bmahe 815: rr.unlock();
1.47 bmahe 816: }
1.52 bmahe 817: urlpath = ( uri.endsWith("/") ? uri+path : uri+"/"+path );
818: } else {
819: urlpath = path;
1.47 bmahe 820: }
821: return JigsawRequestDispatcher.getRequestDispatcher(urlpath,
1.52 bmahe 822: getServer(),
823: rr);
1.47 bmahe 824: }
825:
826: /**
1.25 bmahe 827: * Gets the part of this request's URI that refers to the servlet
828: * being invoked. Analogous to the CGI variable SCRIPT_NAME.
829: */
1.52 bmahe 830: public String getServletPath() {
831: if (request.hasState(JigsawRequestDispatcher.SERVLET_PATH_P)) {
832: return (String)
833: request.getState(JigsawRequestDispatcher.SERVLET_PATH_P);
834: } else {
835: ResourceReference rr = request.getTargetResource();
836: try {
837: return rr.lock().getURLPath();
838: } catch (InvalidResourceException ex) {
839: return null;
840: } finally {
841: rr.unlock();
842: }
1.16 bmahe 843: }
1.18 bmahe 844: }
1.57 ylafon 845:
1.25 bmahe 846: /**
847: * @return the scheme of the URL used in this request, for example "http",
848: * "https", or "ftp". Different schemes have different rules
849: * for constructing URLs, as noted in RFC 1738. The URL used to create
850: * a request may be reconstructed using this scheme, the server name
851: * and port, and additional information such as URIs.
852: */
1.18 bmahe 853: public String getScheme() {
854: return request.getURL().getProtocol();
855: }
1.16 bmahe 856:
1.25 bmahe 857: /**
858: * Gets the array of cookies found in this request.
1.36 bmahe 859: * @return the array of cookies found in this request or
860: * <strong>null</strong> if there is no cookie.
1.25 bmahe 861: */
1.18 bmahe 862: public Cookie[] getCookies() {
1.19 bmahe 863: HttpCookieList cookielist = request.getCookie();
1.36 bmahe 864: Cookie[] Scookies = null;
865: if (cookielist != null) {
866: HttpCookie[] cookies = cookielist.getCookies();
867: Scookies = new Cookie[cookies.length];
868: for (int i = 0 ; i < cookies.length ; i++ ) {
869: Scookies[i] = convertCookie(cookies[i]);
870: }
1.19 bmahe 871: }
872: return Scookies;
873: }
1.57 ylafon 874:
1.19 bmahe 875: protected Cookie convertCookie(HttpCookie httpCookie) {
876: Cookie cookie = new Cookie(httpCookie.getName(),
877: httpCookie.getValue());
1.40 bmahe 878: String val = null;
879: if ((val = httpCookie.getDomain()) != null)
880: cookie.setDomain(val);
881: if ((val = httpCookie.getPath()) != null)
882: cookie.setPath(val);
1.19 bmahe 883: cookie.setVersion(httpCookie.getVersion());
884: return cookie;
885: }
886:
887: protected String getRequestedSessionIdFromCookie() {
888: HttpCookieList cookielist = request.getCookie();
889: if (cookielist != null) {
890: HttpCookie httpCookie =
1.28 bmahe 891: request.getCookie().getCookie(getCookieName());
1.19 bmahe 892: if (httpCookie != null)
893: return httpCookie.getValue();
894: }
1.18 bmahe 895: return null;
896: }
1.19 bmahe 897:
1.31 bmahe 898: protected String getRequestedSessionIdFromURL() {
899: return getURLParameter(getCookieName());
900: }
901:
1.25 bmahe 902: /**
903: * Gets the session id specified with this request. This may differ
904: * from the actual session id. For example, if the request specified an
905: * id for an invalid session, then this will get a new session with a
906: * new id.
907: * @return the session id specified by this request, or null if the
908: * request did not specify a session id.
909: */
1.18 bmahe 910: public String getRequestedSessionId() {
1.31 bmahe 911: if (requestedSessionID == null) {
1.27 bmahe 912: requestedSessionID = getRequestedSessionIdFromCookie();
1.31 bmahe 913: if (requestedSessionID == null)
914: requestedSessionID = getRequestedSessionIdFromURL();
915: }
1.19 bmahe 916: return requestedSessionID;
917: }
918:
919: protected synchronized JigsawHttpSessionContext getSessionContext() {
920: return sessionContext;
1.15 benoit 921: }
1.14 bmahe 922:
1.25 bmahe 923: /**
924: * Gets the current valid session associated with this request, if create
925: * is false or, if necessary, creates a new session for the request, if
926: * create is true.
927: * @return the session associated with this request or null if create
928: * was false and no valid session is associated with this request.
929: */
1.18 bmahe 930: public HttpSession getSession(boolean create) {
1.19 bmahe 931: if (httpSession == null) {
1.27 bmahe 932: httpSession = (JigsawHttpSession)
933: getSession(getRequestedSessionId());
1.29 bmahe 934: if (httpSession != null) // the client join the session
935: httpSession.setNoMoreNew();
1.27 bmahe 936: }
937: if (httpSession == null & create) {
938: httpSession = new JigsawHttpSession(getSessionContext(),
939: createCookie());
940: response.addCookie(httpSession.getCookie());
941: } else if (httpSession != null) {
942: httpSession.setLastAccessedTime();
943: if (! httpSession.isValid()) {
1.19 bmahe 944: httpSession = new JigsawHttpSession(getSessionContext(),
945: createCookie());
946: response.addCookie(httpSession.getCookie());
947: }
948: }
949: return httpSession;
950: }
951:
1.42 bmahe 952: /**
953: * Gets the current valid session associated with this request.
954: * @return the session associated with this request.
955: */
956: public HttpSession getSession() {
957: return getSession(true);
958: }
959:
1.33 bmahe 960: protected String getCookieName() {
961: ObservableProperties props =
962: request.getClient().getServer().getProperties();
963: return props.getString(ServletProps.SERVLET_COOKIE_NAME,
964: ServletProps.DEFAULT_COOKIE_NAME);
965: }
966:
1.19 bmahe 967: protected Cookie createCookie() {
1.33 bmahe 968: ObservableProperties props =
969: request.getClient().getServer().getProperties();
1.34 bmahe 970: String name = props.getString(ServletProps.SERVLET_COOKIE_NAME,
971: ServletProps.DEFAULT_COOKIE_NAME);
972: String path = props.getString(ServletProps.SERVLET_COOKIE_PATH,
973: "/");
974: String domain = props.getString(ServletProps.SERVLET_COOKIE_DOMAIN,
1.35 bmahe 975: null);
1.34 bmahe 976: String comment = props.getString(ServletProps.SERVLET_COOKIE_COMMENT,
977: null);
978: int maxage = props.getInteger(ServletProps.SERVLET_COOKIE_MAXAGE,
979: 86400);
980: boolean secure = props.getBoolean(ServletProps.SERVLET_COOKIE_SECURE,
981: false);
1.33 bmahe 982:
983: Cookie cookie = new Cookie(name, null);
984: cookie.setPath(path);
985: cookie.setMaxAge(maxage);
986: if ((comment != null) && (comment.length() > 0))
987: cookie.setComment(comment);
988: if ((domain != null) && (domain.length() > 0))
989: cookie.setDomain(domain);
990: cookie.setSecure(secure);
1.19 bmahe 991: return cookie;
992: }
993:
994: protected HttpSession getSession(String sessionId) {
995: if (sessionId != null)
996: return getSessionContext().getSession(sessionId);
1.18 bmahe 997: return null;
998: }
1.57 ylafon 999:
1.25 bmahe 1000: /**
1001: * Checks whether this request is associated with a session that is valid
1002: * in the current session context. If it is not valid, the requested
1003: * session will never be returned from the getSession method.
1004: * @return true if this request is assocated with a session that is valid
1005: * in the current session context.
1006: */
1.18 bmahe 1007: public boolean isRequestedSessionIdValid() {
1.27 bmahe 1008: JigsawHttpSession session = (JigsawHttpSession)
1009: getSession(getRequestedSessionId());
1.19 bmahe 1010: if (session == null)
1011: return false;
1012: return (session.isValid());
1.18 bmahe 1013: }
1014:
1.25 bmahe 1015: /**
1016: * Checks whether the session id specified by this request came in as
1017: * a cookie. (The requested session may not be one returned by the
1018: * getSession method.)
1019: * @return true if the session id specified by this request came
1020: * in as a cookie; false otherwise
1021: */
1.18 bmahe 1022: public boolean isRequestedSessionIdFromCookie() {
1.29 bmahe 1023: return (getRequestedSessionIdFromCookie() != null);
1.18 bmahe 1024: }
1025:
1.25 bmahe 1026: /**
1027: * Checks whether the session id specified by this request came in as
1028: * part of the URL. (The requested session may not be the one returned
1029: * by the getSession method.)
1030: * @return true if the session id specified by the request for this
1031: * session came in as part of the URL; false otherwise
1.42 bmahe 1032: * @deprecated since jsdk2.1
1.25 bmahe 1033: */
1.18 bmahe 1034: public boolean isRequestedSessionIdFromUrl() {
1.31 bmahe 1035: return (getRequestedSessionIdFromURL() != null);
1.18 bmahe 1036: }
1037:
1.42 bmahe 1038: /**
1039: * Checks whether the session id specified by this request came in as
1040: * part of the URL. (The requested session may not be the one returned
1041: * by the getSession method.)
1042: * @return true if the session id specified by the request for this
1043: * session came in as part of the URL; false otherwise
1044: */
1045: public boolean isRequestedSessionIdFromURL() {
1046: return (getRequestedSessionIdFromURL() != null);
1047: }
1048:
1.18 bmahe 1049: protected BufferedReader reader = null;
1.25 bmahe 1050:
1051: /**
1.32 bmahe 1052: * Returns a buffered reader for reading text in the request body.
1.25 bmahe 1053: * This translates character set encodings as appropriate.
1.32 bmahe 1054: * @exception UnsupportedEncodingException if the character set encoding
1055: * is unsupported, so the text can't be correctly decoded.
1056: * @exception IllegalStateException if getInputStream has been called on
1057: * this same request.
1058: * @exception IOException on other I/O related errors.
1.41 ylafon 1059: * @see JigsawHttpServletRequest#getInputStream
1.25 bmahe 1060: */
1.18 bmahe 1061: public BufferedReader getReader()
1062: throws IOException
1063: {
1064: if (stream_state == INPUT_STREAM_USED)
1065: throw new IllegalStateException("Input Stream used");
1066: stream_state = STREAM_READER_USED;
1067: if (reader == null) {
1.43 ylafon 1068: String enc[] = request.getContentEncoding();
1.44 ylafon 1069: InputStream is = getJigsawInputStream();
1.43 ylafon 1070: if (enc != null) {
1071: InputStreamReader isr = null;
1072: for (int i=0; i < enc.length; i++) {
1073: try {
1074: isr = new InputStreamReader(is, enc[i]);
1075: break;
1076: } catch (UnsupportedEncodingException ex) {
1077: // not a valid encoding, skip it
1078: isr = null;
1079: }
1080: }
1081: if (isr != null)
1082: reader = new BufferedReader(isr);
1083: else
1084: reader = new BufferedReader(new InputStreamReader(is));
1085: } else {
1086: reader = new BufferedReader(new InputStreamReader(is));
1087: }
1.18 bmahe 1088: }
1089: return reader;
1.42 bmahe 1090: }
1091:
1092: /**
1.47 bmahe 1093: * Get the wrapped Jigsaw Request.
1094: * @return the request
1.42 bmahe 1095: */
1096: protected Request getRequest() {
1097: return request;
1.19 bmahe 1098: }
1099:
1100: JigsawHttpServletRequest(Servlet servlet,
1101: Request request,
1.29 bmahe 1102: JigsawHttpServletResponse response,
1103: JigsawHttpSessionContext sessionContext) {
1104: this.servlet = servlet;
1105: this.request = request;
1106: this.response = response;
1107: this.sessionContext = sessionContext;
1.58 ! ylafon 1108: prepareQueryParameters();
1.17 bmahe 1109: }
1110:
1.1 abaird 1111: }
Webmaster