//$Header$
/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstr. 19
53115 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.enterprise.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.util.CharsetUtils;
import org.deegree.framework.util.KVP2Map;
import org.deegree.framework.util.StringTools;
import org.deegree.i18n.Messages;
import org.deegree.ogcwebservices.OGCRequestFactory;
import org.deegree.ogcwebservices.OGCWebServiceException;
import org.deegree.ogcwebservices.OGCWebServiceRequest;
/**
* simple proxy servlet The servlet is intended to run in its own
* context combined with ServletFilter (e.g. OWSProxyServletFilter )
* to filter out invalid requests/responses
*
* @version $Revision$
* @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
* @author last edited by: $Author$
*
* @version 1.0. $Revision$, $Date$
*
* @since 1.1
*/
public class SimpleProxyServlet extends HttpServlet {
private ILogger LOG = LoggerFactory.getLogger( SimpleProxyServlet.class );
private static final long serialVersionUID = 3086952074808203858L;
private Map<String, String> host = null;
/**
* @see javax.servlet.GenericServlet#init()
*/
@Override
public void init()
throws ServletException {
super.init();
host = new HashMap<String, String>();
Enumeration enu = getInitParameterNames();
while ( enu.hasMoreElements() ) {
String pn = (String) enu.nextElement();
String[] tmp = StringTools.toArray( pn, ":", false );
String hostAddr = this.getInitParameter( pn );
host.put( tmp[0], hostAddr );
}
}
/**
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doGet( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException {
InputStream is = null;
OutputStream os = null;
try {
String query = request.getQueryString();
String service = getService( KVP2Map.toMap( query ) );
String hostAddr = host.get( service );
String req = hostAddr + "?" + query;
URL url = new URL( req );
LOG.logDebug( "forward URL: " + url );
URLConnection con = url.openConnection();
con.setDoInput( true );
con.setDoOutput( false );
is = con.getInputStream();
response.setContentType( con.getContentType() );
os = response.getOutputStream();
int c = 0;
while ( ( c = is.read() ) > -1 ) {
os.write( c );
}
} catch ( Exception e ) {
e.printStackTrace();
response.setContentType( "text/plain; charset=" + CharsetUtils.getSystemCharset() );
os.write( StringTools.stackTraceToString( e ).getBytes() );
} finally {
try {
is.close();
} catch ( Exception e ) {
}
try {
os.close();
} catch ( Exception e ) {
}
}
}
/**
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doPost( HttpServletRequest origReq, HttpServletResponse response )
throws ServletException, IOException {
// wrap request to enable access of the requests InputStream more
// than one time
ServletRequestWrapper request = new ServletRequestWrapper( origReq );
OutputStream os = null;
try {
if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
// because this is an expensive operation it just will
// performed if debug level is set too DEBUG
InputStream reqIs = request.getInputStream();
StringBuffer sb = new StringBuffer( 10000 );
int c = 0;
while ( ( c = reqIs.read() ) > -1 ) {
sb.append( (char) c );
}
reqIs.close();
LOG.logDebug( "Request: " + sb );
}
OGCWebServiceRequest req = OGCRequestFactory.create( request );
String hostAddr = host.get( req.getServiceName() );
LOG.logDebug( "forward URL: " + hostAddr );
if ( hostAddr == null ) {
throw new Exception( Messages.getMessage( "PROXY_SERVLET_UNDEFINED_HOST",
req.getServiceName() ) );
}
// determine charset for setting request content type
// use system charset if no charset can be determined
// from incoming request
String charset = origReq.getCharacterEncoding();
LOG.logDebug( "request character encoding: ", charset );
if ( charset == null ) {
charset = CharsetUtils.getSystemCharset();
LOG.logDebug( "use sytem character encoding: ", charset );
}
HttpClient client = new HttpClient();
PostMethod post = new PostMethod( hostAddr );
post.setRequestHeader( "Content-type", "text/xml; charset=" + charset );
post.setRequestEntity( new InputStreamRequestEntity( request.getInputStream() ) );
client.executeMethod( post );
LOG.logDebug( "Content-type: ", post.getResponseHeader( "Content-type" ) );
os = response.getOutputStream();
os.write( post.getResponseBody() );
} catch ( Exception e ) {
e.printStackTrace();
response.setContentType( "text/plain; charset=" + CharsetUtils.getSystemCharset() );
os.write( StringTools.stackTraceToString( e ).getBytes() );
} finally {
try {
os.close();
} catch ( Exception e ) {
}
}
}
/**
* @return the name of the service that is targeted by the passed
* KVP encoded request
*
* @param map
* @throws Exception
*/
private String getService( Map map )
throws Exception {
String service = null;
String req = (String) map.get( "REQUEST" );
if ( "WMS".equals( map.get( "SERVICE" ) ) || req.equals( "GetMap" )
|| req.equals( "GetFeatureInfo" ) || req.equals( "GetLegend" ) ) {
service = "WMS";
} else if ( "WFS".equals( map.get( "SERVICE" ) ) || req.equals( "DescribeFeatureType" )
|| req.equals( "GetFeature" ) ) {
service = "WFS";
} else if ( "WCS".equals( map.get( "SERVICE" ) ) || req.equals( "GetCoverage" )
|| req.equals( "DescribeCoverage" ) ) {
service = "WCS";
} else if ( "CSW".equals( map.get( "SERVICE" ) ) ) {
service = "CSW";
} else {
throw new OGCWebServiceException( "unknown service/request: " + map.get( "SERVICE" ) );
}
return service;
}
}
/* ********************************************************************
Changes to this class. What the people have been up to:
$Log$
Revision 1.17 2006/11/24 12:51:11 poth
*** empty log message ***
Revision 1.16 2006/11/16 15:04:11 poth
explicit setting of content type and character encoding added
Revision 1.15 2006/10/22 20:32:08 poth
support for vendor specific operation GetScaleBar removed
Revision 1.14 2006/10/17 20:31:18 poth
*** empty log message ***
Revision 1.13 2006/09/08 15:14:38 schmitz
Updated the core of deegree to use the HttpServletRequest methods
to create the KVP maps, and not to try to parse as XML every time.
Updated the tests to create maps for testing instead of strings.
Updated the OWSProxy subsystem to use ServletRequest classes instead
of strings for request dispatching.
Revision 1.12 2006/08/29 19:54:14 poth
footer corrected
Revision 1.11 2006/08/14 13:41:38 poth
determination of service type for HTTP post enhanced
Revision 1.10 2006/07/23 10:05:54 poth
setting content type for Http responses enhanced by adding charset (for mime types text/plain and text/xml)
Revision 1.9 2006/07/12 14:46:15 poth
comment footer added
********************************************************************** */