/*
* soapUI, copyright (C) 2004-2011 eviware.com
*
* soapUI is free software; you can redistribute it and/or modify it under the
* terms of version 2.1 of the GNU Lesser General Public License as published by
* the Free Software Foundation.
*
* soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details at gnu.org.
*/
package com.eviware.soapui.impl.wsdl.mock;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Vector;
import javax.mail.MessagingException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.w3c.dom.Document;
import com.eviware.soapui.SoapUI;
import com.eviware.soapui.impl.wsdl.WsdlOperation;
import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MockRequestDataSource;
import com.eviware.soapui.impl.wsdl.submit.transports.http.support.attachments.MultipartMessageSupport;
import com.eviware.soapui.impl.wsdl.support.CompressionSupport;
import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
import com.eviware.soapui.impl.wsdl.support.soap.SoapUtils;
import com.eviware.soapui.impl.wsdl.support.soap.SoapVersion;
import com.eviware.soapui.impl.wsdl.support.wss.IncomingWss;
import com.eviware.soapui.model.iface.Attachment;
import com.eviware.soapui.model.mock.MockRequest;
import com.eviware.soapui.settings.WsdlSettings;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.Tools;
import com.eviware.soapui.support.types.StringToStringMap;
import com.eviware.soapui.support.types.StringToStringsMap;
import com.eviware.soapui.support.xml.XmlUtils;
/**
* Request-class created when receiving an external request to a WsdlMockService
*
* @author ole.matzura
*/
public class WsdlMockRequest implements MockRequest
{
private StringToStringsMap requestHeaders;
private String requestContent;
private MultipartMessageSupport mmSupport;
private XmlObject requestXmlObject;
private SoapVersion soapVersion;
private final HttpServletResponse response;
private String protocol;
private String path;
private String soapAction;
private final WsdlMockRunContext context;
private final WsdlMockRunContext requestContext;
private final HttpServletRequest request;
private Vector<Object> wssResult;
private MockRequestDataSource mockRequestDataSource;
private String actualRequestContent;
private boolean responseMessage;
private String method;
public WsdlMockRequest( HttpServletRequest request, HttpServletResponse response, WsdlMockRunContext context )
throws Exception
{
this.request = request;
this.response = response;
this.context = context;
requestContext = new WsdlMockRunContext( context.getMockService(), null );
requestHeaders = new StringToStringsMap();
for( Enumeration<?> e = request.getHeaderNames(); e.hasMoreElements(); )
{
String header = ( String )e.nextElement();
String lcHeader = header.toLowerCase();
if( lcHeader.equals( "soapaction" ) )
requestHeaders.put( "SOAPAction", request.getHeader( header ) );
else if( lcHeader.equals( "content-type" ) )
requestHeaders.put( "Content-Type", request.getHeader( header ) );
else if( lcHeader.equals( "content-length" ) )
requestHeaders.put( "Content-Length", request.getHeader( header ) );
else if( lcHeader.equals( "content-encoding" ) )
requestHeaders.put( "Content-Encoding", request.getHeader( header ) );
else
requestHeaders.put( header, request.getHeader( header ) );
}
protocol = request.getProtocol();
path = request.getPathInfo();
if( path == null )
path = "";
if( request.getMethod().equals( "POST" ) )
{
initPostRequest( request, context );
}
}
protected void initPostRequest( HttpServletRequest request, WsdlMockRunContext context ) throws Exception
{
String contentType = request.getContentType();
if( contentType != null && contentType.toUpperCase().startsWith( "MULTIPART" ) )
{
readMultipartRequest( request );
if( mmSupport != null && mmSupport.getRootPart() != null )
contentType = mmSupport.getRootPart().getContentType();
}
else
{
this.requestContent = readRequestContent( request );
if( StringUtils.hasContent( context.getMockService().getIncomingWss() ) )
{
IncomingWss incoming = context.getMockService().getProject().getWssContainer()
.getIncomingWssByName( context.getMockService().getIncomingWss() );
if( incoming != null )
{
Document dom = XmlUtils.parseXml( requestContent );
try
{
wssResult = incoming.processIncoming( dom, context );
if( wssResult != null && wssResult.size() > 0 )
{
StringWriter writer = new StringWriter();
XmlUtils.serialize( dom, writer );
actualRequestContent = requestContent;
requestContent = writer.toString();
}
}
catch( Exception e )
{
if( wssResult == null )
wssResult = new Vector<Object>();
wssResult.add( e );
}
}
}
}
try
{
soapVersion = SoapUtils.deduceSoapVersion( contentType, getRequestXmlObject() );
}
catch( Exception e )
{
// ignore non xml requests
}
if( soapVersion == null )
soapVersion = SoapVersion.Soap11;
soapAction = SoapUtils.getSoapAction( soapVersion, requestHeaders );
}
public SoapVersion getSoapVersion()
{
return soapVersion;
}
public String getProtocol()
{
return protocol;
}
public Vector<?> getWssResult()
{
return wssResult;
}
private void readMultipartRequest( HttpServletRequest request ) throws MessagingException
{
StringToStringMap values = StringToStringMap.fromHttpHeader( request.getContentType() );
mockRequestDataSource = new MockRequestDataSource( request );
mmSupport = new MultipartMessageSupport( mockRequestDataSource, values.get( "start" ), null, true, requestContext
.getMockService().getSettings().getBoolean( WsdlSettings.PRETTY_PRINT_RESPONSE_MESSAGES ) );
}
private String readRequestContent( HttpServletRequest request ) throws Exception
{
String messageContent = null;
String encoding = request.getCharacterEncoding();
if( encoding != null )
encoding = StringUtils.unquote( encoding );
ServletInputStream is = request.getInputStream();
if( is.markSupported() && request.getContentLength() > 0 )
is.mark( request.getContentLength() );
ByteArrayOutputStream out = Tools.readAll( is, Tools.READ_ALL );
byte[] data = out.toByteArray();
if( is.markSupported() && request.getContentLength() > 0 )
{
try
{
is.reset();
}
catch( IOException e )
{
SoapUI.logError( e );
}
}
// decompress
String compressionAlg = HttpClientSupport.getCompressionType( request.getContentType(),
requestHeaders.get( "Content-Encoding", ( String )null ) );
if( compressionAlg != null )
{
try
{
data = CompressionSupport.decompress( compressionAlg, data );
}
catch( Exception e )
{
IOException ioe = new IOException( "Decompression of response failed" );
ioe.initCause( e );
throw ioe;
}
}
int contentOffset = 0;
String contentType = request.getContentType();
if( contentType != null && data.length > 0 )
{
if( contentType.toLowerCase().endsWith( "xml" ) )
{
if( data.length > 3 && data[0] == ( byte )239 && data[1] == ( byte )187 && data[2] == ( byte )191 )
{
encoding = "UTF-8";
contentOffset = 3;
}
}
encoding = StringUtils.unquote( encoding );
messageContent = encoding == null ? new String( data ) : new String( data, contentOffset,
( int )( data.length - contentOffset ), encoding );
}
if( encoding == null )
encoding = "UTF-8";
if( messageContent == null )
{
messageContent = new String( data, encoding );
}
return messageContent;
}
public Attachment[] getRequestAttachments()
{
return mmSupport == null ? new Attachment[0] : mmSupport.getAttachments();
}
public String getRequestContent()
{
return mmSupport == null ? requestContent : mmSupport.getContentAsString();
}
public StringToStringsMap getRequestHeaders()
{
return requestHeaders;
}
public void setRequestContent( String requestContent )
{
this.requestContent = requestContent;
requestXmlObject = null;
try
{
soapVersion = SoapUtils.deduceSoapVersion( request.getContentType(), getRequestXmlObject() );
}
catch( XmlException e )
{
SoapUI.logError( e );
}
if( soapVersion == null )
soapVersion = SoapVersion.Soap11;
}
public XmlObject getRequestXmlObject() throws XmlException
{
if( requestXmlObject == null && StringUtils.hasContent( getRequestContent() ) )
// requestXmlObject = XmlObject.Factory.parse( getRequestContent() );
requestXmlObject = XmlUtils.createXmlObject( getRequestContent(), XmlUtils.createDefaultXmlOptions() );
return requestXmlObject;
}
public HttpServletResponse getHttpResponse()
{
return response;
}
public HttpServletRequest getHttpRequest()
{
return request;
}
public String getMethod()
{
return method == null ? request.getMethod() : method;
}
public void setMethod( String method )
{
this.method = method;
}
public XmlObject getContentElement() throws XmlException
{
return SoapUtils.getContentElement( getRequestXmlObject(), soapVersion );
}
public String getPath()
{
return path;
}
public WsdlMockRunContext getContext()
{
return context;
}
public void setOperation( WsdlOperation operation )
{
if( mmSupport != null )
mmSupport.setOperation( operation );
}
public WsdlMockRunContext getRequestContext()
{
return requestContext;
}
public String getSoapAction()
{
return soapAction;
}
public void setSoapAction( String soapAction )
{
this.soapAction = soapAction;
}
public byte[] getRawRequestData()
{
return mockRequestDataSource == null ? actualRequestContent == null ? requestContent.getBytes()
: actualRequestContent.getBytes() : mockRequestDataSource.getData();
}
public void setResponseMessage( boolean responseMessage )
{
this.responseMessage = responseMessage;
}
public boolean isResponseMessage()
{
return responseMessage;
}
}