1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.impl.wsdl.mock;
14
15 import groovy.lang.Binding;
16 import groovy.lang.Script;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import javax.activation.DataHandler;
24 import javax.mail.MessagingException;
25 import javax.mail.internet.MimeBodyPart;
26 import javax.mail.internet.MimeMessage;
27 import javax.mail.internet.MimeMultipart;
28 import javax.mail.internet.PreencodedMimeBodyPart;
29 import javax.swing.ImageIcon;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33
34 import com.eviware.soapui.SoapUI;
35 import com.eviware.soapui.config.AttachmentConfig;
36 import com.eviware.soapui.config.HeaderConfig;
37 import com.eviware.soapui.config.MockResponseConfig;
38 import com.eviware.soapui.impl.actions.ShowDesktopPanelAction;
39 import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
40 import com.eviware.soapui.impl.wsdl.AttachmentContainer;
41 import com.eviware.soapui.impl.wsdl.WsdlAttachmentPart;
42 import com.eviware.soapui.impl.wsdl.WsdlOperation;
43 import com.eviware.soapui.impl.wsdl.actions.mockresponse.CloneMockResponseAction;
44 import com.eviware.soapui.impl.wsdl.actions.mockresponse.DeleteMockResponseAction;
45 import com.eviware.soapui.impl.wsdl.actions.mockresponse.RenameMockResponseAction;
46 import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
47 import com.eviware.soapui.impl.wsdl.submit.transports.http.AttachmentUtils;
48 import com.eviware.soapui.impl.wsdl.submit.transports.http.BodyPartAttachment;
49 import com.eviware.soapui.impl.wsdl.submit.transports.http.MimeMessageMockResponseEntity;
50 import com.eviware.soapui.impl.wsdl.submit.transports.http.MockResponseDataSource;
51 import com.eviware.soapui.impl.wsdl.support.FileAttachment;
52 import com.eviware.soapui.impl.wsdl.support.HelpUrls;
53 import com.eviware.soapui.impl.wsdl.support.MessageXmlObject;
54 import com.eviware.soapui.impl.wsdl.support.MessageXmlPart;
55 import com.eviware.soapui.impl.wsdl.support.MockFileAttachment;
56 import com.eviware.soapui.impl.wsdl.support.ModelItemIconAnimator;
57 import com.eviware.soapui.impl.wsdl.support.WsdlAttachment;
58 import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
59 import com.eviware.soapui.model.iface.Attachment;
60 import com.eviware.soapui.model.mock.MockResponse;
61 import com.eviware.soapui.model.mock.MockRunContext;
62 import com.eviware.soapui.settings.WsdlSettings;
63 import com.eviware.soapui.support.Tools;
64 import com.eviware.soapui.support.UISupport;
65 import com.eviware.soapui.support.action.ActionSupport;
66 import com.eviware.soapui.support.types.StringToStringMap;
67
68 public class WsdlMockResponse extends AbstractWsdlModelItem<MockResponseConfig> implements MockResponse, AttachmentContainer
69 {
70 private final static Log log = LogFactory.getLog( WsdlMockResponse.class );
71
72 public final static String MOCKRESULT_PROPERTY = WsdlMockResponse.class.getName() + "@mockresult";
73 public final static String SCRIPT_PROPERTY = WsdlMockResponse.class.getName() + "@script";
74 public final static String HEADERS_PROPERTY = WsdlMockResponse.class.getName() + "@headers";
75 public static final String DISABLE_MULTIPART_ATTACHMENTS = WsdlMockResponse.class.getName() + "@disable-multipart-attachments";
76
77 protected List<FileAttachment> attachments = new ArrayList<FileAttachment>();
78 private List<WsdlAttachmentPart> definedAttachmentParts;
79 private ModelItemIconAnimator iconAnimator;
80 private WsdlMockResult mockResult;
81
82 public WsdlMockResponse( WsdlMockOperation operation, MockResponseConfig config )
83 {
84 super( config, operation, "/mockResponse.gif" );
85
86 for( AttachmentConfig ac : getConfig().getAttachmentList() )
87 {
88 attachments.add( new MockFileAttachment( ac, this ));
89 }
90
91 if( !config.isSetEncoding() )
92 config.setEncoding( "UTF-8" );
93
94 addAction( new ShowDesktopPanelAction( "Open MockResponse Editor", "Opens the MockResponse Editor for this MockResponse", this ));
95 addAction( ActionSupport.SEPARATOR_ACTION );
96
97 addAction( new CloneMockResponseAction( this ));
98 addAction( ActionSupport.SEPARATOR_ACTION );
99 addAction( new RenameMockResponseAction( this ));
100 addAction( new DeleteMockResponseAction( this ));
101 addAction( ActionSupport.SEPARATOR_ACTION );
102 addAction( new ShowOnlineHelpAction( HelpUrls.MOCKRESPONSE_HELP_URL ));
103
104 iconAnimator = new ModelItemIconAnimator( this, "/mockResponse.gif",
105 new String[] {"/exec_request_1.gif", "/exec_request_2.gif",
106 "/exec_request_3.gif", "/exec_request_4.gif"} );
107 }
108
109 public Attachment[] getAttachments()
110 {
111 return attachments.toArray( new Attachment[attachments.size()] );
112 }
113
114 public String getScript()
115 {
116 return getConfig().isSetScript() ? getConfig().getScript().getStringValue() : null;
117 }
118
119 public String getEncoding()
120 {
121 return getConfig().getEncoding();
122 }
123
124 public void setEncoding( String encoding )
125 {
126 String old = getEncoding();
127 getConfig().setEncoding( encoding );
128 notifyPropertyChanged( ENCODING_PROPERTY, old, encoding );
129 }
130
131 public String getResponseContent()
132 {
133 return getConfig().getResponseContent();
134 }
135
136 public void setResponseContent( String responseContent )
137 {
138 String oldContent = getResponseContent();
139 if( !responseContent.equals( oldContent ))
140 {
141 getConfig().setResponseContent( responseContent );
142 notifyPropertyChanged( RESPONSECONTENT_PROPERTY, oldContent, responseContent );
143 }
144 }
145
146 @Override
147 public ImageIcon getIcon()
148 {
149 return iconAnimator.getIcon();
150 }
151
152 public WsdlMockOperation getMockOperation()
153 {
154 return ( WsdlMockOperation ) getParent();
155 }
156
157 public WsdlMockResult execute( WsdlMockRequest request, WsdlMockResult result ) throws DispatchException
158 {
159 try
160 {
161 iconAnimator.start();
162 StringToStringMap responseHeaders = getResponseHeaders();
163 StringToStringMap contextProperties = request.getContext().toStringToStringMap();
164 for( String name : responseHeaders.keySet() )
165 {
166 result.addHeader( name, Tools.expandProperties( contextProperties, responseHeaders.get( name ), false ));
167 }
168
169 String responseContent = getResponseContent();
170 String script = getScript();
171 if( script != null && script.trim().length() > 0 )
172 {
173 evaluateScript( request );
174 contextProperties = request.getContext().toStringToStringMap();
175 responseContent = Tools.expandProperties( contextProperties, responseContent, false );
176 }
177
178 if( !result.isCommitted())
179 {
180 responseContent = writeResponse( result, responseContent );
181 }
182
183 result.setReponseContent( responseContent );
184
185 setMockResult( result );
186
187 return mockResult;
188 }
189 catch( Throwable e )
190 {
191 throw new DispatchException( e );
192 }
193 finally
194 {
195 iconAnimator.stop();
196 }
197 }
198
199 public void evaluateScript( WsdlMockRequest request )
200 {
201 String script = getScript();
202 if( script == null || script.trim().length() == 0 )
203 return ;
204
205
206 Binding localBinding = new Binding();
207
208 WsdlMockService mockService = getMockOperation().getMockService();
209 WsdlMockRunner mockRunner = mockService.getMockRunner();
210 MockRunContext context = mockRunner == null ? new WsdlMockRunContext( mockService ) : mockRunner.getMockContext();
211
212 localBinding.setVariable( "context", context );
213 localBinding.setVariable( "mockRequest", request);
214 localBinding.setVariable( "mockResponse", this );
215 localBinding.setVariable( "log", SoapUI.ensureGroovyLog() );
216
217 Script localScript = mockService.getScriptShell().parse( script );
218 localScript.setBinding( localBinding );
219 localScript.run();
220 }
221
222 public void setScript( String script )
223 {
224 String oldScript = getScript();
225 if( !script.equals( oldScript ))
226 {
227 if( !getConfig().isSetScript())
228 getConfig().addNewScript();
229 getConfig().getScript().setStringValue( script );
230
231 notifyPropertyChanged( SCRIPT_PROPERTY, oldScript, script );
232 }
233 }
234
235 public void setResponseHeaders( StringToStringMap headers )
236 {
237 StringToStringMap oldHeaders = getResponseHeaders();
238
239 HeaderConfig [] headerConfigs = new HeaderConfig[headers.size()];
240 int ix = 0;
241 for( String header : headers.keySet() )
242 {
243 headerConfigs[ix] = HeaderConfig.Factory.newInstance();
244 headerConfigs[ix].setName( header );
245 headerConfigs[ix].setValue( headers.get( header ) );
246 ix++;
247 }
248
249 getConfig().setHeaderArray( headerConfigs );
250
251 notifyPropertyChanged( HEADERS_PROPERTY, oldHeaders, headers );
252 }
253
254 public StringToStringMap getResponseHeaders()
255 {
256 StringToStringMap result = new StringToStringMap();
257 List<HeaderConfig> headerList = getConfig().getHeaderList();
258 for( HeaderConfig header : headerList )
259 {
260 result.put( header.getName(), header.getValue() );
261 }
262
263 return result;
264 }
265
266 public Attachment attachFile( File file, boolean cache )
267 {
268 try
269 {
270 FileAttachment fileAttachment = new MockFileAttachment( file, cache, this );
271 attachments.add( fileAttachment );
272 notifyPropertyChanged(ATTACHMENTS_PROPERTY, null, fileAttachment );
273 return fileAttachment;
274 }
275 catch (IOException e)
276 {
277 UISupport.showErrorMessage( e );
278 return null;
279 }
280 }
281
282 public int getAttachmentCount()
283 {
284 return attachments.size();
285 }
286
287 public WsdlAttachment getAttachmentAt( int index )
288 {
289 return attachments.get( index );
290 }
291
292 public void removeAttachment( Attachment attachment )
293 {
294 int ix = attachments.indexOf( attachment );
295 attachments.remove( ix );
296
297 try
298 {
299 notifyPropertyChanged(ATTACHMENTS_PROPERTY, attachment, null );
300 }
301 finally
302 {
303 getConfig().removeAttachment( ix);
304 }
305 }
306
307 public WsdlAttachmentPart[] getDefinedAttachmentParts()
308 {
309 if( definedAttachmentParts == null )
310 {
311 try
312 {
313 WsdlOperation operation = getMockOperation().getOperation();
314 if( operation == null )
315 {
316 definedAttachmentParts = new ArrayList<WsdlAttachmentPart>();
317 }
318 else
319 {
320 UISupport.setHourglassCursor();
321 definedAttachmentParts = AttachmentUtils.extractAttachmentParts(
322 operation, getResponseContent(), true );
323 }
324 }
325 catch (Exception e)
326 {
327 log.warn( e.toString() );
328 }
329 finally
330 {
331 UISupport.resetCursor();
332 }
333 }
334
335 return definedAttachmentParts.toArray( new WsdlAttachmentPart[definedAttachmentParts.size()] );
336 }
337
338 public WsdlAttachmentPart getAttachmentPart( String partName )
339 {
340 WsdlAttachmentPart[] parts = getDefinedAttachmentParts();
341 for( WsdlAttachmentPart part : parts )
342 {
343 if( part.getName().equals( partName ))
344 return part;
345 }
346
347 return null;
348 }
349
350 public Attachment[] getAttachmentsForPart( String partName )
351 {
352 List<Attachment> result = new ArrayList<Attachment>();
353
354 for( Attachment attachment : attachments )
355 {
356 if( attachment.getPart().equals( partName ))
357 result.add( attachment );
358 }
359
360 return result.toArray( new Attachment[result.size()]);
361 }
362
363 public boolean isMtomEnabled()
364 {
365 return getSettings().getBoolean( WsdlSettings.ENABLE_MTOM );
366 }
367
368 public void setMtomEnabled( boolean mtomEnabled )
369 {
370 boolean old = isMtomEnabled();
371 getSettings().setBoolean( WsdlSettings.ENABLE_MTOM, mtomEnabled );
372 definedAttachmentParts = null;
373 notifyPropertyChanged( MTOM_NABLED_PROPERTY, old, mtomEnabled );
374 }
375
376 private String writeResponse(WsdlMockResult response, String responseContent) throws Exception
377 {
378 MimeMultipart mp = null;
379 WsdlOperation operation = getMockOperation().getOperation();
380 if( operation == null )
381 throw new Exception( "Missing WsdlOperation for mock response");
382
383 SoapVersion soapVersion = operation.getInterface().getSoapVersion();
384
385 StringToStringMap contentIds = new StringToStringMap();
386 boolean isXOP = false;
387
388
389 if( isMtomEnabled() || getAttachmentCount() > 0 )
390 {
391 try
392 {
393 mp = new MimeMultipart();
394
395 MessageXmlObject requestXmlObject = new MessageXmlObject(( WsdlOperation ) operation,
396 getResponseContent(), true);
397 MessageXmlPart[] requestParts = requestXmlObject.getMessageParts();
398 for (MessageXmlPart requestPart : requestParts)
399 {
400 if (AttachmentUtils.prepareMessagePart(this, mp, requestPart, contentIds))
401 isXOP = true;
402 }
403 responseContent = requestXmlObject.getMessageContent();
404 }
405 catch (Exception e)
406 {
407 log.warn( "Failed to process inline/MTOM attachments; " + e );
408 }
409 }
410
411 response.initResponse();
412
413
414 if( !isXOP && (mp == null || mp.getCount() == 0 ) && getAttachmentCount() == 0 )
415 {
416 String encoding = getEncoding();
417 byte[] content = encoding == null ? responseContent.getBytes() : responseContent.getBytes(encoding);
418
419 response.setContentType( soapVersion.getContentTypeHttpHeader( encoding ));
420 response.getOutputStream().write( content );
421 }
422 else
423 {
424
425 if( mp == null )
426 mp = new MimeMultipart();
427
428
429 initRootPart(responseContent, mp, isXOP);
430
431
432 AttachmentUtils.addMimeParts(this, mp, contentIds);
433
434
435 MimeMessage message = new MimeMessage( AttachmentUtils.JAVAMAIL_SESSION );
436 message.setContent( mp );
437 message.saveChanges();
438 MimeMessageMockResponseEntity mimeMessageRequestEntity = new MimeMessageMockResponseEntity( message, isXOP, this );
439
440 response.addHeader( "Content-Type", mimeMessageRequestEntity.getContentType() );
441 response.addHeader( "MIME-Version", "1.0" );
442 mimeMessageRequestEntity.writeRequest( response.getOutputStream() );
443 }
444
445 return responseContent;
446 }
447
448 private void initRootPart(String requestContent, MimeMultipart mp, boolean isXOP) throws MessagingException
449 {
450 MimeBodyPart rootPart = new PreencodedMimeBodyPart( "8bit" );
451 rootPart.setContentID( AttachmentUtils.ROOTPART_SOAPUI_ORG );
452 mp.addBodyPart( rootPart, 0 );
453
454 DataHandler dataHandler = new DataHandler( new MockResponseDataSource( this, requestContent, isXOP ) );
455 rootPart.setDataHandler( dataHandler);
456 }
457
458 public Attachment addAttachment( Attachment attachment )
459 {
460 if( attachment instanceof BodyPartAttachment )
461 {
462 try
463 {
464 BodyPartAttachment att = ( BodyPartAttachment ) attachment;
465
466 AttachmentConfig newConfig = (AttachmentConfig) getConfig().addNewAttachment();
467 newConfig.setData( Tools.readAll( att.getInputStream(), 0 ).toByteArray() );
468 newConfig.setContentId( att.getContentID() );
469 newConfig.setContentType( att.getContentType() );
470 newConfig.setName( att.getName() );
471
472 FileAttachment newAttachment = new MockFileAttachment( newConfig, this );
473 attachments.add( newAttachment);
474 return newAttachment;
475 }
476 catch( IOException e )
477 {
478 e.printStackTrace();
479 }
480 }
481 else if( attachment instanceof FileAttachment )
482 {
483 AttachmentConfig oldConfig = ((FileAttachment)attachment).getConfig();
484 AttachmentConfig newConfig = (AttachmentConfig) getConfig().addNewAttachment().set( oldConfig );
485 FileAttachment newAttachment = new MockFileAttachment( newConfig, this );
486 attachments.add( newAttachment);
487 return newAttachment;
488 }
489
490 return null;
491 }
492
493 public void setMockResult( WsdlMockResult mockResult )
494 {
495 WsdlMockResult oldResult = this.mockResult;
496 this.mockResult = mockResult;
497 notifyPropertyChanged( MOCKRESULT_PROPERTY, oldResult, mockResult );
498 }
499
500 public WsdlMockResult getMockResult()
501 {
502 return mockResult;
503 }
504
505 public boolean isMultipartEnabled()
506 {
507 return !getSettings().getBoolean( DISABLE_MULTIPART_ATTACHMENTS );
508 }
509
510 public void setMultipartEnabled( boolean multipartEnabled )
511 {
512 getSettings().setBoolean( DISABLE_MULTIPART_ATTACHMENTS, multipartEnabled );
513 }
514 }