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.log4j.Logger;
32
33 import com.eviware.soapui.SoapUI;
34 import com.eviware.soapui.config.AttachmentConfig;
35 import com.eviware.soapui.config.HeaderConfig;
36 import com.eviware.soapui.config.MockResponseConfig;
37 import com.eviware.soapui.impl.actions.ShowDesktopPanelAction;
38 import com.eviware.soapui.impl.wsdl.AbstractWsdlModelItem;
39 import com.eviware.soapui.impl.wsdl.AttachmentContainer;
40 import com.eviware.soapui.impl.wsdl.WsdlAttachmentPart;
41 import com.eviware.soapui.impl.wsdl.WsdlOperation;
42 import com.eviware.soapui.impl.wsdl.actions.mockresponse.CloneMockResponseAction;
43 import com.eviware.soapui.impl.wsdl.actions.mockresponse.DeleteMockResponseAction;
44 import com.eviware.soapui.impl.wsdl.actions.mockresponse.RenameMockResponseAction;
45 import com.eviware.soapui.impl.wsdl.actions.support.ShowOnlineHelpAction;
46 import com.eviware.soapui.impl.wsdl.submit.filters.PropertyExpansionRequestFilter;
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 Logger log = Logger.getLogger( 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 for( String name : responseHeaders.keySet() )
164 {
165 result.addHeader( name, PropertyExpansionRequestFilter.expandProperties( request.getContext(), responseHeaders.get( name ) ));
166 }
167
168 String responseContent = getResponseContent();
169 String script = getScript();
170 if( script != null && script.trim().length() > 0 )
171 {
172 evaluateScript( request );
173 }
174
175 responseContent = PropertyExpansionRequestFilter.expandProperties( request.getContext(), responseContent );
176
177 if( !result.isCommitted())
178 {
179 responseContent = writeResponse( result, responseContent );
180 }
181
182 result.setReponseContent( responseContent );
183
184 setMockResult( result );
185
186 return mockResult;
187 }
188 catch( Throwable e )
189 {
190 throw new DispatchException( e );
191 }
192 finally
193 {
194 iconAnimator.stop();
195 }
196 }
197
198 public void evaluateScript( WsdlMockRequest request )
199 {
200 String script = getScript();
201 if( script == null || script.trim().length() == 0 )
202 return ;
203
204
205 Binding localBinding = new Binding();
206
207 WsdlMockService mockService = getMockOperation().getMockService();
208 WsdlMockRunner mockRunner = mockService.getMockRunner();
209 MockRunContext context = mockRunner == null ? new WsdlMockRunContext( mockService, null ) : mockRunner.getMockContext();
210
211 localBinding.setVariable( "context", context );
212 localBinding.setVariable( "mockRequest", request);
213 localBinding.setVariable( "mockResponse", this );
214 localBinding.setVariable( "log", SoapUI.ensureGroovyLog() );
215
216 Script localScript = mockService.getScriptShell().parse( script );
217 localScript.setBinding( localBinding );
218 localScript.run();
219 }
220
221 public void setScript( String script )
222 {
223 String oldScript = getScript();
224 if( !script.equals( oldScript ))
225 {
226 if( !getConfig().isSetScript())
227 getConfig().addNewScript();
228 getConfig().getScript().setStringValue( script );
229
230 notifyPropertyChanged( SCRIPT_PROPERTY, oldScript, script );
231 }
232 }
233
234 public void setResponseHeaders( StringToStringMap headers )
235 {
236 StringToStringMap oldHeaders = getResponseHeaders();
237
238 HeaderConfig [] headerConfigs = new HeaderConfig[headers.size()];
239 int ix = 0;
240 for( String header : headers.keySet() )
241 {
242 headerConfigs[ix] = HeaderConfig.Factory.newInstance();
243 headerConfigs[ix].setName( header );
244 headerConfigs[ix].setValue( headers.get( header ) );
245 ix++;
246 }
247
248 getConfig().setHeaderArray( headerConfigs );
249
250 notifyPropertyChanged( HEADERS_PROPERTY, oldHeaders, headers );
251 }
252
253 public StringToStringMap getResponseHeaders()
254 {
255 StringToStringMap result = new StringToStringMap();
256 List<HeaderConfig> headerList = getConfig().getHeaderList();
257 for( HeaderConfig header : headerList )
258 {
259 result.put( header.getName(), header.getValue() );
260 }
261
262 return result;
263 }
264
265 public Attachment attachFile( File file, boolean cache )
266 {
267 try
268 {
269 FileAttachment fileAttachment = new MockFileAttachment( file, cache, this );
270 attachments.add( fileAttachment );
271 notifyPropertyChanged(ATTACHMENTS_PROPERTY, null, fileAttachment );
272 return fileAttachment;
273 }
274 catch (IOException e)
275 {
276 UISupport.showErrorMessage( e );
277 return null;
278 }
279 }
280
281 public int getAttachmentCount()
282 {
283 return attachments.size();
284 }
285
286 public WsdlAttachment getAttachmentAt( int index )
287 {
288 return attachments.get( index );
289 }
290
291 public void removeAttachment( Attachment attachment )
292 {
293 int ix = attachments.indexOf( attachment );
294 attachments.remove( ix );
295
296 try
297 {
298 notifyPropertyChanged(ATTACHMENTS_PROPERTY, attachment, null );
299 }
300 finally
301 {
302 getConfig().removeAttachment( ix);
303 }
304 }
305
306 public WsdlAttachmentPart[] getDefinedAttachmentParts()
307 {
308 if( definedAttachmentParts == null )
309 {
310 try
311 {
312 WsdlOperation operation = getMockOperation().getOperation();
313 if( operation == null )
314 {
315 definedAttachmentParts = new ArrayList<WsdlAttachmentPart>();
316 }
317 else
318 {
319 UISupport.setHourglassCursor();
320 definedAttachmentParts = AttachmentUtils.extractAttachmentParts(
321 operation, getResponseContent(), true );
322 }
323 }
324 catch (Exception e)
325 {
326 log.warn( e.toString() );
327 }
328 finally
329 {
330 UISupport.resetCursor();
331 }
332 }
333
334 return definedAttachmentParts.toArray( new WsdlAttachmentPart[definedAttachmentParts.size()] );
335 }
336
337 public WsdlAttachmentPart getAttachmentPart( String partName )
338 {
339 WsdlAttachmentPart[] parts = getDefinedAttachmentParts();
340 for( WsdlAttachmentPart part : parts )
341 {
342 if( part.getName().equals( partName ))
343 return part;
344 }
345
346 return null;
347 }
348
349 public Attachment[] getAttachmentsForPart( String partName )
350 {
351 List<Attachment> result = new ArrayList<Attachment>();
352
353 for( Attachment attachment : attachments )
354 {
355 if( attachment.getPart().equals( partName ))
356 result.add( attachment );
357 }
358
359 return result.toArray( new Attachment[result.size()]);
360 }
361
362 public boolean isMtomEnabled()
363 {
364 return getSettings().getBoolean( WsdlSettings.ENABLE_MTOM );
365 }
366
367 public void setMtomEnabled( boolean mtomEnabled )
368 {
369 boolean old = isMtomEnabled();
370 getSettings().setBoolean( WsdlSettings.ENABLE_MTOM, mtomEnabled );
371 definedAttachmentParts = null;
372 notifyPropertyChanged( MTOM_NABLED_PROPERTY, old, mtomEnabled );
373 }
374
375 private String writeResponse(WsdlMockResult response, String responseContent) throws Exception
376 {
377 MimeMultipart mp = null;
378 WsdlOperation operation = getMockOperation().getOperation();
379 if( operation == null )
380 throw new Exception( "Missing WsdlOperation for mock response");
381
382 SoapVersion soapVersion = operation.getInterface().getSoapVersion();
383
384 StringToStringMap contentIds = new StringToStringMap();
385 boolean isXOP = false;
386
387
388 if( isMtomEnabled() || getAttachmentCount() > 0 )
389 {
390 try
391 {
392 mp = new MimeMultipart();
393
394 MessageXmlObject requestXmlObject = new MessageXmlObject(( WsdlOperation ) operation,
395 getResponseContent(), true);
396 MessageXmlPart[] requestParts = requestXmlObject.getMessageParts();
397 for (MessageXmlPart requestPart : requestParts)
398 {
399 if (AttachmentUtils.prepareMessagePart(this, mp, requestPart, contentIds))
400 isXOP = true;
401 }
402 responseContent = requestXmlObject.getMessageContent();
403 }
404 catch (Exception e)
405 {
406 log.warn( "Failed to process inline/MTOM attachments; " + e );
407 }
408 }
409
410 response.initResponse();
411
412
413 if( !isXOP && (mp == null || mp.getCount() == 0 ) && getAttachmentCount() == 0 )
414 {
415 String encoding = getEncoding();
416 byte[] content = encoding == null ? responseContent.getBytes() : responseContent.getBytes(encoding);
417
418 response.setContentType( soapVersion.getContentTypeHttpHeader( encoding ));
419 response.getOutputStream().write( content );
420 }
421 else
422 {
423
424 if( mp == null )
425 mp = new MimeMultipart();
426
427
428 initRootPart(responseContent, mp, isXOP);
429
430
431 AttachmentUtils.addMimeParts(this, mp, contentIds);
432
433
434 MimeMessage message = new MimeMessage( AttachmentUtils.JAVAMAIL_SESSION );
435 message.setContent( mp );
436 message.saveChanges();
437 MimeMessageMockResponseEntity mimeMessageRequestEntity = new MimeMessageMockResponseEntity( message, isXOP, this );
438
439 response.addHeader( "Content-Type", mimeMessageRequestEntity.getContentType() );
440 response.addHeader( "MIME-Version", "1.0" );
441 mimeMessageRequestEntity.writeRequest( response.getOutputStream() );
442 }
443
444 return responseContent;
445 }
446
447 private void initRootPart(String requestContent, MimeMultipart mp, boolean isXOP) throws MessagingException
448 {
449 MimeBodyPart rootPart = new PreencodedMimeBodyPart( "8bit" );
450 rootPart.setContentID( AttachmentUtils.ROOTPART_SOAPUI_ORG );
451 mp.addBodyPart( rootPart, 0 );
452
453 DataHandler dataHandler = new DataHandler( new MockResponseDataSource( this, requestContent, isXOP ) );
454 rootPart.setDataHandler( dataHandler);
455 }
456
457 public Attachment addAttachment( Attachment attachment )
458 {
459 if( attachment instanceof BodyPartAttachment )
460 {
461 try
462 {
463 BodyPartAttachment att = ( BodyPartAttachment ) attachment;
464
465 AttachmentConfig newConfig = (AttachmentConfig) getConfig().addNewAttachment();
466 newConfig.setData( Tools.readAll( att.getInputStream(), 0 ).toByteArray() );
467 newConfig.setContentId( att.getContentID() );
468 newConfig.setContentType( att.getContentType() );
469 newConfig.setName( att.getName() );
470
471 FileAttachment newAttachment = new MockFileAttachment( newConfig, this );
472 attachments.add( newAttachment);
473 return newAttachment;
474 }
475 catch( IOException e )
476 {
477 e.printStackTrace();
478 }
479 }
480 else if( attachment instanceof FileAttachment )
481 {
482 AttachmentConfig oldConfig = ((FileAttachment)attachment).getConfig();
483 AttachmentConfig newConfig = (AttachmentConfig) getConfig().addNewAttachment().set( oldConfig );
484 FileAttachment newAttachment = new MockFileAttachment( newConfig, this );
485 attachments.add( newAttachment);
486 return newAttachment;
487 }
488
489 return null;
490 }
491
492 public void setMockResult( WsdlMockResult mockResult )
493 {
494 WsdlMockResult oldResult = this.mockResult;
495 this.mockResult = mockResult;
496 notifyPropertyChanged( MOCKRESULT_PROPERTY, oldResult, mockResult );
497 }
498
499 public WsdlMockResult getMockResult()
500 {
501 return mockResult;
502 }
503
504 public boolean isMultipartEnabled()
505 {
506 return !getSettings().getBoolean( DISABLE_MULTIPART_ATTACHMENTS );
507 }
508
509 public void setMultipartEnabled( boolean multipartEnabled )
510 {
511 getSettings().setBoolean( DISABLE_MULTIPART_ATTACHMENTS, multipartEnabled );
512 }
513 }