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