001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/ogcwebservices/wass/wss/operation/DoServiceHandler.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.ogcwebservices.wass.wss.operation;
038
039 import java.io.ByteArrayInputStream;
040 import java.io.IOException;
041 import java.io.InputStream;
042 import java.io.UnsupportedEncodingException;
043 import java.net.MalformedURLException;
044 import java.net.URI;
045 import java.net.URL;
046 import java.net.URLDecoder;
047 import java.util.ArrayList;
048 import java.util.List;
049
050 import org.apache.commons.httpclient.Header;
051 import org.apache.commons.httpclient.HttpClient;
052 import org.apache.commons.httpclient.HttpException;
053 import org.apache.commons.httpclient.HttpMethod;
054 import org.apache.commons.httpclient.methods.GetMethod;
055 import org.apache.commons.httpclient.methods.PostMethod;
056 import org.apache.commons.httpclient.methods.StringRequestEntity;
057 import org.apache.commons.httpclient.params.HttpClientParams;
058 import org.deegree.enterprise.WebUtils;
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.xml.XMLParsingException;
063 import org.deegree.i18n.Messages;
064 import org.deegree.ogcwebservices.csw.capabilities.CatalogueCapabilities;
065 import org.deegree.ogcwebservices.csw.capabilities.CatalogueCapabilitiesDocument;
066 import org.deegree.ogcwebservices.getcapabilities.HTTP;
067 import org.deegree.ogcwebservices.getcapabilities.InvalidCapabilitiesException;
068 import org.deegree.ogcwebservices.getcapabilities.OGCCapabilitiesDocument;
069 import org.deegree.ogcwebservices.getcapabilities.Operation;
070 import org.deegree.ogcwebservices.wass.exceptions.DoServiceException;
071 import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilities;
072 import org.deegree.ogcwebservices.wcs.getcapabilities.WCSCapabilitiesDocument;
073 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
074 import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilitiesDocument;
075 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilities;
076 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocument;
077 import org.deegree.ogcwebservices.wms.capabilities.WMSCapabilitiesDocumentFactory;
078 import org.deegree.owscommon_new.DCP;
079 import org.xml.sax.SAXException;
080
081 /**
082 * This base class will makes the connection to the requested service on the "hidden" machines.
083 * Every Subclass must implement the handleRequest method to check the credentials. A call to
084 * another service can only be made, if the requestAllowed values is true;
085 *
086 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
087 *
088 * @author last edited by: $Author: mschneider $
089 *
090 * @version 2.0, $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Thu, 18 Jun 2009) $
091 *
092 * @since 2.0
093 */
094
095 public abstract class DoServiceHandler {
096
097 private ILogger LOG = LoggerFactory.getLogger( DoServiceHandler.class );
098
099 private boolean requestAllowed = false;
100
101 /**
102 * Each subclass must implement this method, appropriate to its needs. For example password
103 * handling.
104 *
105 * @param request
106 * the request the client sent to the secured service
107 * @throws DoServiceException
108 * if an error occured while processing the clients credentials.
109 */
110 public abstract void handleRequest( DoService request )
111 throws DoServiceException;
112
113 /**
114 * @return Returns the requestAllowed.
115 */
116 public boolean requestAllowed() {
117 return requestAllowed;
118 }
119
120 /**
121 * @param isAllowed
122 * The requestAllowed to set.
123 */
124 public void setRequestAllowed( boolean isAllowed ) {
125 this.requestAllowed = isAllowed;
126 }
127
128 /**
129 * This method does the actual request to the secured service. It returns the response of the
130 * secured service as an inputstream. It also replace the GetCapabilities request - responses
131 * with the facadeurl given by the client.
132 *
133 * @param request
134 * send by the client a DoService Request.
135 * @param securedService
136 * the service for which this wss is proxying, must be put in the deegreeparams of
137 * the configuration file.
138 * @param requestedCharset
139 * this wss uses, also read from the deegreeparams in the configuration file.
140 * @param timeout
141 * how long to wait for a response. Service dependable therefor also read from the
142 * deegreeparams in the config file.
143 * @param securedServiceName
144 * the name of the service for which we are proxying -> config.
145 * @return the http response of the secured service as an inputstream.
146 * @throws DoServiceException
147 * if an error occurs wile sending the request or treating the response. see
148 * org.deegree.ogcwebservices.csw.manager.CatalogueHarvester#getNextMetadataRecord
149 */
150 public DoServiceResponse sendRequest( DoService request, URL securedService, String requestedCharset, int timeout,
151 String securedServiceName )
152 throws DoServiceException {
153 if ( requestAllowed ) {
154
155 Header[] headers = null;
156 InputStream body = null;
157 Header[] footers = null;
158 String proxyRequest = null;
159 try {
160 proxyRequest = URLDecoder.decode( request.getPayload(), CharsetUtils.getSystemCharset() );
161 } catch ( UnsupportedEncodingException e ) {
162 LOG.logError( e.getMessage(), e );
163 throw new DoServiceException( Messages.getMessage( "WASS_ERROR_INTERNAL", "WSS" ) );
164 }
165 LOG.logDebug( "encoded proxyrequest: " + request.getPayload() + "\ndecoded proxy: " + proxyRequest );
166 String dcp = request.getDcp();
167 HttpClient client = new HttpClient();
168 client = WebUtils.enableProxyUsage( client, securedService );
169 StringRequestEntity requestEntity = null;
170 HttpClientParams params = client.getParams();
171 params.setSoTimeout( timeout );
172 HttpMethod requestMethod = null;
173 try {
174 String contentType = null;
175 for ( RequestParameter param : request.getRequestParameters() ) {
176 if ( param.getId().toLowerCase().trim().contains( "mime-type" ) )
177 contentType = param.getParameter();
178 }
179 requestEntity = new StringRequestEntity( proxyRequest, contentType, requestedCharset );
180 } catch ( UnsupportedEncodingException e1 ) {
181 throw new DoServiceException( Messages.getMessage( "WASS_ERROR_ENCODING_NOT_SUPPORTED", "WSS" ) );
182 }
183 if ( dcp.equalsIgnoreCase( "http_post" ) ) {
184
185 // the url to the service must be written in the deegreeparams in the configuration
186 // xml
187 requestMethod = new PostMethod( securedService.toExternalForm() );
188 ( (PostMethod) requestMethod ).setRequestEntity( requestEntity );
189 } else if ( dcp.equalsIgnoreCase( "http_get" ) ) {
190 requestMethod = new GetMethod( securedService.toExternalForm() );
191 requestMethod.setQueryString( proxyRequest );
192 } else {
193 throw new DoServiceException( Messages.getMessage( "WASS_ERROR_NOT_POST_OR_GET", "WSS" ) );
194 }
195 // getDataRequest
196 try {
197 // make header parameters of the requestParameters.
198 for ( RequestParameter param : request.getRequestParameters() ) {
199 if ( !param.getId().toLowerCase().trim().contains( "mime-type" ) )// Contenttype
200 requestMethod.addRequestHeader( param.getId(), param.getParameter() );
201 }
202 // Call the secured service
203 client.executeMethod( requestMethod );
204 headers = requestMethod.getResponseHeaders();
205 footers = requestMethod.getResponseFooters();
206 body = requestMethod.getResponseBodyAsStream();
207
208 if ( body == null )
209 throw new DoServiceException( Messages.getMessage( "WASS_ERROR_GOT_NO_RESPONSE", "WSS" ) );
210 } catch ( HttpException e ) {
211 LOG.logError( e.getMessage(), e );
212 throw new DoServiceException( Messages.getMessage( "WASS_ERROR_EXCEPTION_IN_RESPONSE", "WSS" ) );
213 } catch ( IOException e ) {
214 LOG.logError( e.getMessage(), e );
215 throw new DoServiceException( Messages.getMessage( "WASS_ERROR_IN_TRANSPORT", "WSS" ) );
216 }
217 try {
218 // Replace the given urls with the facadeurls if it is a GetCapabilities request
219 if ( proxyRequest.trim().contains( "GetCapabilities" ) ) {
220 Operation[] operations = null;
221 OGCCapabilitiesDocument doc = null;
222 /*
223 * For now just check these service, others may be "secured" in the future.
224 */
225 if ( "WFS".equals( securedServiceName ) ) {
226 doc = new WFSCapabilitiesDocument();
227 doc.load( body, securedService.toExternalForm() );
228 WFSCapabilities cap = (WFSCapabilities) doc.parseCapabilities();
229 operations = cap.getOperationsMetadata().getOperations();
230 replaceFacadeURL( operations, request.getFacadeURL() );
231 doc = org.deegree.ogcwebservices.wfs.XMLFactory.export( cap );
232 } else if ( ( "WMS" ).equals( securedServiceName ) ) {
233 doc = new WMSCapabilitiesDocument();
234 doc.load( body, securedService.toExternalForm() );
235 doc = WMSCapabilitiesDocumentFactory.getWMSCapabilitiesDocument( doc.getRootElement() );
236 WMSCapabilities cap = (WMSCapabilities) doc.parseCapabilities();
237 org.deegree.owscommon_new.Operation[] ops = cap.getOperationMetadata().getOperations().toArray(
238 new org.deegree.owscommon_new.Operation[0] );
239 replaceFacadeURL( ops, request.getFacadeURL() );
240 doc = org.deegree.ogcwebservices.wms.XMLFactory.export( cap );
241 } else if ( ( "WCS" ).equals( securedServiceName ) ) {
242 doc = new WCSCapabilitiesDocument();
243 doc.load( body, securedService.toExternalForm() );
244 WCSCapabilities cap = (WCSCapabilities) doc.parseCapabilities();
245 operations = cap.getCapabilitiy().getOperations().getOperations();
246 replaceFacadeURL( operations, request.getFacadeURL() );
247 doc = org.deegree.ogcwebservices.wcs.XMLFactory.export( cap );
248 } else if ( ( "CSW" ).equals( securedServiceName ) ) {
249 doc = new CatalogueCapabilitiesDocument();
250 doc.load( body, securedService.toExternalForm() );
251 CatalogueCapabilities cap = (CatalogueCapabilities) doc.parseCapabilities();
252 operations = cap.getOperationsMetadata().getOperations();
253 replaceFacadeURL( operations, request.getFacadeURL() );
254 doc = org.deegree.ogcwebservices.csw.XMLFactory_2_0_0.export( cap, null );
255 }
256
257 body = new ByteArrayInputStream( doc.getAsString().getBytes() );
258 }
259 } catch ( IOException e ) {
260 LOG.logError( e.getMessage(), e );
261 throw new DoServiceException( Messages.getMessage( "WASS_ERROR_READING_BODY", "WSS" ) );
262 } catch ( InvalidCapabilitiesException e ) {
263 LOG.logError( e.getMessage(), e );
264 throw new DoServiceException( Messages.getMessage( "WASS_ERROR_CAPABILITIES_RESPONSE", "WSS" ) );
265 } catch ( SAXException e ) {
266 LOG.logError( e.getMessage(), e );
267 throw new DoServiceException( Messages.getMessage( "WASS_ERROR_FACADE_URL", "WSS" ) );
268 } catch ( XMLParsingException e ) {
269 LOG.logError( e.getMessage(), e );
270 throw new DoServiceException( Messages.getMessage( "WASS_ERROR_READING_BODY", "WSS" ) );
271 }
272 return new DoServiceResponse( headers, body, footers );
273 }
274
275 return null;
276 }
277
278 private void replaceFacadeURL( Operation[] operations, URI facadeURI ) {
279
280 if ( operations != null && facadeURI != null ) {
281 for ( int i = 0; i < operations.length; i++ ) {
282 setNewOnlineResource( operations[i], facadeURI );
283 }
284 }
285 }
286
287 private void replaceFacadeURL( org.deegree.owscommon_new.Operation[] operations, URI facadeURI ) {
288
289 if ( operations != null && facadeURI != null ) {
290 for ( int i = 0; i < operations.length; i++ ) {
291 setNewOnlineResource( operations[i], facadeURI );
292 }
293 }
294 }
295
296 /**
297 * Resets all the url in the response body with the facade urls
298 *
299 * @param op
300 * the operation which has the secured service url in it
301 * @param facadeURI
302 * the url of this wss.
303 */
304 private void setNewOnlineResource( Operation op, URI facadeURI ) {
305
306 if ( op.getDCPs() != null ) {
307 for ( int i = 0; i < op.getDCPs().length; i++ ) {
308 HTTP http = (HTTP) op.getDCPs()[i].getProtocol();
309 try {
310 if ( http.getGetOnlineResources().length > 0 ) {
311 URL urls[] = new URL[http.getGetOnlineResources().length];
312 for ( int k = 0; k < http.getGetOnlineResources().length; ++k )
313 urls[k] = facadeURI.toURL();
314
315 http.setGetOnlineResources( urls );
316 }
317 if ( http.getPostOnlineResources().length > 0 ) {
318 URL urls[] = new URL[http.getPostOnlineResources().length];
319 for ( int k = 0; k < http.getPostOnlineResources().length; ++k ) {
320 urls[k] = facadeURI.toURL();
321 }
322
323 http.setPostOnlineResources( urls );
324 }
325 } catch ( MalformedURLException e1 ) {
326 e1.printStackTrace();
327 }
328 }
329 }
330
331 }
332
333 private void setNewOnlineResource( org.deegree.owscommon_new.Operation op, URI facadeURI ) {
334
335 if ( op.getDCP() != null ) {
336 for ( DCP dcp : op.getDCP() ) {
337 // assuming HTTP here, SOAP won't work!
338 org.deegree.owscommon_new.HTTP http = (org.deegree.owscommon_new.HTTP) dcp;
339 try {
340 if ( http.getGetOnlineResources().size() > 0 ) {
341 List<URL> urls = http.getGetOnlineResources();
342 List<URL> urlsnew = new ArrayList<URL>( urls.size() );
343 for ( int i = 0; i < urls.size(); ++i ) {
344 urlsnew.add( facadeURI.toURL() );
345 }
346
347 http.setGetOnlineResources( urlsnew );
348 }
349 if ( http.getPostOnlineResources().size() > 0 ) {
350 List<URL> urls = http.getPostOnlineResources();
351 List<URL> urlsnew = new ArrayList<URL>( urls.size() );
352 for ( int i = 0; i < urls.size(); ++i ) {
353 urlsnew.add( facadeURI.toURL() );
354 }
355
356 http.setPostOnlineResources( urls );
357 }
358 } catch ( MalformedURLException e1 ) {
359 e1.printStackTrace();
360 }
361 }
362 }
363
364 }
365 }