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  import java.io.StringWriter;
17  import java.lang.ref.WeakReference;
18  import java.util.Vector;
19  
20  import javax.xml.namespace.QName;
21  
22  import org.apache.commons.codec.binary.Base64;
23  import org.apache.commons.codec.binary.Hex;
24  import org.apache.commons.httpclient.Header;
25  import org.apache.commons.httpclient.HeaderElement;
26  import org.apache.commons.httpclient.NameValuePair;
27  import org.apache.xmlbeans.SchemaGlobalElement;
28  import org.apache.xmlbeans.SchemaType;
29  import org.apache.xmlbeans.SchemaTypeSystem;
30  import org.apache.xmlbeans.XmlCursor;
31  import org.apache.xmlbeans.XmlHexBinary;
32  import org.apache.xmlbeans.XmlObject;
33  import org.w3c.dom.Document;
34  import org.w3c.dom.Element;
35  import org.w3c.dom.Node;
36  
37  import com.eviware.soapui.SoapUI;
38  import com.eviware.soapui.impl.wsdl.WsdlRequest;
39  import com.eviware.soapui.impl.wsdl.support.wss.IncomingWss;
40  import com.eviware.soapui.impl.wsdl.support.wss.WssContainer;
41  import com.eviware.soapui.impl.wsdl.support.xsd.SchemaUtils;
42  import com.eviware.soapui.model.iface.Attachment;
43  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
44  import com.eviware.soapui.settings.HttpSettings;
45  import com.eviware.soapui.support.Tools;
46  import com.eviware.soapui.support.types.StringToStringMap;
47  import com.eviware.soapui.support.xml.XmlUtils;
48  
49  /***
50   * WsdlMockResponse for a MimeResponse
51   * 
52   * @author ole.matzura
53   */
54  
55  public class MimeMessageResponse implements WsdlResponse
56  {
57  	private final WeakReference<WsdlRequest> wsdlRequest;
58  	private long timeTaken;
59  	private long responseContentLength;
60  	private StringToStringMap requestHeaders;
61  	private StringToStringMap responseHeaders;
62  	private final String requestContent;
63  	private SSLInfo sslInfo;
64  	private MultipartMessageSupport mmSupport;
65  	private long timestamp;
66  	private Vector wssResult;
67  	private PostResponseDataSource postResponseDataSource;
68  	private byte[] requestData;
69  
70  	public MimeMessageResponse(WsdlRequest wsdlRequest, final TimeablePostMethod postMethod, String requestContent, PropertyExpansionContext context)
71  	{
72  		this.wsdlRequest = new WeakReference<WsdlRequest>( wsdlRequest );
73  		this.requestContent = requestContent;
74  		this.timeTaken = postMethod.getTimeTaken();
75  		this.timestamp = System.currentTimeMillis();
76  		
77  		try
78  		{
79  			initHeaders( postMethod );
80  			sslInfo = postMethod.getSSLInfo();
81  			postResponseDataSource = new PostResponseDataSource( postMethod );
82  			responseContentLength = postResponseDataSource.getDataSize();
83  			
84  			Header h = postMethod.getResponseHeader( "Content-Type" );
85  			HeaderElement[] elements = h.getElements();
86  			
87  			String rootPartId = null;
88  			String multipartType = null;
89  			
90  			for( HeaderElement element : elements )
91  			{
92  				String name = element.getName().toUpperCase();
93  				if( name.startsWith( "MULTIPART/" ))
94  				{
95  					NameValuePair parameter = element.getParameterByName("start");
96  					if (parameter != null)
97  						rootPartId = parameter.getValue();
98  					
99  					parameter = element.getParameterByName("type");
100 					if (parameter != null)
101 						multipartType = parameter.getValue();
102 				}
103 			}
104 			
105 			mmSupport = new MultipartMessageSupport( postResponseDataSource, rootPartId, wsdlRequest.getOperation(), false,
106 						wsdlRequest.isPrettyPrint() );
107 			
108 			processIncomingWss( wsdlRequest, context );
109 			
110 			if (wsdlRequest.getSettings().getBoolean(HttpSettings.INCLUDE_RESPONSE_IN_TIME_TAKEN))
111 				this.timeTaken = postMethod.getTimeTakenUntilNow();
112 			
113 			if (wsdlRequest.isExpandMtomResponseAttachments() && "application/xop+xml".equals( multipartType ))
114 			{
115 				expandMtomAttachments( wsdlRequest );
116 			}
117 			
118 			ByteArrayOutputStream out = new ByteArrayOutputStream();
119 			postMethod.getRequestEntity().writeRequest( out );
120 			requestData = out.toByteArray();
121 		}
122 		catch ( Exception e)
123 		{
124 			SoapUI.logError( e );
125 		}
126 	}
127 
128 	private void processIncomingWss( WsdlRequest wsdlRequest, PropertyExpansionContext context )
129 	{
130 		WssContainer wssContainer = wsdlRequest.getOperation().getInterface().getProject().getWssContainer();
131 		IncomingWss incomingWss = wssContainer.getIncomingByName( wsdlRequest.getIncomingWss() );
132 		if( incomingWss != null )
133 		{
134 			try
135 			{
136 				Document document = XmlUtils.parseXml( mmSupport.getContentAsString() );
137 				wssResult = incomingWss.processIncoming( document, context );
138 				if( wssResult != null && wssResult.size() > 0 )
139 				{
140 					StringWriter writer = new StringWriter();
141 					XmlUtils.serializePretty( document, writer );
142 					mmSupport.setResponseContent( writer.toString() );
143 				}
144 			}
145 			catch( Exception e )
146 			{
147 				if( wssResult != null )
148 					wssResult = new Vector();
149 				wssResult.add( e );
150 			}
151 		}
152 	}
153 	
154 	private void expandMtomAttachments(WsdlRequest wsdlRequest)
155 	{
156 		try
157 		{
158 			XmlObject xmlObject = XmlObject.Factory.parse(getContentAsString());
159 			XmlObject[] includes = xmlObject.selectPath( "declare namespace xop='http://www.w3.org/2004/08/xop/include'; //xop:Include" );
160 			
161 			for( XmlObject include : includes )
162 			{
163 				Element elm = ( Element ) include.getDomNode();
164 				String href = elm.getAttribute( "href" );
165 				Attachment attachment = mmSupport.getAttachmentWithContentId( "<" + href.substring( 4 ) + ">" );
166 				if( attachment != null )
167 				{
168 					ByteArrayOutputStream data = Tools.readAll( attachment.getInputStream(), 0 );
169 					byte[] byteArray = data.toByteArray();
170 					
171 					XmlCursor cursor = include.newCursor();
172 					cursor.toParent();
173 					XmlObject parentXmlObject = cursor.getObject();
174 					cursor.dispose();
175 					
176 					SchemaType schemaType = parentXmlObject.schemaType();
177 					Node parentNode = elm.getParentNode();
178 					
179 					if( schemaType.isNoType())
180 					{
181 						SchemaTypeSystem typeSystem = wsdlRequest.getOperation().getInterface().getWsdlContext().getSchemaTypeSystem();
182 						SchemaGlobalElement schemaElement = typeSystem.findElement( new QName( parentNode.getNamespaceURI(), parentNode.getLocalName() ) );
183 						if( schemaElement != null )
184 						{
185 							schemaType = schemaElement.getType();
186 						}
187 					}
188 
189 					String txt = null;
190 					
191 					if( SchemaUtils.isInstanceOf( schemaType, XmlHexBinary.type ))
192 					{
193 						txt = new String( Hex.encodeHex( byteArray ));
194 					}
195 					else
196 					{
197 						txt = new String( Base64.encodeBase64( byteArray ));
198 					}
199 					 
200 					
201 					parentNode.replaceChild( elm.getOwnerDocument().createTextNode( txt ), elm );
202 				}
203 			}
204 			
205 			mmSupport.setResponseContent( xmlObject.toString() );
206 		}
207 		catch( Exception e )
208 		{
209 			SoapUI.logError( e );
210 		}
211 	}
212 
213 	public SSLInfo getSSLInfo()
214 	{
215 		return sslInfo;
216 	}
217 
218 	public long getContentLength()
219 	{
220 		return responseContentLength;
221 	}
222 
223 	public WsdlRequest getRequest()
224 	{
225 		return wsdlRequest.get();
226 	}
227 
228 	public long getTimeTaken()
229 	{
230 		return timeTaken;
231 	}
232 
233 	private void initHeaders(TimeablePostMethod postMethod)
234 	{
235 		requestHeaders = new StringToStringMap();
236 		Header[] headers = postMethod.getRequestHeaders();
237 		for( Header header : headers )
238 		{
239 			requestHeaders.put( header.getName(), header.getValue() );
240 		}
241 		
242 		responseHeaders = new StringToStringMap();
243 		headers = postMethod.getResponseHeaders();
244 		for( Header header : headers )
245 		{
246 			responseHeaders.put( header.getName(), header.getValue() );
247 		}
248 		
249 		responseHeaders.put( "#status#", postMethod.getStatusLine().toString() );
250 	}
251 	
252 	public StringToStringMap getRequestHeaders()
253 	{
254 		return requestHeaders;
255 	}
256 
257 	public StringToStringMap getResponseHeaders()
258 	{
259 		return responseHeaders;
260 	}
261 	
262 	public String getRequestContent()
263 	{
264 		return requestContent;
265 	}
266 
267 	public void setResponseContent( String responseContent )
268 	{
269 		String oldContent = getContentAsString();
270 		mmSupport.setResponseContent( responseContent );
271 		
272 		getRequest().notifyPropertyChanged( WsdlRequest.RESPONSE_CONTENT_PROPERTY, oldContent, responseContent );
273 	}
274 
275 	public Attachment[] getAttachments()
276 	{
277 		return mmSupport.getAttachments();
278 	}
279 
280 	public Attachment[] getAttachmentsForPart( String partName )
281 	{
282 		return mmSupport.getAttachmentsForPart( partName );
283 	}
284 
285 	public String getContentAsString()
286 	{
287 		return mmSupport.getContentAsString();
288 	}
289 
290 	public long getTimestamp()
291 	{
292 		return timestamp;
293 	}
294 
295 	public Vector getWssResult()
296 	{
297 		return wssResult;
298 	}
299 	
300 	public byte[] getRawRequestData()
301 	{
302 		return requestData;
303 	}
304 
305 	public byte[] getRawResponseData()
306 	{
307 		return postResponseDataSource.getData();
308 	}
309 }