0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017:
0018: package org.apache.catalina.connector;
0019:
0020: import java.io.InputStream;
0021: import java.io.IOException;
0022: import java.io.BufferedReader;
0023: import java.io.UnsupportedEncodingException;
0024: import java.security.Principal;
0025: import java.text.SimpleDateFormat;
0026: import java.util.ArrayList;
0027: import java.util.Enumeration;
0028: import java.util.HashMap;
0029: import java.util.Iterator;
0030: import java.util.Locale;
0031: import java.util.Map;
0032: import java.util.TimeZone;
0033: import java.util.TreeMap;
0034:
0035: import javax.security.auth.Subject;
0036: import javax.servlet.FilterChain;
0037: import javax.servlet.RequestDispatcher;
0038: import javax.servlet.ServletContext;
0039: import javax.servlet.ServletInputStream;
0040: import javax.servlet.ServletRequestAttributeEvent;
0041: import javax.servlet.ServletRequestAttributeListener;
0042: import javax.servlet.http.Cookie;
0043: import javax.servlet.http.HttpServletRequest;
0044: import javax.servlet.http.HttpSession;
0045:
0046: import org.apache.tomcat.util.buf.B2CConverter;
0047: import org.apache.tomcat.util.buf.MessageBytes;
0048: import org.apache.tomcat.util.buf.StringCache;
0049: import org.apache.tomcat.util.http.Cookies;
0050: import org.apache.tomcat.util.http.FastHttpDateFormat;
0051: import org.apache.tomcat.util.http.Parameters;
0052: import org.apache.tomcat.util.http.ServerCookie;
0053: import org.apache.tomcat.util.http.mapper.MappingData;
0054:
0055: import org.apache.coyote.ActionCode;
0056:
0057: import org.apache.catalina.Context;
0058: import org.apache.catalina.Globals;
0059: import org.apache.catalina.Host;
0060: import org.apache.catalina.Manager;
0061: import org.apache.catalina.Realm;
0062: import org.apache.catalina.Session;
0063: import org.apache.catalina.Wrapper;
0064: import org.apache.catalina.core.ApplicationFilterFactory;
0065: import org.apache.catalina.realm.GenericPrincipal;
0066: import org.apache.catalina.util.Enumerator;
0067: import org.apache.catalina.util.ParameterMap;
0068: import org.apache.catalina.util.RequestUtil;
0069: import org.apache.catalina.util.StringManager;
0070: import org.apache.catalina.util.StringParser;
0071:
0072: /**
0073: * Wrapper object for the Coyote request.
0074: *
0075: * @author Remy Maucherat
0076: * @author Craig R. McClanahan
0077: * @version $Revision: 535030 $ $Date: 2007-05-04 01:54:31 +0200 (ven., 04 mai 2007) $
0078: */
0079:
0080: public class Request implements HttpServletRequest {
0081:
0082: // ----------------------------------------------------------- Constructors
0083:
0084: static {
0085: // Ensure that classes are loaded for SM
0086: new StringCache.ByteEntry();
0087: new StringCache.CharEntry();
0088: }
0089:
0090: public Request() {
0091:
0092: formats[0].setTimeZone(GMT_ZONE);
0093: formats[1].setTimeZone(GMT_ZONE);
0094: formats[2].setTimeZone(GMT_ZONE);
0095:
0096: }
0097:
0098: // ------------------------------------------------------------- Properties
0099:
0100: /**
0101: * Coyote request.
0102: */
0103: protected org.apache.coyote.Request coyoteRequest;
0104:
0105: /**
0106: * Set the Coyote request.
0107: *
0108: * @param coyoteRequest The Coyote request
0109: */
0110: public void setCoyoteRequest(org.apache.coyote.Request coyoteRequest) {
0111: this .coyoteRequest = coyoteRequest;
0112: inputBuffer.setRequest(coyoteRequest);
0113: }
0114:
0115: /**
0116: * Get the Coyote request.
0117: */
0118: public org.apache.coyote.Request getCoyoteRequest() {
0119: return (this .coyoteRequest);
0120: }
0121:
0122: // ----------------------------------------------------- Variables
0123:
0124: protected static final TimeZone GMT_ZONE = TimeZone
0125: .getTimeZone("GMT");
0126:
0127: /**
0128: * The string manager for this package.
0129: */
0130: protected static StringManager sm = StringManager
0131: .getManager(Constants.Package);
0132:
0133: /**
0134: * The set of cookies associated with this Request.
0135: */
0136: protected Cookie[] cookies = null;
0137:
0138: /**
0139: * The set of SimpleDateFormat formats to use in getDateHeader().
0140: *
0141: * Notice that because SimpleDateFormat is not thread-safe, we can't
0142: * declare formats[] as a static variable.
0143: */
0144: protected SimpleDateFormat formats[] = {
0145: new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz",
0146: Locale.US),
0147: new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz",
0148: Locale.US),
0149: new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US) };
0150:
0151: /**
0152: * The default Locale if none are specified.
0153: */
0154: protected static Locale defaultLocale = Locale.getDefault();
0155:
0156: /**
0157: * The attributes associated with this Request, keyed by attribute name.
0158: */
0159: protected HashMap attributes = new HashMap();
0160:
0161: /**
0162: * List of read only attributes for this Request.
0163: */
0164: private HashMap readOnlyAttributes = new HashMap();
0165:
0166: /**
0167: * The preferred Locales assocaited with this Request.
0168: */
0169: protected ArrayList locales = new ArrayList();
0170:
0171: /**
0172: * Internal notes associated with this request by Catalina components
0173: * and event listeners.
0174: */
0175: private transient HashMap notes = new HashMap();
0176:
0177: /**
0178: * Authentication type.
0179: */
0180: protected String authType = null;
0181:
0182: /**
0183: * Associated event.
0184: */
0185: protected CometEventImpl event = null;
0186:
0187: /**
0188: * Comet state
0189: */
0190: protected boolean comet = false;
0191:
0192: /**
0193: * The current dispatcher type.
0194: */
0195: protected Object dispatcherType = null;
0196:
0197: /**
0198: * The associated input buffer.
0199: */
0200: protected InputBuffer inputBuffer = new InputBuffer();
0201:
0202: /**
0203: * ServletInputStream.
0204: */
0205: protected CoyoteInputStream inputStream = new CoyoteInputStream(
0206: inputBuffer);
0207:
0208: /**
0209: * Reader.
0210: */
0211: protected CoyoteReader reader = new CoyoteReader(inputBuffer);
0212:
0213: /**
0214: * Using stream flag.
0215: */
0216: protected boolean usingInputStream = false;
0217:
0218: /**
0219: * Using writer flag.
0220: */
0221: protected boolean usingReader = false;
0222:
0223: /**
0224: * User principal.
0225: */
0226: protected Principal userPrincipal = null;
0227:
0228: /**
0229: * Session parsed flag.
0230: */
0231: protected boolean sessionParsed = false;
0232:
0233: /**
0234: * Request parameters parsed flag.
0235: */
0236: protected boolean parametersParsed = false;
0237:
0238: /**
0239: * Cookies parsed flag.
0240: */
0241: protected boolean cookiesParsed = false;
0242:
0243: /**
0244: * Secure flag.
0245: */
0246: protected boolean secure = false;
0247:
0248: /**
0249: * The Subject associated with the current AccessControllerContext
0250: */
0251: protected transient Subject subject = null;
0252:
0253: /**
0254: * Post data buffer.
0255: */
0256: protected static int CACHED_POST_LEN = 8192;
0257: protected byte[] postData = null;
0258:
0259: /**
0260: * Hash map used in the getParametersMap method.
0261: */
0262: protected ParameterMap parameterMap = new ParameterMap();
0263:
0264: /**
0265: * The currently active session for this request.
0266: */
0267: protected Session session = null;
0268:
0269: /**
0270: * The current request dispatcher path.
0271: */
0272: protected Object requestDispatcherPath = null;
0273:
0274: /**
0275: * Was the requested session ID received in a cookie?
0276: */
0277: protected boolean requestedSessionCookie = false;
0278:
0279: /**
0280: * The requested session ID (if any) for this request.
0281: */
0282: protected String requestedSessionId = null;
0283:
0284: /**
0285: * Was the requested session ID received in a URL?
0286: */
0287: protected boolean requestedSessionURL = false;
0288:
0289: /**
0290: * Parse locales.
0291: */
0292: protected boolean localesParsed = false;
0293:
0294: /**
0295: * The string parser we will use for parsing request lines.
0296: */
0297: private StringParser parser = new StringParser();
0298:
0299: /**
0300: * Local port
0301: */
0302: protected int localPort = -1;
0303:
0304: /**
0305: * Remote address.
0306: */
0307: protected String remoteAddr = null;
0308:
0309: /**
0310: * Remote host.
0311: */
0312: protected String remoteHost = null;
0313:
0314: /**
0315: * Remote port
0316: */
0317: protected int remotePort = -1;
0318:
0319: /**
0320: * Local address
0321: */
0322: protected String localAddr = null;
0323:
0324: /**
0325: * Local address
0326: */
0327: protected String localName = null;
0328:
0329: // --------------------------------------------------------- Public Methods
0330:
0331: /**
0332: * Release all object references, and initialize instance variables, in
0333: * preparation for reuse of this object.
0334: */
0335: public void recycle() {
0336:
0337: context = null;
0338: wrapper = null;
0339:
0340: dispatcherType = null;
0341: requestDispatcherPath = null;
0342:
0343: comet = false;
0344: if (event != null) {
0345: event.clear();
0346: event = null;
0347: }
0348:
0349: authType = null;
0350: inputBuffer.recycle();
0351: usingInputStream = false;
0352: usingReader = false;
0353: userPrincipal = null;
0354: subject = null;
0355: sessionParsed = false;
0356: parametersParsed = false;
0357: cookiesParsed = false;
0358: locales.clear();
0359: localesParsed = false;
0360: secure = false;
0361: remoteAddr = null;
0362: remoteHost = null;
0363: remotePort = -1;
0364: localPort = -1;
0365: localAddr = null;
0366: localName = null;
0367:
0368: attributes.clear();
0369: notes.clear();
0370: cookies = null;
0371:
0372: if (session != null) {
0373: session.endAccess();
0374: }
0375: session = null;
0376: requestedSessionCookie = false;
0377: requestedSessionId = null;
0378: requestedSessionURL = false;
0379:
0380: if (Globals.IS_SECURITY_ENABLED || Connector.RECYCLE_FACADES) {
0381: parameterMap = new ParameterMap();
0382: } else {
0383: parameterMap.setLocked(false);
0384: parameterMap.clear();
0385: }
0386:
0387: mappingData.recycle();
0388:
0389: if (Globals.IS_SECURITY_ENABLED || Connector.RECYCLE_FACADES) {
0390: if (facade != null) {
0391: facade.clear();
0392: facade = null;
0393: }
0394: if (inputStream != null) {
0395: inputStream.clear();
0396: inputStream = null;
0397: }
0398: if (reader != null) {
0399: reader.clear();
0400: reader = null;
0401: }
0402: }
0403:
0404: }
0405:
0406: /**
0407: * Clear cached encoders (to save memory for Comet requests).
0408: */
0409: public void clearEncoders() {
0410: inputBuffer.clearEncoders();
0411: }
0412:
0413: /**
0414: * Clear cached encoders (to save memory for Comet requests).
0415: */
0416: public boolean read() throws IOException {
0417: return (inputBuffer.realReadBytes(null, 0, 0) > 0);
0418: }
0419:
0420: // -------------------------------------------------------- Request Methods
0421:
0422: /**
0423: * Associated Catalina connector.
0424: */
0425: protected Connector connector;
0426:
0427: /**
0428: * Return the Connector through which this Request was received.
0429: */
0430: public Connector getConnector() {
0431: return (this .connector);
0432: }
0433:
0434: /**
0435: * Set the Connector through which this Request was received.
0436: *
0437: * @param connector The new connector
0438: */
0439: public void setConnector(Connector connector) {
0440: this .connector = connector;
0441: }
0442:
0443: /**
0444: * Associated context.
0445: */
0446: protected Context context = null;
0447:
0448: /**
0449: * Return the Context within which this Request is being processed.
0450: */
0451: public Context getContext() {
0452: return (this .context);
0453: }
0454:
0455: /**
0456: * Set the Context within which this Request is being processed. This
0457: * must be called as soon as the appropriate Context is identified, because
0458: * it identifies the value to be returned by <code>getContextPath()</code>,
0459: * and thus enables parsing of the request URI.
0460: *
0461: * @param context The newly associated Context
0462: */
0463: public void setContext(Context context) {
0464: this .context = context;
0465: }
0466:
0467: /**
0468: * Filter chain associated with the request.
0469: */
0470: protected FilterChain filterChain = null;
0471:
0472: /**
0473: * Get filter chain associated with the request.
0474: */
0475: public FilterChain getFilterChain() {
0476: return (this .filterChain);
0477: }
0478:
0479: /**
0480: * Set filter chain associated with the request.
0481: *
0482: * @param filterChain new filter chain
0483: */
0484: public void setFilterChain(FilterChain filterChain) {
0485: this .filterChain = filterChain;
0486: }
0487:
0488: /**
0489: * Return the Host within which this Request is being processed.
0490: */
0491: public Host getHost() {
0492: if (getContext() == null)
0493: return null;
0494: return (Host) getContext().getParent();
0495: //return ((Host) mappingData.host);
0496: }
0497:
0498: /**
0499: * Set the Host within which this Request is being processed. This
0500: * must be called as soon as the appropriate Host is identified, and
0501: * before the Request is passed to a context.
0502: *
0503: * @param host The newly associated Host
0504: */
0505: public void setHost(Host host) {
0506: mappingData.host = host;
0507: }
0508:
0509: /**
0510: * Descriptive information about this Request implementation.
0511: */
0512: protected static final String info = "org.apache.coyote.catalina.CoyoteRequest/1.0";
0513:
0514: /**
0515: * Return descriptive information about this Request implementation and
0516: * the corresponding version number, in the format
0517: * <code><description>/<version></code>.
0518: */
0519: public String getInfo() {
0520: return (info);
0521: }
0522:
0523: /**
0524: * Mapping data.
0525: */
0526: protected MappingData mappingData = new MappingData();
0527:
0528: /**
0529: * Return mapping data.
0530: */
0531: public MappingData getMappingData() {
0532: return (mappingData);
0533: }
0534:
0535: /**
0536: * The facade associated with this request.
0537: */
0538: protected RequestFacade facade = null;
0539:
0540: /**
0541: * Return the <code>ServletRequest</code> for which this object
0542: * is the facade. This method must be implemented by a subclass.
0543: */
0544: public HttpServletRequest getRequest() {
0545: if (facade == null) {
0546: facade = new RequestFacade(this );
0547: }
0548: return (facade);
0549: }
0550:
0551: /**
0552: * The response with which this request is associated.
0553: */
0554: protected org.apache.catalina.connector.Response response = null;
0555:
0556: /**
0557: * Return the Response with which this Request is associated.
0558: */
0559: public org.apache.catalina.connector.Response getResponse() {
0560: return (this .response);
0561: }
0562:
0563: /**
0564: * Set the Response with which this Request is associated.
0565: *
0566: * @param response The new associated response
0567: */
0568: public void setResponse(
0569: org.apache.catalina.connector.Response response) {
0570: this .response = response;
0571: }
0572:
0573: /**
0574: * Return the input stream associated with this Request.
0575: */
0576: public InputStream getStream() {
0577: if (inputStream == null) {
0578: inputStream = new CoyoteInputStream(inputBuffer);
0579: }
0580: return inputStream;
0581: }
0582:
0583: /**
0584: * Set the input stream associated with this Request.
0585: *
0586: * @param stream The new input stream
0587: */
0588: public void setStream(InputStream stream) {
0589: // Ignore
0590: }
0591:
0592: /**
0593: * URI byte to char converter (not recycled).
0594: */
0595: protected B2CConverter URIConverter = null;
0596:
0597: /**
0598: * Return the URI converter.
0599: */
0600: protected B2CConverter getURIConverter() {
0601: return URIConverter;
0602: }
0603:
0604: /**
0605: * Set the URI converter.
0606: *
0607: * @param URIConverter the new URI connverter
0608: */
0609: protected void setURIConverter(B2CConverter URIConverter) {
0610: this .URIConverter = URIConverter;
0611: }
0612:
0613: /**
0614: * Associated wrapper.
0615: */
0616: protected Wrapper wrapper = null;
0617:
0618: /**
0619: * Return the Wrapper within which this Request is being processed.
0620: */
0621: public Wrapper getWrapper() {
0622: return (this .wrapper);
0623: }
0624:
0625: /**
0626: * Set the Wrapper within which this Request is being processed. This
0627: * must be called as soon as the appropriate Wrapper is identified, and
0628: * before the Request is ultimately passed to an application servlet.
0629: * @param wrapper The newly associated Wrapper
0630: */
0631: public void setWrapper(Wrapper wrapper) {
0632: this .wrapper = wrapper;
0633: }
0634:
0635: // ------------------------------------------------- Request Public Methods
0636:
0637: /**
0638: * Create and return a ServletInputStream to read the content
0639: * associated with this Request.
0640: *
0641: * @exception IOException if an input/output error occurs
0642: */
0643: public ServletInputStream createInputStream() throws IOException {
0644: if (inputStream == null) {
0645: inputStream = new CoyoteInputStream(inputBuffer);
0646: }
0647: return inputStream;
0648: }
0649:
0650: /**
0651: * Perform whatever actions are required to flush and close the input
0652: * stream or reader, in a single operation.
0653: *
0654: * @exception IOException if an input/output error occurs
0655: */
0656: public void finishRequest() throws IOException {
0657: // The reader and input stream don't need to be closed
0658: }
0659:
0660: /**
0661: * Return the object bound with the specified name to the internal notes
0662: * for this request, or <code>null</code> if no such binding exists.
0663: *
0664: * @param name Name of the note to be returned
0665: */
0666: public Object getNote(String name) {
0667: return (notes.get(name));
0668: }
0669:
0670: /**
0671: * Return an Iterator containing the String names of all notes bindings
0672: * that exist for this request.
0673: */
0674: public Iterator getNoteNames() {
0675: return (notes.keySet().iterator());
0676: }
0677:
0678: /**
0679: * Remove any object bound to the specified name in the internal notes
0680: * for this request.
0681: *
0682: * @param name Name of the note to be removed
0683: */
0684: public void removeNote(String name) {
0685: notes.remove(name);
0686: }
0687:
0688: /**
0689: * Bind an object to a specified name in the internal notes associated
0690: * with this request, replacing any existing binding for this name.
0691: *
0692: * @param name Name to which the object should be bound
0693: * @param value Object to be bound to the specified name
0694: */
0695: public void setNote(String name, Object value) {
0696: notes.put(name, value);
0697: }
0698:
0699: /**
0700: * Set the content length associated with this Request.
0701: *
0702: * @param length The new content length
0703: */
0704: public void setContentLength(int length) {
0705: // Not used
0706: }
0707:
0708: /**
0709: * Set the content type (and optionally the character encoding)
0710: * associated with this Request. For example,
0711: * <code>text/html; charset=ISO-8859-4</code>.
0712: *
0713: * @param type The new content type
0714: */
0715: public void setContentType(String type) {
0716: // Not used
0717: }
0718:
0719: /**
0720: * Set the protocol name and version associated with this Request.
0721: *
0722: * @param protocol Protocol name and version
0723: */
0724: public void setProtocol(String protocol) {
0725: // Not used
0726: }
0727:
0728: /**
0729: * Set the IP address of the remote client associated with this Request.
0730: *
0731: * @param remoteAddr The remote IP address
0732: */
0733: public void setRemoteAddr(String remoteAddr) {
0734: // Not used
0735: }
0736:
0737: /**
0738: * Set the fully qualified name of the remote client associated with this
0739: * Request.
0740: *
0741: * @param remoteHost The remote host name
0742: */
0743: public void setRemoteHost(String remoteHost) {
0744: // Not used
0745: }
0746:
0747: /**
0748: * Set the name of the scheme associated with this request. Typical values
0749: * are <code>http</code>, <code>https</code>, and <code>ftp</code>.
0750: *
0751: * @param scheme The scheme
0752: */
0753: public void setScheme(String scheme) {
0754: // Not used
0755: }
0756:
0757: /**
0758: * Set the value to be returned by <code>isSecure()</code>
0759: * for this Request.
0760: *
0761: * @param secure The new isSecure value
0762: */
0763: public void setSecure(boolean secure) {
0764: this .secure = secure;
0765: }
0766:
0767: /**
0768: * Set the name of the server (virtual host) to process this request.
0769: *
0770: * @param name The server name
0771: */
0772: public void setServerName(String name) {
0773: coyoteRequest.serverName().setString(name);
0774: }
0775:
0776: /**
0777: * Set the port number of the server to process this request.
0778: *
0779: * @param port The server port
0780: */
0781: public void setServerPort(int port) {
0782: coyoteRequest.setServerPort(port);
0783: }
0784:
0785: // ------------------------------------------------- ServletRequest Methods
0786:
0787: /**
0788: * Return the specified request attribute if it exists; otherwise, return
0789: * <code>null</code>.
0790: *
0791: * @param name Name of the request attribute to return
0792: */
0793: public Object getAttribute(String name) {
0794:
0795: if (name.equals(Globals.DISPATCHER_TYPE_ATTR)) {
0796: return (dispatcherType == null) ? ApplicationFilterFactory.REQUEST_INTEGER
0797: : dispatcherType;
0798: } else if (name.equals(Globals.DISPATCHER_REQUEST_PATH_ATTR)) {
0799: return (requestDispatcherPath == null) ? getRequestPathMB()
0800: .toString() : requestDispatcherPath.toString();
0801: }
0802:
0803: Object attr = attributes.get(name);
0804:
0805: if (attr != null)
0806: return (attr);
0807:
0808: attr = coyoteRequest.getAttribute(name);
0809: if (attr != null)
0810: return attr;
0811: if (isSSLAttribute(name)) {
0812: coyoteRequest.action(ActionCode.ACTION_REQ_SSL_ATTRIBUTE,
0813: coyoteRequest);
0814: attr = coyoteRequest
0815: .getAttribute(Globals.CERTIFICATES_ATTR);
0816: if (attr != null) {
0817: attributes.put(Globals.CERTIFICATES_ATTR, attr);
0818: }
0819: attr = coyoteRequest
0820: .getAttribute(Globals.CIPHER_SUITE_ATTR);
0821: if (attr != null) {
0822: attributes.put(Globals.CIPHER_SUITE_ATTR, attr);
0823: }
0824: attr = coyoteRequest.getAttribute(Globals.KEY_SIZE_ATTR);
0825: if (attr != null) {
0826: attributes.put(Globals.KEY_SIZE_ATTR, attr);
0827: }
0828: attr = coyoteRequest
0829: .getAttribute(Globals.SSL_SESSION_ID_ATTR);
0830: if (attr != null) {
0831: attributes.put(Globals.SSL_SESSION_ID_ATTR, attr);
0832: }
0833: attr = attributes.get(name);
0834: }
0835: return attr;
0836: }
0837:
0838: /**
0839: * Test if a given name is one of the special Servlet-spec SSL attributes.
0840: */
0841: static boolean isSSLAttribute(String name) {
0842: return Globals.CERTIFICATES_ATTR.equals(name)
0843: || Globals.CIPHER_SUITE_ATTR.equals(name)
0844: || Globals.KEY_SIZE_ATTR.equals(name)
0845: || Globals.SSL_SESSION_ID_ATTR.equals(name);
0846: }
0847:
0848: /**
0849: * Return the names of all request attributes for this Request, or an
0850: * empty <code>Enumeration</code> if there are none.
0851: */
0852: public Enumeration getAttributeNames() {
0853: if (isSecure()) {
0854: getAttribute(Globals.CERTIFICATES_ATTR);
0855: }
0856: return new Enumerator(attributes.keySet(), true);
0857: }
0858:
0859: /**
0860: * Return the character encoding for this Request.
0861: */
0862: public String getCharacterEncoding() {
0863: return (coyoteRequest.getCharacterEncoding());
0864: }
0865:
0866: /**
0867: * Return the content length for this Request.
0868: */
0869: public int getContentLength() {
0870: return (coyoteRequest.getContentLength());
0871: }
0872:
0873: /**
0874: * Return the content type for this Request.
0875: */
0876: public String getContentType() {
0877: return (coyoteRequest.getContentType());
0878: }
0879:
0880: /**
0881: * Return the servlet input stream for this Request. The default
0882: * implementation returns a servlet input stream created by
0883: * <code>createInputStream()</code>.
0884: *
0885: * @exception IllegalStateException if <code>getReader()</code> has
0886: * already been called for this request
0887: * @exception IOException if an input/output error occurs
0888: */
0889: public ServletInputStream getInputStream() throws IOException {
0890:
0891: if (usingReader)
0892: throw new IllegalStateException(sm
0893: .getString("coyoteRequest.getInputStream.ise"));
0894:
0895: usingInputStream = true;
0896: if (inputStream == null) {
0897: inputStream = new CoyoteInputStream(inputBuffer);
0898: }
0899: return inputStream;
0900:
0901: }
0902:
0903: /**
0904: * Return the preferred Locale that the client will accept content in,
0905: * based on the value for the first <code>Accept-Language</code> header
0906: * that was encountered. If the request did not specify a preferred
0907: * language, the server's default Locale is returned.
0908: */
0909: public Locale getLocale() {
0910:
0911: if (!localesParsed)
0912: parseLocales();
0913:
0914: if (locales.size() > 0) {
0915: return ((Locale) locales.get(0));
0916: } else {
0917: return (defaultLocale);
0918: }
0919:
0920: }
0921:
0922: /**
0923: * Return the set of preferred Locales that the client will accept
0924: * content in, based on the values for any <code>Accept-Language</code>
0925: * headers that were encountered. If the request did not specify a
0926: * preferred language, the server's default Locale is returned.
0927: */
0928: public Enumeration getLocales() {
0929:
0930: if (!localesParsed)
0931: parseLocales();
0932:
0933: if (locales.size() > 0)
0934: return (new Enumerator(locales));
0935: ArrayList results = new ArrayList();
0936: results.add(defaultLocale);
0937: return (new Enumerator(results));
0938:
0939: }
0940:
0941: /**
0942: * Return the value of the specified request parameter, if any; otherwise,
0943: * return <code>null</code>. If there is more than one value defined,
0944: * return only the first one.
0945: *
0946: * @param name Name of the desired request parameter
0947: */
0948: public String getParameter(String name) {
0949:
0950: if (!parametersParsed)
0951: parseParameters();
0952:
0953: return coyoteRequest.getParameters().getParameter(name);
0954:
0955: }
0956:
0957: /**
0958: * Returns a <code>Map</code> of the parameters of this request.
0959: * Request parameters are extra information sent with the request.
0960: * For HTTP servlets, parameters are contained in the query string
0961: * or posted form data.
0962: *
0963: * @return A <code>Map</code> containing parameter names as keys
0964: * and parameter values as map values.
0965: */
0966: public Map getParameterMap() {
0967:
0968: if (parameterMap.isLocked())
0969: return parameterMap;
0970:
0971: Enumeration enumeration = getParameterNames();
0972: while (enumeration.hasMoreElements()) {
0973: String name = enumeration.nextElement().toString();
0974: String[] values = getParameterValues(name);
0975: parameterMap.put(name, values);
0976: }
0977:
0978: parameterMap.setLocked(true);
0979:
0980: return parameterMap;
0981:
0982: }
0983:
0984: /**
0985: * Return the names of all defined request parameters for this request.
0986: */
0987: public Enumeration getParameterNames() {
0988:
0989: if (!parametersParsed)
0990: parseParameters();
0991:
0992: return coyoteRequest.getParameters().getParameterNames();
0993:
0994: }
0995:
0996: /**
0997: * Return the defined values for the specified request parameter, if any;
0998: * otherwise, return <code>null</code>.
0999: *
1000: * @param name Name of the desired request parameter
1001: */
1002: public String[] getParameterValues(String name) {
1003:
1004: if (!parametersParsed)
1005: parseParameters();
1006:
1007: return coyoteRequest.getParameters().getParameterValues(name);
1008:
1009: }
1010:
1011: /**
1012: * Return the protocol and version used to make this Request.
1013: */
1014: public String getProtocol() {
1015: return coyoteRequest.protocol().toString();
1016: }
1017:
1018: /**
1019: * Read the Reader wrapping the input stream for this Request. The
1020: * default implementation wraps a <code>BufferedReader</code> around the
1021: * servlet input stream returned by <code>createInputStream()</code>.
1022: *
1023: * @exception IllegalStateException if <code>getInputStream()</code>
1024: * has already been called for this request
1025: * @exception IOException if an input/output error occurs
1026: */
1027: public BufferedReader getReader() throws IOException {
1028:
1029: if (usingInputStream)
1030: throw new IllegalStateException(sm
1031: .getString("coyoteRequest.getReader.ise"));
1032:
1033: usingReader = true;
1034: inputBuffer.checkConverter();
1035: if (reader == null) {
1036: reader = new CoyoteReader(inputBuffer);
1037: }
1038: return reader;
1039:
1040: }
1041:
1042: /**
1043: * Return the real path of the specified virtual path.
1044: *
1045: * @param path Path to be translated
1046: *
1047: * @deprecated As of version 2.1 of the Java Servlet API, use
1048: * <code>ServletContext.getRealPath()</code>.
1049: */
1050: public String getRealPath(String path) {
1051:
1052: if (context == null)
1053: return (null);
1054: ServletContext servletContext = context.getServletContext();
1055: if (servletContext == null)
1056: return (null);
1057: else {
1058: try {
1059: return (servletContext.getRealPath(path));
1060: } catch (IllegalArgumentException e) {
1061: return (null);
1062: }
1063: }
1064:
1065: }
1066:
1067: /**
1068: * Return the remote IP address making this Request.
1069: */
1070: public String getRemoteAddr() {
1071: if (remoteAddr == null) {
1072: coyoteRequest.action(
1073: ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE,
1074: coyoteRequest);
1075: remoteAddr = coyoteRequest.remoteAddr().toString();
1076: }
1077: return remoteAddr;
1078: }
1079:
1080: /**
1081: * Return the remote host name making this Request.
1082: */
1083: public String getRemoteHost() {
1084: if (remoteHost == null) {
1085: if (!connector.getEnableLookups()) {
1086: remoteHost = getRemoteAddr();
1087: } else {
1088: coyoteRequest.action(
1089: ActionCode.ACTION_REQ_HOST_ATTRIBUTE,
1090: coyoteRequest);
1091: remoteHost = coyoteRequest.remoteHost().toString();
1092: }
1093: }
1094: return remoteHost;
1095: }
1096:
1097: /**
1098: * Returns the Internet Protocol (IP) source port of the client
1099: * or last proxy that sent the request.
1100: */
1101: public int getRemotePort() {
1102: if (remotePort == -1) {
1103: coyoteRequest.action(
1104: ActionCode.ACTION_REQ_REMOTEPORT_ATTRIBUTE,
1105: coyoteRequest);
1106: remotePort = coyoteRequest.getRemotePort();
1107: }
1108: return remotePort;
1109: }
1110:
1111: /**
1112: * Returns the host name of the Internet Protocol (IP) interface on
1113: * which the request was received.
1114: */
1115: public String getLocalName() {
1116: if (localName == null) {
1117: coyoteRequest.action(
1118: ActionCode.ACTION_REQ_LOCAL_NAME_ATTRIBUTE,
1119: coyoteRequest);
1120: localName = coyoteRequest.localName().toString();
1121: }
1122: return localName;
1123: }
1124:
1125: /**
1126: * Returns the Internet Protocol (IP) address of the interface on
1127: * which the request was received.
1128: */
1129: public String getLocalAddr() {
1130: if (localAddr == null) {
1131: coyoteRequest.action(
1132: ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE,
1133: coyoteRequest);
1134: localAddr = coyoteRequest.localAddr().toString();
1135: }
1136: return localAddr;
1137: }
1138:
1139: /**
1140: * Returns the Internet Protocol (IP) port number of the interface
1141: * on which the request was received.
1142: */
1143: public int getLocalPort() {
1144: if (localPort == -1) {
1145: coyoteRequest.action(
1146: ActionCode.ACTION_REQ_LOCALPORT_ATTRIBUTE,
1147: coyoteRequest);
1148: localPort = coyoteRequest.getLocalPort();
1149: }
1150: return localPort;
1151: }
1152:
1153: /**
1154: * Return a RequestDispatcher that wraps the resource at the specified
1155: * path, which may be interpreted as relative to the current request path.
1156: *
1157: * @param path Path of the resource to be wrapped
1158: */
1159: public RequestDispatcher getRequestDispatcher(String path) {
1160:
1161: if (context == null)
1162: return (null);
1163:
1164: // If the path is already context-relative, just pass it through
1165: if (path == null)
1166: return (null);
1167: else if (path.startsWith("/"))
1168: return (context.getServletContext()
1169: .getRequestDispatcher(path));
1170:
1171: // Convert a request-relative path to a context-relative one
1172: String servletPath = (String) getAttribute(Globals.INCLUDE_SERVLET_PATH_ATTR);
1173: if (servletPath == null)
1174: servletPath = getServletPath();
1175:
1176: // Add the path info, if there is any
1177: String pathInfo = getPathInfo();
1178: String requestPath = null;
1179:
1180: if (pathInfo == null) {
1181: requestPath = servletPath;
1182: } else {
1183: requestPath = servletPath + pathInfo;
1184: }
1185:
1186: int pos = requestPath.lastIndexOf('/');
1187: String relative = null;
1188: if (pos >= 0) {
1189: relative = RequestUtil.normalize(requestPath.substring(0,
1190: pos + 1)
1191: + path);
1192: } else {
1193: relative = RequestUtil.normalize(requestPath + path);
1194: }
1195:
1196: return (context.getServletContext()
1197: .getRequestDispatcher(relative));
1198:
1199: }
1200:
1201: /**
1202: * Return the scheme used to make this Request.
1203: */
1204: public String getScheme() {
1205: return (coyoteRequest.scheme().toString());
1206: }
1207:
1208: /**
1209: * Return the server name responding to this Request.
1210: */
1211: public String getServerName() {
1212: return (coyoteRequest.serverName().toString());
1213: }
1214:
1215: /**
1216: * Return the server port responding to this Request.
1217: */
1218: public int getServerPort() {
1219: return (coyoteRequest.getServerPort());
1220: }
1221:
1222: /**
1223: * Was this request received on a secure connection?
1224: */
1225: public boolean isSecure() {
1226: return (secure);
1227: }
1228:
1229: /**
1230: * Remove the specified request attribute if it exists.
1231: *
1232: * @param name Name of the request attribute to remove
1233: */
1234: public void removeAttribute(String name) {
1235: Object value = null;
1236: boolean found = false;
1237:
1238: // Remove the specified attribute
1239: // Check for read only attribute
1240: // requests are per thread so synchronization unnecessary
1241: if (readOnlyAttributes.containsKey(name)) {
1242: return;
1243: }
1244:
1245: // Pass special attributes to the native layer
1246: if (name.startsWith("org.apache.tomcat.")) {
1247: coyoteRequest.getAttributes().remove(name);
1248: }
1249:
1250: found = attributes.containsKey(name);
1251: if (found) {
1252: value = attributes.get(name);
1253: attributes.remove(name);
1254: } else {
1255: return;
1256: }
1257:
1258: // Notify interested application event listeners
1259: Object listeners[] = context.getApplicationEventListeners();
1260: if ((listeners == null) || (listeners.length == 0))
1261: return;
1262: ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(
1263: context.getServletContext(), getRequest(), name, value);
1264: for (int i = 0; i < listeners.length; i++) {
1265: if (!(listeners[i] instanceof ServletRequestAttributeListener))
1266: continue;
1267: ServletRequestAttributeListener listener = (ServletRequestAttributeListener) listeners[i];
1268: try {
1269: listener.attributeRemoved(event);
1270: } catch (Throwable t) {
1271: context
1272: .getLogger()
1273: .error(
1274: sm
1275: .getString("coyoteRequest.attributeEvent"),
1276: t);
1277: // Error valve will pick this execption up and display it to user
1278: attributes.put(Globals.EXCEPTION_ATTR, t);
1279: }
1280: }
1281: }
1282:
1283: /**
1284: * Set the specified request attribute to the specified value.
1285: *
1286: * @param name Name of the request attribute to set
1287: * @param value The associated value
1288: */
1289: public void setAttribute(String name, Object value) {
1290:
1291: // Name cannot be null
1292: if (name == null)
1293: throw new IllegalArgumentException(sm
1294: .getString("coyoteRequest.setAttribute.namenull"));
1295:
1296: // Null value is the same as removeAttribute()
1297: if (value == null) {
1298: removeAttribute(name);
1299: return;
1300: }
1301:
1302: if (name.equals(Globals.DISPATCHER_TYPE_ATTR)) {
1303: dispatcherType = value;
1304: return;
1305: } else if (name.equals(Globals.DISPATCHER_REQUEST_PATH_ATTR)) {
1306: requestDispatcherPath = value;
1307: return;
1308: }
1309:
1310: Object oldValue = null;
1311: boolean replaced = false;
1312:
1313: // Add or replace the specified attribute
1314: // Check for read only attribute
1315: // requests are per thread so synchronization unnecessary
1316: if (readOnlyAttributes.containsKey(name)) {
1317: return;
1318: }
1319:
1320: oldValue = attributes.put(name, value);
1321: if (oldValue != null) {
1322: replaced = true;
1323: }
1324:
1325: // Pass special attributes to the native layer
1326: if (name.startsWith("org.apache.tomcat.")) {
1327: coyoteRequest.setAttribute(name, value);
1328: }
1329:
1330: // Notify interested application event listeners
1331: Object listeners[] = context.getApplicationEventListeners();
1332: if ((listeners == null) || (listeners.length == 0))
1333: return;
1334: ServletRequestAttributeEvent event = null;
1335: if (replaced)
1336: event = new ServletRequestAttributeEvent(context
1337: .getServletContext(), getRequest(), name, oldValue);
1338: else
1339: event = new ServletRequestAttributeEvent(context
1340: .getServletContext(), getRequest(), name, value);
1341:
1342: for (int i = 0; i < listeners.length; i++) {
1343: if (!(listeners[i] instanceof ServletRequestAttributeListener))
1344: continue;
1345: ServletRequestAttributeListener listener = (ServletRequestAttributeListener) listeners[i];
1346: try {
1347: if (replaced) {
1348: listener.attributeReplaced(event);
1349: } else {
1350: listener.attributeAdded(event);
1351: }
1352: } catch (Throwable t) {
1353: context
1354: .getLogger()
1355: .error(
1356: sm
1357: .getString("coyoteRequest.attributeEvent"),
1358: t);
1359: // Error valve will pick this execption up and display it to user
1360: attributes.put(Globals.EXCEPTION_ATTR, t);
1361: }
1362: }
1363: }
1364:
1365: /**
1366: * Overrides the name of the character encoding used in the body of
1367: * this request. This method must be called prior to reading request
1368: * parameters or reading input using <code>getReader()</code>.
1369: *
1370: * @param enc The character encoding to be used
1371: *
1372: * @exception UnsupportedEncodingException if the specified encoding
1373: * is not supported
1374: *
1375: * @since Servlet 2.3
1376: */
1377: public void setCharacterEncoding(String enc)
1378: throws UnsupportedEncodingException {
1379:
1380: if (usingReader)
1381: return;
1382:
1383: // Ensure that the specified encoding is valid
1384: byte buffer[] = new byte[1];
1385: buffer[0] = (byte) 'a';
1386: String dummy = new String(buffer, enc);
1387:
1388: // Save the validated encoding
1389: coyoteRequest.setCharacterEncoding(enc);
1390:
1391: }
1392:
1393: // ---------------------------------------------------- HttpRequest Methods
1394:
1395: /**
1396: * Add a Cookie to the set of Cookies associated with this Request.
1397: *
1398: * @param cookie The new cookie
1399: */
1400: public void addCookie(Cookie cookie) {
1401:
1402: if (!cookiesParsed)
1403: parseCookies();
1404:
1405: int size = 0;
1406: if (cookies != null) {
1407: size = cookies.length;
1408: }
1409:
1410: Cookie[] newCookies = new Cookie[size + 1];
1411: for (int i = 0; i < size; i++) {
1412: newCookies[i] = cookies[i];
1413: }
1414: newCookies[size] = cookie;
1415:
1416: cookies = newCookies;
1417:
1418: }
1419:
1420: /**
1421: * Add a Header to the set of Headers associated with this Request.
1422: *
1423: * @param name The new header name
1424: * @param value The new header value
1425: */
1426: public void addHeader(String name, String value) {
1427: // Not used
1428: }
1429:
1430: /**
1431: * Add a Locale to the set of preferred Locales for this Request. The
1432: * first added Locale will be the first one returned by getLocales().
1433: *
1434: * @param locale The new preferred Locale
1435: */
1436: public void addLocale(Locale locale) {
1437: locales.add(locale);
1438: }
1439:
1440: /**
1441: * Add a parameter name and corresponding set of values to this Request.
1442: * (This is used when restoring the original request on a form based
1443: * login).
1444: *
1445: * @param name Name of this request parameter
1446: * @param values Corresponding values for this request parameter
1447: */
1448: public void addParameter(String name, String values[]) {
1449: coyoteRequest.getParameters().addParameterValues(name, values);
1450: }
1451:
1452: /**
1453: * Clear the collection of Cookies associated with this Request.
1454: */
1455: public void clearCookies() {
1456: cookiesParsed = true;
1457: cookies = null;
1458: }
1459:
1460: /**
1461: * Clear the collection of Headers associated with this Request.
1462: */
1463: public void clearHeaders() {
1464: // Not used
1465: }
1466:
1467: /**
1468: * Clear the collection of Locales associated with this Request.
1469: */
1470: public void clearLocales() {
1471: locales.clear();
1472: }
1473:
1474: /**
1475: * Clear the collection of parameters associated with this Request.
1476: */
1477: public void clearParameters() {
1478: // Not used
1479: }
1480:
1481: /**
1482: * Set the authentication type used for this request, if any; otherwise
1483: * set the type to <code>null</code>. Typical values are "BASIC",
1484: * "DIGEST", or "SSL".
1485: *
1486: * @param type The authentication type used
1487: */
1488: public void setAuthType(String type) {
1489: this .authType = type;
1490: }
1491:
1492: /**
1493: * Set the context path for this Request. This will normally be called
1494: * when the associated Context is mapping the Request to a particular
1495: * Wrapper.
1496: *
1497: * @param path The context path
1498: */
1499: public void setContextPath(String path) {
1500:
1501: if (path == null) {
1502: mappingData.contextPath.setString("");
1503: } else {
1504: mappingData.contextPath.setString(path);
1505: }
1506:
1507: }
1508:
1509: /**
1510: * Set the HTTP request method used for this Request.
1511: *
1512: * @param method The request method
1513: */
1514: public void setMethod(String method) {
1515: // Not used
1516: }
1517:
1518: /**
1519: * Set the query string for this Request. This will normally be called
1520: * by the HTTP Connector, when it parses the request headers.
1521: *
1522: * @param query The query string
1523: */
1524: public void setQueryString(String query) {
1525: // Not used
1526: }
1527:
1528: /**
1529: * Set the path information for this Request. This will normally be called
1530: * when the associated Context is mapping the Request to a particular
1531: * Wrapper.
1532: *
1533: * @param path The path information
1534: */
1535: public void setPathInfo(String path) {
1536: mappingData.pathInfo.setString(path);
1537: }
1538:
1539: /**
1540: * Set a flag indicating whether or not the requested session ID for this
1541: * request came in through a cookie. This is normally called by the
1542: * HTTP Connector, when it parses the request headers.
1543: *
1544: * @param flag The new flag
1545: */
1546: public void setRequestedSessionCookie(boolean flag) {
1547:
1548: this .requestedSessionCookie = flag;
1549:
1550: }
1551:
1552: /**
1553: * Set the requested session ID for this request. This is normally called
1554: * by the HTTP Connector, when it parses the request headers.
1555: *
1556: * @param id The new session id
1557: */
1558: public void setRequestedSessionId(String id) {
1559:
1560: this .requestedSessionId = id;
1561:
1562: }
1563:
1564: /**
1565: * Set a flag indicating whether or not the requested session ID for this
1566: * request came in through a URL. This is normally called by the
1567: * HTTP Connector, when it parses the request headers.
1568: *
1569: * @param flag The new flag
1570: */
1571: public void setRequestedSessionURL(boolean flag) {
1572:
1573: this .requestedSessionURL = flag;
1574:
1575: }
1576:
1577: /**
1578: * Set the unparsed request URI for this Request. This will normally be
1579: * called by the HTTP Connector, when it parses the request headers.
1580: *
1581: * @param uri The request URI
1582: */
1583: public void setRequestURI(String uri) {
1584: // Not used
1585: }
1586:
1587: /**
1588: * Set the decoded request URI.
1589: *
1590: * @param uri The decoded request URI
1591: */
1592: public void setDecodedRequestURI(String uri) {
1593: // Not used
1594: }
1595:
1596: /**
1597: * Get the decoded request URI.
1598: *
1599: * @return the URL decoded request URI
1600: */
1601: public String getDecodedRequestURI() {
1602: return (coyoteRequest.decodedURI().toString());
1603: }
1604:
1605: /**
1606: * Get the decoded request URI.
1607: *
1608: * @return the URL decoded request URI
1609: */
1610: public MessageBytes getDecodedRequestURIMB() {
1611: return (coyoteRequest.decodedURI());
1612: }
1613:
1614: /**
1615: * Set the servlet path for this Request. This will normally be called
1616: * when the associated Context is mapping the Request to a particular
1617: * Wrapper.
1618: *
1619: * @param path The servlet path
1620: */
1621: public void setServletPath(String path) {
1622: if (path != null)
1623: mappingData.wrapperPath.setString(path);
1624: }
1625:
1626: /**
1627: * Set the Principal who has been authenticated for this Request. This
1628: * value is also used to calculate the value to be returned by the
1629: * <code>getRemoteUser()</code> method.
1630: *
1631: * @param principal The user Principal
1632: */
1633: public void setUserPrincipal(Principal principal) {
1634:
1635: if (Globals.IS_SECURITY_ENABLED) {
1636: HttpSession session = getSession(false);
1637: if ((subject != null)
1638: && (!subject.getPrincipals().contains(principal))) {
1639: subject.getPrincipals().add(principal);
1640: } else if (session != null
1641: && session.getAttribute(Globals.SUBJECT_ATTR) == null) {
1642: subject = new Subject();
1643: subject.getPrincipals().add(principal);
1644: }
1645: if (session != null) {
1646: session.setAttribute(Globals.SUBJECT_ATTR, subject);
1647: }
1648: }
1649:
1650: this .userPrincipal = principal;
1651: }
1652:
1653: // --------------------------------------------- HttpServletRequest Methods
1654:
1655: /**
1656: * Return the authentication type used for this Request.
1657: */
1658: public String getAuthType() {
1659: return (authType);
1660: }
1661:
1662: /**
1663: * Return the portion of the request URI used to select the Context
1664: * of the Request.
1665: */
1666: public String getContextPath() {
1667: return (mappingData.contextPath.toString());
1668: }
1669:
1670: /**
1671: * Get the context path.
1672: *
1673: * @return the context path
1674: */
1675: public MessageBytes getContextPathMB() {
1676: return (mappingData.contextPath);
1677: }
1678:
1679: /**
1680: * Return the set of Cookies received with this Request.
1681: */
1682: public Cookie[] getCookies() {
1683:
1684: if (!cookiesParsed)
1685: parseCookies();
1686:
1687: return cookies;
1688:
1689: }
1690:
1691: /**
1692: * Set the set of cookies recieved with this Request.
1693: */
1694: public void setCookies(Cookie[] cookies) {
1695:
1696: this .cookies = cookies;
1697:
1698: }
1699:
1700: /**
1701: * Return the value of the specified date header, if any; otherwise
1702: * return -1.
1703: *
1704: * @param name Name of the requested date header
1705: *
1706: * @exception IllegalArgumentException if the specified header value
1707: * cannot be converted to a date
1708: */
1709: public long getDateHeader(String name) {
1710:
1711: String value = getHeader(name);
1712: if (value == null)
1713: return (-1L);
1714:
1715: // Attempt to convert the date header in a variety of formats
1716: long result = FastHttpDateFormat.parseDate(value, formats);
1717: if (result != (-1L)) {
1718: return result;
1719: }
1720: throw new IllegalArgumentException(value);
1721:
1722: }
1723:
1724: /**
1725: * Return the first value of the specified header, if any; otherwise,
1726: * return <code>null</code>
1727: *
1728: * @param name Name of the requested header
1729: */
1730: public String getHeader(String name) {
1731: return coyoteRequest.getHeader(name);
1732: }
1733:
1734: /**
1735: * Return all of the values of the specified header, if any; otherwise,
1736: * return an empty enumeration.
1737: *
1738: * @param name Name of the requested header
1739: */
1740: public Enumeration getHeaders(String name) {
1741: return coyoteRequest.getMimeHeaders().values(name);
1742: }
1743:
1744: /**
1745: * Return the names of all headers received with this request.
1746: */
1747: public Enumeration getHeaderNames() {
1748: return coyoteRequest.getMimeHeaders().names();
1749: }
1750:
1751: /**
1752: * Return the value of the specified header as an integer, or -1 if there
1753: * is no such header for this request.
1754: *
1755: * @param name Name of the requested header
1756: *
1757: * @exception IllegalArgumentException if the specified header value
1758: * cannot be converted to an integer
1759: */
1760: public int getIntHeader(String name) {
1761:
1762: String value = getHeader(name);
1763: if (value == null) {
1764: return (-1);
1765: } else {
1766: return (Integer.parseInt(value));
1767: }
1768:
1769: }
1770:
1771: /**
1772: * Return the HTTP request method used in this Request.
1773: */
1774: public String getMethod() {
1775: return coyoteRequest.method().toString();
1776: }
1777:
1778: /**
1779: * Return the path information associated with this Request.
1780: */
1781: public String getPathInfo() {
1782: return (mappingData.pathInfo.toString());
1783: }
1784:
1785: /**
1786: * Get the path info.
1787: *
1788: * @return the path info
1789: */
1790: public MessageBytes getPathInfoMB() {
1791: return (mappingData.pathInfo);
1792: }
1793:
1794: /**
1795: * Return the extra path information for this request, translated
1796: * to a real path.
1797: */
1798: public String getPathTranslated() {
1799:
1800: if (context == null)
1801: return (null);
1802:
1803: if (getPathInfo() == null) {
1804: return (null);
1805: } else {
1806: return (context.getServletContext()
1807: .getRealPath(getPathInfo()));
1808: }
1809:
1810: }
1811:
1812: /**
1813: * Return the query string associated with this request.
1814: */
1815: public String getQueryString() {
1816: String queryString = coyoteRequest.queryString().toString();
1817: if (queryString == null || queryString.equals("")) {
1818: return (null);
1819: } else {
1820: return queryString;
1821: }
1822: }
1823:
1824: /**
1825: * Return the name of the remote user that has been authenticated
1826: * for this Request.
1827: */
1828: public String getRemoteUser() {
1829:
1830: if (userPrincipal != null) {
1831: return (userPrincipal.getName());
1832: } else {
1833: return (null);
1834: }
1835:
1836: }
1837:
1838: /**
1839: * Get the request path.
1840: *
1841: * @return the request path
1842: */
1843: public MessageBytes getRequestPathMB() {
1844: return (mappingData.requestPath);
1845: }
1846:
1847: /**
1848: * Return the session identifier included in this request, if any.
1849: */
1850: public String getRequestedSessionId() {
1851: return (requestedSessionId);
1852: }
1853:
1854: /**
1855: * Return the request URI for this request.
1856: */
1857: public String getRequestURI() {
1858: return coyoteRequest.requestURI().toString();
1859: }
1860:
1861: /**
1862: * Reconstructs the URL the client used to make the request.
1863: * The returned URL contains a protocol, server name, port
1864: * number, and server path, but it does not include query
1865: * string parameters.
1866: * <p>
1867: * Because this method returns a <code>StringBuffer</code>,
1868: * not a <code>String</code>, you can modify the URL easily,
1869: * for example, to append query parameters.
1870: * <p>
1871: * This method is useful for creating redirect messages and
1872: * for reporting errors.
1873: *
1874: * @return A <code>StringBuffer</code> object containing the
1875: * reconstructed URL
1876: */
1877: public StringBuffer getRequestURL() {
1878:
1879: StringBuffer url = new StringBuffer();
1880: String scheme = getScheme();
1881: int port = getServerPort();
1882: if (port < 0)
1883: port = 80; // Work around java.net.URL bug
1884:
1885: url.append(scheme);
1886: url.append("://");
1887: url.append(getServerName());
1888: if ((scheme.equals("http") && (port != 80))
1889: || (scheme.equals("https") && (port != 443))) {
1890: url.append(':');
1891: url.append(port);
1892: }
1893: url.append(getRequestURI());
1894:
1895: return (url);
1896:
1897: }
1898:
1899: /**
1900: * Return the portion of the request URI used to select the servlet
1901: * that will process this request.
1902: */
1903: public String getServletPath() {
1904: return (mappingData.wrapperPath.toString());
1905: }
1906:
1907: /**
1908: * Get the servlet path.
1909: *
1910: * @return the servlet path
1911: */
1912: public MessageBytes getServletPathMB() {
1913: return (mappingData.wrapperPath);
1914: }
1915:
1916: /**
1917: * Return the session associated with this Request, creating one
1918: * if necessary.
1919: */
1920: public HttpSession getSession() {
1921: Session session = doGetSession(true);
1922: if (session != null) {
1923: return session.getSession();
1924: } else {
1925: return null;
1926: }
1927: }
1928:
1929: /**
1930: * Return the session associated with this Request, creating one
1931: * if necessary and requested.
1932: *
1933: * @param create Create a new session if one does not exist
1934: */
1935: public HttpSession getSession(boolean create) {
1936: Session session = doGetSession(create);
1937: if (session != null) {
1938: return session.getSession();
1939: } else {
1940: return null;
1941: }
1942: }
1943:
1944: /**
1945: * Return <code>true</code> if the session identifier included in this
1946: * request came from a cookie.
1947: */
1948: public boolean isRequestedSessionIdFromCookie() {
1949:
1950: if (requestedSessionId != null)
1951: return (requestedSessionCookie);
1952: else
1953: return (false);
1954:
1955: }
1956:
1957: /**
1958: * Return <code>true</code> if the session identifier included in this
1959: * request came from the request URI.
1960: */
1961: public boolean isRequestedSessionIdFromURL() {
1962:
1963: if (requestedSessionId != null)
1964: return (requestedSessionURL);
1965: else
1966: return (false);
1967:
1968: }
1969:
1970: /**
1971: * Return <code>true</code> if the session identifier included in this
1972: * request came from the request URI.
1973: *
1974: * @deprecated As of Version 2.1 of the Java Servlet API, use
1975: * <code>isRequestedSessionIdFromURL()</code> instead.
1976: */
1977: public boolean isRequestedSessionIdFromUrl() {
1978: return (isRequestedSessionIdFromURL());
1979: }
1980:
1981: /**
1982: * Return <code>true</code> if the session identifier included in this
1983: * request identifies a valid session.
1984: */
1985: public boolean isRequestedSessionIdValid() {
1986:
1987: if (requestedSessionId == null)
1988: return (false);
1989: if (context == null)
1990: return (false);
1991: Manager manager = context.getManager();
1992: if (manager == null)
1993: return (false);
1994: Session session = null;
1995: try {
1996: session = manager.findSession(requestedSessionId);
1997: } catch (IOException e) {
1998: session = null;
1999: }
2000: if ((session != null) && session.isValid())
2001: return (true);
2002: else
2003: return (false);
2004:
2005: }
2006:
2007: /**
2008: * Return <code>true</code> if the authenticated user principal
2009: * possesses the specified role name.
2010: *
2011: * @param role Role name to be validated
2012: */
2013: public boolean isUserInRole(String role) {
2014:
2015: // Have we got an authenticated principal at all?
2016: if (userPrincipal == null)
2017: return (false);
2018:
2019: // Identify the Realm we will use for checking role assignmenets
2020: if (context == null)
2021: return (false);
2022: Realm realm = context.getRealm();
2023: if (realm == null)
2024: return (false);
2025:
2026: // Check for a role alias defined in a <security-role-ref> element
2027: if (wrapper != null) {
2028: String realRole = wrapper.findSecurityReference(role);
2029: if ((realRole != null)
2030: && realm.hasRole(userPrincipal, realRole))
2031: return (true);
2032: }
2033:
2034: // Check for a role defined directly as a <security-role>
2035: return (realm.hasRole(userPrincipal, role));
2036:
2037: }
2038:
2039: /**
2040: * Return the principal that has been authenticated for this Request.
2041: */
2042: public Principal getPrincipal() {
2043: return (userPrincipal);
2044: }
2045:
2046: /**
2047: * Return the principal that has been authenticated for this Request.
2048: */
2049: public Principal getUserPrincipal() {
2050: if (userPrincipal instanceof GenericPrincipal) {
2051: return ((GenericPrincipal) userPrincipal)
2052: .getUserPrincipal();
2053: } else {
2054: return (userPrincipal);
2055: }
2056: }
2057:
2058: /**
2059: * Return the session associated with this Request, creating one
2060: * if necessary.
2061: */
2062: public Session getSessionInternal() {
2063: return doGetSession(true);
2064: }
2065:
2066: /**
2067: * Return the session associated with this Request, creating one
2068: * if necessary and requested.
2069: *
2070: * @param create Create a new session if one does not exist
2071: */
2072: public Session getSessionInternal(boolean create) {
2073: return doGetSession(create);
2074: }
2075:
2076: /**
2077: * Get the event associated with the request.
2078: * @return
2079: */
2080: public CometEventImpl getEvent() {
2081: if (event == null) {
2082: event = new CometEventImpl(this , response);
2083: }
2084: return event;
2085: }
2086:
2087: /**
2088: * Return true if the current request is handling Comet traffic.
2089: */
2090: public boolean isComet() {
2091: return comet;
2092: }
2093:
2094: /**
2095: * Set comet state.
2096: */
2097: public void setComet(boolean comet) {
2098: this .comet = comet;
2099: }
2100:
2101: /**
2102: * Return true if bytes are available.
2103: */
2104: public boolean getAvailable() {
2105: return (inputBuffer.available() > 0);
2106: }
2107:
2108: // ------------------------------------------------------ Protected Methods
2109:
2110: protected Session doGetSession(boolean create) {
2111:
2112: // There cannot be a session if no context has been assigned yet
2113: if (context == null)
2114: return (null);
2115:
2116: // Return the current session if it exists and is valid
2117: if ((session != null) && !session.isValid())
2118: session = null;
2119: if (session != null)
2120: return (session);
2121:
2122: // Return the requested session if it exists and is valid
2123: Manager manager = null;
2124: if (context != null)
2125: manager = context.getManager();
2126: if (manager == null)
2127: return (null); // Sessions are not supported
2128: if (requestedSessionId != null) {
2129: try {
2130: session = manager.findSession(requestedSessionId);
2131: } catch (IOException e) {
2132: session = null;
2133: }
2134: if ((session != null) && !session.isValid())
2135: session = null;
2136: if (session != null) {
2137: session.access();
2138: return (session);
2139: }
2140: }
2141:
2142: // Create a new session if requested and the response is not committed
2143: if (!create)
2144: return (null);
2145: if ((context != null) && (response != null)
2146: && context.getCookies()
2147: && response.getResponse().isCommitted()) {
2148: throw new IllegalStateException(sm
2149: .getString("coyoteRequest.sessionCreateCommitted"));
2150: }
2151:
2152: // Attempt to reuse session id if one was submitted in a cookie
2153: // Do not reuse the session id if it is from a URL, to prevent possible
2154: // phishing attacks
2155: if (connector.getEmptySessionPath()
2156: && isRequestedSessionIdFromCookie()) {
2157: session = manager.createSession(getRequestedSessionId());
2158: } else {
2159: session = manager.createSession(null);
2160: }
2161:
2162: // Creating a new session cookie based on that session
2163: if ((session != null) && (getContext() != null)
2164: && getContext().getCookies()) {
2165: Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME,
2166: session.getIdInternal());
2167: configureSessionCookie(cookie);
2168: response.addCookieInternal(cookie);
2169: }
2170:
2171: if (session != null) {
2172: session.access();
2173: return (session);
2174: } else {
2175: return (null);
2176: }
2177:
2178: }
2179:
2180: /**
2181: * Configures the given JSESSIONID cookie.
2182: *
2183: * @param cookie The JSESSIONID cookie to be configured
2184: */
2185: protected void configureSessionCookie(Cookie cookie) {
2186: cookie.setMaxAge(-1);
2187: String contextPath = null;
2188: if (!connector.getEmptySessionPath() && (getContext() != null)) {
2189: contextPath = getContext().getEncodedPath();
2190: }
2191: if ((contextPath != null) && (contextPath.length() > 0)) {
2192: cookie.setPath(contextPath);
2193: } else {
2194: cookie.setPath("/");
2195: }
2196: if (isSecure()) {
2197: cookie.setSecure(true);
2198: }
2199: }
2200:
2201: /**
2202: * Parse cookies.
2203: */
2204: protected void parseCookies() {
2205:
2206: cookiesParsed = true;
2207:
2208: Cookies serverCookies = coyoteRequest.getCookies();
2209: int count = serverCookies.getCookieCount();
2210: if (count <= 0)
2211: return;
2212:
2213: cookies = new Cookie[count];
2214:
2215: int idx = 0;
2216: for (int i = 0; i < count; i++) {
2217: ServerCookie scookie = serverCookies.getCookie(i);
2218: try {
2219: Cookie cookie = new Cookie(
2220: scookie.getName().toString(), scookie
2221: .getValue().toString());
2222: cookie.setPath(scookie.getPath().toString());
2223: cookie.setVersion(scookie.getVersion());
2224: String domain = scookie.getDomain().toString();
2225: if (domain != null) {
2226: cookie.setDomain(scookie.getDomain().toString());
2227: }
2228: cookies[idx++] = cookie;
2229: } catch (IllegalArgumentException e) {
2230: // Ignore bad cookie
2231: }
2232: }
2233: if (idx < count) {
2234: Cookie[] ncookies = new Cookie[idx];
2235: System.arraycopy(cookies, 0, ncookies, 0, idx);
2236: cookies = ncookies;
2237: }
2238:
2239: }
2240:
2241: /**
2242: * Parse request parameters.
2243: */
2244: protected void parseParameters() {
2245:
2246: parametersParsed = true;
2247:
2248: Parameters parameters = coyoteRequest.getParameters();
2249:
2250: // getCharacterEncoding() may have been overridden to search for
2251: // hidden form field containing request encoding
2252: String enc = getCharacterEncoding();
2253:
2254: boolean useBodyEncodingForURI = connector
2255: .getUseBodyEncodingForURI();
2256: if (enc != null) {
2257: parameters.setEncoding(enc);
2258: if (useBodyEncodingForURI) {
2259: parameters.setQueryStringEncoding(enc);
2260: }
2261: } else {
2262: parameters
2263: .setEncoding(org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
2264: if (useBodyEncodingForURI) {
2265: parameters
2266: .setQueryStringEncoding(org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
2267: }
2268: }
2269:
2270: parameters.handleQueryParameters();
2271:
2272: if (usingInputStream || usingReader)
2273: return;
2274:
2275: if (!getMethod().equalsIgnoreCase("POST"))
2276: return;
2277:
2278: String contentType = getContentType();
2279: if (contentType == null)
2280: contentType = "";
2281: int semicolon = contentType.indexOf(';');
2282: if (semicolon >= 0) {
2283: contentType = contentType.substring(0, semicolon).trim();
2284: } else {
2285: contentType = contentType.trim();
2286: }
2287: if (!("application/x-www-form-urlencoded".equals(contentType)))
2288: return;
2289:
2290: int len = getContentLength();
2291:
2292: if (len > 0) {
2293: int maxPostSize = connector.getMaxPostSize();
2294: if ((maxPostSize > 0) && (len > maxPostSize)) {
2295: if (context.getLogger().isDebugEnabled()) {
2296: context.getLogger().debug("Post too large");
2297: }
2298: return;
2299: }
2300: byte[] formData = null;
2301: if (len < CACHED_POST_LEN) {
2302: if (postData == null)
2303: postData = new byte[CACHED_POST_LEN];
2304: formData = postData;
2305: } else {
2306: formData = new byte[len];
2307: }
2308: try {
2309: if (readPostBody(formData, len) != len) {
2310: return;
2311: }
2312: } catch (IOException e) {
2313: // Client disconnect
2314: if (context.getLogger().isDebugEnabled()) {
2315: context
2316: .getLogger()
2317: .debug(
2318: sm
2319: .getString("coyoteRequest.parseParameters"),
2320: e);
2321: }
2322: }
2323: parameters.processParameters(formData, 0, len);
2324: }
2325:
2326: }
2327:
2328: /**
2329: * Read post body in an array.
2330: */
2331: protected int readPostBody(byte body[], int len) throws IOException {
2332:
2333: int offset = 0;
2334: do {
2335: int inputLen = getStream().read(body, offset, len - offset);
2336: if (inputLen <= 0) {
2337: return offset;
2338: }
2339: offset += inputLen;
2340: } while ((len - offset) > 0);
2341: return len;
2342:
2343: }
2344:
2345: /**
2346: * Parse request locales.
2347: */
2348: protected void parseLocales() {
2349:
2350: localesParsed = true;
2351:
2352: Enumeration values = getHeaders("accept-language");
2353:
2354: while (values.hasMoreElements()) {
2355: String value = values.nextElement().toString();
2356: parseLocalesHeader(value);
2357: }
2358:
2359: }
2360:
2361: /**
2362: * Parse accept-language header value.
2363: */
2364: protected void parseLocalesHeader(String value) {
2365:
2366: // Store the accumulated languages that have been requested in
2367: // a local collection, sorted by the quality value (so we can
2368: // add Locales in descending order). The values will be ArrayLists
2369: // containing the corresponding Locales to be added
2370: TreeMap locales = new TreeMap();
2371:
2372: // Preprocess the value to remove all whitespace
2373: int white = value.indexOf(' ');
2374: if (white < 0)
2375: white = value.indexOf('\t');
2376: if (white >= 0) {
2377: StringBuffer sb = new StringBuffer();
2378: int len = value.length();
2379: for (int i = 0; i < len; i++) {
2380: char ch = value.charAt(i);
2381: if ((ch != ' ') && (ch != '\t'))
2382: sb.append(ch);
2383: }
2384: value = sb.toString();
2385: }
2386:
2387: // Process each comma-delimited language specification
2388: parser.setString(value); // ASSERT: parser is available to us
2389: int length = parser.getLength();
2390: while (true) {
2391:
2392: // Extract the next comma-delimited entry
2393: int start = parser.getIndex();
2394: if (start >= length)
2395: break;
2396: int end = parser.findChar(',');
2397: String entry = parser.extract(start, end).trim();
2398: parser.advance(); // For the following entry
2399:
2400: // Extract the quality factor for this entry
2401: double quality = 1.0;
2402: int semi = entry.indexOf(";q=");
2403: if (semi >= 0) {
2404: try {
2405: quality = Double.parseDouble(entry
2406: .substring(semi + 3));
2407: } catch (NumberFormatException e) {
2408: quality = 0.0;
2409: }
2410: entry = entry.substring(0, semi);
2411: }
2412:
2413: // Skip entries we are not going to keep track of
2414: if (quality < 0.00005)
2415: continue; // Zero (or effectively zero) quality factors
2416: if ("*".equals(entry))
2417: continue; // FIXME - "*" entries are not handled
2418:
2419: // Extract the language and country for this entry
2420: String language = null;
2421: String country = null;
2422: String variant = null;
2423: int dash = entry.indexOf('-');
2424: if (dash < 0) {
2425: language = entry;
2426: country = "";
2427: variant = "";
2428: } else {
2429: language = entry.substring(0, dash);
2430: country = entry.substring(dash + 1);
2431: int vDash = country.indexOf('-');
2432: if (vDash > 0) {
2433: String cTemp = country.substring(0, vDash);
2434: variant = country.substring(vDash + 1);
2435: country = cTemp;
2436: } else {
2437: variant = "";
2438: }
2439: }
2440: if (!isAlpha(language) || !isAlpha(country)
2441: || !isAlpha(variant)) {
2442: continue;
2443: }
2444:
2445: // Add a new Locale to the list of Locales for this quality level
2446: Locale locale = new Locale(language, country, variant);
2447: Double key = new Double(-quality); // Reverse the order
2448: ArrayList values = (ArrayList) locales.get(key);
2449: if (values == null) {
2450: values = new ArrayList();
2451: locales.put(key, values);
2452: }
2453: values.add(locale);
2454:
2455: }
2456:
2457: // Process the quality values in highest->lowest order (due to
2458: // negating the Double value when creating the key)
2459: Iterator keys = locales.keySet().iterator();
2460: while (keys.hasNext()) {
2461: Double key = (Double) keys.next();
2462: ArrayList list = (ArrayList) locales.get(key);
2463: Iterator values = list.iterator();
2464: while (values.hasNext()) {
2465: Locale locale = (Locale) values.next();
2466: addLocale(locale);
2467: }
2468: }
2469:
2470: }
2471:
2472: protected static final boolean isAlpha(String value) {
2473: for (int i = 0; i < value.length(); i++) {
2474: char c = value.charAt(i);
2475: if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) {
2476: return false;
2477: }
2478: }
2479: return true;
2480: }
2481:
2482: }
|