001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/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: 31357 $, $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 public void reinitParameterMap() {
123 paramMap = new HashMap<String, String[]>();
124
125 // encoding heuristics for URL encoding
126 // if %c3 is found (a sign of UTF-8 encoding) parse it manually, setting the encoding right
127 if ( queryString != null && queryString.toLowerCase().indexOf( "%c3" ) != -1 ) {
128 try {
129 for ( String kv : queryString.split( "&" ) ) {
130 String[] pair = kv.split( "=", 2 );
131 if ( pair.length == 2 ) {
132 paramMap.put( decode( pair[0], "UTF-8" ), decode( pair[1], "UTF-8" ).split( "," ) );
133 }
134 }
135 } catch ( UnsupportedEncodingException e ) {
136 LOG.logError( "Unknown error", e );
137 }
138 } else {
139 paramMap = super.getParameterMap();
140 }
141 }
142
143 @Override
144 public Map<String, String[]> getParameterMap() {
145 if ( paramMap == null ) {
146 reinitParameterMap();
147 }
148 return paramMap;
149 }
150
151 @Override
152 public String getParameter( String key ) {
153 if ( paramMap == null ) {
154 paramMap = getParameterMap();
155 }
156 String[] o = paramMap.get( key );
157 String tmp = null;
158 if ( o != null ) {
159 tmp = StringTools.arrayToString( o, ',' );
160 }
161 return tmp;
162 }
163
164 @Override
165 public String[] getParameterValues( String arg0 ) {
166 if ( paramMap == null ) {
167 paramMap = getParameterMap();
168 }
169 return paramMap.get( arg0 );
170 }
171
172 /**
173 *
174 * @param param
175 */
176 public void setParameter( Map<String, String> param ) {
177 this.paramMap = new HashMap<String, String[]>( param.size() );
178
179 Iterator<String> iter = param.keySet().iterator();
180 StringBuffer sb = new StringBuffer( 500 );
181 while ( iter.hasNext() ) {
182 String key = iter.next();
183 String value = param.get( key );
184 sb.append( key ).append( '=' ).append( value );
185 if ( iter.hasNext() ) {
186 sb.append( '&' );
187 }
188 this.paramMap.put( key, StringTools.toArray( value, ",", false ) );
189 }
190 this.queryString = sb.toString();
191 }
192
193 @Override
194 public String getQueryString() {
195 return queryString;
196 }
197
198 /**
199 * marks an instance of a {@link #ServletRequestWrapper(HttpServletRequest)} as using HTTP POST. This method just
200 * should be invoked if a request body as an @see {@link InputStream} (byte array) is available
201 */
202 public void markAsPostRequest() {
203 method = "POST";
204 if ( bytes == null || bytes.length == 0 ) {
205 LOG.logWarning( "no request body as an InputStream (byte array) is available" );
206 }
207 // a post request shall not have a parameter string
208 this.queryString = null;
209 this.paramMap = new HashMap<String, String[]>();
210 }
211
212 @Override
213 public String getMethod() {
214 return method;
215 }
216
217 /**
218 * sets the content of the @see {@link InputStream} returned by the
219 *
220 * @see #getReader() and the
221 * @see #getInputStream() method as a byte array. Calling this method will override the content that may has been
222 * read from the <code>HttpServletRequest</code> that has been passed to the constructor
223 *
224 * @param b
225 */
226 public void setInputStreamAsByteArray( byte[] b ) {
227 LOG.logDebug( "ServletRequestWrapper: setting inputstream#byteArray to given byte array" );
228 this.bytes = b;
229 markAsPostRequest();
230 }
231
232 @Override
233 public BufferedReader getReader()
234 throws IOException {
235 return new BufferedReader( new InputStreamReader( getInputStream(), CharsetUtils.getSystemCharset() ) );
236 }
237
238 /**
239 * @see javax.servlet.ServletRequest#getInputStream()
240 */
241 @Override
242 public ServletInputStream getInputStream()
243 throws IOException {
244 if ( bytes == null ) {
245 LOG.logDebug( "Creating new bytearray in the HttpServletRequestWrapper#getInputStream" );
246 ByteArrayOutputStream bos = new ByteArrayOutputStream( 10000 );
247 InputStream is = origReq.getInputStream();
248 int c = 0;
249 while ( ( c = is.read() ) > -1 ) {
250 bos.write( c );
251 }
252 bytes = bos.toByteArray();
253 }
254
255 return new ProxyServletInputStream( new ByteArrayInputStream( bytes ), bytes.length );
256 }
257
258 @Override
259 public Principal getUserPrincipal() {
260 if ( origReq.getUserPrincipal() != null ) {
261 return origReq.getUserPrincipal();
262 }
263 return new Principal() {
264 public String getName() {
265 return RESOURCE_BUNDLE.getString( "defaultuser" );
266 }
267 };
268
269 }
270
271 // ///////////////////////////////////////////////////////////////////////
272 // inner classes //
273 // ///////////////////////////////////////////////////////////////////////
274
275 /**
276 * @author Administrator
277 *
278 * TODO To change the template for this generated type comment go to Window - Preferences - Java - Code
279 * Style - Code Templates
280 */
281 private class ProxyServletInputStream extends ServletInputStream {
282
283 private BufferedInputStream buffered;
284
285 /**
286 * @param in
287 * the InputStream which will be buffered.
288 * @param length
289 */
290 public ProxyServletInputStream( InputStream in, int length ) {
291 if ( length > 0 )
292 buffered = new BufferedInputStream( in, length );
293 else
294 buffered = new BufferedInputStream( in );
295 }
296
297 @Override
298 public synchronized int read()
299 throws IOException {
300 return buffered.read();
301 }
302
303 @Override
304 public synchronized int read( byte b[], int off, int len )
305 throws IOException {
306 return buffered.read( b, off, len );
307 }
308
309 @Override
310 public synchronized long skip( long n )
311 throws IOException {
312 return buffered.skip( n );
313 }
314
315 @Override
316 public synchronized int available()
317 throws IOException {
318 return buffered.available();
319 }
320
321 @Override
322 public synchronized void mark( int readlimit ) {
323 buffered.mark( readlimit );
324 }
325
326 @Override
327 public synchronized void reset()
328 throws IOException {
329 buffered.reset();
330 }
331
332 @Override
333 public boolean markSupported() {
334 return buffered.markSupported();
335 }
336
337 @Override
338 public void close()
339 throws IOException {
340 buffered.close();
341 }
342 }
343
344 }