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