View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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.mock;
14  
15  import java.io.File;
16  import java.io.IOException;
17  import java.util.ArrayList;
18  import java.util.Arrays;
19  import java.util.List;
20  import java.util.zip.GZIPOutputStream;
21  
22  import javax.activation.DataHandler;
23  import javax.mail.MessagingException;
24  import javax.mail.internet.MimeBodyPart;
25  import javax.mail.internet.MimeMessage;
26  import javax.mail.internet.MimeMultipart;
27  import javax.mail.internet.PreencodedMimeBodyPart;
28  import javax.swing.ImageIcon;
29  import javax.wsdl.BindingOperation;
30  import javax.wsdl.Message;
31  
32  import org.apache.log4j.Logger;
33  import org.apache.xmlbeans.SchemaType;
34  
35  import com.eviware.soapui.SoapUI;
36  import com.eviware.soapui.config.AttachmentConfig;
37  import com.eviware.soapui.config.HeaderConfig;
38  import com.eviware.soapui.config.MockResponseConfig;
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.WsdlContentPart;
43  import com.eviware.soapui.impl.wsdl.WsdlHeaderPart;
44  import com.eviware.soapui.impl.wsdl.WsdlOperation;
45  import com.eviware.soapui.impl.wsdl.WsdlSubmitContext;
46  import com.eviware.soapui.impl.wsdl.submit.filters.PropertyExpansionRequestFilter;
47  import com.eviware.soapui.impl.wsdl.submit.filters.RemoveEmptyContentRequestFilter;
48  import com.eviware.soapui.impl.wsdl.submit.transports.http.AttachmentUtils;
49  import com.eviware.soapui.impl.wsdl.submit.transports.http.BodyPartAttachment;
50  import com.eviware.soapui.impl.wsdl.submit.transports.http.MimeMessageMockResponseEntity;
51  import com.eviware.soapui.impl.wsdl.submit.transports.http.MockResponseDataSource;
52  import com.eviware.soapui.impl.wsdl.support.CompressedStringSupport;
53  import com.eviware.soapui.impl.wsdl.support.FileAttachment;
54  import com.eviware.soapui.impl.wsdl.support.MessageXmlObject;
55  import com.eviware.soapui.impl.wsdl.support.MessageXmlPart;
56  import com.eviware.soapui.impl.wsdl.support.MockFileAttachment;
57  import com.eviware.soapui.impl.wsdl.support.ModelItemIconAnimator;
58  import com.eviware.soapui.impl.wsdl.support.WsdlAttachment;
59  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
60  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
61  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
62  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils.SoapHeader;
63  import com.eviware.soapui.model.iface.Attachment;
64  import com.eviware.soapui.model.iface.MessagePart;
65  import com.eviware.soapui.model.mock.MockResponse;
66  import com.eviware.soapui.model.mock.MockRunContext;
67  import com.eviware.soapui.settings.WsdlSettings;
68  import com.eviware.soapui.support.Tools;
69  import com.eviware.soapui.support.UISupport;
70  import com.eviware.soapui.support.scripting.ScriptEnginePool;
71  import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
72  import com.eviware.soapui.support.types.StringToStringMap;
73  import com.eviware.soapui.support.xml.XmlUtils;
74  
75  /***
76   * A WsdlMockResponse contained by a WsdlMockOperation
77   * 
78   * @author ole.matzura
79   */
80  
81  public class WsdlMockResponse extends AbstractWsdlModelItem<MockResponseConfig> implements MockResponse,
82  			AttachmentContainer
83  {
84  	private final static Logger log = Logger.getLogger( WsdlMockResponse.class );
85  
86  	public final static String MOCKRESULT_PROPERTY = WsdlMockResponse.class.getName() + "@mockresult";
87  	public final static String SCRIPT_PROPERTY = WsdlMockResponse.class.getName() + "@script";
88  	public final static String HEADERS_PROPERTY = WsdlMockResponse.class.getName() + "@headers";
89  	public final static String DISABLE_MULTIPART_ATTACHMENTS = WsdlMockResponse.class.getName()
90  				+ "@disable-multipart-attachments";
91  	public final static String RESPONSE_DELAY_PROPERTY = WsdlMockResponse.class.getName() + "@response-delay";
92  	public static final String STRIP_WHITESPACES = WsdlMockResponse.class.getName() + "@strip-whitespaces";
93  	public static final String REMOVE_EMPTY_CONTENT = WsdlMockResponse.class.getName() + "@remove_empty_content";
94  	public static final String ENCODE_ATTACHMENTS = WsdlMockResponse.class.getName() + "@encode_attachments";
95  
96  	protected List<FileAttachment> attachments = new ArrayList<FileAttachment>();
97  	private List<WsdlAttachmentPart> definedAttachmentParts;
98  	private ModelItemIconAnimator iconAnimator;
99  	private WsdlMockResult mockResult;
100 	private String responseContent;
101 	private ScriptEnginePool scriptEnginePool;
102 
103 	public WsdlMockResponse( WsdlMockOperation operation, MockResponseConfig config )
104 	{
105 		super( config, operation, "/mockResponse.gif" );
106 
107 		for( AttachmentConfig ac : getConfig().getAttachmentList() )
108 		{
109 			attachments.add( new MockFileAttachment( ac, this ) );
110 		}
111 
112 		if( !config.isSetEncoding() )
113 			config.setEncoding( "UTF-8" );
114 
115 		iconAnimator = new ModelItemIconAnimator( this, "/mockResponse.gif", new String[] { "/exec_request_1.gif",
116 					"/exec_request_2.gif", "/exec_request_3.gif", "/exec_request_4.gif" } );
117 
118 		scriptEnginePool = new ScriptEnginePool( this );
119 		scriptEnginePool.setScript( getScript() );
120 	}
121 
122 	public Attachment[] getAttachments()
123 	{
124 		return attachments.toArray( new Attachment[attachments.size()] );
125 	}
126 
127 	public String getScript()
128 	{
129 		return getConfig().isSetScript() ? getConfig().getScript().getStringValue() : null;
130 	}
131 
132 	public String getEncoding()
133 	{
134 		return getConfig().getEncoding();
135 	}
136 
137 	public void setEncoding( String encoding )
138 	{
139 		String old = getEncoding();
140 		getConfig().setEncoding( encoding );
141 		notifyPropertyChanged( ENCODING_PROPERTY, old, encoding );
142 	}
143 
144 	public String getResponseContent()
145 	{
146 		if( getConfig().getResponseContent() == null )
147 			getConfig().addNewResponseContent();
148 
149 		if( responseContent == null )
150 			responseContent = CompressedStringSupport.getString( getConfig().getResponseContent() );
151 
152 		return responseContent;
153 	}
154 
155 	public void setResponseContent( String responseContent )
156 	{
157 		String oldContent = getResponseContent();
158 		if( !responseContent.equals( oldContent ) )
159 		{
160 			this.responseContent = responseContent;
161 			notifyPropertyChanged( RESPONSECONTENT_PROPERTY, oldContent, responseContent );
162 		}
163 	}
164 
165 	@Override
166 	public ImageIcon getIcon()
167 	{
168 		return iconAnimator.getIcon();
169 	}
170 
171 	public WsdlMockOperation getMockOperation()
172 	{
173 		return ( WsdlMockOperation ) getParent();
174 	}
175 
176 	public WsdlMockResult execute( WsdlMockRequest request, WsdlMockResult result ) throws DispatchException
177 	{
178 		try
179 		{
180 			iconAnimator.start();
181 
182 			long delay = getResponseDelay();
183 			if( delay > 0 )
184 				Thread.sleep( delay );
185 
186 			String responseContent = getResponseContent();
187 			String script = getScript();
188 			if( script != null && script.trim().length() > 0 )
189 			{
190 				evaluateScript( request );
191 			}
192 			
193 			// create merged context
194 			WsdlSubmitContext context = new WsdlSubmitContext();
195 			context.putAll( request.getContext() );
196 			context.putAll( request.getRequestContext() );
197 			
198 			StringToStringMap responseHeaders = getResponseHeaders();
199 			for( String name : responseHeaders.keySet() )
200 			{
201 				result.addHeader( name, PropertyExpansionRequestFilter.expandProperties( context,
202 							responseHeaders.get( name ) ) );
203 			}
204 
205 			responseContent = PropertyExpansionRequestFilter.expandProperties( context, responseContent );
206 
207 			if( !result.isCommitted() )
208 			{
209 				responseContent = writeResponse( result, responseContent );
210 			}
211 
212 			result.setResponseContent( responseContent );
213 
214 			setMockResult( result );
215 
216 			return mockResult;
217 		}
218 		catch( Throwable e )
219 		{
220 			throw new DispatchException( e );
221 		}
222 		finally
223 		{
224 			iconAnimator.stop();
225 		}
226 	}
227 
228 	public void evaluateScript( WsdlMockRequest request ) throws Exception
229 	{
230 		String script = getScript();
231 		if( script == null || script.trim().length() == 0 )
232 			return;
233 
234 		// unsatisfactory way of handling multiple threads -> create pool of
235 		// scripts instead
236 		WsdlMockService mockService = getMockOperation().getMockService();
237 		WsdlMockRunner mockRunner = mockService.getMockRunner();
238 		MockRunContext context = mockRunner == null ? new WsdlMockRunContext( mockService, null ) : mockRunner
239 					.getMockContext();
240 
241 		SoapUIScriptEngine scriptEngine = scriptEnginePool.getScriptEngine();
242 
243 		try
244 		{
245 			scriptEngine.setVariable( "context", request.getContext() );
246 			scriptEngine.setVariable( "requestContext", request.getRequestContext() );
247 			scriptEngine.setVariable( "mockContext", context );
248 			scriptEngine.setVariable( "mockRequest", request );
249 			scriptEngine.setVariable( "mockResponse", this );
250 			scriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
251 
252 			scriptEngine.run();
253 		}
254 		catch( RuntimeException e )
255 		{
256 			throw new Exception( e.getMessage(), e );
257 		}
258 		finally
259 		{
260 			scriptEnginePool.returnScriptEngine( scriptEngine );
261 		}
262 	}
263 
264 	@Override
265 	public void release()
266 	{
267 		super.release();
268 
269 		scriptEnginePool.release();
270 	}
271 
272 	public void setScript( String script )
273 	{
274 		String oldScript = getScript();
275 		if( !script.equals( oldScript ) )
276 		{
277 			if( !getConfig().isSetScript() )
278 				getConfig().addNewScript();
279 			getConfig().getScript().setStringValue( script );
280 
281 			scriptEnginePool.setScript( script );
282 
283 			notifyPropertyChanged( SCRIPT_PROPERTY, oldScript, script );
284 		}
285 	}
286 
287 	public void setResponseHeaders( StringToStringMap headers )
288 	{
289 		StringToStringMap oldHeaders = getResponseHeaders();
290 
291 		HeaderConfig[] headerConfigs = new HeaderConfig[headers.size()];
292 		int ix = 0;
293 		for( String header : headers.keySet() )
294 		{
295 			headerConfigs[ix] = HeaderConfig.Factory.newInstance();
296 			headerConfigs[ix].setName( header );
297 			headerConfigs[ix].setValue( headers.get( header ) );
298 			ix++;
299 		}
300 
301 		getConfig().setHeaderArray( headerConfigs );
302 
303 		notifyPropertyChanged( HEADERS_PROPERTY, oldHeaders, headers );
304 	}
305 
306 	public StringToStringMap getResponseHeaders()
307 	{
308 		StringToStringMap result = new StringToStringMap();
309 		List<HeaderConfig> headerList = getConfig().getHeaderList();
310 		for( HeaderConfig header : headerList )
311 		{
312 			result.put( header.getName(), header.getValue() );
313 		}
314 
315 		return result;
316 	}
317 
318 	public MessagePart[] getResponseParts()
319 	{
320 		try
321 		{
322 			// init
323 			List<MessagePart> result = new ArrayList<MessagePart>();
324 			WsdlOperation op = getMockOperation().getOperation();
325 			WsdlContext wsdlContext = op.getInterface().getWsdlContext();
326 			BindingOperation bindingOperation = op.findBindingOperation( wsdlContext.getDefinition() );
327 
328 			if( bindingOperation == null )
329 				return new MessagePart[0];
330 
331 			// header parts
332 			List<SoapHeader> headers = WsdlUtils.getSoapHeaders( bindingOperation.getBindingOutput()
333 						.getExtensibilityElements() );
334 
335 			for( int i = 0; i < headers.size(); i++ )
336 			{
337 				SoapHeader header = headers.get( i );
338 
339 				Message message = wsdlContext.getDefinition().getMessage( header.getMessage() );
340 				if( message == null )
341 				{
342 					log.error( "Missing message for header: " + header.getMessage() );
343 					continue;
344 				}
345 
346 				javax.wsdl.Part part = message.getPart( header.getPart() );
347 
348 				if( part != null )
349 				{
350 					SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
351 					if( schemaType != null )
352 						result.add( new WsdlHeaderPart( part.getName(), schemaType, part.getElementName() ) );
353 				}
354 				else
355 					log.error( "Missing part for header; " + header.getPart() );
356 			}
357 
358 			// content parts
359 			javax.wsdl.Part[] parts = WsdlUtils.getOutputParts( bindingOperation );
360 
361 			for( int i = 0; i < parts.length; i++ )
362 			{
363 				javax.wsdl.Part part = parts[i];
364 
365 				if( !WsdlUtils.isAttachmentOutputPart( part, bindingOperation ) )
366 				{
367 					SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
368 					if( schemaType != null )
369 						result.add( new WsdlContentPart( part.getName(), schemaType, part.getElementName() ) );
370 				}
371 			}
372 
373 			result.addAll( Arrays.asList( getDefinedAttachmentParts() ) );
374 
375 			return result.toArray( new MessagePart[result.size()] );
376 		}
377 		catch( Exception e )
378 		{
379 			SoapUI.logError( e );
380 			return new MessagePart[0];
381 		}
382 	}
383 
384 	public Attachment attachFile( File file, boolean cache )
385 	{
386 		try
387 		{
388 			FileAttachment fileAttachment = new MockFileAttachment( file, cache, this );
389 			attachments.add( fileAttachment );
390 			notifyPropertyChanged( ATTACHMENTS_PROPERTY, null, fileAttachment );
391 			return fileAttachment;
392 		}
393 		catch( IOException e )
394 		{
395 			UISupport.showErrorMessage( e );
396 			return null;
397 		}
398 	}
399 
400 	public int getAttachmentCount()
401 	{
402 		return attachments.size();
403 	}
404 
405 	public WsdlAttachment getAttachmentAt( int index )
406 	{
407 		return attachments.get( index );
408 	}
409 
410 	public void removeAttachment( Attachment attachment )
411 	{
412 		int ix = attachments.indexOf( attachment );
413 		attachments.remove( ix );
414 
415 		try
416 		{
417 			notifyPropertyChanged( ATTACHMENTS_PROPERTY, attachment, null );
418 		}
419 		finally
420 		{
421 			getConfig().removeAttachment( ix );
422 		}
423 	}
424 
425 	public WsdlAttachmentPart[] getDefinedAttachmentParts()
426 	{
427 		if( definedAttachmentParts == null )
428 		{
429 			try
430 			{
431 				WsdlOperation operation = getMockOperation().getOperation();
432 				if( operation == null )
433 				{
434 					definedAttachmentParts = new ArrayList<WsdlAttachmentPart>();
435 				}
436 				else
437 				{
438 					UISupport.setHourglassCursor();
439 					definedAttachmentParts = AttachmentUtils.extractAttachmentParts( operation, getResponseContent(), true,
440 								true );
441 				}
442 			}
443 			catch( Exception e )
444 			{
445 				log.warn( e.toString() );
446 			}
447 			finally
448 			{
449 				UISupport.resetCursor();
450 			}
451 		}
452 
453 		return definedAttachmentParts.toArray( new WsdlAttachmentPart[definedAttachmentParts.size()] );
454 	}
455 
456 	public WsdlAttachmentPart getAttachmentPart( String partName )
457 	{
458 		WsdlAttachmentPart[] parts = getDefinedAttachmentParts();
459 		for( WsdlAttachmentPart part : parts )
460 		{
461 			if( part.getName().equals( partName ) )
462 				return part;
463 		}
464 
465 		return null;
466 	}
467 
468 	public Attachment[] getAttachmentsForPart( String partName )
469 	{
470 		List<Attachment> result = new ArrayList<Attachment>();
471 
472 		for( Attachment attachment : attachments )
473 		{
474 			if( attachment.getPart().equals( partName ) )
475 				result.add( attachment );
476 		}
477 
478 		return result.toArray( new Attachment[result.size()] );
479 	}
480 
481 	public boolean isMtomEnabled()
482 	{
483 		return getSettings().getBoolean( WsdlSettings.ENABLE_MTOM );
484 	}
485 
486 	public void setMtomEnabled( boolean mtomEnabled )
487 	{
488 		boolean old = isMtomEnabled();
489 		getSettings().setBoolean( WsdlSettings.ENABLE_MTOM, mtomEnabled );
490 		definedAttachmentParts = null;
491 		notifyPropertyChanged( MTOM_NABLED_PROPERTY, old, mtomEnabled );
492 	}
493 
494 	private String writeResponse( WsdlMockResult response, String responseContent ) throws Exception
495 	{
496 		MimeMultipart mp = null;
497 		WsdlOperation operation = getMockOperation().getOperation();
498 		if( operation == null )
499 			throw new Exception( "Missing WsdlOperation for mock response" );
500 
501 		SoapVersion soapVersion = operation.getInterface().getSoapVersion();
502 
503 		StringToStringMap contentIds = new StringToStringMap();
504 		boolean isXOP = false;
505 
506 		// preprocess only if neccessary
507 		if( isMtomEnabled() || getAttachmentCount() > 0 )
508 		{
509 			try
510 			{
511 				mp = new MimeMultipart();
512 
513 				MessageXmlObject requestXmlObject = new MessageXmlObject( ( WsdlOperation ) operation,
514 							getResponseContent(), true );
515 				MessageXmlPart[] requestParts = requestXmlObject.getMessageParts();
516 				for( MessageXmlPart requestPart : requestParts )
517 				{
518 					if( AttachmentUtils.prepareMessagePart( this, mp, requestPart, contentIds ) )
519 						isXOP = true;
520 				}
521 				responseContent = requestXmlObject.getMessageContent();
522 			}
523 			catch( Exception e )
524 			{
525 				log.warn( "Failed to process inline/MTOM attachments; " + e );
526 			}
527 		}
528 
529 		response.initResponse();
530 		
531 		if( isRemoveEmptyContent() )
532 		{
533 			responseContent = RemoveEmptyContentRequestFilter.removeEmptyContent( responseContent );
534 		}
535 		
536 		if( isStripWhitespaces() )
537 		{
538 			responseContent = XmlUtils.stripWhitespaces( responseContent );
539 		}
540 
541 		// non-multipart request?
542 		if( !isXOP && ( mp == null || mp.getCount() == 0 ) && getAttachmentCount() == 0 )
543 		{
544 			String encoding = getEncoding();
545 			byte[] content = encoding == null ? responseContent.getBytes() : responseContent.getBytes( encoding );
546 
547 			response.setContentType( soapVersion.getContentTypeHttpHeader( encoding ) );
548 
549 			String acceptEncoding = response.getMockRequest().getRequestHeaders().get( "Accept-Encoding" );
550 			if( acceptEncoding != null && acceptEncoding.toUpperCase().contains( "GZIP" ) )
551 			{
552 				response.addHeader( "Content-Encoding", "gzip" );
553 				GZIPOutputStream zipOut = new GZIPOutputStream( response.getOutputStream() );
554 				zipOut.write( content );
555 				zipOut.close();
556 			}
557 			else
558 			{
559 				response.getOutputStream().write( content );
560 			}
561 		}
562 		else
563 		{
564 			// make sure..
565 			if( mp == null )
566 				mp = new MimeMultipart();
567 
568 			// init root part
569 			initRootPart( responseContent, mp, isXOP );
570 
571 			// init mimeparts
572 			AttachmentUtils.addMimeParts( this, mp, contentIds );
573 
574 			// create request message
575 			MimeMessage message = new MimeMessage( AttachmentUtils.JAVAMAIL_SESSION );
576 			message.setContent( mp );
577 			message.saveChanges();
578 			MimeMessageMockResponseEntity mimeMessageRequestEntity = new MimeMessageMockResponseEntity( message, isXOP,
579 						this );
580 
581 			response.addHeader( "Content-Type", mimeMessageRequestEntity.getContentType() );
582 			response.addHeader( "MIME-Version", "1.0" );
583 			mimeMessageRequestEntity.writeRequest( response.getOutputStream() );
584 		}
585 
586 		return responseContent;
587 	}
588 
589 	private void initRootPart( String requestContent, MimeMultipart mp, boolean isXOP ) throws MessagingException
590 	{
591 		MimeBodyPart rootPart = new PreencodedMimeBodyPart( "8bit" );
592 		rootPart.setContentID( AttachmentUtils.ROOTPART_SOAPUI_ORG );
593 		mp.addBodyPart( rootPart, 0 );
594 
595 		DataHandler dataHandler = new DataHandler( new MockResponseDataSource( this, requestContent, isXOP ) );
596 		rootPart.setDataHandler( dataHandler );
597 	}
598 
599 	public Attachment addAttachment( Attachment attachment )
600 	{
601 		if( attachment instanceof BodyPartAttachment )
602 		{
603 			try
604 			{
605 				BodyPartAttachment att = ( BodyPartAttachment ) attachment;
606 
607 				AttachmentConfig newConfig = ( AttachmentConfig ) getConfig().addNewAttachment();
608 				newConfig.setData( Tools.readAll( att.getInputStream(), 0 ).toByteArray() );
609 				newConfig.setContentId( att.getContentID() );
610 				newConfig.setContentType( att.getContentType() );
611 				newConfig.setName( att.getName() );
612 
613 				FileAttachment newAttachment = new MockFileAttachment( newConfig, this );
614 				attachments.add( newAttachment );
615 				return newAttachment;
616 			}
617 			catch( Exception e )
618 			{
619 				SoapUI.logError( e );
620 			}
621 		}
622 		else if( attachment instanceof FileAttachment )
623 		{
624 			AttachmentConfig oldConfig = ( ( FileAttachment ) attachment ).getConfig();
625 			AttachmentConfig newConfig = ( AttachmentConfig ) getConfig().addNewAttachment().set( oldConfig );
626 			FileAttachment newAttachment = new MockFileAttachment( newConfig, this );
627 			attachments.add( newAttachment );
628 			return newAttachment;
629 		}
630 
631 		return null;
632 	}
633 
634 	public void setResponseDelay( long delay )
635 	{
636 		long oldDelay = getResponseDelay();
637 
638 		if( delay == 0 )
639 			getSettings().clearSetting( RESPONSE_DELAY_PROPERTY );
640 		else
641 			getSettings().setLong( RESPONSE_DELAY_PROPERTY, delay );
642 
643 		notifyPropertyChanged( RESPONSE_DELAY_PROPERTY, oldDelay, delay );
644 	}
645 
646 	public long getResponseDelay()
647 	{
648 		return getSettings().getLong( RESPONSE_DELAY_PROPERTY, 0 );
649 	}
650 
651 	public void setMockResult( WsdlMockResult mockResult )
652 	{
653 		WsdlMockResult oldResult = this.mockResult;
654 		this.mockResult = mockResult;
655 		notifyPropertyChanged( MOCKRESULT_PROPERTY, oldResult, mockResult );
656 	}
657 
658 	public WsdlMockResult getMockResult()
659 	{
660 		return mockResult;
661 	}
662 
663 	public long getContentLength()
664 	{
665 		return getResponseContent().length();
666 	}
667 
668 	public boolean isMultipartEnabled()
669 	{
670 		return !getSettings().getBoolean( DISABLE_MULTIPART_ATTACHMENTS );
671 	}
672 
673 	public void setMultipartEnabled( boolean multipartEnabled )
674 	{
675 		getSettings().setBoolean( DISABLE_MULTIPART_ATTACHMENTS, multipartEnabled );
676 	}
677 
678 	public boolean isRemoveEmptyContent()
679 	{
680 		return getSettings().getBoolean( REMOVE_EMPTY_CONTENT );
681 	}
682 
683 	public void setRemoveEmptyContent( boolean removeEmptyContent )
684 	{
685 		boolean old = getSettings().getBoolean( REMOVE_EMPTY_CONTENT );
686 		getSettings().setBoolean( REMOVE_EMPTY_CONTENT, removeEmptyContent );
687 		notifyPropertyChanged( REMOVE_EMPTY_CONTENT, old, removeEmptyContent );
688 	}
689 
690 	public boolean isEncodeAttachments()
691 	{
692 		return getSettings().getBoolean( ENCODE_ATTACHMENTS );
693 	}
694 
695 	public void setEncodeAttachments( boolean encodeAttachments )
696 	{
697 		boolean old = getSettings().getBoolean( ENCODE_ATTACHMENTS );
698 		getSettings().setBoolean( ENCODE_ATTACHMENTS, encodeAttachments );
699 		notifyPropertyChanged( ENCODE_ATTACHMENTS, old, encodeAttachments );
700 	}
701 
702 	public boolean isStripWhitespaces()
703 	{
704 		return getSettings().getBoolean( STRIP_WHITESPACES );
705 	}
706 
707 	public void setStripWhitespaces( boolean stripWhitespaces )
708 	{
709 		boolean old = getSettings().getBoolean( STRIP_WHITESPACES );
710 		getSettings().setBoolean( STRIP_WHITESPACES, stripWhitespaces );
711 		notifyPropertyChanged( STRIP_WHITESPACES, old, stripWhitespaces );
712 	}
713 
714 	@Override
715 	public void onSave()
716 	{
717 		if( responseContent != null )
718 		{
719 			CompressedStringSupport.setString( getConfig().getResponseContent(), responseContent );
720 			responseContent = null;
721 		}
722 	}
723 }