001package votorola.g.web; // Copyright 2011-2013, Michael Allan.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Votorola Software"), to deal in the Votorola Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Votorola Software, and to permit persons to whom the Votorola Software is furnished to do so, subject to the following conditions: The preceding copyright notice and this permission notice shall be included in all copies or substantial portions of the Votorola Software. THE VOTOROLA 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 VOTOROLA SOFTWARE OR THE USE OR OTHER DEALINGS IN THE VOTOROLA SOFTWARE.
002
003import java.net.*;
004import java.util.*;
005import javax.servlet.*;
006import javax.servlet.http.*;
007import votorola.g.lang.*;
008
009
010/** Servlet request utilities.
011  *
012  *     @see HttpServletRequest
013  */
014public @ThreadSafe final class HTTPServletRequestX
015{
016
017
018    private HTTPServletRequestX() {}
019
020
021
022    /** Constructs a standard log message summarizing the request, and returns it in a
023      * string builder.
024      */
025    public static StringBuilder buildRequestSummary( final HttpServletRequest reqHS )
026    {
027        final StringBuilder b = getRequestURLFull( reqHS );
028        b.insert( 0, ": " );
029        b.insert( 0, reqHS.getRemoteAddr() );
030        b.insert( 0, "Request from " );
031        return b;
032    }
033
034
035
036    /** Returns the boolean value of a request parameter, where true is encoded as a 'Y',
037      * 'y' or empty value '', and false as an 'N', 'n' or omitted value (null).
038      *
039      *   @throws HTTPRequestException if the value is present and malformed.
040      */
041    public static boolean getBooleanParameter( final String key, final ServletRequest reqS )
042      throws HTTPRequestException
043    {
044        final String value = reqS.getParameter( key );
045        if( value == null || "N".equals(value) || "n".equals(value) ) return false;
046
047        if( "".equals(value) || "Y".equals(value) || "y".equals(value) ) return true;
048
049        throw new HTTPRequestException( HttpServletResponse.SC_BAD_REQUEST, // 400
050          "Unrecognized '" + key + "' value: " + value );
051    }
052
053
054
055    /** Returns the apparent address of the remote client after taking into account any
056      * proxying declared in the <code>x-forwarded-for</code> header.  No attempt is made
057      * to authenticate the proxying declaration, which may easily be bogus.  Therefore do
058      * not depend on the returned value being correct, or even well formed.
059      */
060    public static String getForwardedRemoteAddr( final HttpServletRequest reqHS )
061    {
062        // http://johannburkard.de/blog/programming/java/x-forwarded-for-http-header.html
063        String a = reqHS.getHeader( "X-Forwarded-For" );
064        if( a == null ) a = reqHS.getRemoteAddr();
065        else
066        {
067            final int c = a.indexOf( ',' );
068            if( c >= 0 ) a = a.substring( 0, c ); // first address in list is most remote
069        }
070        return a;
071    }
072
073
074
075 // /** Returns the value of a request parameter, or a default value if the parameter is
076 //   * not specified.
077 //   *
078 //   *   @param defaultValue the value to return in the event the parameter is not
079 //   *     specified.
080 //   *
081 //   *   @throws HTTPRequestException if the actual value is the empty string "".
082 //   */
083 // public static String getParameter( final String key, final String defaultValue,
084 //   final ServletRequest reqS ) throws HTTPRequestException
085 // {
086 //     String value = getParameterNonEmpty( key, reqS );
087 //     if( value == null ) value = defaultValue;
088 //     return value;
089 // }
090
091
092
093    /** Returns the non-empty value of a request parameter, or null if the parameter is
094      * not specified.
095      *
096      *   @throws HTTPRequestException if the value is the empty string "".
097      *
098      *   @see votorola.a.web.wic.VPage#stringNonEmpty(org.apache.wicket.request.mapper.parameter.PageParameters,String)
099      *   @see votorola.g.web.wic.PageParametersX#getStringNonEmpty(org.apache.wicket.request.mapper.parameter.PageParameters,String)
100      */
101    public static String getParameterNonEmpty( final String key, final ServletRequest reqS )
102      throws HTTPRequestException
103    {
104        final String value = reqS.getParameter( key );
105        if( !"".equals( value )) return value;
106
107        throw new HTTPRequestException( HttpServletResponse.SC_BAD_REQUEST, // 400
108          "Empty request parameter '" + key + "'" );
109    }
110
111
112
113    /** Returns the non-null, non-empty value of a request parameter.
114      *
115      *   @throws HTTPRequestException if the value is either null or the empty string "".
116      *
117      *   @see votorola.a.web.wic.VPage#stringRequired(org.apache.wicket.request.mapper.parameter.PageParameters,String)
118      *   @see votorola.g.web.wic.PageParametersX#getStringRequired(org.apache.wicket.request.mapper.parameter.PageParameters,String)
119      */
120    public static String getParameterRequired( final String key, final ServletRequest reqS )
121      throws HTTPRequestException
122    {
123        final String value = reqS.getParameter( key );
124        if( value != null && !"".equals( value )) return value;
125
126        throw new HTTPRequestException( HttpServletResponse.SC_BAD_REQUEST, // 400
127          "Missing request parameter '" + key + "'" );
128    }
129
130
131
132    /** Reconstructs the full URL the client used to make the request, including any query
133      * portion, and returns it in a string builder.
134      *
135      *     @see HttpServletRequest#getRequestURL()
136      */
137    public static StringBuilder getRequestURLFull( final HttpServletRequest reqHS )
138    {
139        final StringBuilder b = new StringBuilder( reqHS.getRequestURL().toString() );
140        final String q = reqHS.getQueryString();
141        if( q != null ) b.append( '?' ).append( q );
142        return b;
143    }
144
145
146
147    /** Copies headers of the specified name from an incoming client request (reqHS) to an
148      * outgoing server request (http).
149      */
150    public static void relayHeaders( final String name, final HttpServletRequest reqHS,
151      final URLConnection http )
152    {
153        final Enumeration<?> values = reqHS.getHeaders( name );
154        while( values.hasMoreElements() )
155        {
156            http.setRequestProperty( name, values.nextElement().toString() );
157        }
158    }
159
160
161}