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.submit.transports.http;
14  
15  import java.io.ByteArrayOutputStream;
16  
17  import javax.xml.namespace.QName;
18  
19  import org.apache.commons.codec.binary.Base64;
20  import org.apache.commons.codec.binary.Hex;
21  import org.apache.commons.httpclient.Header;
22  import org.apache.commons.httpclient.HeaderElement;
23  import org.apache.commons.httpclient.NameValuePair;
24  import org.apache.xmlbeans.SchemaGlobalElement;
25  import org.apache.xmlbeans.SchemaType;
26  import org.apache.xmlbeans.SchemaTypeSystem;
27  import org.apache.xmlbeans.XmlCursor;
28  import org.apache.xmlbeans.XmlHexBinary;
29  import org.apache.xmlbeans.XmlObject;
30  import org.w3c.dom.Element;
31  import org.w3c.dom.Node;
32  
33  import com.eviware.soapui.impl.wsdl.WsdlRequest;
34  import com.eviware.soapui.impl.wsdl.support.xsd.SchemaUtils;
35  import com.eviware.soapui.model.iface.Attachment;
36  import com.eviware.soapui.model.iface.Request;
37  import com.eviware.soapui.settings.HttpSettings;
38  import com.eviware.soapui.support.Tools;
39  import com.eviware.soapui.support.types.StringToStringMap;
40  
41  public class MimeMessageResponse implements WsdlResponse
42  {
43  	private final WsdlRequest wsdlRequest;
44  	private long timeTaken;
45  	private long responseContentLength;
46  	private StringToStringMap requestHeaders;
47  	private StringToStringMap responseHeaders;
48  	private final String requestContent;
49  	private SSLInfo sslInfo;
50  	private MultipartMessageSupport mmSupport;
51  	private long timestamp;
52  
53  	public MimeMessageResponse(WsdlRequest wsdlRequest, final TimeablePostMethod postMethod, String requestContent)
54  	{
55  		this.wsdlRequest = wsdlRequest;
56  		this.requestContent = requestContent;
57  		this.timeTaken = postMethod.getTimeTaken();
58  		this.timestamp = System.currentTimeMillis();
59  		
60  		try
61  		{
62  			initHeaders( postMethod );
63  			sslInfo = postMethod.getSSLInfo();
64  			PostResponseDataSource postResponseDataSource = new PostResponseDataSource( postMethod );
65  			responseContentLength = postResponseDataSource.getDataSize();
66  			
67  			Header h = postMethod.getResponseHeader( "Content-Type" );
68  			HeaderElement[] elements = h.getElements();
69  			
70  			String rootPartId = null;
71  			String multipartType = null;
72  			
73  			for( HeaderElement element : elements )
74  			{
75  				String name = element.getName().toUpperCase();
76  				if( name.startsWith( "MULTIPART/" ))
77  				{
78  					NameValuePair parameter = element.getParameterByName("start");
79  					if (parameter != null)
80  						rootPartId = parameter.getValue();
81  					
82  					parameter = element.getParameterByName("type");
83  					if (parameter != null)
84  						multipartType = parameter.getValue();
85  				}
86  			}
87  			
88  			mmSupport = new MultipartMessageSupport( postResponseDataSource, rootPartId );
89  			
90  			if (wsdlRequest.getSettings().getBoolean(HttpSettings.INCLUDE_RESPONSE_IN_TIME_TAKEN))
91  				this.timeTaken = postMethod.getTimeTakenUntilNow();
92  			
93  			if (wsdlRequest.isExpandMtomResponseAttachments() && "application/xop+xml".equals( multipartType ))
94  			{
95  				expandMtomAttachments();
96  			}
97  		}
98  		catch ( Exception e)
99  		{
100 			e.printStackTrace();
101 		}
102 	}
103 
104 	private void expandMtomAttachments()
105 	{
106 		try
107 		{
108 			XmlObject xmlObject = XmlObject.Factory.parse(getContentAsString());
109 			XmlObject[] includes = xmlObject.selectPath( "declare namespace xop='http://www.w3.org/2004/08/xop/include'; //xop:Include" );
110 			
111 			for( XmlObject include : includes )
112 			{
113 				Element elm = ( Element ) include.getDomNode();
114 				String href = elm.getAttribute( "href" );
115 				Attachment attachment = mmSupport.getAttachmentWithContentId( "<" + href.substring( 4 ) + ">" );
116 				if( attachment != null )
117 				{
118 					ByteArrayOutputStream data = Tools.readAll( attachment.getInputStream(), 0 );
119 					byte[] byteArray = data.toByteArray();
120 					
121 					XmlCursor cursor = include.newCursor();
122 					cursor.toParent();
123 					XmlObject parentXmlObject = cursor.getObject();
124 					cursor.dispose();
125 					
126 					SchemaType schemaType = parentXmlObject.schemaType();
127 					Node parentNode = elm.getParentNode();
128 					
129 					if( schemaType.isNoType())
130 					{
131 						SchemaTypeSystem typeSystem = wsdlRequest.getOperation().getInterface().getWsdlContext().getSchemaTypeSystem();
132 						SchemaGlobalElement schemaElement = typeSystem.findElement( new QName( parentNode.getNamespaceURI(), parentNode.getLocalName() ) );
133 						if( schemaElement != null )
134 						{
135 							schemaType = schemaElement.getType();
136 						}
137 					}
138 
139 					String txt = null;
140 					
141 					if( SchemaUtils.isInstanceOf( schemaType, XmlHexBinary.type ))
142 					{
143 						txt = new String( Hex.encodeHex( byteArray ));
144 					}
145 					else
146 					{
147 						txt = new String( Base64.encodeBase64( byteArray ));
148 					}
149 					 
150 					
151 					parentNode.replaceChild( elm.getOwnerDocument().createTextNode( txt ), elm );
152 				}
153 			}
154 			
155 			mmSupport.setResponseContent( xmlObject.toString() );
156 		}
157 		catch( Exception e )
158 		{
159 			e.printStackTrace();
160 		}
161 	}
162 
163 	public SSLInfo getSSLInfo()
164 	{
165 		return sslInfo;
166 	}
167 
168 	public long getContentLength()
169 	{
170 		return responseContentLength;
171 	}
172 
173 	public Request getRequest()
174 	{
175 		return wsdlRequest;
176 	}
177 
178 	public long getTimeTaken()
179 	{
180 		return timeTaken;
181 	}
182 
183 	private void initHeaders(TimeablePostMethod postMethod)
184 	{
185 		requestHeaders = new StringToStringMap();
186 		Header[] headers = postMethod.getRequestHeaders();
187 		for( Header header : headers )
188 		{
189 			requestHeaders.put( header.getName(), header.getValue() );
190 		}
191 		
192 		responseHeaders = new StringToStringMap();
193 		headers = postMethod.getResponseHeaders();
194 		for( Header header : headers )
195 		{
196 			responseHeaders.put( header.getName(), header.getValue() );
197 		}
198 		
199 		responseHeaders.put( "#status#", postMethod.getStatusLine().toString() );
200 	}
201 	
202 	public StringToStringMap getRequestHeaders()
203 	{
204 		return requestHeaders;
205 	}
206 
207 	public StringToStringMap getResponseHeaders()
208 	{
209 		return responseHeaders;
210 	}
211 	
212 	public String getRequestContent()
213 	{
214 		return requestContent;
215 	}
216 
217 	public void setResponseContent( String responseContent )
218 	{
219 		mmSupport.setResponseContent( responseContent );
220 	}
221 
222 	public Attachment[] getAttachments()
223 	{
224 		return mmSupport.getAttachments();
225 	}
226 
227 	public Attachment[] getAttachmentsForPart( String partName )
228 	{
229 		return mmSupport.getAttachmentsForPart( partName );
230 	}
231 
232 	public String getContentAsString()
233 	{
234 		return mmSupport.getContentAsString();
235 	}
236 
237 	public long getTimestamp()
238 	{
239 		return timestamp;
240 	}
241 }