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    }