    001    /*----------------------------------------------------------------------------
    002     This file is part of deegree, http://deegree.org/
    003     Copyright (C) 2001-2009 by:
    004       Department of Geography, University of Bonn
    005     and
    006       lat/lon GmbH
    007
    008     This library is free software; you can redistribute it and/or modify it under
    009     the terms of the GNU Lesser General Public License as published by the Free
    010     Software Foundation; either version 2.1 of the License, or (at your option)
    011     any later version.
    012     This library is distributed in the hope that it will be useful, but WITHOUT
    013     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    014     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
    015     details.
    016     You should have received a copy of the GNU Lesser General Public License
    017     along with this library; if not, write to the Free Software Foundation, Inc.,
    018     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    019
    020     Contact information:
    021
    022     lat/lon GmbH
    023     Aennchenstr. 19, 53177 Bonn
    024     Germany
    025     http://lat-lon.de/
    026
    027     Department of Geography, University of Bonn
    028     Prof. Dr. Klaus Greve
    029     Postfach 1147, 53001 Bonn
    030     Germany
    031     http://www.geographie.uni-bonn.de/deegree/
    032
    033     e-mail: info@deegree.org
    034    ----------------------------------------------------------------------------*/
    035    package org.deegree.ogcwebservices.csw.iso_profile.ebrim;
    036
    037    import java.net.MalformedURLException;
    038    import java.security.InvalidParameterException;
    039    import java.util.List;
    040
    041    import org.deegree.framework.log.ILogger;
    042    import org.deegree.framework.log.LoggerFactory;
    043    import org.deegree.framework.xml.XMLFragment;
    044    import org.deegree.framework.xml.XMLParsingException;
    045    import org.deegree.framework.xml.XMLTools;
    046    import org.deegree.ogcbase.CommonNamespaces;
    047    import org.deegree.ogcwebservices.OGCWebServiceException;
    048    import org.deegree.ogcwebservices.csw.CSWExceptionCode;
    049    import org.w3c.dom.Document;
    050    import org.w3c.dom.Element;
    051    import org.w3c.dom.Node;
    052
    053    /**
    054     * The <code>CSWSOAPFilter</code> class parses an incoming soap - (post)request which (if the root element is bound to
    055     * the soap name space "http://www.w3.org/2003/05/soap-envelope") will copy the csw:Operation inside the envelope. Sets
    056     * the user name and passwords inside the root element of the csw:reqquest and sends it to the chain.
    057     *
    058     * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
    059     *
    060     * @author last edited by: $Author: bezema $
    061     *
    062     * @version $Revision: 1.4 $, $Date: 2007-06-21 13:53:49 $
    063     *
    064     */
    065
    066    public class CSWSOAPHandler {
    067        private static ILogger LOG = LoggerFactory.getLogger( CSWSOAPHandler.class );
    068
    069        private XMLFragment incomingRequest;
    070
    071        private boolean isSOAPRequest;
    072
    073        private String userName = "anonymous";
    074
    075        private String password = "";
    076
    077        /**
    078         * Create an empty CSWSoapHandler with username set to anonymous and password to "". No xml-data is set.
    079         */
    080        public CSWSOAPHandler() {
    081            incomingRequest = null;
    082            isSOAPRequest = false;
    083        }
    084
    085        /**
    086         * Simple constructor buffering the request.
    087         *
    088         * @param incomingRequest
    089         */
    090        public CSWSOAPHandler( XMLFragment incomingRequest ) {
    091            if ( incomingRequest == null ) {
    092                throw new InvalidParameterException( "The incomingRequest parameter may not be null" );
    093            }
    094            this.incomingRequest = incomingRequest;
    095            String ns = incomingRequest.getRootElement().getNamespaceURI();
    096            LOG.logDebug( " The namespace of the rootelement = " + ns );
    097            isSOAPRequest = CommonNamespaces.W3SOAP_ENVELOPE.toASCIIString().equals( ns );
    098        }
    099
    100        /**
    101         * @return true if the namespace of the root element is 'http://www.w3.org/2003/05/soap-envelope' false otherwise.
    102         */
    103        public boolean isSOAPRequest() {
    104            return isSOAPRequest;
    105        }
    106
    107        /**
    108         * Finds a user and a password from a given soap request, and inserts them as attributes into the rootelement of the
    109         * csw:request inside the body of the soap. This request is returned.
    110         *
    111         * @return the XMLTree inside the soap:body or <code>null</code> if the element has no localname of Envelope, or
    112         *         the data (aka as doc) was not set.
    113         * @throws OGCWebServiceException
    114         *             if some required elements are not set.
    115         */
    116        public XMLFragment createCSWRequestFromSOAP()
    117                                throws OGCWebServiceException {
    118            if ( !isSOAPRequest ) {
    119                LOG.logDebug( " not a soaprequest, so returning the unparsed xmlfragment." );
    120                return this.incomingRequest;
    121            }
    122            if ( incomingRequest == null ) {
    123                LOG.logDebug( " no data was set, so returning null." );
    124                return null;
    125            }
    126
    127            Element rootElement = this.incomingRequest.getRootElement();
    128
    129            String localName = rootElement.getLocalName();
    130            if ( localName == null || !"Envelope".equals( localName ) ) {
    131                LOG.logDebug( " The localname of the root element is not: 'Envelope', so not parsing the SOAP request. " );
    132                throw new OGCWebServiceException(
    133                                                  "A SOAP-Request must contain the root element with a localname of 'Envelope', you supplied: "
    134                                                                          + localName, CSWExceptionCode.WRS_INVALIDREQUEST );
    135            }
    136            Element header = null;
    137            Element cswRequest = null;
    138            try {
    139                header = XMLTools.getRequiredElement( rootElement, CommonNamespaces.W3SOAP_ENVELOPE_PREFIX + ":Header",
    140                                                      CommonNamespaces.getNamespaceContext() );
    141                Element body = XMLTools.getRequiredElement( rootElement, CommonNamespaces.W3SOAP_ENVELOPE_PREFIX + ":Body",
    142                                                            CommonNamespaces.getNamespaceContext() );
    143                List<Element> cswRequests = XMLTools.getElements( body, "*", CommonNamespaces.getNamespaceContext() );
    144                if ( cswRequests.size() != 1 ) {
    145                    StringBuffer sb = new StringBuffer();
    146                    for ( int i = 0; i < cswRequests.size(); ++i ) {
    147                        sb.append( cswRequests.get( i ).getLocalName() + ( ( ( i + 1 ) < cswRequests.size() ) ? ", " : "" ) );
    148                    }
    149                    LOG.logDebug( " Not enough csw requests found in the body of the soap envelope, found: "
    150                                  + sb.toString() );
    151                    throw new OGCWebServiceException(
    152                                                      "You have not supplied exactly one csw requests in the body of the soap envelope (you supplied:  "
    153                                                                              + sb.toString()
    154                                                                              + "), only one request per soap envelope is allowed.",
    155                                                      CSWExceptionCode.WRS_INVALIDREQUEST );
    156                }
    157                cswRequest = cswRequests.get( 0 );
    158                LOG.logDebug( " found csw request: " + cswRequest.getLocalName() );
    159
    160            } catch ( XMLParsingException e ) {
    161                LOG.logDebug( " No soap:header or soap:body found: " + e.getMessage() );
    162                throw new OGCWebServiceException(
    163                                                  "While parsing your soap request, a required element (soap:Header or soap:Body) wasn't found, the exact error message is: "
    164                                                                          + e.getMessage(),
    165                                                  CSWExceptionCode.WRS_INVALIDREQUEST );
    166
    167            }
    168
    169            try {
    170                userName = XMLTools.getNodeAsString( header, CommonNamespaces.DGSEC_PREFIX + ":user",
    171                                                     CommonNamespaces.getNamespaceContext(), "default" );
    172                password = XMLTools.getNodeAsString( header, CommonNamespaces.DGSEC_PREFIX + ":password",
    173                                                     CommonNamespaces.getNamespaceContext(), "default" );
    174            } catch ( XMLParsingException e ) {
    175                LOG.logDebug( " No deegreesec:user/deegreesec:password found: " + e.getMessage() );
    176                throw new OGCWebServiceException(
    177                                                  "While parsing your soap request, a required element (deegreesec:user/deegreesec:password) wasn't found, the exact error message is: "
    178                                                                          + e.getMessage(),
    179                                                  CSWExceptionCode.WRS_INVALIDREQUEST );
    180            }
    181
    182            LOG.logDebug( " found user: " + userName );
    183            LOG.logDebug( " found password: " + password );
    184
    185            String ns = cswRequest.getNamespaceURI();
    186            if ( !CommonNamespaces.CSWNS.toASCIIString().equals( ns ) ) {
    187                LOG.logDebug( " The namespace of the enveloped request-root element is not: " + CommonNamespaces.CSWNS
    188                              + " so not using the SOAP servlet filter. " );
    189                throw new OGCWebServiceException( "The namespace of the enveloped request-root element is not: "
    190                                                  + CommonNamespaces.CSWNS, CSWExceptionCode.WRS_INVALIDREQUEST );
    191            }
    192
    193            Document newRequestDoc = XMLTools.create();
    194            Node a = newRequestDoc.importNode( cswRequest, true );
    195            if ( a.getNodeType() != Node.ELEMENT_NODE ) {
    196                throw new OGCWebServiceException( "The copied request is not of type w3c.ELEMENT_NODE, this cannot be.",
    197                                                  CSWExceptionCode.WRS_INVALIDREQUEST );
    198            }
    199            Element insertedRequest = (Element) newRequestDoc.appendChild( a );
    200            insertedRequest.setAttribute( "user", userName );
    201            insertedRequest.setAttribute( "password", password );
    202
    203            XMLFragment frag = null;
    204            try {
    205                frag = new XMLFragment( newRequestDoc, XMLFragment.DEFAULT_URL );
    206                XMLTools.appendNSBinding( frag.getRootElement(), "rim", CommonNamespaces.OASIS_EBRIMNS );
    207                if ( LOG.isDebug() ) {
    208                    LOG.logDebug( " the resulting request:\n " + frag.getAsPrettyString() );
    209                }
    210            } catch ( MalformedURLException e ) {
    211                // never happens because using default url
    212            }
    213            return frag;
    214        }
    215
    216        /**
    217         * @return the password.
    218         */
    219        public String getPassword() {
    220            return password;
    221        }
    222
    223        /**
    224         * @return the userName.
    225         */
    226        public String getUserName() {
    227            return userName;
    228        }
    229
    230        /**
    231         * @param doc
    232         *            sets the incomingRequest to doc.
    233         */
    234        public void setIncomingRequest( XMLFragment doc ) {
    235            if ( doc == null ) {
    236                throw new InvalidParameterException( "The incomingRequest parameter may not be null" );
    237            }
    238            incomingRequest = doc;
    239            String ns = incomingRequest.getRootElement().getNamespaceURI();
    240            LOG.logDebug( " The namespace of the rootelement = " + ns );
    241            isSOAPRequest = CommonNamespaces.W3SOAP_ENVELOPE.toASCIIString().equals( ns );
    242
    243        }
    244
    245    }