All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.meterware.servletunit.ServletUnitHttpRequest Maven / Gradle / Ivy

The newest version!
package com.meterware.servletunit;
/********************************************************************************************************************
* $Id$
*
* Copyright (c) 2000-2008, Russell Gold
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
*******************************************************************************************************************/
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebClient;
import com.meterware.httpunit.Base64;
import com.meterware.httpunit.HttpUnitUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import javax.servlet.ServletInputStream;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;


/**
 * This class represents a servlet request created from a WebRequest.
 **/
class ServletUnitHttpRequest implements HttpServletRequest {

    private ServletInputStreamImpl _inputStream;
    // TODO remove when test case for [ 1509117 ] getContentType()
    // gets available
    private String                 _contentType;
    private Vector                 _locales;
    private String                 _protocol;
    private boolean                _secure;
    private RequestContext         _requestContext;
    private String                 _charset;
    private boolean                _gotReader;
    private boolean                _gotInputStream;
    private BufferedReader         _reader;
    private int 		           _serverPort;
    private String		           _serverName;   


    /**
     * Constructs a ServletUnitHttpRequest from a WebRequest object.
     **/
    ServletUnitHttpRequest( ServletMetaData servletRequest, WebRequest request, ServletUnitContext context, Dictionary clientHeaders, byte[] messageBody ) throws MalformedURLException {
        if (context == null) throw new IllegalArgumentException( "Context must not be null" );

        _servletRequest = servletRequest;
        _request = request;
        _context = context;
        _headers = new WebClient.HeaderDictionary();
        _headers.addEntries( clientHeaders );
        _headers.addEntries( request.getHeaders() );
        setCookiesFromHeader( _headers );
        _messageBody = messageBody;
        _protocol=request.getURL().getProtocol().toLowerCase();
        _secure = _protocol.endsWith("s" );
        _serverName = request.getURL().getHost();
        _serverPort = request.getURL().getPort();
        if ( _serverPort == -1 ) {
            _serverPort = request.getURL().getDefaultPort();
        }

        _requestContext = new RequestContext( request.getURL() );
        String contentTypeHeader = (String) _headers.get( "Content-Type" );
        if (contentTypeHeader != null) {
            String[] res = HttpUnitUtils.parseContentTypeHeader( contentTypeHeader );
            _contentType = res[0];
            _charset     = res[1];
            _requestContext.setMessageEncoding( _charset );
        }
        if (_headers.get( "Content-Length") == null) _headers.put( "Content-Length", Integer.toString( messageBody.length ) );

        boolean setBody=
        // pre [ 1509117 ] getContentType()
        // _messageBody != null && (_contentType == null || _contentType.indexOf( "x-www-form-urlencoded" ) >= 0 );
        // patch version:
        	_messageBody != null && (contentTypeHeader == null ||	contentTypeHeader.indexOf( "x-www-form-urlencoded" ) >= 0 );
        if (setBody) {
            _requestContext.setMessageBody( _messageBody );
        }
    }


//----------------------------------------- HttpServletRequest methods --------------------------


    /**
     * Returns the name of the authentication scheme used to protect the servlet, for example, "BASIC" or "SSL,"
     * or null if the servlet was not protected.
     **/
    public String getAuthType() {
        return null;
    }


    /**
     * Returns the query string that is contained in the request URL after the path.
     **/
    public String getQueryString() {
        return _request.getQueryString();
    }


    /**
     * Returns an array containing all of the Cookie objects the client sent with this request.
     * This method returns null if no cookies were sent.
     **/
    public Cookie[] getCookies() {
        if (_cookies.size() == 0) {
            return null;
        } else {
            Cookie[] result = new Cookie[ _cookies.size() ];
            _cookies.copyInto( result );
            return result;
        }
    }


    /**
     * Returns the value of the specified request header as an int. If the request does not have a header
     * of the specified name, this method returns -1. If the header cannot be converted to an integer,
     * this method throws a NumberFormatException.
     **/
    public int getIntHeader( String name ) {
        return Integer.parseInt( getHeader( name ) );
    }


    /**
     * Returns the value of the specified request header as a long value that represents a Date object.
     * Use this method with headers that contain dates, such as If-Modified-Since.
     * 
* The date is returned as the number of milliseconds since January 1, 1970 GMT. The header name is case insensitive. * * If the request did not have a header of the specified name, this method returns -1. * If the header can't be converted to a date, the method throws an IllegalArgumentException. **/ public long getDateHeader( String name ) { try { String dateString=getHeader(name); Date headerDate=new Date(dateString); return headerDate.getTime(); } catch (Exception e) { return -1; } } /** * Returns the value of the specified request header as a String. If the request did not include * a header of the specified name, this method returns null. The header name is case insensitive. * You can use this method with any request header. **/ public String getHeader( String name ) { return (String) _headers.get( name ); } /** * Returns an enumeration of all the header names this request contains. If the request has no headers, * this method returns an empty enumeration. * * Some servlet containers do not allow do not allow servlets to access headers using this method, * in which case this method returns null. **/ public Enumeration getHeaderNames() { return _headers.keys(); } /** * Returns the part of this request's URL that calls the servlet. This includes either the servlet name * or a path to the servlet, but does not include any extra path information or a query string. **/ public String getServletPath() { return _servletRequest.getServletPath(); } /** * Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT. **/ public String getMethod() { return _request.getMethod(); } /** * Returns any extra path information associated with the URL the client sent when it made this request. * The extra path information follows the servlet path but precedes the query string. * This method returns null if there was no extra path information. **/ public String getPathInfo() { return _servletRequest.getPathInfo(); } /** * Returns any extra path information after the servlet name but before the query string, * and translates it to a real path. If the URL does not have any extra path information, this method returns null. **/ public String getPathTranslated() { return null; } /** * Checks whether the requested session ID came in as a cookie. **/ public boolean isRequestedSessionIdFromCookie() { return _sessionID != null; } /** * Returns the login of the user making this request, if the user has been authenticated, * or null if the user has not been authenticated. * Whether the user name is sent with each subsequent request depends on the browser and type of authentication. **/ public String getRemoteUser() { return _userName; } /** * Returns the session ID specified by the client. This may not be the same as the ID of the actual session in use. * For example, if the request specified an old (expired) session ID and the server has started a new session, * this method gets a new session with a new ID. If the request did not specify a session ID, this method returns null. **/ public String getRequestedSessionId() { return _sessionID; } /** * Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request. **/ public String getRequestURI() { return _requestContext.getRequestURI(); } /** * Returns the current HttpSession associated with this request or, if there is no current session * and create is true, returns a new session. *
* If create is false and the request has no valid HttpSession, this method returns null. **/ public HttpSession getSession( boolean create ) { _session = _context.getValidSession( getRequestedSessionId(), _session, create ); return _session; } /** * Returns the current session associated with this request, or if the request does not have a session, creates one. **/ public HttpSession getSession() { return getSession( true ); } /** * Checks whether the requested session ID is still valid. **/ public boolean isRequestedSessionIdValid() { return false; } /** * Checks whether the requested session ID came in as part of the request URL. **/ public boolean isRequestedSessionIdFromURL() { return false; } /** * @deprecated use #isRequestedSessionIdFromURL **/ public boolean isRequestedSessionIdFromUrl() { return isRequestedSessionIdFromURL(); } //--------------------------------- ServletRequest methods ---------------------------------------------------- /** * Returns the length, in bytes, of the content contained in the * request and sent by way of the input stream or -1 if the * length is not known. **/ public int getContentLength() { return getIntHeader( "Content-length" ); } /** * * Returns the value of the named attribute as an Object. * This method allows the servlet engine to give the servlet * custom information about a request. This method returns * null if no attribute of the given name exists. **/ public Object getAttribute( String name ) { return _attributes.get( name ); } /** * Returns an Enumeration containing the * names of the attributes available to this request. * This method returns an empty Enumeration * if the request has no attributes available to it. **/ public Enumeration getAttributeNames() { return _attributes.keys(); } /** * Retrieves binary data from the body of the request as * a {@link ServletInputStream}, which * gives you the ability to read one line at a time. * * @return a {@link ServletInputStream} object containing * the body of the request * * @exception IllegalStateException if the {@link #getReader} method * has already been called for this request * * @exception IOException if an input or output exception occurred * */ public ServletInputStream getInputStream() throws IOException { if (_gotReader) { throw new IllegalStateException("getReader() has already been called for this request"); } initializeInputStream(); _gotInputStream = true; return _inputStream; } /** * initialize the inputStream */ private void initializeInputStream() { if (_inputStream == null) { _inputStream = new ServletInputStreamImpl( _messageBody ); } } /** * Returns the name of the character encoding style used in this * request. This method returns null if the request * does not use character encoding. **/ public String getCharacterEncoding() { return _charset; } /** * * Returns an Enumeration of String * objects containing the names of the parameters contained * in this request. If the request has * no parameters or if the input stream is empty, returns an * empty Enumeration. The input stream is empty * when all the data returned by {@link #getInputStream} has * been read. **/ public Enumeration getParameterNames() { return _requestContext.getParameterNames(); } /** * Returns the MIME type of the content of the request, or * null if the type is not known. Same as the value * of the CGI variable CONTENT_TYPE. **/ public String getContentType() { String result; result=_contentType; /** * suggested fix by bug report * [ 1509117 ] getContentType() * by Tom Parker */ result=this.getHeader( "Content-Type" ); return result; } /** * Returns the value of a request parameter as a String, * or null if the parameter does not exist. Request parameters * are extra information sent with the request. **/ public String getParameter( String name ) { String[] parameters = getParameterValues( name ); return parameters == null ? null : parameters[0]; } /** * Returns an array of String objects containing * all of the values the * given request parameter has, or null if the * parameter does not exist. For example, in an HTTP servlet, * this method returns an array of String objects * containing the values of a query string or posted form. **/ public String[] getParameterValues( String name ) { return _requestContext.getParameterValues( name ); } /** * Returns the name and version of the protocol the request uses * in the form protocol/majorVersion.minorVersion, for * example, HTTP/1.1. **/ public String getProtocol() { return "HTTP/1.1"; } /** * Returns the name of the scheme used to make this request, * for example, * http, https, or ftp. * Different schemes have different rules for constructing URLs, * as noted in RFC 1738. **/ public String getScheme() { String result= isSecure() ? "https" : "http"; result=_protocol; return result; } /** * Returns the fully qualified name of the client that sent the * request. **/ public String getRemoteHost() { return "localhost"; } /** * Returns the host name of the server that received the request. **/ public String getServerName() { return _serverName; } /** * Returns the port number on which this request was received. **/ public int getServerPort() { return _serverPort; } /** * * @deprecated As of Version 2.1 of the Java Servlet API, * use {@link javax.servlet.ServletContext#getRealPath} instead. * */ public String getRealPath( String path ) { throwNotImplementedYet(); return ""; } /** * Returns the body of the request as a BufferedReader * that translates character set encodings. * @since [ 1221537 ] Patch: ServletUnitHttpRequest.getReader not implemented yet * @author Tim - timmorrow (SourceForge) * @return the reader **/ public BufferedReader getReader() throws IOException { if (_gotInputStream) { throw new IllegalStateException("getInputStream() has already been called on this request"); } if (_reader == null) { initializeInputStream(); String encoding = getCharacterEncoding(); if (encoding == null) { encoding = HttpUnitUtils.DEFAULT_CHARACTER_SET; } _reader = new BufferedReader(new InputStreamReader(_inputStream, encoding)); _gotReader = true; } return _reader; } /** * Returns the Internet Protocol (IP) address of the client * that sent the request. **/ public String getRemoteAddr() { return LOOPBACK_ADDRESS; } /** * * Stores an attribute in the context of this request. * Attributes are reset between requests. **/ public void setAttribute( String key, Object o ) { if (o == null) _attributes.remove( key ); else _attributes.put( key, o ); } //--------------------------------- methods added to ServletRequest in Servlet API 2.2 ------------------------------------------------ /** * Returns a boolean indicating whether this request was made using a secure channel, such as HTTPS. **/ public boolean isSecure() { return _secure; } /** * Returns the preferred Locale that the client will accept content in, based on the Accept-Language header. * If the client request doesn't provide an Accept-Language header, this method returns the default locale for the server. **/ public Locale getLocale() { return (Locale) getPreferredLocales().firstElement(); } /** * Returns an Enumeration of Locale objects indicating, in decreasing order starting with the preferred locale, * the locales that are acceptable to the client based on the Accept-Language header. * If the client request doesn't provide an Accept-Language header, this * method returns an Enumeration containing one Locale, the default locale for the server. **/ public java.util.Enumeration getLocales() { return getPreferredLocales().elements(); } /** * Parses the accept-language header to obtain a vector of preferred locales * @return the preferred locales, sorted by qvalue */ private Vector getPreferredLocales() { if (_locales == null) { _locales = new Vector(); String languages = getHeader( "accept-language" ); if (languages == null) { _locales.add( Locale.getDefault() ); } else { StringTokenizer st = new StringTokenizer( languages, "," ); ArrayList al = new ArrayList(); while (st.hasMoreTokens()) { String token = st.nextToken(); al.add( new PrioritizedLocale( token ) ); } Collections.sort( al ); for (Iterator iterator = al.iterator(); iterator.hasNext();) { _locales.add( ((PrioritizedLocale) iterator.next()).getLocale() ); } } } return _locales; } /** * Removes an attribute from this request. This method is not generally needed * as attributes only persist as long as the request is being handled. **/ public void removeAttribute( String name ) { _attributes.remove( name ); } /** * Returns a RequestDispatcher object that acts as a wrapper for the resource located at the given path. * A RequestDispatcher object can be used to forward a request to the resource or to include the * resource in a response. The resource can be dynamic or static. * * The pathname specified may be relative, although it cannot extend outside the current servlet * context. If the path begins with a "/" it is interpreted as relative to the current context root. * This method returns null if the servlet container cannot return a RequestDispatcher. * * The difference between this method and ServletContext.getRequestDispatcher(java.lang.String) * is that this method can take a relative path. **/ public RequestDispatcher getRequestDispatcher( String path ) { try { if (!path.startsWith( "/" )) path = combinedPath( getServletPath(), path ); return _servletRequest.getServlet().getServletConfig().getServletContext().getRequestDispatcher( path ); } catch (ServletException e) { return null; } } private String combinedPath( String basePath, String relativePath ) { if (basePath.indexOf( '/' ) < 0) return relativePath; return basePath.substring( 0, basePath.lastIndexOf( '/' ) ) + '/' + relativePath; } //--------------------------------- methods added to HttpServletRequest in Servlet API 2.2 ------------------------------------------------ /** * Returns a java.security.Principal object containing the name of the current authenticated user. * If the user has not been authenticated, the method returns null. **/ public java.security.Principal getUserPrincipal() { return null; } /** * Returns a boolean indicating whether the authenticated user is included in the specified * logical "role". Roles and role membership can be defined using deployment descriptors. * If the user has not been authenticated, the method returns false. **/ public boolean isUserInRole( String role ) { if (_roles == null) return false; for (int i = 0; i < _roles.length; i++) { if (role.equals( _roles[i] )) return true; } return false; } /** * Returns all the values of the specified request header as an Enumeration of String objects. **/ public java.util.Enumeration getHeaders( String name ) { Vector list = new Vector(); if (_headers.containsKey( name )) list.add( _headers.get( name )); return list.elements(); } /** * Returns the portion of the request URI that indicates the context of the request. * The context path always comes first in a request URI. The path starts with a "/" character * but does not end with a "/" character. For servlets in the default (root) context, * this method returns "". **/ public String getContextPath() { return _context.getContextPath(); } //--------------------------------------- methods added to ServletRequest in Servlet API 2.3 ---------------------------- /** * Returns a java.util.Map of the parameters of this request. * Request parameters are extra information sent with the request. For HTTP servlets, parameters are contained * in the query string or posted form data. * * @since 1.3 **/ public Map getParameterMap() { return _requestContext.getParameterMap(); } /** * Overrides the name of the character encoding used in the body of this request. * This method must be called prior to reading request parameters or reading input using getReader(). * * @since 1.3 **/ public void setCharacterEncoding( String charset ) throws UnsupportedEncodingException { _charset = charset; _requestContext.setMessageEncoding( charset ); } //--------------------------------------- methods added to HttpServletRequest in Servlet API 2.3 ---------------------------- /** * Reconstructs the URL the client used to make the request. * The returned URL contains a protocol, server name, port number, and server path, but * it does not include query string parameters. * * Because this method returns a StringBuffer, not a string, you can modify the URL easily, for example, * to append query parameters. * * This method is useful for creating redirect messages and for reporting errors. * * @since 1.3 */ public StringBuffer getRequestURL() { StringBuffer url = new StringBuffer(); try { url.append( _request.getURL().getProtocol() ).append( "://" ); url.append( _request.getURL().getHost() ); String portPortion = _request.getURL().getPort() == -1 ? "" : (":" + _request.getURL().getPort()); url.append(portPortion); url.append( _request.getURL().getPath() ); } catch (MalformedURLException e) { throw new RuntimeException( "unable to read URL from request: " + _request ); } return url; } //--------------------------------------- methods added to ServletRequest in Servlet API 2.4 ---------------------------- public int getRemotePort() { return 0; //To change body of implemented methods use File | Settings | File Templates. } public String getLocalName() { return "localhost"; } public String getLocalAddr() { return "127.0.0.1"; } public int getLocalPort() { return 0; //To change body of implemented methods use File | Settings | File Templates. } //--------------------------------------------- package members ---------------------------------------------- private void addCookie( Cookie cookie ) { _cookies.addElement( cookie ); if (cookie.getName().equalsIgnoreCase( ServletUnitHttpSession.SESSION_COOKIE_NAME )) { _sessionID = cookie.getValue(); } } private ServletUnitHttpSession getServletSession() { return (ServletUnitHttpSession) getSession(); } void readFormAuthentication() { if (getSession( /* create */ false ) != null) { recordAuthenticationInfo( getServletSession().getUserName(), getServletSession().getRoles() ); } } void readBasicAuthentication() { String authorizationHeader = (String) _headers.get( "Authorization" ); if (authorizationHeader != null) { String userAndPassword = Base64.decode( authorizationHeader.substring( authorizationHeader.indexOf( ' ' ) + 1 ) ); int colonPos = userAndPassword.indexOf( ':' ); recordAuthenticationInfo( userAndPassword.substring( 0, colonPos ), toArray( userAndPassword.substring( colonPos+1 ) ) ); } } static String[] toArray( String roleList ) { StringTokenizer st = new StringTokenizer( roleList, "," ); String[] result = new String[ st.countTokens() ]; for (int i = 0; i < result.length; i++) { result[i] = st.nextToken(); } return result; } void recordAuthenticationInfo( String userName, String[] roles ) { _userName = userName; _roles = roles; } //--------------------------------------------- private members ---------------------------------------------- final static private String LOOPBACK_ADDRESS = "127.0.0.1"; private WebRequest _request; private ServletMetaData _servletRequest; private WebClient.HeaderDictionary _headers; private ServletUnitContext _context; private ServletUnitHttpSession _session; private Hashtable _attributes = new Hashtable(); private Vector _cookies = new Vector(); private String _sessionID; private byte[] _messageBody; private String _userName; private String[] _roles; private void throwNotImplementedYet() { throw new RuntimeException( "Not implemented yet" ); } private void setCookiesFromHeader( Dictionary clientHeaders ) { String cookieHeader = (String) clientHeaders.get( "Cookie" ); if (cookieHeader == null) return; StringTokenizer st = new StringTokenizer( cookieHeader, ",;=", true ); String lastToken = st.nextToken(); while (st.hasMoreTokens()) { String token = st.nextToken(); if (token.equals( "=" )) { if (st.hasMoreTokens()) addCookie( new Cookie( lastToken.trim(), st.nextToken().trim() ) ); } lastToken = token; } } static class PrioritizedLocale implements Comparable { private Locale _locale; private float _priority; PrioritizedLocale( String languageSpec ) { int semiIndex = languageSpec.indexOf( ';' ); if (semiIndex < 0) { _priority = 1; _locale = parseLocale( languageSpec ); } else { _priority = Float.parseFloat( languageSpec.substring( languageSpec.indexOf( '=', semiIndex )+1 ) ); _locale = parseLocale( languageSpec.substring( 0, semiIndex ) ); } } private Locale parseLocale( String range ) { range = range.trim(); int dashIndex = range.indexOf( '-' ); if (dashIndex < 0) { return new Locale( range, "" ); } else { return new Locale( range.substring( 0, dashIndex ), range.substring( dashIndex+1 ) ); } } public Locale getLocale() { return _locale; } public int compareTo( Object o ) { if (!(o instanceof PrioritizedLocale)) throw new IllegalArgumentException( "may only combine with other prioritized locales" ); PrioritizedLocale other = (PrioritizedLocale) o; return _priority == other._priority ? _locale.getLanguage().compareTo( other._locale.getLanguage() ) : (_priority < other._priority ? +1 : -1 ); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy