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 }