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