/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.esl.servlet.http; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; public class HttpServletRequestWrapper extends javax.servlet.http.HttpServletRequestWrapper { // private HttpServletRequestWrapper request; private String servletPath; /** * A local set with values which overrides the parameters in the <code>HttpServletRequest</code> that is wrapped. Whether the * <code>HttpServletRequest</code> values are just overwritten or completely ignored, depends on the setting in the <code>inherit</code> * value. */ private final Map<String, String[]> queryParams; /** * Determines if the request parameters are taken into account when looking for a parameter. If this value is <code>true</code>, and no * parameter value can be found in the wrapper, the request object is searched for the same parameter. If this value is * <code>false</code>, then the request object is ignored completely as far as parameters are concerned, but is still used for all other * methods. */ private boolean inherit = false; // simulated variables //private String contextPath; ex: /vertical //private String queryString; ex: foo=bar&x=y //private String requestURI; ex: /vertical/page //private String requestURL; ex: http://somehost.com/vertical/page public HttpServletRequestWrapper( HttpServletRequest request ) { this( request, null ); } public HttpServletRequestWrapper( HttpServletRequest request, Map<String, String[]> params ) { this( request, params, false ); } private HttpServletRequestWrapper( HttpServletRequest request, Map<String, String[]> params, boolean i ) { super( request ); queryParams = new HashMap<String, String[]>(); inherit = i; if ( params != null ) { Iterator<Map.Entry<String, String[]>> itr = params.entrySet().iterator(); while ( itr.hasNext() ) { Map.Entry<String, String[]> entry = itr.next(); queryParams.put( entry.getKey(), makeStringArray( entry.getValue() ) ); } } // If this wrapper wraps and already wrapped request, replace the old wrapper, to avoid extra layers: if ( inherit && ( request instanceof HttpServletRequestWrapper ) ) { HttpServletRequestWrapper dynamicReq = (HttpServletRequestWrapper) request; Map<String, String[]> reqParams = dynamicReq.getWrapperParameterMap(); if ( reqParams != null ) { Iterator<Map.Entry<String, String[]>> itr = reqParams.entrySet().iterator(); while ( itr.hasNext() ) { Map.Entry<String, String[]> entry = itr.next(); String name = entry.getKey(); String[] oldValues = entry.getValue(); String[] curValues = queryParams.get( name ); if ( curValues == null ) { queryParams.put( name, oldValues ); } else { String[] newValues = new String[oldValues.length + curValues.length]; System.arraycopy( oldValues, 0, newValues, 0, oldValues.length ); System.arraycopy( curValues, 0, newValues, oldValues.length, curValues.length ); queryParams.put( name, newValues ); } } } // After pulling out all the parameters of the wrapper object, it can be discarded, so we don't have a wrapper around a wrapper. setRequest( dynamicReq.getRequest() ); } } private static String[] makeStringArray( Object value ) { if ( value == null ) { // Don't really know when this occurs, but it has occured on Enonic and Helsebiblioteket return new String[0]; } else if ( value instanceof String[] ) { return (String[]) value; } else { return new String[]{value.toString()}; } } /** * @return A map of all parameters stored locally in this wrapper. */ public Map<String, String[]> getWrapperParameterMap() { return queryParams; } /** * A provided method with this wrapper implementation, allowing the user set a parameter. * <p/> * If the request already contains a value with the same name, it is kept, although it will no longer be visible. However if the * wrapper contains a value with the same name, this new value will override the existing one. * * @param name Parameter name. * @param value Parameter value. */ public void setParameter( String name, String value ) { queryParams.put( name, new String[]{value} ); } /** * A provided method with this wrapper implementation, allowing the user to set multiple parameter values. * <p/> * If the request already contains a value with the same name, it is kept, although it will no longer be visible. However if the * wrapper contains a value with the same name, these new values will override the existing one. * * @param name Parameter name. * @param values Parameter values. */ public void setParameterValues( String name, String[] values ) { queryParams.put( name, values ); } public Enumeration<String> getParameterNames() { Set<String> names = new HashSet<String>(); if ( inherit ) { Enumeration<?> enumer = super.getParameterNames(); while ( enumer.hasMoreElements() ) { names.add( enumer.nextElement().toString() ); } } names.addAll( queryParams.keySet() ); return Collections.enumeration( names ); } public String[] getParameterValues( String name ) { String[] values = queryParams.get( name ); if ( inherit && ( values == null ) ) { return super.getParameterValues( name ); } return values; } /** * Creates and returns a new <code>Map</code> with all the valid parameters. These may or may not include the values in the * <code>request</code>, depending on the setting of the <code>inherit</code> parameter on this class. */ public Map<String, String[]> getParameterMap() { String s; Map<String, String[]> map = new HashMap<String, String[]>(); Enumeration<String> enumer = getParameterNames(); // No need to check the inherit parameter, since the getParameterNames() and getParameterValues() methods do it. while ( enumer.hasMoreElements() ) { s = enumer.nextElement(); map.put( s, getParameterValues( s ) ); } return map; } /** * Returns the value of the parameter as a <code>String</code>, or <code>null</code> if the parameter does not exist. Depending on the * <code>inherit</code> setting for this instance, the parameter will be searched for only in the wrapper, or also in the wrapped * request. * <p/> * If the parameter has multiple values, it will return one of the values at random, so you should only use this method when you are * sure the parameter has only one value. */ public String getParameter( String name ) { String[] values = queryParams.get( name ); if ( inherit && ( values == null ) ) { return super.getParameter( name ); } if ( ( values != null ) && ( values.length > 0 ) ) { return values[0]; } else { return null; } } public String getQueryString() { StringBuffer queryString = new StringBuffer(); Enumeration<String> keys = getParameterNames(); for ( boolean appendAmp = false; keys.hasMoreElements(); appendAmp = true ) { String key = keys.nextElement(); String[] values = getParameterValues( key ); if ( values.length > 1 ) { for ( int cnt = 0; cnt < values.length; cnt++, appendAmp = true ) { if ( appendAmp ) { queryString.append( '&' ); } queryString.append( key ); queryString.append( '=' ); queryString.append( values[cnt] ); } } else { if ( appendAmp ) { queryString.append( '&' ); } queryString.append( key ); queryString.append( '=' ); queryString.append( getParameter( key ) ); } } return queryString.toString(); } public String getRequestURI() { String requestURI; if ( servletPath != null ) { if ( servletPath.length() == 0 || servletPath.charAt( 0 ) != '/' ) { requestURI = getContextPath() + '/' + servletPath; } else { requestURI = getContextPath() + servletPath; } } else { // requestURI = request.getRequestURI(); requestURI = super.getRequestURI(); } return requestURI; } public StringBuffer getRequestURL() { StringBuffer requestURL = new StringBuffer( "http" ); if ( super.isSecure() ) { // if (request.isSecure()) { requestURL.append( "s://" ); } else { requestURL.append( "://" ); } // requestURL.append(request.getServerName()); // int origServerPort = request.getServerPort(); requestURL.append( super.getServerName() ); int origServerPort = super.getServerPort(); if ( origServerPort != 80 ) { requestURL.append( ':' ); requestURL.append( origServerPort ); } requestURL.append( getRequestURI() ); return requestURL; } public String getServletPath() { if ( servletPath != null ) { if ( servletPath.length() > 0 && servletPath.charAt( 0 ) == '/' ) { return servletPath; } else { return '/' + servletPath; } } else { return super.getServletPath(); } } /** * @param string */ public void setServletPath( String string ) { servletPath = string; } /** * @return * @deprecated This method is provided for backwards compatibility. The old <code>paramsMasked</code> parameter is the exact opposite * of the new <code>inherit</code> parameter, so calls to this method should be replace by <code>isInherit()</code>, * negating the result. */ public boolean isParamsMasked() { return !inherit; } /** * This method * * @param b * @deprecated This method is provided for backwards compatibility. The old <code>paramsMasked</code> parameter is the exact opposite * of the new <code>inherit</code> parameter, so calls to this method should be replaced by calls to * <code>setInherit()</code>, with the parameter negated. */ public void setParamsMasked( boolean b ) { inherit = !b; } public boolean isInherit() { return inherit; } /** * Defines whether the parameters in the request is included in the result set, when working with parameters. * * @param b <code>true</code>, includes the parameters from the request, <code>false</code> does not. * @deprecated This method should not be used. The parameter should only be set in the constructor, and not be changed after that. */ public void setInherit( boolean b ) { inherit = b; } // /** // * @see javax.servlet.ServletRequestWrapper#getRequest() // */ // public ServletRequest getRequest() { // return this.request; // } // // /** // * @see javax.servlet.ServletRequestWrapper#setRequest(javax.servlet.ServletRequest) // */ // public void setRequest(HttpServletRequestWrapper req) { // request = req; // } }