001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_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 }