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