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