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.submit.filters;
14  
15  import com.eviware.soapui.SoapUI;
16  import com.eviware.soapui.impl.rest.RestRequest;
17  import com.eviware.soapui.impl.rest.support.XmlBeansRestParamsTestPropertyHolder;
18  import com.eviware.soapui.impl.rest.support.XmlBeansRestParamsTestPropertyHolder.RestParamProperty;
19  import com.eviware.soapui.impl.wsdl.submit.transports.http.BaseHttpRequestTransport;
20  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.AttachmentDataSource;
21  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.AttachmentUtils;
22  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.RestRequestDataSource;
23  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.RestRequestMimeMessageRequestEntity;
24  import com.eviware.soapui.impl.wsdl.support.PathUtils;
25  import com.eviware.soapui.model.iface.Attachment;
26  import com.eviware.soapui.model.iface.SubmitContext;
27  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
28  import com.eviware.soapui.support.StringUtils;
29  import com.eviware.soapui.support.editor.inspectors.attachments.ContentTypeHandler;
30  import com.eviware.soapui.support.types.StringToStringMap;
31  
32  import org.apache.commons.httpclient.HttpMethod;
33  import org.apache.commons.httpclient.URI;
34  import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
35  import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
36  import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
37  import org.apache.commons.httpclient.methods.StringRequestEntity;
38  import org.apache.xmlbeans.XmlBoolean;
39  
40  import javax.activation.DataHandler;
41  import javax.activation.FileDataSource;
42  import javax.mail.MessagingException;
43  import javax.mail.internet.MimeBodyPart;
44  import javax.mail.internet.MimeMessage;
45  import javax.mail.internet.MimeMultipart;
46  import javax.mail.internet.PreencodedMimeBodyPart;
47  
48  import java.io.File;
49  import java.io.UnsupportedEncodingException;
50  import java.net.URLEncoder;
51  import java.util.ArrayList;
52  import java.util.List;
53  
54  /***
55   * RequestFilter that adds SOAP specific headers
56   *
57   * @author Ole.Matzura
58   */
59  
60  public class RestRequestFilter extends AbstractRequestFilter
61  {
62     @SuppressWarnings( "deprecation" )
63     @Override
64     public void filterRestRequest( SubmitContext context, RestRequest request )
65     {
66        HttpMethod httpMethod = (HttpMethod) context.getProperty( BaseHttpRequestTransport.HTTP_METHOD );
67  
68        String path = request.getPath();
69        StringBuffer query = new StringBuffer();
70  
71        StringToStringMap responseProperties = (StringToStringMap) context.getProperty( BaseHttpRequestTransport.RESPONSE_PROPERTIES );
72  
73        MimeMultipart formMp = "multipart/form-data".equals( request.getMediaType() ) ? new MimeMultipart() : null;
74  
75        XmlBeansRestParamsTestPropertyHolder params = request.getParams();
76        for( int c = 0; c < params.getPropertyCount(); c++ )
77        {
78           RestParamProperty param = params.getPropertyAt( c );
79  
80           String value = PropertyExpansionUtils.expandProperties( context, param.getValue() );
81           responseProperties.put( param.getName(), value );
82  
83           if( value != null && formMp == null && !param.isDisableUrlEncoding() )
84              value = URLEncoder.encode( value );
85  
86           if( !StringUtils.hasContent( value ) && !param.getRequired() )
87              continue;
88  
89           switch( param.getStyle() )
90           {
91              case HEADER:
92                 httpMethod.setRequestHeader( param.getName(), value );
93                 break;
94              case QUERY:
95                 if( formMp == null )
96                 {
97                    if( query.length() > 0 )
98                       query.append( '&' );
99  
100                   query.append( URLEncoder.encode( param.getName() ) );
101                   query.append( '=' );
102                   if( StringUtils.hasContent( value ) )
103                      query.append( value );
104                }
105                else
106                {
107                   try
108                   {
109                      addFormMultipart( request, formMp, param.getName(), value );
110                   }
111                   catch( MessagingException e )
112                   {
113                      e.printStackTrace();
114                   }
115                }
116 
117                break;
118             case TEMPLATE:
119                path = path.replaceAll( "//{" + param.getName() + "//}", value );
120                break;
121             case MATRIX:
122                if( param.getType().equals( XmlBoolean.type.getName() ) )
123                {
124                   if( value.toUpperCase().equals( "TRUE" ) || value.equals( "1" ) )
125                   {
126                      path += ";" + param.getName();
127                   }
128                }
129                else
130                {
131                   path += ";" + param.getName();
132                   if( StringUtils.hasContent( value ) )
133                   {
134                      path += "=" + value;
135                   }
136                }
137             case PLAIN:
138                break;
139          }
140       }
141 
142       if( PathUtils.isHttpPath( path ) )
143       {
144          try
145          {
146             httpMethod.setURI( new URI( path ) );
147          }
148          catch( Exception e )
149          {
150             e.printStackTrace();
151          }
152       }
153       else
154       {
155          httpMethod.setPath( path );
156       }
157 
158       if( query.length() > 0 && !request.isPostQueryString() )
159       {
160          httpMethod.setQueryString( query.toString() );
161       }
162 
163       String acceptEncoding = request.getAccept();
164       if( StringUtils.hasContent( acceptEncoding ) )
165       {
166          httpMethod.setRequestHeader( "Accept", acceptEncoding );
167       }
168 
169       String encoding = StringUtils.unquote( request.getEncoding() );
170 
171       if( formMp != null )
172       {
173          // create request message
174          try
175          {
176             if( request.hasRequestBody() && httpMethod instanceof EntityEnclosingMethod )
177             {
178                String requestContent = PropertyExpansionUtils.expandProperties( context, request.getRequestContent() );
179                if( StringUtils.hasContent( requestContent ) )
180                {
181                   initRootPart( request, requestContent, formMp );
182                }
183             }
184 
185             for( Attachment attachment : request.getAttachments() )
186             {
187                MimeBodyPart part = new MimeBodyPart();
188                part.setDisposition( "form-data; name=\"" + attachment.getName() + "\"" );
189                part.setDataHandler( new DataHandler( new AttachmentDataSource( attachment ) ) );
190 
191                formMp.addBodyPart( part );
192             }
193 
194             MimeMessage message = new MimeMessage( AttachmentUtils.JAVAMAIL_SESSION );
195             message.setContent( formMp );
196             message.saveChanges();
197             RestRequestMimeMessageRequestEntity mimeMessageRequestEntity = new RestRequestMimeMessageRequestEntity( message, request );
198             ( (EntityEnclosingMethod) httpMethod ).setRequestEntity( mimeMessageRequestEntity );
199             httpMethod.setRequestHeader( "Content-Type", mimeMessageRequestEntity.getContentType() );
200             httpMethod.setRequestHeader( "MIME-Version", "1.0" );
201          }
202          catch( Throwable e )
203          {
204             SoapUI.logError( e );
205          }
206       }
207       else if( request.hasRequestBody() && httpMethod instanceof EntityEnclosingMethod )
208       {
209          httpMethod.setRequestHeader( "Content-Type", request.getMediaType() );
210 
211          if( request.isPostQueryString() )
212          {
213             ( (EntityEnclosingMethod) httpMethod ).setRequestEntity( new StringRequestEntity( query.toString() ) );
214          }
215          else
216          {
217             String requestContent = PropertyExpansionUtils.expandProperties( context, request.getRequestContent() );
218             List<Attachment> attachments = new ArrayList<Attachment>();
219 
220             for( Attachment attachment : request.getAttachments() )
221             {
222                if( attachment.getContentType().equals( request.getMediaType() ) )
223                {
224                   attachments.add( attachment );
225                }
226             }
227 
228             if( StringUtils.hasContent( requestContent ) && attachments.isEmpty() )
229             {
230                try
231                {
232                   byte[] content = encoding == null ? requestContent.getBytes() : requestContent.getBytes( encoding );
233                   ( (EntityEnclosingMethod) httpMethod ).setRequestEntity( new ByteArrayRequestEntity( content ) );
234                }
235                catch( UnsupportedEncodingException e )
236                {
237                   ( (EntityEnclosingMethod) httpMethod ).setRequestEntity( new ByteArrayRequestEntity( requestContent.getBytes() ) );
238                }
239             }
240             else if( attachments.size() > 0 )
241             {
242                try
243                {
244                   MimeMultipart mp = null;
245 
246                   if( StringUtils.hasContent( requestContent ) )
247                   {
248                      mp = new MimeMultipart();
249                      initRootPart( request, requestContent, mp );
250                   }
251                   else if( attachments.size() == 1 )
252                   {
253                      ( (EntityEnclosingMethod) httpMethod ).setRequestEntity( new InputStreamRequestEntity(
254                              attachments.get( 0 ).getInputStream() ) );
255 
256                      httpMethod.setRequestHeader( "Content-Type", request.getMediaType() );
257                   }
258 
259                   if( ( (EntityEnclosingMethod) httpMethod ).getRequestEntity() == null )
260                   {
261                      if( mp == null )
262                         mp = new MimeMultipart();
263 
264                      // init mimeparts
265                      AttachmentUtils.addMimeParts( request, attachments, mp, new StringToStringMap() );
266 
267                      // create request message
268                      MimeMessage message = new MimeMessage( AttachmentUtils.JAVAMAIL_SESSION );
269                      message.setContent( mp );
270                      message.saveChanges();
271                      RestRequestMimeMessageRequestEntity mimeMessageRequestEntity = new RestRequestMimeMessageRequestEntity( message, request );
272                      ( (EntityEnclosingMethod) httpMethod ).setRequestEntity( mimeMessageRequestEntity );
273                      httpMethod.setRequestHeader( "Content-Type", mimeMessageRequestEntity.getContentType() );
274                      httpMethod.setRequestHeader( "MIME-Version", "1.0" );
275                   }
276                }
277                catch( Exception e )
278                {
279                   e.printStackTrace();
280                }
281             }
282          }
283       }
284    }
285 
286    private void addFormMultipart( RestRequest request, MimeMultipart formMp, String name, String value ) throws MessagingException
287    {
288       MimeBodyPart part = new MimeBodyPart();
289 
290       if( value.startsWith( "file:" ) )
291       {
292          File file = new File( value.substring( 5 ) );
293          part.setDisposition( "form-data; name=\"" + name + "\"; filename=\"" + file.getName() + "\"" );
294          if( file.exists() )
295          {
296             part.setDataHandler( new DataHandler( new FileDataSource( file ) ) );
297          }
298 
299          part.setHeader( "Content-Type", ContentTypeHandler.getContentTypeFromFilename( file.getName() ) );
300       }
301       else
302       {
303          part.setDisposition( "form-data; name=\"" + name + "\"" );
304          part.setText( URLEncoder.encode( value ), request.getEncoding() );
305       }
306 
307       if( part != null )
308       {
309          formMp.addBodyPart( part );
310       }
311    }
312 
313    protected void initRootPart( RestRequest wsdlRequest, String requestContent, MimeMultipart mp ) throws MessagingException
314    {
315       MimeBodyPart rootPart = new PreencodedMimeBodyPart( "8bit" );
316 //      rootPart.setContentID( AttachmentUtils.ROOTPART_SOAPUI_ORG );
317       mp.addBodyPart( rootPart, 0 );
318 
319       DataHandler dataHandler = new DataHandler( new RestRequestDataSource( wsdlRequest, requestContent ) );
320       rootPart.setDataHandler( dataHandler );
321    }
322 }