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.RestRepresentation;
16  import com.eviware.soapui.impl.rest.RestRepresentation.Type;
17  import com.eviware.soapui.impl.rest.RestRequest;
18  import com.eviware.soapui.impl.support.AbstractHttpRequest.RequestMethod;
19  import com.eviware.soapui.impl.support.HttpUtils;
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.model.ModelItem;
25  import com.eviware.soapui.model.iface.Request.SubmitException;
26  import com.eviware.soapui.model.iface.Submit;
27  import com.eviware.soapui.model.iface.SubmitContext;
28  import com.eviware.soapui.support.DocumentListenerAdapter;
29  import com.eviware.soapui.support.UISupport;
30  import com.eviware.soapui.support.components.JUndoableTextField;
31  import com.eviware.soapui.support.components.JXToolBar;
32  import com.eviware.soapui.support.editor.xml.support.AbstractXmlDocument;
33  
34  import javax.swing.*;
35  import javax.swing.text.Document;
36  import java.awt.*;
37  import java.awt.event.ItemEvent;
38  import java.awt.event.ItemListener;
39  import java.beans.PropertyChangeEvent;
40  import java.beans.PropertyChangeListener;
41  import java.util.ArrayList;
42  import java.util.Arrays;
43  import java.util.List;
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 JButton recreatePathButton;
55  
56     public AbstractRestRequestDesktopPanel( T modelItem, T2 requestItem )
57     {
58        super( modelItem, requestItem );
59  
60        if( requestItem.getResource() != null )
61           requestItem.getResource().addPropertyChangeListener( this );
62     }
63  
64     public void propertyChange( PropertyChangeEvent evt )
65     {
66        if( evt.getPropertyName().equals( "method" ) && !updatingRequest )
67        {
68           methodCombo.setSelectedItem( evt.getNewValue() );
69        }
70        else if( evt.getPropertyName().equals( "accept" ) && !updatingRequest )
71        {
72           acceptCombo.setSelectedItem( evt.getNewValue() );
73        }
74        else if( evt.getPropertyName().equals( "responseMediaTypes" ) && !updatingRequest )
75        {
76           Object item = acceptCombo.getSelectedItem();
77           acceptCombo.setModel( new DefaultComboBoxModel( ( Object[] ) evt.getNewValue() ) );
78           acceptCombo.setSelectedItem( item );
79        }
80        else if( evt.getPropertyName().equals( "path" ) &&
81                ( getRequest().getResource() == null || getRequest().getResource() == evt.getSource() ) )
82        {
83           if( pathLabel != null )
84           {
85              pathLabel.setText( getRequest().getResource().getFullPath() );
86           }
87  
88           if( !updating )
89           {
90              updating = true;
91              pathTextField.setText( ( String ) evt.getNewValue() );
92              updating = false;
93           }
94        }
95  
96        super.propertyChange( evt );
97     }
98  
99     @Override
100    protected ModelItemXmlEditor<?, ?> buildRequestEditor()
101    {
102       return new RestRequestMessageEditor( getRequest() );
103    }
104 
105    @Override
106    protected ModelItemXmlEditor<?, ?> buildResponseEditor()
107    {
108       return new RestResponseMessageEditor( getRequest() );
109    }
110 
111    @Override
112    protected Submit doSubmit() throws SubmitException
113    {
114       return getRequest().submit( new WsdlSubmitContext( getModelItem() ), true );
115    }
116 
117    @Override
118    public void afterSubmit( Submit submit, SubmitContext context )
119    {
120       super.afterSubmit( submit, context );
121 
122       HttpResponse response = getRequest().getResponse();
123       if( response != null )
124       {
125          if( HttpUtils.isErrorStatus( response.getStatusCode() ) )
126          {
127             extractRepresentation( response, RestRepresentation.Type.FAULT );
128          }
129          else
130          {
131             extractRepresentation( response, RestRepresentation.Type.RESPONSE );
132          }
133       }
134    }
135 
136    @SuppressWarnings( "unchecked" )
137    private void extractRepresentation( HttpResponse response, Type type )
138    {
139       RestRepresentation[] representations = getRequest().getRepresentations( type, null );
140       int c = 0;
141       for( ; c < representations.length; c++ )
142       {
143          if( representations[c].getMediaType().equals( response.getContentType() ) )
144          {
145             List status = representations[c].getStatus();
146             if( status == null || !status.contains( response.getStatusCode() ) )
147             {
148                status = status == null ? new ArrayList<Integer>() : new ArrayList<Integer>( status );
149                status.add( response.getStatusCode() );
150                representations[c].setStatus( status );
151             }
152             break;
153          }
154       }
155 
156       if( c == representations.length )
157       {
158          RestRepresentation representation = getRequest().addNewRepresentation( type );
159          representation.setMediaType( response.getContentType() );
160          representation.setStatus( Arrays.asList( response.getStatusCode() ) );
161       }
162    }
163 
164    @Override
165    protected String getHelpUrl()
166    {
167       return null;
168    }
169 
170    @Override
171    protected void insertButtons( JXToolBar toolbar )
172    {
173       if( getRequest().getResource() == null )
174       {
175          addToolbarComponents( toolbar );
176       }
177    }
178 
179    protected JComponent buildEndpointComponent()
180    {
181       return getRequest().getResource() == null ? null : super.buildEndpointComponent();
182    }
183 
184    @Override
185    protected JComponent buildToolbar()
186    {
187       if( getRequest().getResource() != null )
188       {
189          JPanel panel = new JPanel( new BorderLayout() );
190          panel.add( super.buildToolbar(), BorderLayout.NORTH );
191 
192          JXToolBar toolbar = UISupport.createToolbar();
193          addToolbarComponents( toolbar );
194 
195          panel.add( toolbar, BorderLayout.SOUTH );
196          return panel;
197       }
198       else
199       {
200          return super.buildToolbar();
201       }
202    }
203 
204    protected void addToolbarComponents( JXToolBar toolbar )
205    {
206       toolbar.addSeparator();
207       methodCombo = new JComboBox( new Object[]{RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT,
208               RequestMethod.DELETE, RequestMethod.HEAD} );
209 
210       methodCombo.setSelectedItem( getRequest().getMethod() );
211       methodCombo.setToolTipText( "Set desired HTTP method" );
212       methodCombo.addItemListener( new ItemListener()
213       {
214 
215          public void itemStateChanged( ItemEvent e )
216          {
217             updatingRequest = true;
218             getRequest().setMethod( ( RequestMethod ) methodCombo.getSelectedItem() );
219             updatingRequest = false;
220          }
221       } );
222 
223       toolbar.addLabeledFixed( "Method", methodCombo );
224       toolbar.addSeparator();
225 
226       if( getRequest().getResource() != null )
227       {
228          acceptCombo = new JComboBox( getRequest().getResponseMediaTypes() );
229          acceptCombo.setEditable( true );
230          acceptCombo.setToolTipText( "Sets accepted encoding(s) for response" );
231          acceptCombo.setSelectedItem( getRequest().getAccept() );
232          acceptCombo.addItemListener( new ItemListener()
233          {
234             public void itemStateChanged( ItemEvent e )
235             {
236                updatingRequest = true;
237                getRequest().setAccept( String.valueOf( acceptCombo.getSelectedItem() ) );
238                updatingRequest = false;
239             }
240          } );
241 
242          toolbar.addLabeledFixed( "Accept", acceptCombo );
243          toolbar.addSeparator();
244 
245          pathTextField = new JUndoableTextField();
246          pathTextField.setPreferredSize( new Dimension( 200, 20 ) );
247          pathTextField.setText( getRequest().getResource().getPath() );
248          pathTextField.getDocument().addDocumentListener( new DocumentListenerAdapter()
249          {
250             @Override
251             public void update( Document document )
252             {
253                if( updating )
254                   return;
255 
256                updating = true;
257                getRequest().getResource().setPath( pathTextField.getText() );
258                updating = false;
259             }
260          } );
261 
262          toolbar.addLabeledFixed( "Resource Path:", pathTextField );
263 
264          pathLabel = new JLabel( getRequest().getResource().getFullPath() );
265          pathLabel.setPreferredSize( new Dimension( 200, 20 ) );
266 
267          toolbar.addSeparator();
268          toolbar.addLabeledFixed( "Full Path:", pathLabel );
269       }
270       else
271       {
272          pathTextField = new JUndoableTextField();
273          pathTextField.setPreferredSize( new Dimension( 300, 20 ) );
274          pathTextField.setText( getRequest().getPath() );
275          pathTextField.getDocument().addDocumentListener( new DocumentListenerAdapter()
276          {
277             @Override
278             public void update( Document document )
279             {
280                getRequest().setPath( pathTextField.getText() );
281             }
282          } );
283 
284          toolbar.addLabeledFixed( "Request URL:", pathTextField );
285       }
286 
287       toolbar.addSeparator();
288    }
289 
290    protected boolean release()
291    {
292       if( getRequest().getResource() != null )
293       {
294          getRequest().getResource().removePropertyChangeListener( this );
295       }
296 
297       return super.release();
298    }
299 
300    public class RestRequestMessageEditor extends
301            AbstractHttpRequestDesktopPanel<?, ?>.AbstractHttpRequestMessageEditor<RestRequestDocument>
302    {
303       public RestRequestMessageEditor( RestRequest modelItem )
304       {
305          super( new RestRequestDocument( modelItem ) );
306       }
307    }
308 
309    public class RestResponseMessageEditor extends
310            AbstractHttpRequestDesktopPanel<?, ?>.AbstractHttpResponseMessageEditor<RestResponseDocument>
311    {
312       public RestResponseMessageEditor( RestRequest modelItem )
313       {
314          super( new RestResponseDocument( modelItem ) );
315       }
316    }
317 
318    public class RestRequestDocument extends AbstractXmlDocument implements PropertyChangeListener
319    {
320       private final RestRequest modelItem;
321       private boolean updating;
322 
323       public RestRequestDocument( RestRequest modelItem )
324       {
325          this.modelItem = modelItem;
326 
327          modelItem.addPropertyChangeListener( this );
328       }
329 
330       public RestRequest getRequest()
331       {
332          return modelItem;
333       }
334 
335       public String getXml()
336       {
337          return getRequest().getRequestContent();
338       }
339 
340       public void setXml( String xml )
341       {
342          if( !updating )
343          {
344             updating = true;
345             getRequest().setRequestContent( xml );
346             updating = false;
347          }
348       }
349 
350       public void propertyChange( PropertyChangeEvent evt )
351       {
352          if( evt.getPropertyName().equals( RestRequest.REQUEST_PROPERTY ) && !updating )
353          {
354             updating = true;
355             fireXmlChanged( ( String ) evt.getOldValue(), ( String ) evt.getNewValue() );
356             updating = false;
357          }
358       }
359    }
360 
361    public class RestResponseDocument extends AbstractXmlDocument implements PropertyChangeListener
362    {
363       private final RestRequest modelItem;
364 
365       public RestResponseDocument( RestRequest modelItem )
366       {
367          this.modelItem = modelItem;
368 
369          modelItem.addPropertyChangeListener( RestRequest.RESPONSE_PROPERTY, this );
370       }
371 
372       public RestRequest getRequest()
373       {
374          return modelItem;
375       }
376 
377       public String getXml()
378       {
379          return modelItem.getResponseContentAsXml();
380       }
381 
382       public void setXml( String xml )
383       {
384          HttpResponse response = getRequest().getResponse();
385          if( response != null )
386             response.setResponseContent( xml );
387       }
388 
389       public void propertyChange( PropertyChangeEvent evt )
390       {
391          fireXmlChanged( evt.getOldValue() == null ? null : ( ( HttpResponse ) evt.getOldValue() ).getContentAsString(),
392                  getXml() );
393       }
394    }
395 }