001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/enterprise/servlet/ServletRequestWrapper.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.enterprise.servlet; 038 039 import static java.net.URLDecoder.decode; 040 041 import java.io.BufferedInputStream; 042 import java.io.BufferedReader; 043 import java.io.ByteArrayInputStream; 044 import java.io.ByteArrayOutputStream; 045 import java.io.IOException; 046 import java.io.InputStream; 047 import java.io.InputStreamReader; 048 import java.io.UnsupportedEncodingException; 049 import java.security.Principal; 050 import java.util.HashMap; 051 import java.util.Iterator; 052 import java.util.Map; 053 import java.util.ResourceBundle; 054 055 import javax.servlet.ServletInputStream; 056 import javax.servlet.http.HttpServletRequest; 057 import javax.servlet.http.HttpServletRequestWrapper; 058 059 import org.deegree.framework.log.ILogger; 060 import org.deegree.framework.log.LoggerFactory; 061 import org.deegree.framework.util.CharsetUtils; 062 import org.deegree.framework.util.StringTools; 063 064 /** 065 * TODO describe function and usage of the class here. 066 * 067 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 068 * @author last edited by: $Author: mays$ 069 * 070 * @version $Revision: 25948 $, $Date: 23.05.2007 18:09:52$ 071 */ 072 public class ServletRequestWrapper extends HttpServletRequestWrapper { 073 074 private static ILogger LOG = LoggerFactory.getLogger( ServletRequestWrapper.class ); 075 076 private static final String BUNDLE_NAME = "org.deegree.enterprise.servlet.ServletRequestWrapper"; 077 078 /** 079 * The resource to load the users from. 080 */ 081 static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle( BUNDLE_NAME ); 082 083 private HttpServletRequest origReq = null; 084 085 private byte[] bytes = null; 086 087 private Map<String, String[]> paramMap; 088 089 private String queryString; 090 091 private String method; 092 093 /** 094 * @param request 095 */ 096 public ServletRequestWrapper( HttpServletRequest request ) { 097 super( request ); 098 099 this.origReq = request; 100 this.method = request.getMethod(); 101 102 ByteArrayOutputStream bos = new ByteArrayOutputStream( 10000 ); 103 try { 104 InputStream is = origReq.getInputStream(); 105 int c = 0; 106 while ( ( c = is.read() ) > -1 ) { 107 bos.write( c ); 108 } 109 bytes = bos.toByteArray(); 110 LOG.logDebug( "The constructor created a new bytearray in the HttpServletRequestWrapper" ); 111 } catch ( IOException ioe ) { 112 LOG.logError( "An error occured while creating a byte-buffered inputstream from the HttpServletRequest " 113 + "inputstream because: " + ioe.getMessage(), ioe ); 114 bytes = null; 115 } 116 queryString = request.getQueryString(); 117 // init parameter map 118 getParameterMap(); 119 } 120 121 @SuppressWarnings("unchecked") 122 @Override 123 public Map<String, String[]> getParameterMap() { 124 if ( paramMap == null ) { 125 paramMap = new HashMap<String, String[]>(); 126 127 // encoding heuristics for URL encoding 128 // if %c3 is found (a sign of UTF-8 encoding) parse it manually, setting the encoding right 129 if ( queryString != null && queryString.toLowerCase().indexOf( "%c3" ) != -1 ) { 130 try { 131 for ( String kv : queryString.split( "&" ) ) { 132 String[] pair = kv.split( "=", 2 ); 133 if ( pair.length == 2 ) { 134 paramMap.put( decode( pair[0], "UTF-8" ), decode( pair[1], "UTF-8" ).split( "," ) ); 135 } 136 } 137 } catch ( UnsupportedEncodingException e ) { 138 LOG.logError( "Unknown error", e ); 139 } 140 } else { 141 paramMap = super.getParameterMap(); 142 } 143 } 144 return paramMap; 145 } 146 147 @Override 148 public String getParameter( String key ) { 149 if ( paramMap == null ) { 150 paramMap = getParameterMap(); 151 } 152 String[] o = paramMap.get( key ); 153 String tmp = null; 154 if ( o != null ) { 155 tmp = StringTools.arrayToString( o, ',' ); 156 } 157 return tmp; 158 } 159 160 @Override 161 public String[] getParameterValues( String arg0 ) { 162 if ( paramMap == null ) { 163 paramMap = getParameterMap(); 164 } 165 return paramMap.get( arg0 ); 166 } 167 168 /** 169 * 170 * @param param 171 */ 172 public void setParameter( Map<String, String> param ) { 173 this.paramMap = new HashMap<String, String[]>( param.size() ); 174 175 Iterator<String> iter = param.keySet().iterator(); 176 StringBuffer sb = new StringBuffer( 500 ); 177 while ( iter.hasNext() ) { 178 String key = iter.next(); 179 String value = param.get( key ); 180 sb.append( key ).append( '=' ).append( value ); 181 if ( iter.hasNext() ) { 182 sb.append( '&' ); 183 } 184 this.paramMap.put( key, StringTools.toArray( value, ",", false ) ); 185 } 186 this.queryString = sb.toString(); 187 } 188 189 @Override 190 public String getQueryString() { 191 return queryString; 192 } 193 194 /** 195 * marks an instance of a {@link #ServletRequestWrapper(HttpServletRequest)} as using HTTP POST. This method just 196 * should be invoked if a request body as an @see {@link InputStream} (byte array) is available 197 */ 198 public void markAsPostRequest() { 199 method = "POST"; 200 if ( bytes == null || bytes.length == 0 ) { 201 LOG.logWarning( "no request body as an InputStream (byte array) is available" ); 202 } 203 // a post request shall not have a parameter string 204 this.queryString = null; 205 this.paramMap = new HashMap<String, String[]>(); 206 } 207 208 @Override 209 public String getMethod() { 210 return method; 211 } 212 213 /** 214 * sets the content of the @see {@link InputStream} returned by the 215 * 216 * @see #getReader() and the 217 * @see #getInputStream() method as a byte array. Calling this method will override the content that may has been 218 * read from the <code>HttpServletRequest</code> that has been passed to the constructor 219 * 220 * @param b 221 */ 222 public void setInputStreamAsByteArray( byte[] b ) { 223 LOG.logDebug( "ServletRequestWrapper: setting inputstream#byteArray to given byte array" ); 224 this.bytes = b; 225 markAsPostRequest(); 226 } 227 228 @Override 229 public BufferedReader getReader() 230 throws IOException { 231 return new BufferedReader( new InputStreamReader( getInputStream(), CharsetUtils.getSystemCharset() ) ); 232 } 233 234 /** 235 * @see javax.servlet.ServletRequest#getInputStream() 236 */ 237 @Override 238 public ServletInputStream getInputStream() 239 throws IOException { 240 if ( bytes == null ) { 241 LOG.logDebug( "Creating new bytearray in the HttpServletRequestWrapper#getInputStream" ); 242 ByteArrayOutputStream bos = new ByteArrayOutputStream( 10000 ); 243 InputStream is = origReq.getInputStream(); 244 int c = 0; 245 while ( ( c = is.read() ) > -1 ) { 246 bos.write( c ); 247 } 248 bytes = bos.toByteArray(); 249 } 250 251 return new ProxyServletInputStream( new ByteArrayInputStream( bytes ), bytes.length ); 252 } 253 254 @Override 255 public Principal getUserPrincipal() { 256 if ( origReq.getUserPrincipal() != null ) { 257 return origReq.getUserPrincipal(); 258 } 259 return new Principal() { 260 public String getName() { 261 return RESOURCE_BUNDLE.getString( "defaultuser" ); 262 } 263 }; 264 265 } 266 267 // /////////////////////////////////////////////////////////////////////// 268 // inner classes // 269 // /////////////////////////////////////////////////////////////////////// 270 271 /** 272 * @author Administrator 273 * 274 * TODO To change the template for this generated type comment go to Window - Preferences - Java - Code 275 * Style - Code Templates 276 */ 277 private class ProxyServletInputStream extends ServletInputStream { 278 279 private BufferedInputStream buffered; 280 281 /** 282 * @param in 283 * the InputStream which will be buffered. 284 * @param length 285 */ 286 public ProxyServletInputStream( InputStream in, int length ) { 287 if ( length > 0 ) 288 buffered = new BufferedInputStream( in, length ); 289 else 290 buffered = new BufferedInputStream( in ); 291 } 292 293 @Override 294 public synchronized int read() 295 throws IOException { 296 return buffered.read(); 297 } 298 299 @Override 300 public synchronized int read( byte b[], int off, int len ) 301 throws IOException { 302 return buffered.read( b, off, len ); 303 } 304 305 @Override 306 public synchronized long skip( long n ) 307 throws IOException { 308 return buffered.skip( n ); 309 } 310 311 @Override 312 public synchronized int available() 313 throws IOException { 314 return buffered.available(); 315 } 316 317 @Override 318 public synchronized void mark( int readlimit ) { 319 buffered.mark( readlimit ); 320 } 321 322 @Override 323 public synchronized void reset() 324 throws IOException { 325 buffered.reset(); 326 } 327 328 @Override 329 public boolean markSupported() { 330 return buffered.markSupported(); 331 } 332 333 @Override 334 public void close() 335 throws IOException { 336 buffered.close(); 337 } 338 } 339 340 }