001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/enterprise/servlet/SimpleProxyServlet.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2007 by:
006     EXSE, Department of Geography, University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Prof. Dr. Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: greve@giub.uni-bonn.de
041    
042     
043     ---------------------------------------------------------------------------*/
044    package org.deegree.enterprise.servlet;
045    
046    import java.io.IOException;
047    import java.io.InputStream;
048    import java.io.OutputStream;
049    import java.net.URL;
050    import java.net.URLConnection;
051    import java.util.Enumeration;
052    import java.util.HashMap;
053    import java.util.Map;
054    
055    import javax.servlet.ServletException;
056    import javax.servlet.http.HttpServlet;
057    import javax.servlet.http.HttpServletRequest;
058    import javax.servlet.http.HttpServletResponse;
059    
060    import org.apache.commons.httpclient.HttpClient;
061    import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
062    import org.apache.commons.httpclient.methods.PostMethod;
063    import org.deegree.enterprise.WebUtils;
064    import org.deegree.framework.log.ILogger;
065    import org.deegree.framework.log.LoggerFactory;
066    import org.deegree.framework.util.CharsetUtils;
067    import org.deegree.framework.util.KVP2Map;
068    import org.deegree.framework.util.StringTools;
069    import org.deegree.i18n.Messages;
070    import org.deegree.ogcwebservices.OGCRequestFactory;
071    import org.deegree.ogcwebservices.OGCWebServiceException;
072    import org.deegree.ogcwebservices.OGCWebServiceRequest;
073    
074    /**
075     * simple proxy servlet The servlet is intended to run in its own context combined with
076     * ServletFilter (e.g. OWSProxyServletFilter ) to filter out invalid requests/responses
077     * 
078     * @version $Revision: 7149 $
079     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
080     * @author last edited by: $Author: apoth $
081     * 
082     * @version 1.0. $Revision: 7149 $, $Date: 2007-05-16 08:31:47 +0200 (Mi, 16 Mai 2007) $
083     * 
084     * @since 1.1
085     */
086    public class SimpleProxyServlet extends HttpServlet {
087    
088        private ILogger LOG = LoggerFactory.getLogger( SimpleProxyServlet.class );
089    
090        private static final long serialVersionUID = 3086952074808203858L;
091    
092        private Map<String, String> host = null;
093    
094        /**
095         * @see javax.servlet.GenericServlet#init()
096         */
097        @Override
098        public void init()
099                                throws ServletException {
100            super.init();
101            host = new HashMap<String, String>();
102            Enumeration enu = getInitParameterNames();
103            while ( enu.hasMoreElements() ) {
104                String pn = (String) enu.nextElement();
105                String[] tmp = StringTools.toArray( pn, ":", false );
106                String hostAddr = this.getInitParameter( pn );
107                host.put( tmp[0], hostAddr );
108            }
109        }
110    
111        /**
112         * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
113         *      javax.servlet.http.HttpServletResponse)
114         */
115        @Override
116        protected void doGet( HttpServletRequest request, HttpServletResponse response )
117                                throws ServletException, IOException {
118            InputStream is = null;
119            OutputStream os = null;
120            try {
121                String query = request.getQueryString();
122                String service = getService( KVP2Map.toMap( query ) );
123                String hostAddr = host.get( service );
124                String req = hostAddr + "?" + query;
125                URL url = new URL( req );
126                LOG.logDebug( "forward URL: " + url );
127    
128                URLConnection con = url.openConnection();
129                con.setDoInput( true );
130                con.setDoOutput( false );
131                is = con.getInputStream();
132                response.setContentType( con.getContentType() );
133                os = response.getOutputStream();
134                int c = 0;
135                if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
136                    StringBuffer sb = new StringBuffer( 5000 );
137                    while ( ( c = is.read() ) > -1 ) {
138                        sb.append( (char) c );
139                        os.write( c );
140                    }
141                    LOG.logDebug( sb.toString() );
142                } else {
143                    while ( ( c = is.read() ) > -1 ) {
144                        os.write( c );
145                    }
146                }
147    
148            } catch ( Exception e ) {
149                e.printStackTrace();
150                response.setContentType( "text/plain; charset=" + CharsetUtils.getSystemCharset() );
151                os.write( StringTools.stackTraceToString( e ).getBytes() );
152            } finally {
153                try {
154                    is.close();
155                } catch ( Exception e ) {
156                }
157                try {
158                    os.close();
159                } catch ( Exception e ) {
160                }
161            }
162        }
163    
164        /**
165         * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
166         *      javax.servlet.http.HttpServletResponse)
167         */
168        @Override
169        protected void doPost( HttpServletRequest origReq, HttpServletResponse response )
170                                throws ServletException, IOException {
171            // wrap request to enable access of the requests InputStream more
172            // than one time
173            ServletRequestWrapper request = new ServletRequestWrapper( origReq );
174            OutputStream os = null;
175            try {
176                if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
177                    // because this is an expensive operation it just will
178                    // performed if debug level is set too DEBUG
179                    InputStream reqIs = request.getInputStream();
180                    StringBuffer sb = new StringBuffer( 10000 );
181                    int c = 0;
182                    while ( ( c = reqIs.read() ) > -1 ) {
183                        sb.append( (char) c );
184                    }
185                    reqIs.close();
186                    LOG.logDebug( "Request: " + sb );
187                }
188                OGCWebServiceRequest req = OGCRequestFactory.create( request );
189    
190                String hostAddr = host.get( req.getServiceName() );
191                LOG.logDebug( "forward URL: " + hostAddr );
192                if ( hostAddr == null ) {
193                    throw new Exception( Messages.getMessage( "PROXY_SERVLET_UNDEFINED_HOST", req.getServiceName() ) );
194                }
195    
196                // determine charset for setting request content type
197                // use system charset if no charset can be determined
198                // from incoming request
199                String charset = origReq.getCharacterEncoding();
200                LOG.logDebug( "request character encoding: ", charset );
201                if ( charset == null ) {
202                    charset = CharsetUtils.getSystemCharset();
203                    LOG.logDebug( "use sytem character encoding: ", charset );
204                }
205    
206                HttpClient client = new HttpClient();
207                client = WebUtils.enableProxyUsage( client, new URL( hostAddr ) );
208                PostMethod post = new PostMethod( hostAddr );
209                post.setRequestHeader( "Content-type", "text/xml; charset=" + charset );
210                post.setRequestEntity( new InputStreamRequestEntity( request.getInputStream() ) );
211                client.executeMethod( post );
212    
213                LOG.logDebug( "Content-type: ", post.getResponseHeader( "Content-type" ) );
214    
215                os = response.getOutputStream();
216                os.write( post.getResponseBody() );
217            } catch ( Exception e ) {
218                e.printStackTrace();
219                response.setContentType( "text/plain; charset=" + CharsetUtils.getSystemCharset() );
220                os.write( StringTools.stackTraceToString( e ).getBytes() );
221            } finally {
222                try {
223                    os.close();
224                } catch ( Exception e ) {
225                    e.printStackTrace();
226                }
227            }
228        }
229    
230        /**
231         * @return the name of the service that is targeted by the passed KVP encoded request
232         * 
233         * @param map
234         * @throws Exception
235         */
236        private String getService( Map map )
237                                throws Exception {
238            String service = null;
239            String req = (String) map.get( "REQUEST" );
240            if ( "WMS".equals( map.get( "SERVICE" ) ) || req.equals( "GetMap" ) || req.equals( "GetFeatureInfo" )
241                 || req.equals( "GetLegendGraphic" ) ) {
242                service = "WMS";
243            } else if ( "WFS".equals( map.get( "SERVICE" ) ) || req.equals( "DescribeFeatureType" )
244                        || req.equals( "GetFeature" ) ) {
245                service = "WFS";
246            } else if ( "WCS".equals( map.get( "SERVICE" ) ) || req.equals( "GetCoverage" )
247                        || req.equals( "DescribeCoverage" ) ) {
248                service = "WCS";
249            } else if ( "CSW".equals( map.get( "SERVICE" ) ) || req.equals( "GetRecords" ) || req.equals( "GetRecordById" )
250                        || req.equals( "Harvest" ) || req.equals( "DescribeRecord" ) ) {
251                service = "CSW";
252            } else {
253                throw new OGCWebServiceException( "unknown service/request: " + map.get( "SERVICE" ) );
254            }
255            return service;
256        }
257    
258    }