View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2008 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  package com.eviware.soapui.impl.wsdl.support.wsa;
13  
14  import org.apache.xmlbeans.XmlException;
15  import org.apache.xmlbeans.XmlObject;
16  import org.w3c.dom.Element;
17  
18  import com.eviware.soapui.SoapUI;
19  import com.eviware.soapui.config.AnonymousTypeConfig;
20  import com.eviware.soapui.impl.wsdl.WsdlOperation;
21  import com.eviware.soapui.impl.wsdl.submit.WsdlMessageExchange;
22  import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
23  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
24  import com.eviware.soapui.model.testsuite.AssertionError;
25  import com.eviware.soapui.model.testsuite.AssertionException;
26  import com.eviware.soapui.support.StringUtils;
27  import com.eviware.soapui.support.xml.XmlUtils;
28  
29  /***
30   * Validating class for WS Addressing implemented according to WSDL 1.1
31   * specification
32   * 
33   * @author dragica.soldo
34   * @see {@link}http://www.w3.org/TR/2006/WD-ws-addr-wsdl-20060216/#WSDL11MEPS
35   */
36  public class WsaValidator
37  {
38  	WsdlMessageExchange messageExchange;
39  	Element header;
40  	String wsaVersionNameSpace;
41  
42  	public WsaValidator(WsdlMessageExchange messageExchange)
43  	{
44  		this.messageExchange = messageExchange;
45  	}
46  
47  	private void validateWsAddressingCommon( String content ) throws AssertionException
48     {
49        try
50        {
51           SoapVersion soapVersion = messageExchange.getOperation().getInterface()
52                   .getSoapVersion();
53  
54           XmlObject xmlObject = XmlObject.Factory.parse( content );
55           XmlObject[] envS = xmlObject.selectChildren( soapVersion.getEnvelopeQName() );
56           Element envelope = (Element) envS[0].getDomNode();
57  
58           header = (Element) SoapUtils.getHeaderElement( xmlObject, soapVersion, true ).getDomNode();
59  
60           if( !header.hasChildNodes() )
61           {
62              throw new AssertionException( new AssertionError( "WS-A not enabled" ) );
63           }
64  
65           String wsaNameSpace = header.getAttribute( "xmlns:wsa" );
66           if( wsaNameSpace == null || wsaNameSpace.length() == 0)
67           {
68              wsaNameSpace = envelope.getAttribute( "xmlns:wsa" );
69              if( wsaNameSpace == null || wsaNameSpace.length() == 0 )
70              {
71                 throw new AssertionException( new AssertionError( "WS-A version is missing." ) );
72              }
73           }
74           if( wsaNameSpace.equals( WsaUtils.WS_A_VERSION_200508 ) )
75           {
76              wsaVersionNameSpace = WsaUtils.WS_A_VERSION_200508;
77           }
78           else if( wsaNameSpace.equals( WsaUtils.WS_A_VERSION_200408 ) )
79           {
80              wsaVersionNameSpace = WsaUtils.WS_A_VERSION_200408;
81           }
82           else
83           {
84              throw new AssertionException( new AssertionError( "WS-A version is wrong" ) );
85           }
86  
87           // Action is Mandatory
88           Element actionNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "Action" );
89           if( actionNode == null )
90           {
91              throw new AssertionException( new AssertionError( "WS-A Action property is not specified" ) );
92           }
93           String actionValue = XmlUtils.getElementText( actionNode );
94           if( StringUtils.isNullOrEmpty( actionValue ) )
95           {
96              throw new AssertionException( new AssertionError( "WS-A Action property is empty" ) );
97           }
98  
99           // To is Mandatory
100          Element toNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "To" );
101          if( toNode == null )
102          {
103             throw new AssertionException( new AssertionError( "WS-A To property is not specified" ) );
104          }
105          Element addressNode = XmlUtils.getFirstChildElementNS( toNode, wsaVersionNameSpace, "Address" );
106          if( addressNode == null )
107          {
108             throw new AssertionException( new AssertionError( "WS-A To Address property is not specified" ) );
109          }
110          String toAddressValue = XmlUtils.getElementText( addressNode );
111          if( StringUtils.isNullOrEmpty( toAddressValue ) )
112          {
113             throw new AssertionException( new AssertionError( "WS-A To Address property is empty" ) );
114          }
115          else
116          {
117             // check for anonymous - in case of mock response to=request.replyTo
118             if( AnonymousTypeConfig.PROHIBITED.toString().equals( messageExchange.getOperation().getAnonymous() )
119                     && WsaUtils.isAnonymousAddress(toAddressValue,wsaVersionNameSpace) )
120             {
121 					throw new AssertionException( new AssertionError("WS-A InvalidAddressingHeader To , Anonymous addresses are prohibited") );
122             }
123          }
124          // if fault_to is specified check if anonymous allowed
125          Element faultToNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "FaultTo" );
126          if( faultToNode != null )
127          {
128             addressNode = XmlUtils.getFirstChildElementNS( faultToNode, wsaVersionNameSpace, "Address" );
129             if( addressNode != null )
130             {
131                String faultToAddressValue = XmlUtils.getElementText( addressNode );
132                if( !StringUtils.isNullOrEmpty( faultToAddressValue ) )
133                {
134                   // check for anonymous
135                   if( AnonymousTypeConfig.PROHIBITED.toString().equals( messageExchange.getOperation().getAnonymous() )
136                           && WsaUtils.isAnonymousAddress(faultToAddressValue,wsaVersionNameSpace) )
137                   {
138                      throw new AssertionException( new AssertionError( "WS-A InvalidAddressingHeader FaultTo , Anonymous addresses are prohibited" ) );
139                   } else if (AnonymousTypeConfig.REQUIRED.toString().equals( ((WsdlMessageExchange) messageExchange).getOperation().getAnonymous() )
140                         && !(WsaUtils.isAnonymousAddress(faultToAddressValue,wsaVersionNameSpace) || WsaUtils.isNoneAddress(faultToAddressValue,wsaVersionNameSpace)))
141                   {
142                   	throw new AssertionException( new AssertionError( "WS-A InvalidAddressingHeader FaultTo , Anonymous addresses are required" ) );
143                   }
144                }
145             }
146          }
147 
148       }
149       catch( XmlException e )
150       {
151          SoapUI.logError( e );
152       }
153    }
154 
155 	public void validateWsAddressingRequest() throws AssertionException
156 	{
157 		String content = messageExchange.getRequestContent();
158 		validateWsAddressingCommon(content);
159 		WsdlOperation operation = messageExchange.getOperation();
160 
161 		if (operation.isRequestResponse())
162 		{
163 			// MessageId is Mandatory
164 			Element msgNode = XmlUtils.getFirstChildElementNS(header, wsaVersionNameSpace, "MessageID");
165 			if (msgNode == null)
166 			{
167 				throw new AssertionException(new AssertionError("WS-A MessageID property is not specified"));
168 			}
169 			String msgValue = XmlUtils.getElementText(msgNode);
170 			if (StringUtils.isNullOrEmpty(msgValue))
171 			{
172 				throw new AssertionException(new AssertionError("WS-A MessageID property is empty"));
173 			}
174 
175 			// ReplyTo is Mandatory
176 			Element replyToNode = XmlUtils.getFirstChildElementNS(header, wsaVersionNameSpace, "ReplyTo");
177 			if (replyToNode == null)
178 			{
179 				throw new AssertionException(new AssertionError("WS-A ReplyTo property is not specified"));
180 			}
181 			Element addressNode = XmlUtils.getFirstChildElementNS(replyToNode, wsaVersionNameSpace, "Address");
182 			if (addressNode == null)
183 			{
184 				throw new AssertionException(new AssertionError("WS-A ReplyTo Address property is not specified"));
185 			}
186 			String replyToAddressValue = XmlUtils.getElementText(addressNode);
187 			if (StringUtils.isNullOrEmpty(replyToAddressValue))
188 			{
189 				throw new AssertionException(new AssertionError("WS-A ReplyTo Address property is empty"));
190 			} else {
191             // check for anonymous
192             if( AnonymousTypeConfig.PROHIBITED.toString().equals( ((WsdlMessageExchange) messageExchange).getOperation().getAnonymous() )
193                     && WsaUtils.isAnonymousAddress(replyToAddressValue,wsaVersionNameSpace) )
194             {
195                throw new AssertionException( new AssertionError( "WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are prohibited" ) );
196             } else if (AnonymousTypeConfig.REQUIRED.toString().equals( ((WsdlMessageExchange) messageExchange).getOperation().getAnonymous() )
197                   && !(WsaUtils.isAnonymousAddress(replyToAddressValue,wsaVersionNameSpace)|| WsaUtils.isNoneAddress(replyToAddressValue,wsaVersionNameSpace)))
198             {
199             	throw new AssertionException( new AssertionError( "WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are required" ) );
200             }
201 			}
202 		}
203 	}
204 
205 	public void validateWsAddressingResponse() throws AssertionException
206 	{
207 		String content = messageExchange.getResponseContent();
208 		validateWsAddressingCommon(content);
209 
210 		// RelatesTo is Mandatory
211 		Element relatesToNode = XmlUtils.getFirstChildElementNS(header, wsaVersionNameSpace, "RelatesTo");
212 		if (relatesToNode == null)
213 		{
214 			throw new AssertionException(new AssertionError("WS-A RelatesTo property is not specified"));
215 		}
216 		String relationshipType = relatesToNode.getAttribute("RelationshipType");
217 		if (StringUtils.isNullOrEmpty(relationshipType))
218 		{
219 			throw new AssertionException(new AssertionError("WS-A RelationshipType is not specified"));
220 		}
221 		Element relatesToAddressNode = XmlUtils.getFirstChildElementNS(relatesToNode, wsaVersionNameSpace, "Address");
222 		if (relatesToAddressNode == null)
223 		{
224 			throw new AssertionException(new AssertionError("WS-A RelatesTo Address property is not specified"));
225 		}
226 		String relatesToAddressesValue = XmlUtils.getElementText(relatesToAddressNode);
227 		if (StringUtils.isNullOrEmpty(relatesToAddressesValue))
228 		{
229 			throw new AssertionException(new AssertionError("WS-A RelatesTo Address property is empty"));
230 		}
231       // if fault_to is specified check if anonymous allowed
232       Element replyToNode = XmlUtils.getFirstChildElementNS( header, wsaVersionNameSpace, "ReplyTo" );
233       if( replyToNode != null )
234       {
235          Element addressNode = XmlUtils.getFirstChildElementNS( replyToNode, wsaVersionNameSpace, "Address" );
236          if( addressNode != null )
237          {
238             String replyToAddressValue = XmlUtils.getElementText( addressNode );
239             if( !StringUtils.isNullOrEmpty( replyToAddressValue ) )
240             {
241                // check for anonymous
242                if( AnonymousTypeConfig.PROHIBITED.toString().equals( ((WsdlMessageExchange) messageExchange).getOperation().getAnonymous() )
243                        && WsaUtils.isAnonymousAddress(replyToAddressValue,wsaVersionNameSpace) )
244                {
245                   throw new AssertionException( new AssertionError( "WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are prohibited" ) );
246                } else if (AnonymousTypeConfig.REQUIRED.toString().equals( ((WsdlMessageExchange) messageExchange).getOperation().getAnonymous() )
247                      && !(WsaUtils.isAnonymousAddress(replyToAddressValue,wsaVersionNameSpace) || WsaUtils.isNoneAddress(replyToAddressValue,wsaVersionNameSpace)))
248                {
249                	throw new AssertionException( new AssertionError( "WS-A InvalidAddressingHeader ReplyTo , Anonymous addresses are required" ) );
250                }
251             }
252          }
253       }
254 	}
255 
256 }