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  
13  package com.eviware.soapui.impl.wsdl.teststeps.assertions.basic;
14  
15  import com.eviware.soapui.config.TestAssertionConfig;
16  import com.eviware.soapui.impl.rest.RestResource;
17  import com.eviware.soapui.impl.rest.RestService;
18  import com.eviware.soapui.impl.support.AbstractInterface;
19  import com.eviware.soapui.impl.support.DefinitionContext;
20  import com.eviware.soapui.impl.wadl.WadlDefinitionContext;
21  import com.eviware.soapui.impl.wadl.support.WadlValidator;
22  import com.eviware.soapui.impl.wsdl.WsdlInterface;
23  import com.eviware.soapui.impl.wsdl.WsdlOperation;
24  import com.eviware.soapui.impl.wsdl.submit.RestMessageExchange;
25  import com.eviware.soapui.impl.wsdl.submit.WsdlMessageExchange;
26  import com.eviware.soapui.impl.wsdl.support.PathUtils;
27  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
28  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
29  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlValidator;
30  import com.eviware.soapui.impl.wsdl.teststeps.WsdlMessageAssertion;
31  import com.eviware.soapui.impl.wsdl.teststeps.assertions.AbstractTestAssertionFactory;
32  import com.eviware.soapui.model.iface.MessageExchange;
33  import com.eviware.soapui.model.iface.SubmitContext;
34  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
35  import com.eviware.soapui.model.testsuite.*;
36  import com.eviware.soapui.model.testsuite.AssertionError;
37  import com.eviware.soapui.support.StringUtils;
38  import com.eviware.soapui.support.UISupport;
39  import com.eviware.soapui.support.xml.XmlObjectConfigurationBuilder;
40  import com.eviware.soapui.support.xml.XmlObjectConfigurationReader;
41  import org.apache.xmlbeans.XmlObject;
42  
43  import java.util.HashMap;
44  import java.util.Map;
45  
46  /***
47   * Asserts that a request or response message complies with its related
48   * WSDL definition / XML Schema
49   *
50   * @author Ole.Matzura
51   */
52  
53  public class SchemaComplianceAssertion extends WsdlMessageAssertion implements RequestAssertion, ResponseAssertion
54  {
55     public static final String ID = "Schema Compliance";
56     public static final String LABEL = "Schema Compliance";
57  
58     private String definition;
59     private DefinitionContext definitionContext;
60     private String wsdlContextDef;
61     private static Map<String, WsdlContext> wsdlContextMap = new HashMap();
62     private static final String SCHEMA_COMPLIANCE_HAS_CLEARED_CACHE_FLAG = SchemaComplianceAssertion.class.getName() +
63             "@SchemaComplianceHasClearedCacheFlag";
64  
65     public SchemaComplianceAssertion( TestAssertionConfig assertionConfig, Assertable assertable )
66     {
67        super( assertionConfig, assertable, false, true, false, true );
68  
69        XmlObjectConfigurationReader reader = new XmlObjectConfigurationReader( getConfiguration() );
70        definition = reader.readString( "definition", null );
71     }
72  
73     @Override
74     public void prepare( TestRunner testRunner, TestRunContext testRunContext ) throws Exception
75     {
76        super.prepare( testRunner, testRunContext );
77  
78        definitionContext = null;
79        wsdlContextDef = null;
80  
81        // get correct context for checking if cache has been cleared for this run
82        PropertyExpansionContext context = testRunContext.hasProperty( TestRunContext.LOAD_TEST_CONTEXT ) ?
83                (PropertyExpansionContext) testRunContext.getProperty( TestRunContext.LOAD_TEST_CONTEXT ) : testRunContext;
84  
85        synchronized( context )
86        {
87           if( !context.hasProperty( SCHEMA_COMPLIANCE_HAS_CLEARED_CACHE_FLAG ) )
88           {
89              wsdlContextMap.clear();
90              context.setProperty( SCHEMA_COMPLIANCE_HAS_CLEARED_CACHE_FLAG, "yep!" );
91           }
92        }
93     }
94  
95     protected String internalAssertResponse( MessageExchange messageExchange, SubmitContext context ) throws AssertionException
96     {
97        if( messageExchange instanceof WsdlMessageExchange )
98        {
99           return assertWsdlResponse( (WsdlMessageExchange) messageExchange, context );
100       }
101       else if( messageExchange instanceof RestMessageExchange )
102       {
103          return assertWadlResponse( (RestMessageExchange) messageExchange, context );
104       }
105 
106       throw new AssertionException( new AssertionError( "Unknown MessageExchange type" ) );
107    }
108 
109    private String assertWadlResponse( RestMessageExchange messageExchange, SubmitContext context ) throws AssertionException
110    {
111       WadlDefinitionContext wadlContext = null;
112       try
113       {
114          definitionContext = getWadlContext( messageExchange, context );
115       }
116       catch( Exception e1 )
117       {
118          throw new AssertionException( new AssertionError( e1.getMessage() ) );
119       }
120 
121       WadlValidator validator = new WadlValidator( wadlContext );
122 
123       try
124       {
125          AssertionError[] errors = validator.assertResponse( messageExchange );
126          if( errors.length > 0 )
127             throw new AssertionException( errors );
128       }
129       catch( AssertionException e )
130       {
131          throw e;
132       }
133       catch( Exception e )
134       {
135          throw new AssertionException( new AssertionError( e.getMessage() ) );
136       }
137 
138       return "Schema compliance OK";
139    }
140 
141    private String assertWsdlResponse( WsdlMessageExchange messageExchange, SubmitContext context )
142            throws AssertionException
143    {
144       WsdlContext wsdlContext = null;
145       try
146       {
147          wsdlContext = (WsdlContext) getWsdlContext( messageExchange, context );
148       }
149       catch( Exception e1 )
150       {
151          throw new AssertionException( new AssertionError( e1.getMessage() ) );
152       }
153 
154       WsdlValidator validator = new WsdlValidator( wsdlContext );
155 
156       try
157       {
158          AssertionError[] errors = validator.assertResponse( messageExchange, false );
159          if( errors.length > 0 )
160             throw new AssertionException( errors );
161       }
162       catch( AssertionException e )
163       {
164          throw e;
165       }
166       catch( Exception e )
167       {
168          throw new AssertionException( new AssertionError( e.getMessage() ) );
169       }
170 
171       return "Schema compliance OK";
172    }
173 
174    private DefinitionContext getWsdlContext( WsdlMessageExchange messageExchange, SubmitContext context ) throws Exception
175    {
176       WsdlOperation operation = messageExchange.getOperation();
177       WsdlInterface iface = operation.getInterface();
178       if( StringUtils.isNullOrEmpty( definition ) || definition.equals( iface.getDefinition() ) )
179       {
180          definitionContext = ( iface ).getWsdlContext();
181          ( (WsdlContext) definitionContext ).loadIfNecessary();
182       }
183       else
184       {
185          String def = PathUtils.expandPath( definition, iface, context );
186          if( definitionContext == null || !def.equals( wsdlContextDef ) )
187          {
188             definitionContext = getContext( def, iface.getSoapVersion() );
189 //            ( (WsdlContext) definitionContext ).load();
190             ( (WsdlContext) definitionContext ).setInterface( iface );
191             wsdlContextDef = def;
192          }
193       }
194 
195       return definitionContext;
196    }
197 
198    private synchronized WsdlContext getContext( String wsdlLocation, SoapVersion soapVersion ) throws Exception
199    {
200       if( wsdlContextMap.containsKey( wsdlLocation ) )
201       {
202          return wsdlContextMap.get( wsdlLocation );
203       }
204       else
205       {
206          WsdlContext newWsdlContext = new WsdlContext( wsdlLocation, soapVersion );
207          newWsdlContext.load();
208          wsdlContextMap.put( wsdlLocation, newWsdlContext );
209          return newWsdlContext;
210       }
211    }
212 
213    private DefinitionContext getWadlContext( RestMessageExchange messageExchange, SubmitContext context ) throws Exception
214    {
215       RestResource operation = messageExchange.getResource();
216       RestService service = operation.getService();
217       if( StringUtils.isNullOrEmpty( definition ) || definition.equals(
218               PathUtils.expandPath( service.getDefinition(), service, context ) ) )
219       {
220          definitionContext = service.getWadlContext();
221          ( (WadlDefinitionContext) definitionContext ).loadIfNecessary();
222       }
223       else
224       {
225          String def = PathUtils.expandPath( definition, service, context );
226          if( definitionContext == null || !def.equals( wsdlContextDef ) )
227          {
228             definitionContext = new WadlDefinitionContext( def );
229             ( (WadlDefinitionContext) definitionContext ).load();
230             ( (WadlDefinitionContext) definitionContext ).setInterface( service );
231             wsdlContextDef = def;
232          }
233       }
234 
235       return definitionContext;
236    }
237 
238    public boolean configure()
239    {
240       String value = definition;
241 
242       WsdlInterface iface = (WsdlInterface) getAssertable().getInterface();
243       String orgDef = iface == null ? null : iface.getDefinition();
244 
245       if( StringUtils.isNullOrEmpty( value ) )
246       {
247          value = orgDef;
248       }
249 
250       value = UISupport.prompt( "Specify definition url to validate by", "Configure SchemaCompliance Assertion", value );
251 
252       if( value == null ) return false;
253 
254       if( StringUtils.isNullOrEmpty( value ) || value.equals( orgDef ) )
255          definition = "";
256       else
257          definition = value;
258 
259       setConfiguration( createConfiguration() );
260       return true;
261    }
262 
263    protected XmlObject createConfiguration()
264    {
265       XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder();
266       return builder.add( "definition", definition ).finish();
267    }
268 
269    protected String internalAssertRequest( MessageExchange messageExchange, SubmitContext context ) throws AssertionException
270    {
271       WsdlContext wsdlContext = null;
272       try
273       {
274          wsdlContext = (WsdlContext) getWsdlContext( (WsdlMessageExchange) messageExchange, context );
275       }
276       catch( Exception e1 )
277       {
278          throw new AssertionException( new AssertionError( e1.getMessage() ) );
279       }
280       WsdlValidator validator = new WsdlValidator( wsdlContext );
281 
282       try
283       {
284          AssertionError[] errors = validator.assertRequest( (WsdlMessageExchange) messageExchange, false );
285          if( errors.length > 0 )
286             throw new AssertionException( errors );
287       }
288       catch( AssertionException e )
289       {
290          throw e;
291       }
292       catch( Exception e )
293       {
294          throw new AssertionException( new AssertionError( e.getMessage() ) );
295       }
296 
297       return "Schema compliance OK";
298    }
299 
300    public static class Factory extends AbstractTestAssertionFactory
301    {
302       public Factory()
303       {
304          super( SchemaComplianceAssertion.ID, SchemaComplianceAssertion.LABEL, SchemaComplianceAssertion.class );
305       }
306 
307       @Override
308       public boolean canAssert( Assertable assertable )
309       {
310          return super.canAssert( assertable ) && assertable.getInterface() instanceof AbstractInterface &&
311                  ( (AbstractInterface) assertable.getInterface() ).getDefinitionContext().hasSchemaTypes();
312       }
313    }
314 }