    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/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 (Do, 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    }