View Javadoc

1   /*
2    *  soapui, copyright (C) 2005 Ole Matzura / eviware.com 
3    *
4    *  SoapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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;
14  
15  import java.beans.PropertyChangeEvent;
16  import java.beans.PropertyChangeListener;
17  import java.lang.reflect.Constructor;
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.Iterator;
21  import java.util.List;
22  import java.util.Map;
23  
24  import javax.swing.ImageIcon;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  import com.eviware.soapui.SoapUI;
30  import com.eviware.soapui.config.CallConfig;
31  import com.eviware.soapui.config.RequestAssertionConfig;
32  import com.eviware.soapui.impl.wsdl.WsdlOperation;
33  import com.eviware.soapui.impl.wsdl.WsdlRequest;
34  import com.eviware.soapui.impl.wsdl.actions.request.DeleteRequestAction;
35  import com.eviware.soapui.impl.wsdl.actions.request.RenameRequestAction;
36  import com.eviware.soapui.impl.wsdl.panels.request.WsdlTestRequestPanelBuilder;
37  import com.eviware.soapui.impl.wsdl.teststeps.WsdlAssertion.AssertionStatus;
38  import com.eviware.soapui.impl.wsdl.teststeps.actions.AddAssertionAction;
39  import com.eviware.soapui.impl.wsdl.teststeps.assertions.SchemaComplianceAssertion;
40  import com.eviware.soapui.impl.wsdl.teststeps.assertions.SimpleContainsAssertion;
41  import com.eviware.soapui.impl.wsdl.teststeps.assertions.SoapFaultAssertion;
42  import com.eviware.soapui.impl.wsdl.teststeps.assertions.XPathContainsAssertion;
43  import com.eviware.soapui.model.PanelBuilder;
44  import com.eviware.soapui.model.testsuite.TestCase;
45  
46  /***
47   * WsdlRequest extension that adds WsdlAssertions
48   * 
49   * @author Ole.Matzura
50   */
51  
52  public class WsdlTestRequest extends WsdlRequest implements PropertyChangeListener
53  {
54     public static final String RESPONSE_PROPERTY = WsdlTestRequest.class.getName() + "@response";
55     public static final String STATUS_PROPERTY = WsdlTestRequest.class.getName() + "@status";
56     
57     private List<WsdlAssertion> assertions = new ArrayList<WsdlAssertion>();
58     private Map<String,Class<? extends WsdlAssertion> > availableAssertions = new HashMap<String,Class<? extends WsdlAssertion> >();
59     private final static Log log = LogFactory.getLog( WsdlTestRequest.class );
60     private ImageIcon validRequestIcon;
61     private ImageIcon failedRequestIcon;
62     private ImageIcon unknownRequestIcon;
63     private WsdlAssertion.AssertionStatus currentStatus;
64     private final WsdlTestRequestStep testStep;
65     private List<WsdlTestRequestListener> testRequestListeners = new ArrayList<WsdlTestRequestListener>();
66     
67     public WsdlTestRequest( WsdlOperation operation, CallConfig callConfig, WsdlTestRequestStep testStep )
68     {
69        super( operation, callConfig );
70        this.testStep = testStep;
71        
72        initAssertions();
73     }
74     
75     protected PanelBuilder initPanelBuilder()
76     {
77        return new WsdlTestRequestPanelBuilder( this );
78     }
79     
80     public TestCase getTestCase()
81     {
82        return testStep.getTestCase();
83     }
84  
85     public WsdlTestRequestStep getRequestStep()
86     {
87        return testStep;
88     }
89     
90     protected void initIcons()
91     {
92        super.initIcons();
93        
94        validRequestIcon = SoapUI.createImageIcon("/valid_request.gif");
95        failedRequestIcon = SoapUI.createImageIcon("/invalid_request.gif");
96        unknownRequestIcon = SoapUI.createImageIcon("/unknown_request.gif");
97     }
98     
99     protected void initActions()
100    {
101       addAction( new RenameRequestAction( this ));
102       addAction( new DeleteRequestAction( this ));
103       addAction( new AddAssertionAction( this ));
104    }
105 
106    private void initAssertions()
107    {
108       availableAssertions.put( "Schema Compliance", SchemaComplianceAssertion.class );
109       availableAssertions.put( "Simple Contains", SimpleContainsAssertion.class );
110       availableAssertions.put( "XPath Match", XPathContainsAssertion.class );
111       availableAssertions.put( "SOAP Fault Assertion", SoapFaultAssertion.class );
112       
113       RequestAssertionConfig[] assertionConfigs = getConfig().getAssertionArray();
114       for (int i = 0; i < assertionConfigs.length; i++)
115       {
116          RequestAssertionConfig config = assertionConfigs[i];
117          String type = config.getType();
118          
119          if( availableAssertions.containsKey( type ))
120          {
121             addWsdlAssertion(config, type);
122          }
123       }
124    }
125 
126 	private WsdlAssertion addWsdlAssertion(RequestAssertionConfig config, String type) 
127 	{
128 		try
129 		{
130 		   Class<? extends WsdlAssertion> clazz = availableAssertions.get(type);
131 		   Constructor<? extends WsdlAssertion> ctor = clazz.getConstructor(new Class[] { RequestAssertionConfig.class, WsdlTestRequest.class });
132 
133 		   WsdlAssertion assertion = (WsdlAssertion) ctor.newInstance( config, this );
134 		   assertions.add(assertion);
135 		   assertion.addPropertyChangeListener( this);
136 		   
137 		   return assertion;
138 		}
139 		catch (Exception e)
140 		{
141 		   e.printStackTrace();
142 		   return null;
143 		}
144 	}
145    
146    public int getAssertionCount()
147    {
148       return assertions.size();
149    }
150 
151    public WsdlAssertion getAssertionAt(int c)
152    {
153       return assertions.get( c );
154    }
155 
156    public void setResponse(String response)
157    {
158       super.setResponse( response );
159       
160       assertRequest();
161    }
162 
163    private void assertRequest() 
164    {
165    	PropertyChangeNotifier notifier = new PropertyChangeNotifier();
166       
167       // assert!
168       for (Iterator<WsdlAssertion> iter = assertions.iterator(); iter.hasNext();)
169       {
170          iter.next().assertResponse( this );
171       }
172 
173       notifier.notifyChange();
174    }
175    
176    private class PropertyChangeNotifier
177    {
178 	   private AssertionStatus oldStatus;
179 	   private ImageIcon oldIcon;
180 
181 	   public PropertyChangeNotifier()
182 	   {
183 		   oldStatus = getAssertionStatus();
184 		   oldIcon = getIcon();
185 	   }
186 	   
187 	   public void notifyChange()
188 	   {
189 		   AssertionStatus newStatus = getAssertionStatus();
190 	      ImageIcon newIcon = getIcon();
191 	      
192 	      if( oldStatus != newStatus )
193 	         notifyPropertyChanged( STATUS_PROPERTY, oldStatus, newStatus );
194 	      
195 	      if( oldIcon != newIcon )
196 	         notifyPropertyChanged( ICON_PROPERTY, oldIcon, getIcon() );
197 	   }
198    }
199 
200    public String[] getAvailableAssertions()
201    {
202       return availableAssertions.keySet().toArray( new String[availableAssertions.size()] );
203    }
204 
205    public WsdlAssertion addAssertion(String assertionName)
206    {
207       if( !availableAssertions.containsKey( assertionName )) return null;
208       PropertyChangeNotifier notifier = new PropertyChangeNotifier();
209     
210       RequestAssertionConfig assertionConfig = getConfig().addNewAssertion();
211       assertionConfig.setType( assertionName );
212       
213       try
214       {
215       	WsdlAssertion assertion = addWsdlAssertion( assertionConfig, assertionName );
216       	notifyAssertionAdded( assertion );
217       	
218          if( getResponseContent() != null )
219          {
220             assertion.assertResponse( this );
221             notifier.notifyChange();
222          }
223          
224          return assertion;
225       }
226       catch (Exception e)
227       {
228          e.printStackTrace();
229          return null;
230       }
231    }
232 
233    private void notifyAssertionAdded(WsdlAssertion assertion)
234 	{
235    	WsdlTestRequestListener [] listeners = testRequestListeners.toArray( 
236    			new WsdlTestRequestListener[testRequestListeners.size()] );
237    	
238    	for( int c = 0; c < listeners.length; c++ )
239    	{
240    		listeners[c].assertionAdded( assertion );
241    	}
242 	}
243 
244    private void notifyAssertionRemoved( WsdlAssertion assertion)
245 	{
246    	WsdlTestRequestListener [] listeners = testRequestListeners.toArray( 
247    			new WsdlTestRequestListener[testRequestListeners.size()] );
248    	
249    	for( int c = 0; c < listeners.length; c++ )
250    	{
251    		listeners[c].assertionRemoved( assertion );
252    	}
253 	}
254 
255    
256 	public void removeAssertion(WsdlAssertion assertion)
257    {
258       int ix = assertions.indexOf( assertion );
259       if( ix == -1 ) 
260       {
261       	throw new RuntimeException( "assertion [" + assertion.getName() + "] not available " +
262       			"in test request [" + getName() + "]" );
263       }
264       
265       PropertyChangeNotifier notifier = new PropertyChangeNotifier();
266       
267       assertion.removePropertyChangeListener( this );
268       notifyAssertionRemoved( assertion );
269       
270       assertions.remove( ix );
271       getConfig().removeAssertion( ix );
272       
273       notifier.notifyChange();
274    }
275 
276    public AssertionStatus getAssertionStatus()
277    {
278       currentStatus = AssertionStatus.NONE;
279 
280       int c = getAssertionCount();
281       if( c == 0 ) return currentStatus;
282       
283       currentStatus = AssertionStatus.VALID;
284       
285       for( c = 0; c < getAssertionCount(); c++ )
286       {
287          AssertionStatus status = getAssertionAt( c ).getStatus();
288          if( status == AssertionStatus.FAILED )
289          {
290             currentStatus = AssertionStatus.FAILED;
291             break;
292          }
293          else if( status == AssertionStatus.UNKNOWN )
294          {
295             currentStatus = AssertionStatus.UNKNOWN;
296             break;
297          }
298       }
299       
300       return currentStatus;
301    }
302 
303    public ImageIcon getIcon()
304    {
305    	ImageIcon icon = getIconManager().getIcon();
306       if( icon == getIconManager().getRequestIcon() )
307       {
308          AssertionStatus status = getAssertionStatus();
309          if( status == AssertionStatus.VALID ) return validRequestIcon; 
310          else if( status == AssertionStatus.FAILED ) return failedRequestIcon; 
311          else if( status == AssertionStatus.UNKNOWN ) return unknownRequestIcon; 
312       }
313       
314       return icon;
315    }
316 
317    public void propertyChange(PropertyChangeEvent evt)
318    {
319 	  if( evt.getPropertyName().equals( WsdlAssertion.CONFIGURATION_PROPERTY ))
320 		  assertRequest();
321    }
322 
323    public void addWsdlTestRequestListener( WsdlTestRequestListener listener )
324    {
325    	testRequestListeners.add( listener );
326    }
327    
328    public void removeWsdlTestRequestListener( WsdlTestRequestListener listener )
329    {
330    	testRequestListeners.remove( listener );
331    }
332    
333    public interface WsdlTestRequestListener
334    {
335    	public void assertionAdded( WsdlAssertion assertion );
336    	
337    	public void assertionRemoved( WsdlAssertion assertion );
338    }
339 
340 	public void updateConfig(CallConfig request)
341 	{
342 		super.updateConfig(request);
343 		
344 		RequestAssertionConfig[] assertionConfigs = getConfig().getAssertionArray();
345       for (int i = 0; i < assertionConfigs.length; i++)
346       {
347          RequestAssertionConfig config = assertionConfigs[i];
348          assertions.get( i ).updateConfig( config );
349       }
350 	}
351 
352 	
353 }