001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/enterprise/servlet/SimpleProxyServlet.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 package org.deegree.enterprise.servlet;
037
038 import java.io.IOException;
039 import java.io.InputStream;
040 import java.io.OutputStream;
041 import java.net.URL;
042 import java.net.URLConnection;
043 import java.util.Enumeration;
044 import java.util.HashMap;
045 import java.util.Map;
046
047 import javax.servlet.ServletException;
048 import javax.servlet.http.HttpServlet;
049 import javax.servlet.http.HttpServletRequest;
050 import javax.servlet.http.HttpServletResponse;
051
052 import org.apache.commons.httpclient.HttpClient;
053 import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
054 import org.apache.commons.httpclient.methods.PostMethod;
055 import org.deegree.enterprise.WebUtils;
056 import org.deegree.framework.log.ILogger;
057 import org.deegree.framework.log.LoggerFactory;
058 import org.deegree.framework.util.CharsetUtils;
059 import org.deegree.framework.util.KVP2Map;
060 import org.deegree.framework.util.StringTools;
061 import org.deegree.i18n.Messages;
062 import org.deegree.ogcwebservices.OGCRequestFactory;
063 import org.deegree.ogcwebservices.OGCWebServiceException;
064 import org.deegree.ogcwebservices.OGCWebServiceRequest;
065
066 /**
067 * simple proxy servlet The servlet is intended to run in its own context combined with ServletFilter (e.g.
068 * OWSProxyServletFilter ) to filter out invalid requests/responses
069 *
070 * @version $Revision: 20309 $
071 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
072 * @author last edited by: $Author: aschmitz $
073 *
074 * @version 1.0. $Revision: 20309 $, $Date: 2009-10-22 16:24:01 +0200 (Do, 22. Okt 2009) $
075 *
076 * @since 1.1
077 */
078 public class SimpleProxyServlet extends HttpServlet {
079
080 private ILogger LOG = LoggerFactory.getLogger( SimpleProxyServlet.class );
081
082 private static final long serialVersionUID = 3086952074808203858L;
083
084 private Map<String, String> host = null;
085
086 private boolean removeCredentials = false;
087
088 /**
089 * @see javax.servlet.GenericServlet#init()
090 */
091 @Override
092 public void init()
093 throws ServletException {
094 super.init();
095 host = new HashMap<String, String>();
096 Enumeration<?> enu = getInitParameterNames();
097 while ( enu.hasMoreElements() ) {
098 String pn = (String) enu.nextElement();
099 if ( pn.toLowerCase().equals( "removecredentials" ) ) {
100 removeCredentials = getInitParameter( pn ).equalsIgnoreCase( "true" );
101 continue;
102 }
103 String[] tmp = StringTools.toArray( pn, ":", false );
104 String hostAddr = this.getInitParameter( pn );
105 host.put( tmp[0], hostAddr );
106 }
107 }
108
109 /**
110 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
111 * javax.servlet.http.HttpServletResponse)
112 */
113 @Override
114 protected void doGet( HttpServletRequest request, HttpServletResponse response )
115 throws ServletException, IOException {
116 InputStream is = null;
117 OutputStream os = null;
118 try {
119 String query = request.getQueryString();
120 Map<String, String> map = KVP2Map.toMap( query );
121 if ( removeCredentials ) {
122 map.remove( "USER" );
123 map.remove( "PASSWORD" );
124 map.remove( "SESSIONID" );
125 query = "";
126 for ( String key : map.keySet() ) {
127 query += key + "=" + map.get( key ) + "&";
128 }
129 query = query.substring( 0, query.length() - 1 );
130 }
131 String service = getService( map );
132 String hostAddr = host.get( service );
133 String req = hostAddr + "?" + query;
134 URL url = new URL( req );
135 LOG.logDebug( "forward URL: " + url );
136
137 URLConnection con = url.openConnection();
138 con.setDoInput( true );
139 con.setDoOutput( false );
140 is = con.getInputStream();
141 response.setContentType( con.getContentType() );
142 response.setCharacterEncoding( con.getContentEncoding() );
143 os = response.getOutputStream();
144 int read = 0;
145 byte[] buf = new byte[16384];
146 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
147 while ( ( read = is.read( buf ) ) > -1 ) {
148 os.write( buf, 0, read );
149 LOG.logDebug( new String( buf, 0, read, con.getContentEncoding() ) );
150 }
151 } else {
152 while ( ( read = is.read( buf ) ) > -1 ) {
153 os.write( buf, 0, read );
154 }
155 }
156
157 } catch ( Exception e ) {
158 e.printStackTrace();
159 response.setContentType( "text/plain; charset=" + CharsetUtils.getSystemCharset() );
160 os.write( StringTools.stackTraceToString( e ).getBytes() );
161 } finally {
162 try {
163 is.close();
164 } catch ( Exception e ) {
165 // try to do what ?
166 }
167 try {
168 os.close();
169 } catch ( Exception e ) {
170 // try to do what ?
171 }
172 }
173 }
174
175 /**
176 * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
177 * javax.servlet.http.HttpServletResponse)
178 */
179 @Override
180 protected void doPost( HttpServletRequest origReq, HttpServletResponse response )
181 throws ServletException, IOException {
182 // wrap request to enable access of the requests InputStream more
183 // than one time
184 ServletRequestWrapper request = new ServletRequestWrapper( origReq );
185 OutputStream os = null;
186 try {
187 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
188 // because this is an expensive operation it just will
189 // performed if debug level is set too DEBUG
190 InputStream reqIs = request.getInputStream();
191 StringBuffer sb = new StringBuffer( 10000 );
192 int c = 0;
193 while ( ( c = reqIs.read() ) > -1 ) {
194 sb.append( (char) c );
195 }
196 reqIs.close();
197 LOG.logDebug( "Request: " + sb );
198 }
199 OGCWebServiceRequest req = OGCRequestFactory.create( request );
200
201 String hostAddr = host.get( req.getServiceName() );
202 LOG.logDebug( "forward URL: " + hostAddr );
203 if ( hostAddr == null ) {
204 throw new Exception( Messages.getMessage( "PROXY_SERVLET_UNDEFINED_HOST", req.getServiceName() ) );
205 }
206
207 // determine charset for setting request content type
208 // use system charset if no charset can be determined
209 // from incoming request
210 String charset = origReq.getCharacterEncoding();
211 LOG.logDebug( "request character encoding: ", charset );
212 if ( charset == null ) {
213 charset = CharsetUtils.getSystemCharset();
214 LOG.logDebug( "use sytem character encoding: ", charset );
215 }
216
217 HttpClient client = new HttpClient();
218 client = WebUtils.enableProxyUsage( client, new URL( hostAddr ) );
219 PostMethod post = new PostMethod( hostAddr );
220 post.setRequestHeader( "Content-type", "text/xml; charset=" + charset );
221 post.setRequestEntity( new InputStreamRequestEntity( request.getInputStream() ) );
222 client.executeMethod( post );
223
224 LOG.logDebug( "Content-type: ", post.getResponseHeader( "Content-type" ) );
225
226 os = response.getOutputStream();
227 os.write( post.getResponseBody() );
228 } catch ( Exception e ) {
229 e.printStackTrace();
230 response.setContentType( "text/plain; charset=" + CharsetUtils.getSystemCharset() );
231 os.write( StringTools.stackTraceToString( e ).getBytes() );
232 } finally {
233 try {
234 os.close();
235 } catch ( Exception e ) {
236 e.printStackTrace();
237 }
238 }
239 }
240
241 /**
242 * @return the name of the service that is targeted by the passed KVP encoded request
243 *
244 * @param map
245 * @throws Exception
246 */
247 private String getService( Map<String, String> map )
248 throws Exception {
249 String service = null;
250 String req = map.get( "REQUEST" );
251 if ( "WMS".equals( map.get( "SERVICE" ) ) || req.equals( "GetMap" ) || req.equals( "GetFeatureInfo" )
252 || req.equals( "GetLegendGraphic" ) ) {
253 service = "WMS";
254 } else if ( "WFS".equals( map.get( "SERVICE" ) ) || req.equals( "DescribeFeatureType" )
255 || req.equals( "GetFeature" ) ) {
256 service = "WFS";
257 } else if ( "WCS".equals( map.get( "SERVICE" ) ) || req.equals( "GetCoverage" )
258 || req.equals( "DescribeCoverage" ) ) {
259 service = "WCS";
260 } else if ( "CSW".equals( map.get( "SERVICE" ) ) || req.equals( "GetRecords" ) || req.equals( "GetRecordById" )
261 || req.equals( "Harvest" ) || req.equals( "DescribeRecord" ) ) {
262 service = "CSW";
263 } else {
264 throw new OGCWebServiceException( "unknown service/request: " + map.get( "SERVICE" ) );
265 }
266 return service;
267 }
268
269 }