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.mock;
14  
15  import com.eviware.soapui.SoapUI;
16  import com.eviware.soapui.config.AttachmentConfig;
17  import com.eviware.soapui.config.HeaderConfig;
18  import com.eviware.soapui.config.MockResponseConfig;
19  import com.eviware.soapui.impl.wsdl.*;
20  import com.eviware.soapui.impl.wsdl.submit.filters.RemoveEmptyContentRequestFilter;
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.BodyPartAttachment;
23  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MimeMessageMockResponseEntity;
24  import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MockResponseDataSource;
25  import com.eviware.soapui.impl.wsdl.support.*;
26  import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
27  import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
28  import com.eviware.soapui.impl.wsdl.support.wsa.WsaConfig;
29  import com.eviware.soapui.impl.wsdl.support.wsa.WsaContainer;
30  import com.eviware.soapui.impl.wsdl.support.wsa.WsaUtils;
31  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlContext;
32  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils;
33  import com.eviware.soapui.impl.wsdl.support.wsdl.WsdlUtils.SoapHeader;
34  import com.eviware.soapui.impl.wsdl.support.wss.OutgoingWss;
35  import com.eviware.soapui.model.ModelItem;
36  import com.eviware.soapui.model.TestPropertyHolder;
37  import com.eviware.soapui.model.iface.Attachment;
38  import com.eviware.soapui.model.iface.Attachment.AttachmentEncoding;
39  import com.eviware.soapui.model.iface.MessagePart;
40  import com.eviware.soapui.model.mock.MockResponse;
41  import com.eviware.soapui.model.mock.MockRunContext;
42  import com.eviware.soapui.model.propertyexpansion.PropertyExpansion;
43  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContainer;
44  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionUtils;
45  import com.eviware.soapui.model.testsuite.TestProperty;
46  import com.eviware.soapui.model.testsuite.TestPropertyListener;
47  import com.eviware.soapui.settings.CommonSettings;
48  import com.eviware.soapui.settings.WsdlSettings;
49  import com.eviware.soapui.support.StringUtils;
50  import com.eviware.soapui.support.Tools;
51  import com.eviware.soapui.support.UISupport;
52  import com.eviware.soapui.support.scripting.ScriptEnginePool;
53  import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
54  import com.eviware.soapui.support.types.StringToStringMap;
55  import com.eviware.soapui.support.xml.XmlUtils;
56  import org.apache.log4j.Logger;
57  import org.apache.xmlbeans.SchemaGlobalElement;
58  import org.apache.xmlbeans.SchemaType;
59  import org.w3c.dom.Document;
60  
61  import javax.activation.DataHandler;
62  import javax.mail.MessagingException;
63  import javax.mail.internet.MimeBodyPart;
64  import javax.mail.internet.MimeMessage;
65  import javax.mail.internet.MimeMultipart;
66  import javax.mail.internet.PreencodedMimeBodyPart;
67  import javax.swing.*;
68  import javax.wsdl.BindingOperation;
69  import javax.wsdl.Message;
70  import java.beans.PropertyChangeListener;
71  import java.io.ByteArrayOutputStream;
72  import java.io.File;
73  import java.io.IOException;
74  import java.io.StringWriter;
75  import java.util.ArrayList;
76  import java.util.Arrays;
77  import java.util.List;
78  import java.util.Map;
79  import java.util.zip.GZIPOutputStream;
80  
81  /***
82   * A WsdlMockResponse contained by a WsdlMockOperation
83   *
84   * @author ole.matzura
85   */
86  
87  public class WsdlMockResponse extends AbstractWsdlModelItem<MockResponseConfig> implements MockResponse,
88          MutableWsdlAttachmentContainer, PropertyExpansionContainer, TestPropertyHolder, WsaContainer
89  {
90     private final static Logger log = Logger.getLogger( WsdlMockResponse.class );
91  
92     public final static String MOCKRESULT_PROPERTY = WsdlMockResponse.class.getName() + "@mockresult";
93     public final static String SCRIPT_PROPERTY = WsdlMockResponse.class.getName() + "@script";
94     public final static String HEADERS_PROPERTY = WsdlMockResponse.class.getName() + "@headers";
95     public final static String DISABLE_MULTIPART_ATTACHMENTS = WsdlMockResponse.class.getName() + "@disable-multipart-attachments";
96     public static final String FORCE_MTOM = WsdlMockResponse.class.getName() + "@force_mtom";
97     public static final String ENABLE_INLINE_FILES = WsdlMockResponse.class.getName() + "@enable_inline_files";
98     public final static String RESPONSE_DELAY_PROPERTY = WsdlMockResponse.class.getName() + "@response-delay";
99     public static final String STRIP_WHITESPACES = WsdlMockResponse.class.getName() + "@strip-whitespaces";
100    public static final String REMOVE_EMPTY_CONTENT = WsdlMockResponse.class.getName() + "@remove_empty_content";
101    public static final String ENCODE_ATTACHMENTS = WsdlMockResponse.class.getName() + "@encode_attachments";
102    public static final String RESPONSE_HTTP_STATUS = WsdlMockResponse.class.getName() + "@response-http-status";
103    public static final String OUGOING_WSS = WsdlMockResponse.class.getName() + "@outgoing-wss";
104 
105    protected List<FileAttachment<WsdlMockResponse>> attachments = new ArrayList<FileAttachment<WsdlMockResponse>>();
106    private List<HttpAttachmentPart> definedAttachmentParts;
107    private ModelItemIconAnimator<WsdlMockResponse> iconAnimator;
108    private WsdlMockResult mockResult;
109    private String responseContent;
110    private ScriptEnginePool scriptEnginePool;
111    private MapTestPropertyHolder propertyHolder;
112    private WsaConfig wsaConfig;
113 
114    public WsdlMockResponse( WsdlMockOperation operation, MockResponseConfig config )
115    {
116       super( config, operation, "/mockResponse.gif" );
117 
118       for( AttachmentConfig ac : getConfig().getAttachmentList() )
119       {
120          attachments.add( new MockFileAttachment( ac, this ) );
121       }
122 
123       if( !config.isSetEncoding() )
124          config.setEncoding( "UTF-8" );
125 
126       iconAnimator = new ModelItemIconAnimator<WsdlMockResponse>( this, "/mockResponse.gif", "/exec_request", 4, "gif" );
127 
128       scriptEnginePool = new ScriptEnginePool( this );
129       scriptEnginePool.setScript( getScript() );
130 
131       propertyHolder = new MapTestPropertyHolder( this );
132       propertyHolder.addProperty( "Request" );
133    }
134 
135    @Override
136    public void setConfig( MockResponseConfig config )
137    {
138       super.setConfig( config );
139 
140       if( scriptEnginePool != null )
141          scriptEnginePool.setScript( getScript() );
142    }
143 
144    public Attachment[] getAttachments()
145    {
146       return attachments.toArray( new Attachment[attachments.size()] );
147    }
148 
149    public String getScript()
150    {
151       return getConfig().isSetScript() ? getConfig().getScript().getStringValue() : null;
152    }
153 
154    public String getEncoding()
155    {
156       return getConfig().getEncoding();
157    }
158 
159    public void setEncoding( String encoding )
160    {
161       String old = getEncoding();
162       getConfig().setEncoding( encoding );
163       notifyPropertyChanged( ENCODING_PROPERTY, old, encoding );
164    }
165 
166    public String getResponseContent()
167    {
168       if( getConfig().getResponseContent() == null )
169          getConfig().addNewResponseContent();
170 
171       if( responseContent == null )
172          responseContent = CompressedStringSupport.getString( getConfig().getResponseContent() );
173 
174       return responseContent;
175    }
176 
177    public void setResponseContent( String responseContent )
178    {
179       String oldContent = getResponseContent();
180       if( responseContent.equals( oldContent ) )
181          return;
182 
183       this.responseContent = responseContent;
184       notifyPropertyChanged( RESPONSE_CONTENT_PROPERTY, oldContent, responseContent );
185    }
186 
187    @Override
188    public ImageIcon getIcon()
189    {
190       return iconAnimator.getIcon();
191    }
192 
193    public WsdlMockOperation getMockOperation()
194    {
195       return (WsdlMockOperation) getParent();
196    }
197 
198    public WsdlMockResult execute( WsdlMockRequest request, WsdlMockResult result ) throws DispatchException
199    {
200       try
201       {
202          iconAnimator.start();
203 
204          getProperty( "Request" ).setValue( request.getRequestContent() );
205 
206          long delay = getResponseDelay();
207          if( delay > 0 )
208             Thread.sleep( delay );
209 
210          String script = getScript();
211          if( script != null && script.trim().length() > 0 )
212          {
213             evaluateScript( request );
214          }
215 
216          String responseContent = getResponseContent();
217 
218          // create merged context
219          WsdlMockRunContext context = new WsdlMockRunContext( request.getContext().getMockService(), null );
220          context.setMockResponse( this );
221          context.putAll( request.getContext() );
222          context.putAll( request.getRequestContext() );
223 
224          StringToStringMap responseHeaders = getResponseHeaders();
225          for( String name : responseHeaders.keySet() )
226          {
227             result.addHeader( name, PropertyExpansionUtils.expandProperties( context, responseHeaders.get( name ) ) );
228          }
229 
230          responseContent = PropertyExpansionUtils.expandProperties( context, responseContent, isEntitizeProperties() );
231 
232          if( this.getWsaConfig().isWsaEnabled() )
233          {
234             responseContent = new WsaUtils( responseContent, getSoapVersion(), getMockOperation().getOperation(), context ).addWSAddressingMockResponse( this, request );
235          }
236 
237          String outgoingWss = getOutgoingWss();
238          if( StringUtils.isNullOrEmpty( outgoingWss ) )
239             outgoingWss = getMockOperation().getMockService().getOutgoingWss();
240 
241          if( StringUtils.hasContent( outgoingWss ) )
242          {
243             OutgoingWss outgoing = getMockOperation().getMockService().getProject().getWssContainer().getOutgoingWssByName( outgoingWss );
244             if( outgoing != null )
245             {
246                Document dom = XmlUtils.parseXml( responseContent );
247                outgoing.processOutgoing( dom, context );
248                StringWriter writer = new StringWriter();
249                XmlUtils.serialize( dom, writer );
250                responseContent = writer.toString();
251             }
252          }
253 
254          if( !result.isCommitted() )
255          {
256             responseContent = writeResponse( result, responseContent );
257          }
258 
259          result.setResponseContent( responseContent );
260 
261          setMockResult( result );
262 
263          return mockResult;
264       }
265       catch( Throwable e )
266       {
267          SoapUI.logError( e );
268          throw new DispatchException( e );
269       }
270       finally
271       {
272          iconAnimator.stop();
273       }
274    }
275 
276    public void evaluateScript( WsdlMockRequest request ) throws Exception
277    {
278       String script = getScript();
279       if( script == null || script.trim().length() == 0 )
280          return;
281 
282       WsdlMockService mockService = getMockOperation().getMockService();
283       WsdlMockRunner mockRunner = mockService.getMockRunner();
284       MockRunContext context = mockRunner == null ? new WsdlMockRunContext( mockService, null ) : mockRunner
285               .getMockContext();
286 
287       SoapUIScriptEngine scriptEngine = scriptEnginePool.getScriptEngine();
288 
289       try
290       {
291          scriptEngine.setVariable( "context", context );
292          scriptEngine.setVariable( "requestContext", request == null ? null : request.getRequestContext() );
293          scriptEngine.setVariable( "mockContext", context );
294          scriptEngine.setVariable( "mockRequest", request );
295          scriptEngine.setVariable( "mockResponse", this );
296          scriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );
297 
298          scriptEngine.run();
299       }
300       catch( RuntimeException e )
301       {
302          throw new Exception( e.getMessage(), e );
303       }
304       finally
305       {
306          scriptEnginePool.returnScriptEngine( scriptEngine );
307       }
308    }
309 
310    @Override
311    public void release()
312    {
313       super.release();
314       scriptEnginePool.release();
315    }
316 
317    public void setScript( String script )
318    {
319       String oldScript = getScript();
320       if( !script.equals( oldScript ) )
321       {
322          if( !getConfig().isSetScript() )
323             getConfig().addNewScript();
324          getConfig().getScript().setStringValue( script );
325 
326          scriptEnginePool.setScript( script );
327 
328          notifyPropertyChanged( SCRIPT_PROPERTY, oldScript, script );
329       }
330    }
331 
332    public void setResponseHeaders( StringToStringMap headers )
333    {
334       StringToStringMap oldHeaders = getResponseHeaders();
335 
336       HeaderConfig[] headerConfigs = new HeaderConfig[headers.size()];
337       int ix = 0;
338       for( String header : headers.keySet() )
339       {
340          headerConfigs[ix] = HeaderConfig.Factory.newInstance();
341          headerConfigs[ix].setName( header );
342          headerConfigs[ix].setValue( headers.get( header ) );
343          ix++;
344       }
345 
346       getConfig().setHeaderArray( headerConfigs );
347 
348       notifyPropertyChanged( HEADERS_PROPERTY, oldHeaders, headers );
349    }
350 
351    public StringToStringMap getResponseHeaders()
352    {
353       StringToStringMap result = new StringToStringMap();
354       List<HeaderConfig> headerList = getConfig().getHeaderList();
355       for( HeaderConfig header : headerList )
356       {
357          result.put( header.getName(), header.getValue() );
358       }
359 
360       return result;
361    }
362 
363    public MessagePart[] getRequestParts()
364    {
365       try
366       {
367          List<MessagePart> result = new ArrayList<MessagePart>();
368          result.addAll( Arrays.asList( getMockOperation().getOperation().getDefaultRequestParts() ) );
369 
370          if( getMockResult() != null )
371             result.addAll( AttachmentUtils.extractAttachmentParts(
372                     getMockOperation().getOperation(), getMockResult().getMockRequest().getRequestContent(), true, false, isMtomEnabled() ) );
373 
374          return result.toArray( new MessagePart[result.size()] );
375       }
376       catch( Exception e )
377       {
378          SoapUI.logError( e );
379          return new MessagePart[0];
380       }
381    }
382 
383    public MessagePart[] getResponseParts()
384    {
385       try
386       {
387          // init
388          WsdlOperation op = getMockOperation().getOperation();
389          if( op == null || op.isUnidirectional() )
390             return new MessagePart[0];
391 
392          List<MessagePart> result = new ArrayList<MessagePart>();
393          WsdlContext wsdlContext = op.getInterface().getWsdlContext();
394          BindingOperation bindingOperation = op.findBindingOperation( wsdlContext.getDefinition() );
395 
396          if( bindingOperation == null )
397             return new MessagePart[0];
398 
399          // header parts
400          List<SoapHeader> headers = WsdlUtils.getSoapHeaders( bindingOperation.getBindingOutput()
401                  .getExtensibilityElements() );
402 
403          for( int i = 0; i < headers.size(); i++ )
404          {
405             SoapHeader header = headers.get( i );
406 
407             Message message = wsdlContext.getDefinition().getMessage( header.getMessage() );
408             if( message == null )
409             {
410                log.error( "Missing message for header: " + header.getMessage() );
411                continue;
412             }
413 
414             javax.wsdl.Part part = message.getPart( header.getPart() );
415 
416             if( part != null )
417             {
418                SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
419                SchemaGlobalElement schemaElement = WsdlUtils.getSchemaElementForPart( wsdlContext, part );
420                if( schemaType != null )
421                   result.add( new WsdlHeaderPart( part.getName(), schemaType, part.getElementName(), schemaElement ) );
422             }
423             else
424                log.error( "Missing part for header; " + header.getPart() );
425          }
426 
427          // content parts
428          javax.wsdl.Part[] parts = WsdlUtils.getOutputParts( bindingOperation );
429 
430          for( int i = 0; i < parts.length; i++ )
431          {
432             javax.wsdl.Part part = parts[i];
433 
434             if( !WsdlUtils.isAttachmentOutputPart( part, bindingOperation ) )
435             {
436                SchemaType schemaType = WsdlUtils.getSchemaTypeForPart( wsdlContext, part );
437                SchemaGlobalElement schemaElement = WsdlUtils.getSchemaElementForPart( wsdlContext, part );
438                if( schemaType != null )
439                   result.add( new WsdlContentPart( part.getName(), schemaType, part.getElementName(), schemaElement ) );
440             }
441          }
442 
443          result.addAll( Arrays.asList( getDefinedAttachmentParts() ) );
444 
445          return result.toArray( new MessagePart[result.size()] );
446       }
447       catch( Exception e )
448       {
449          SoapUI.logError( e );
450          return new MessagePart[0];
451       }
452    }
453 
454    public Attachment attachFile( File file, boolean cache ) throws IOException
455    {
456       FileAttachment<WsdlMockResponse> fileAttachment = new MockFileAttachment( file, cache, this );
457       attachments.add( fileAttachment );
458       notifyPropertyChanged( ATTACHMENTS_PROPERTY, null, fileAttachment );
459       return fileAttachment;
460    }
461 
462    public int getAttachmentCount()
463    {
464       return attachments.size();
465    }
466 
467    public WsdlAttachment getAttachmentAt( int index )
468    {
469       return attachments.get( index );
470    }
471 
472    public void removeAttachment( Attachment attachment )
473    {
474       int ix = attachments.indexOf( attachment );
475       attachments.remove( ix );
476 
477       try
478       {
479          notifyPropertyChanged( ATTACHMENTS_PROPERTY, attachment, null );
480       }
481       finally
482       {
483          getConfig().removeAttachment( ix );
484       }
485    }
486 
487    public HttpAttachmentPart[] getDefinedAttachmentParts()
488    {
489       if( definedAttachmentParts == null )
490       {
491          try
492          {
493             WsdlOperation operation = getMockOperation().getOperation();
494             if( operation == null )
495             {
496                definedAttachmentParts = new ArrayList<HttpAttachmentPart>();
497             }
498             else
499             {
500                UISupport.setHourglassCursor();
501                definedAttachmentParts = AttachmentUtils.extractAttachmentParts( operation, getResponseContent(), true,
502                        true, isMtomEnabled() );
503             }
504          }
505          catch( Exception e )
506          {
507             log.warn( e.toString() );
508          }
509          finally
510          {
511             UISupport.resetCursor();
512          }
513       }
514 
515       return definedAttachmentParts.toArray( new HttpAttachmentPart[definedAttachmentParts.size()] );
516    }
517 
518    public HttpAttachmentPart getAttachmentPart( String partName )
519    {
520       HttpAttachmentPart[] parts = getDefinedAttachmentParts();
521       for( HttpAttachmentPart part : parts )
522       {
523          if( part.getName().equals( partName ) )
524             return part;
525       }
526 
527       return null;
528    }
529 
530    public Attachment[] getAttachmentsForPart( String partName )
531    {
532       List<Attachment> result = new ArrayList<Attachment>();
533 
534       for( Attachment attachment : attachments )
535       {
536          if( attachment.getPart().equals( partName ) )
537             result.add( attachment );
538       }
539 
540       return result.toArray( new Attachment[result.size()] );
541    }
542 
543    public boolean isMtomEnabled()
544    {
545       return getSettings().getBoolean( WsdlSettings.ENABLE_MTOM );
546    }
547 
548    public void setMtomEnabled( boolean mtomEnabled )
549    {
550       boolean old = isMtomEnabled();
551       getSettings().setBoolean( WsdlSettings.ENABLE_MTOM, mtomEnabled );
552       definedAttachmentParts = null;
553       notifyPropertyChanged( MTOM_NABLED_PROPERTY, old, mtomEnabled );
554    }
555 
556    private String writeResponse( WsdlMockResult response, String responseContent ) throws Exception
557    {
558       MimeMultipart mp = null;
559       WsdlOperation operation = getMockOperation().getOperation();
560       if( operation == null )
561          throw new Exception( "Missing WsdlOperation for mock response" );
562 
563       SoapVersion soapVersion = operation.getInterface().getSoapVersion();
564 
565       StringToStringMap contentIds = new StringToStringMap();
566       boolean isXOP = isMtomEnabled() && isForceMtom();
567 
568       // preprocess only if neccessary
569       if( isMtomEnabled() || isInlineFilesEnabled() || getAttachmentCount() > 0 )
570       {
571          try
572          {
573             mp = new MimeMultipart();
574 
575             MessageXmlObject requestXmlObject = new MessageXmlObject( operation, getResponseContent(), false );
576             MessageXmlPart[] requestParts = requestXmlObject.getMessageParts();
577             for( MessageXmlPart requestPart : requestParts )
578             {
579                if( AttachmentUtils.prepareMessagePart( this, mp, requestPart, contentIds ) )
580                   isXOP = true;
581             }
582             responseContent = requestXmlObject.getMessageContent();
583          }
584          catch( Exception e )
585          {
586             e.printStackTrace();
587          }
588       }
589 
590       if( isRemoveEmptyContent() )
591       {
592          responseContent = RemoveEmptyContentRequestFilter.removeEmptyContent( responseContent );
593       }
594 
595       if( isStripWhitespaces() )
596       {
597          responseContent = XmlUtils.stripWhitespaces( responseContent );
598       }
599 
600       String status = getResponseHttpStatus();
601       WsdlMockRequest request = response.getMockRequest();
602 
603       if( status == null || status.trim().length() == 0 )
604       {
605          if( SoapUtils.isSoapFault( responseContent, request.getSoapVersion() ) )
606          {
607             request.getHttpResponse().setStatus( 500 );
608             response.setResponseStatus( 500 );
609          }
610          else
611          {
612             request.getHttpResponse().setStatus( 200 );
613             response.setResponseStatus( 200 );
614          }
615       }
616       else
617       {
618          try
619          {
620             int statusCode = Integer.parseInt( status );
621             request.getHttpResponse().setStatus( statusCode );
622             response.setResponseStatus( statusCode );
623          }
624          catch( RuntimeException e )
625          {
626             SoapUI.logError( e );
627          }
628       }
629 
630       ByteArrayOutputStream outData = new ByteArrayOutputStream();
631 
632       // non-multipart request?
633       if( !isXOP && ( mp == null || mp.getCount() == 0 ) && getAttachmentCount() == 0 )
634       {
635          String encoding = getEncoding();
636          if( responseContent == null )
637             responseContent = "";
638 
639          byte[] content = encoding == null ? responseContent.getBytes() : responseContent.getBytes( encoding );
640 
641          response.setContentType( soapVersion.getContentTypeHttpHeader( encoding, null ) );
642 
643          String acceptEncoding = response.getMockRequest().getRequestHeaders().get( "Accept-Encoding" );
644          if( acceptEncoding != null && acceptEncoding.toUpperCase().contains( "GZIP" ) )
645          {
646             response.addHeader( "Content-Encoding", "gzip" );
647             GZIPOutputStream zipOut = new GZIPOutputStream( outData );
648             zipOut.write( content );
649             zipOut.close();
650          }
651          else
652          {
653             outData.write( content );
654          }
655       }
656       else
657       {
658          // make sure..
659          if( mp == null )
660             mp = new MimeMultipart();
661 
662          // init root part
663          initRootPart( responseContent, mp, isXOP );
664 
665          // init mimeparts
666          AttachmentUtils.addMimeParts( this, Arrays.asList( getAttachments() ), mp, contentIds );
667 
668          // create request message
669          MimeMessage message = new MimeMessage( AttachmentUtils.JAVAMAIL_SESSION );
670          message.setContent( mp );
671          message.saveChanges();
672          MimeMessageMockResponseEntity mimeMessageRequestEntity = new MimeMessageMockResponseEntity( message, isXOP,
673                  this );
674 
675          response.addHeader( "Content-Type", mimeMessageRequestEntity.getContentType() );
676          response.addHeader( "MIME-Version", "1.0" );
677          mimeMessageRequestEntity.writeRequest( outData );
678       }
679 
680       response.writeRawResponseData( outData.toByteArray() );
681 
682       return responseContent;
683    }
684 
685    private void initRootPart( String requestContent, MimeMultipart mp, boolean isXOP ) throws MessagingException
686    {
687       MimeBodyPart rootPart = new PreencodedMimeBodyPart( "8bit" );
688       rootPart.setContentID( AttachmentUtils.ROOTPART_SOAPUI_ORG );
689       mp.addBodyPart( rootPart, 0 );
690 
691       DataHandler dataHandler = new DataHandler( new MockResponseDataSource( this, requestContent, isXOP ) );
692       rootPart.setDataHandler( dataHandler );
693    }
694 
695    @SuppressWarnings( "unchecked" )
696    public Attachment addAttachment( Attachment attachment )
697    {
698       if( attachment instanceof BodyPartAttachment )
699       {
700          try
701          {
702             BodyPartAttachment att = (BodyPartAttachment) attachment;
703 
704             AttachmentConfig newConfig = getConfig().addNewAttachment();
705             newConfig.setData( Tools.readAll( att.getInputStream(), 0 ).toByteArray() );
706             newConfig.setContentId( att.getContentID() );
707             newConfig.setContentType( att.getContentType() );
708             newConfig.setName( att.getName() );
709 
710             FileAttachment<WsdlMockResponse> newAttachment = new MockFileAttachment( newConfig, this );
711             attachments.add( newAttachment );
712             return newAttachment;
713          }
714          catch( Exception e )
715          {
716             SoapUI.logError( e );
717          }
718       }
719       else if( attachment instanceof FileAttachment )
720       {
721          AttachmentConfig oldConfig = ( (FileAttachment<WsdlMockResponse>) attachment ).getConfig();
722          AttachmentConfig newConfig = (AttachmentConfig) getConfig().addNewAttachment().set( oldConfig );
723          FileAttachment<WsdlMockResponse> newAttachment = new MockFileAttachment( newConfig, this );
724          attachments.add( newAttachment );
725          return newAttachment;
726       }
727 
728       return null;
729    }
730 
731    public void setResponseDelay( long delay )
732    {
733       long oldDelay = getResponseDelay();
734 
735       if( delay == 0 )
736          getSettings().clearSetting( RESPONSE_DELAY_PROPERTY );
737       else
738          getSettings().setLong( RESPONSE_DELAY_PROPERTY, delay );
739 
740       notifyPropertyChanged( RESPONSE_DELAY_PROPERTY, oldDelay, delay );
741    }
742 
743    public long getResponseDelay()
744    {
745       return getSettings().getLong( RESPONSE_DELAY_PROPERTY, 0 );
746    }
747 
748    public void setResponseHttpStatus( String httpStatus )
749    {
750       String oldStatus = getResponseHttpStatus();
751 
752       getConfig().setHttpResponseStatus( httpStatus );
753 
754       notifyPropertyChanged( RESPONSE_HTTP_STATUS, oldStatus, httpStatus );
755    }
756 
757    public String getResponseHttpStatus()
758    {
759       return getConfig().getHttpResponseStatus();
760    }
761 
762    public void setMockResult( WsdlMockResult mockResult )
763    {
764       WsdlMockResult oldResult = this.mockResult;
765       this.mockResult = mockResult;
766       notifyPropertyChanged( MOCKRESULT_PROPERTY, oldResult, mockResult );
767    }
768 
769    public WsdlMockResult getMockResult()
770    {
771       return mockResult;
772    }
773 
774    public long getContentLength()
775    {
776       return getResponseContent() == null ? 0 : getResponseContent().length();
777    }
778 
779    public boolean isMultipartEnabled()
780    {
781       return !getSettings().getBoolean( DISABLE_MULTIPART_ATTACHMENTS );
782    }
783 
784    public void setMultipartEnabled( boolean multipartEnabled )
785    {
786       getSettings().setBoolean( DISABLE_MULTIPART_ATTACHMENTS, multipartEnabled );
787    }
788 
789    public boolean isEntitizeProperties()
790    {
791       return getSettings().getBoolean( CommonSettings.ENTITIZE_PROPERTIES );
792    }
793 
794    public void setEntitizeProperties( boolean entitizeProperties )
795    {
796       getSettings().setBoolean( CommonSettings.ENTITIZE_PROPERTIES, entitizeProperties );
797    }
798 
799    public boolean isForceMtom()
800    {
801       return getSettings().getBoolean( FORCE_MTOM );
802    }
803 
804    public void setForceMtom( boolean forceMtom )
805    {
806       boolean old = getSettings().getBoolean( FORCE_MTOM );
807       getSettings().setBoolean( FORCE_MTOM, forceMtom );
808       notifyPropertyChanged( FORCE_MTOM, old, forceMtom );
809    }
810 
811    public boolean isRemoveEmptyContent()
812    {
813       return getSettings().getBoolean( REMOVE_EMPTY_CONTENT );
814    }
815 
816    public void setRemoveEmptyContent( boolean removeEmptyContent )
817    {
818       boolean old = getSettings().getBoolean( REMOVE_EMPTY_CONTENT );
819       getSettings().setBoolean( REMOVE_EMPTY_CONTENT, removeEmptyContent );
820       notifyPropertyChanged( REMOVE_EMPTY_CONTENT, old, removeEmptyContent );
821    }
822 
823    public boolean isEncodeAttachments()
824    {
825       return getSettings().getBoolean( ENCODE_ATTACHMENTS );
826    }
827 
828    public void setEncodeAttachments( boolean encodeAttachments )
829    {
830       boolean old = getSettings().getBoolean( ENCODE_ATTACHMENTS );
831       getSettings().setBoolean( ENCODE_ATTACHMENTS, encodeAttachments );
832       notifyPropertyChanged( ENCODE_ATTACHMENTS, old, encodeAttachments );
833    }
834 
835    public boolean isStripWhitespaces()
836    {
837       return getSettings().getBoolean( STRIP_WHITESPACES );
838    }
839 
840    public void setStripWhitespaces( boolean stripWhitespaces )
841    {
842       boolean old = getSettings().getBoolean( STRIP_WHITESPACES );
843       getSettings().setBoolean( STRIP_WHITESPACES, stripWhitespaces );
844       notifyPropertyChanged( STRIP_WHITESPACES, old, stripWhitespaces );
845    }
846 
847    public boolean isInlineFilesEnabled()
848    {
849       return getSettings().getBoolean( WsdlMockResponse.ENABLE_INLINE_FILES );
850    }
851 
852    public void setInlineFilesEnabled( boolean inlineFilesEnabled )
853    {
854       getSettings().setBoolean( WsdlMockResponse.ENABLE_INLINE_FILES, inlineFilesEnabled );
855    }
856 
857    @Override
858    public void beforeSave()
859    {
860       super.beforeSave();
861 
862       if( responseContent != null )
863       {
864          CompressedStringSupport.setString( getConfig().getResponseContent(), responseContent );
865          responseContent = null;
866       }
867    }
868 
869    public void addAttachmentsChangeListener( PropertyChangeListener listener )
870    {
871       addPropertyChangeListener( ATTACHMENTS_PROPERTY, listener );
872    }
873 
874    public boolean isReadOnly()
875    {
876       return false;
877    }
878 
879    public void removeAttachmentsChangeListener( PropertyChangeListener listener )
880    {
881       removePropertyChangeListener( ATTACHMENTS_PROPERTY, listener );
882    }
883 
884    public SoapVersion getSoapVersion()
885    {
886       return getMockOperation().getOperation() == null ? SoapVersion.Soap11 : getMockOperation().getOperation()
887               .getInterface().getSoapVersion();
888    }
889 
890    public PropertyExpansion[] getPropertyExpansions()
891    {
892       List<PropertyExpansion> result = new ArrayList<PropertyExpansion>();
893 
894       result.addAll( PropertyExpansionUtils.extractPropertyExpansions( this, this, "responseContent" ) );
895 
896       StringToStringMap responseHeaders = getResponseHeaders();
897       for( String key : responseHeaders.keySet() )
898       {
899          result.addAll( PropertyExpansionUtils.extractPropertyExpansions( this, new ResponseHeaderHolder(
900                  responseHeaders, key ), "value" ) );
901       }
902 
903       return result.toArray( new PropertyExpansion[result.size()] );
904    }
905 
906    public class ResponseHeaderHolder
907    {
908       private final StringToStringMap valueMap;
909       private final String key;
910 
911       public ResponseHeaderHolder( StringToStringMap valueMap, String key )
912       {
913          this.valueMap = valueMap;
914          this.key = key;
915       }
916 
917       public String getValue()
918       {
919          return valueMap.get( key );
920       }
921 
922       public void setValue( String value )
923       {
924          valueMap.put( key, value );
925          setResponseHeaders( valueMap );
926       }
927    }
928 
929    public void addTestPropertyListener( TestPropertyListener listener )
930    {
931       propertyHolder.addTestPropertyListener( listener );
932    }
933 
934    public ModelItem getModelItem()
935    {
936       return propertyHolder.getModelItem();
937    }
938 
939    public Map<String, TestProperty> getProperties()
940    {
941       return propertyHolder.getProperties();
942    }
943 
944    public TestProperty getProperty( String name )
945    {
946       return propertyHolder.getProperty( name );
947    }
948 
949    public String[] getPropertyNames()
950    {
951       return propertyHolder.getPropertyNames();
952    }
953 
954    public String getPropertyValue( String name )
955    {
956       return propertyHolder.getPropertyValue( name );
957    }
958 
959    public boolean hasProperty( String name )
960    {
961       return propertyHolder.hasProperty( name );
962    }
963 
964    public void removeTestPropertyListener( TestPropertyListener listener )
965    {
966       propertyHolder.removeTestPropertyListener( listener );
967    }
968 
969    public void setPropertyValue( String name, String value )
970    {
971       propertyHolder.setPropertyValue( name, value );
972    }
973 
974    public String getOutgoingWss()
975    {
976       return getConfig().getOutgoingWss();
977    }
978 
979    public void setOutgoingWss( String outgoingWss )
980    {
981       String old = getOutgoingWss();
982       getConfig().setOutgoingWss( outgoingWss );
983       notifyPropertyChanged( OUGOING_WSS, old, outgoingWss );
984    }
985 
986    public TestProperty getPropertyAt( int index )
987    {
988       return propertyHolder.getPropertyAt( index );
989    }
990 
991    public int getPropertyCount()
992    {
993       return propertyHolder.getPropertyCount();
994    }
995 
996    public String getPropertiesLabel()
997    {
998       return "Custom Properties";
999    }
1000 
1001    public AttachmentEncoding getAttachmentEncoding( String partName )
1002    {
1003       return AttachmentUtils.getAttachmentEncoding( getMockOperation().getOperation(), partName, true );
1004    }
1005 
1006    public WsaConfig getWsaConfig()
1007    {
1008       if( wsaConfig == null )
1009       {
1010          if( !getConfig().isSetWsaConfig() )
1011          {
1012             getConfig().addNewWsaConfig();
1013          }
1014          wsaConfig = new WsaConfig( getConfig().getWsaConfig(), this );
1015 //         wsaConfig.setGenerateMessageId(true);
1016       }
1017       return wsaConfig;
1018    }
1019 
1020    public boolean isWsAddressing()
1021    {
1022       return getConfig().getUseWsAddressing();
1023    }
1024 
1025    public void setWsAddressing( boolean wsAddressing )
1026    {
1027       boolean old = getConfig().getUseWsAddressing();
1028       getConfig().setUseWsAddressing( wsAddressing );
1029       notifyPropertyChanged( "wsAddressing", old, wsAddressing );
1030    }
1031 
1032    public boolean isWsaEnabled()
1033    {
1034       return isWsAddressing();
1035    }
1036 
1037    public void setWsaEnabled( boolean arg0 )
1038    {
1039       setWsAddressing( arg0 );
1040 
1041    }
1042 
1043    public WsdlOperation getOperation()
1044    {
1045       return getMockOperation().getOperation();
1046    }
1047 
1048 }