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.rest.panels.request;
14  
15  import com.eviware.soapui.impl.rest.RestRequest;
16  import com.eviware.soapui.impl.rest.RestResource;
17  import com.eviware.soapui.impl.rest.support.RestUtils;
18  import com.eviware.soapui.impl.rest.support.XmlBeansRestParamsTestPropertyHolder;
19  import com.eviware.soapui.impl.support.AbstractHttpRequest.RequestMethod;
20  import com.eviware.soapui.impl.support.components.ModelItemXmlEditor;
21  import com.eviware.soapui.impl.support.panels.AbstractHttpRequestDesktopPanel;
22  import com.eviware.soapui.impl.wsdl.WsdlSubmitContext;
23  import com.eviware.soapui.impl.wsdl.submit.transports.http.HttpResponse;
24  import com.eviware.soapui.impl.wsdl.teststeps.RestTestRequest;
25  import com.eviware.soapui.model.ModelItem;
26  import com.eviware.soapui.model.iface.Request.SubmitException;
27  import com.eviware.soapui.model.iface.Submit;
28  import com.eviware.soapui.model.support.TestPropertyListenerAdapter;
29  import com.eviware.soapui.model.testsuite.TestProperty;
30  import com.eviware.soapui.support.DocumentListenerAdapter;
31  import com.eviware.soapui.support.UISupport;
32  import com.eviware.soapui.support.components.JUndoableTextField;
33  import com.eviware.soapui.support.components.JXToolBar;
34  import com.eviware.soapui.support.editor.xml.support.AbstractXmlDocument;
35  import com.eviware.soapui.support.swing.ModelItemListCellRenderer;
36  
37  import javax.swing.*;
38  import javax.swing.text.Document;
39  import java.awt.*;
40  import java.awt.event.ItemEvent;
41  import java.awt.event.ItemListener;
42  import java.beans.PropertyChangeEvent;
43  import java.beans.PropertyChangeListener;
44  
45  public abstract class AbstractRestRequestDesktopPanel<T extends ModelItem, T2 extends RestRequest>
46          extends AbstractHttpRequestDesktopPanel<T, T2>
47  {
48     private boolean updatingRequest;
49     private JComboBox methodCombo;
50     private JUndoableTextField pathTextField;
51     private JComboBox acceptCombo;
52     private JLabel pathLabel;
53     private boolean updating;
54     private AbstractRestRequestDesktopPanel<T, T2>.InternalTestPropertyListener testPropertyListener = new AbstractRestRequestDesktopPanel.InternalTestPropertyListener();
55     private AbstractRestRequestDesktopPanel<T, T2>.RestParamPropertyChangeListener restParamPropertyChangeListener = new AbstractRestRequestDesktopPanel.RestParamPropertyChangeListener();
56     private JComboBox pathCombo;
57  
58     public AbstractRestRequestDesktopPanel( T modelItem, T2 requestItem )
59     {
60        super( modelItem, requestItem );
61  
62        if( requestItem.getResource() != null )
63        {
64           requestItem.getResource().addPropertyChangeListener( this );
65        }
66  
67        requestItem.addTestPropertyListener( testPropertyListener );
68  
69        for( TestProperty param : requestItem.getParams().getProperties().values() )
70        {
71           ( (XmlBeansRestParamsTestPropertyHolder.RestParamProperty) param ).addPropertyChangeListener( restParamPropertyChangeListener );
72        }
73     }
74  
75     public void propertyChange( PropertyChangeEvent evt )
76     {
77        updateFullPathLabel();
78  
79        if( evt.getPropertyName().equals( "method" ) && !updatingRequest )
80        {
81           methodCombo.setSelectedItem( evt.getNewValue() );
82        }
83        else if( evt.getPropertyName().equals( "accept" ) && !updatingRequest )
84        {
85           acceptCombo.setSelectedItem( evt.getNewValue() );
86        }
87        else if( evt.getPropertyName().equals( "responseMediaTypes" ) && !updatingRequest )
88        {
89           Object item = acceptCombo.getSelectedItem();
90           acceptCombo.setModel( new DefaultComboBoxModel( (Object[]) evt.getNewValue() ) );
91           acceptCombo.setSelectedItem( item );
92        }
93        else if( evt.getPropertyName().equals( "path" ) &&
94                ( getRequest().getResource() == null || getRequest().getResource() == evt.getSource() ) )
95        {
96           if( pathLabel != null )
97           {
98              updateFullPathLabel();
99           }
100 
101          if( !updating && pathTextField != null )
102          {
103             updating = true;
104             pathTextField.setText( (String) evt.getNewValue() );
105             pathTextField.setToolTipText( pathTextField.getText() );
106             updating = false;
107          }
108       }
109 
110       super.propertyChange( evt );
111    }
112 
113    @Override
114    protected ModelItemXmlEditor<?, ?> buildRequestEditor()
115    {
116       return new RestRequestMessageEditor( getRequest() );
117    }
118 
119    @Override
120    protected ModelItemXmlEditor<?, ?> buildResponseEditor()
121    {
122       return new RestResponseMessageEditor( getRequest() );
123    }
124 
125    @Override
126    protected Submit doSubmit() throws SubmitException
127    {
128       return getRequest().submit( new WsdlSubmitContext( getModelItem() ), true );
129    }
130 
131    @Override
132    protected String getHelpUrl()
133    {
134       return null;
135    }
136 
137    @Override
138    protected void insertButtons( JXToolBar toolbar )
139    {
140       if( getRequest().getResource() == null )
141       {
142          addToolbarComponents( toolbar );
143       }
144    }
145 
146    protected JComponent buildEndpointComponent()
147    {
148       return getRequest().getResource() == null ? null : super.buildEndpointComponent();
149    }
150 
151    @Override
152    protected JComponent buildToolbar()
153    {
154       if( getRequest().getResource() != null )
155       {
156          JPanel panel = new JPanel( new BorderLayout() );
157          panel.add( super.buildToolbar(), BorderLayout.NORTH );
158 
159          JXToolBar toolbar = UISupport.createToolbar();
160          addToolbarComponents( toolbar );
161 
162          panel.add( toolbar, BorderLayout.SOUTH );
163          return panel;
164       }
165       else
166       {
167          return super.buildToolbar();
168       }
169    }
170 
171    protected void addToolbarComponents( JXToolBar toolbar )
172    {
173       toolbar.addSeparator();
174       methodCombo = new JComboBox( new Object[]{RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT,
175               RequestMethod.DELETE, RequestMethod.HEAD} );
176 
177       methodCombo.setSelectedItem( getRequest().getMethod() );
178       methodCombo.setToolTipText( "Set desired HTTP method" );
179       methodCombo.addItemListener( new ItemListener()
180       {
181          public void itemStateChanged( ItemEvent e )
182          {
183             updatingRequest = true;
184             getRequest().setMethod( (RequestMethod) methodCombo.getSelectedItem() );
185             updatingRequest = false;
186          }
187       } );
188 
189       toolbar.addLabeledFixed( "Method", methodCombo );
190       toolbar.addSeparator();
191 
192       if( getRequest().getResource() != null )
193       {
194          acceptCombo = new JComboBox( getRequest().getResponseMediaTypes() );
195          acceptCombo.setEditable( true );
196          acceptCombo.setToolTipText( "Sets accepted encoding(s) for response" );
197          acceptCombo.setSelectedItem( getRequest().getAccept() );
198          acceptCombo.addItemListener( new ItemListener()
199          {
200             public void itemStateChanged( ItemEvent e )
201             {
202                updatingRequest = true;
203                getRequest().setAccept( String.valueOf( acceptCombo.getSelectedItem() ) );
204                updatingRequest = false;
205             }
206          } );
207 
208          toolbar.addLabeledFixed( "Accept", acceptCombo );
209          toolbar.addSeparator();
210 
211          if( getRequest() instanceof RestTestRequest )
212          {
213             pathCombo = new JComboBox( new PathComboBoxModel() );
214             pathCombo.setRenderer( new ModelItemListCellRenderer() );
215             pathCombo.setPreferredSize( new Dimension( 200, 20 ) );
216             pathCombo.setSelectedItem( getRequest().getResource().getPath() );
217             pathCombo.addItemListener( new ItemListener()
218             {
219                public void itemStateChanged( ItemEvent e )
220                {
221                   if( updating )
222                      return;
223 
224                   updating = true;
225                   getRequest().getResource().setPath( String.valueOf( pathCombo.getSelectedItem() ) );
226                   updating = false;
227                }
228             } );
229 
230             toolbar.addLabeledFixed( "Resource:", pathCombo );
231             toolbar.addSeparator();
232          }
233          else
234          {
235             toolbar.add( new JLabel( "Full Path: " ));
236          }
237 
238          pathLabel = new JLabel();
239          updateFullPathLabel();
240 
241          toolbar.add( pathLabel );
242       }
243       else
244       {
245          pathTextField = new JUndoableTextField();
246          pathTextField.setPreferredSize( new Dimension( 300, 20 ) );
247          pathTextField.setText( getRequest().getPath() );
248          pathTextField.setToolTipText( pathTextField.getText() );
249          pathTextField.getDocument().addDocumentListener( new DocumentListenerAdapter()
250          {
251             @Override
252             public void update( Document document )
253             {
254                getRequest().setPath( pathTextField.getText() );
255             }
256          } );
257 
258          toolbar.addLabeledFixed( "Request URL:", pathTextField );
259       }
260 
261       toolbar.addSeparator();
262    }
263 
264    protected boolean release()
265    {
266       if( getRequest().getResource() != null )
267       {
268          getRequest().getResource().removePropertyChangeListener( this );
269       }
270 
271       getRequest().removeTestPropertyListener( testPropertyListener );
272 
273       for( TestProperty param : getRequest().getParams().getProperties().values() )
274       {
275          ( (XmlBeansRestParamsTestPropertyHolder.RestParamProperty) param ).removePropertyChangeListener( restParamPropertyChangeListener );
276       }
277 
278       return super.release();
279    }
280 
281    public class RestRequestMessageEditor extends
282            AbstractHttpRequestDesktopPanel<?, ?>.AbstractHttpRequestMessageEditor<RestRequestDocument>
283    {
284       public RestRequestMessageEditor( RestRequest modelItem )
285       {
286          super( new RestRequestDocument( modelItem ) );
287       }
288    }
289 
290    public class RestResponseMessageEditor extends
291            AbstractHttpRequestDesktopPanel<?, ?>.AbstractHttpResponseMessageEditor<RestResponseDocument>
292    {
293       public RestResponseMessageEditor( RestRequest modelItem )
294       {
295          super( new RestResponseDocument( modelItem ) );
296       }
297    }
298 
299    public class RestRequestDocument extends AbstractXmlDocument implements PropertyChangeListener
300    {
301       private final RestRequest modelItem;
302       private boolean updating;
303 
304       public RestRequestDocument( RestRequest modelItem )
305       {
306          this.modelItem = modelItem;
307 
308          modelItem.addPropertyChangeListener( this );
309       }
310 
311       public RestRequest getRequest()
312       {
313          return modelItem;
314       }
315 
316       public String getXml()
317       {
318          return getRequest().getRequestContent();
319       }
320 
321       public void setXml( String xml )
322       {
323          if( !updating )
324          {
325             updating = true;
326             getRequest().setRequestContent( xml );
327             updating = false;
328          }
329       }
330 
331       public void propertyChange( PropertyChangeEvent evt )
332       {
333          if( evt.getPropertyName().equals( RestRequest.REQUEST_PROPERTY ) && !updating )
334          {
335             updating = true;
336             fireXmlChanged( (String) evt.getOldValue(), (String) evt.getNewValue() );
337             updating = false;
338          }
339       }
340    }
341 
342    public class RestResponseDocument extends AbstractXmlDocument implements PropertyChangeListener
343    {
344       private final RestRequest modelItem;
345 
346       public RestResponseDocument( RestRequest modelItem )
347       {
348          this.modelItem = modelItem;
349 
350          modelItem.addPropertyChangeListener( RestRequest.RESPONSE_PROPERTY, this );
351       }
352 
353       public RestRequest getRequest()
354       {
355          return modelItem;
356       }
357 
358       public String getXml()
359       {
360          return modelItem.getResponseContentAsXml();
361       }
362 
363       public void setXml( String xml )
364       {
365          HttpResponse response = getRequest().getResponse();
366          if( response != null )
367             response.setResponseContent( xml );
368       }
369 
370       public void propertyChange( PropertyChangeEvent evt )
371       {
372          fireXmlChanged( evt.getOldValue() == null ? null : ( (HttpResponse) evt.getOldValue() ).getContentAsString(),
373                  getXml() );
374       }
375    }
376 
377    private class InternalTestPropertyListener extends TestPropertyListenerAdapter
378    {
379       @Override
380       public void propertyValueChanged( String name, String oldValue, String newValue )
381       {
382          updateFullPathLabel();
383       }
384 
385       @Override
386       public void propertyAdded( String name )
387       {
388          updateFullPathLabel();
389 
390          getRequest().getParams().getProperty( name ).addPropertyChangeListener( restParamPropertyChangeListener );
391       }
392 
393       @Override
394       public void propertyRemoved( String name )
395       {
396          updateFullPathLabel();
397       }
398 
399       @Override
400       public void propertyRenamed( String oldName, String newName )
401       {
402          updateFullPathLabel();
403       }
404    }
405 
406    private void updateFullPathLabel()
407    {
408       if( pathLabel != null && getRequest().getResource() != null )
409       {
410          String text = RestUtils.expandPath( getRequest().getResource().getFullPath(), getRequest().getParams(), getRequest() );
411          pathLabel.setText( "[" + text + "]" );
412          pathLabel.setToolTipText( text );
413       }
414    }
415 
416    private class RestParamPropertyChangeListener implements PropertyChangeListener
417    {
418       public void propertyChange( PropertyChangeEvent evt )
419       {
420          updateFullPathLabel();
421       }
422    }
423 
424    private class PathComboBoxModel extends AbstractListModel implements ComboBoxModel
425    {
426       public int getSize()
427       {
428          return getRequest().getResource().getService().getAllResources().size();
429       }
430 
431       public Object getElementAt( int index )
432       {
433          return getRequest().getResource().getService().getAllResources().get( index );
434       }
435 
436       public void setSelectedItem( Object anItem )
437       {
438          ( (RestTestRequest) getRequest() ).setResource( (RestResource) anItem );
439       }
440 
441       public Object getSelectedItem()
442       {
443          return getRequest().getResource();
444       }
445    }
446 }