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 }