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