View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2010 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.IOException;
17  import java.lang.ref.WeakReference;
18  import java.net.URL;
19  import java.util.Date;
20  import java.util.List;
21  
22  import org.apache.commons.httpclient.Header;
23  
24  import com.eviware.soapui.SoapUI;
25  import com.eviware.soapui.impl.rest.RestRequestInterface;
26  import com.eviware.soapui.impl.rest.support.MediaTypeHandler;
27  import com.eviware.soapui.impl.rest.support.MediaTypeHandlerRegistry;
28  import com.eviware.soapui.impl.support.AbstractHttpRequestInterface;
29  import com.eviware.soapui.impl.support.http.HttpRequest;
30  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
31  import com.eviware.soapui.impl.wsdl.teststeps.TestRequest;
32  import com.eviware.soapui.model.iface.Attachment;
33  import com.eviware.soapui.model.propertyexpansion.PropertyExpansionContext;
34  import com.eviware.soapui.model.settings.Settings;
35  import com.eviware.soapui.model.testsuite.TestCase;
36  import com.eviware.soapui.settings.HttpSettings;
37  import com.eviware.soapui.settings.UISettings;
38  import com.eviware.soapui.support.types.StringToStringMap;
39  import com.eviware.soapui.support.types.StringToStringsMap;
40  
41  public abstract class BaseHttpResponse implements HttpResponse
42  {
43  
44  	private StringToStringsMap requestHeaders;
45  	private StringToStringsMap responseHeaders;
46  
47  	private long timeTaken;
48  	private long timestamp;
49  	private String contentType;
50  	private int statusCode;
51  	private SSLInfo sslInfo;
52  	private URL url;
53  	private WeakReference<AbstractHttpRequestInterface<?>> httpRequest;
54  	private RestRequestInterface.RequestMethod method;
55  	private String version;
56  	private StringToStringMap properties;
57  	private byte[] rawRequestData;
58  	private byte[] rawResponseData;
59  	private int requestContentPos = -1;
60  	private String xmlContent;
61  	private boolean downloadIncludedResources;
62  	private Attachment[] attachments = new Attachment[0];
63  	protected HTMLPageSourceDownloader downloader;
64  
65  	public BaseHttpResponse( ExtendedHttpMethod httpMethod, AbstractHttpRequestInterface<?> httpRequest,
66  			PropertyExpansionContext context )
67  	{
68  		this.httpRequest = new WeakReference<AbstractHttpRequestInterface<?>>( httpRequest );
69  		this.timeTaken = httpMethod.getTimeTaken();
70  
71  		method = httpMethod.getMethod();
72  		version = httpMethod.getParams().getVersion().toString();
73  		try
74  		{
75  			this.url = new URL( httpMethod.getURI().toString() );
76  		}
77  		catch( Exception e1 )
78  		{
79  			SoapUI.logError( e1 );
80  		}
81  
82  		if( !httpMethod.isFailed() )
83  		{
84  			Settings settings = httpRequest.getSettings();
85  			if( settings.getBoolean( HttpSettings.INCLUDE_RESPONSE_IN_TIME_TAKEN ) )
86  			{
87  				try
88  				{
89  					httpMethod.getResponseBody();
90  				}
91  				catch( IOException e )
92  				{
93  					e.printStackTrace();
94  				}
95  				timeTaken += httpMethod.getResponseReadTime();
96  			}
97  
98  			try
99  			{
100 				this.timestamp = System.currentTimeMillis();
101 				this.contentType = httpMethod.getResponseContentType();
102 
103 				if( httpMethod.hasResponse() )
104 				{
105 					this.statusCode = httpMethod.getStatusCode();
106 					this.sslInfo = httpMethod.getSSLInfo();
107 				}
108 
109 				this.url = new URL( httpMethod.getURI().toString() );
110 			}
111 			catch( Throwable e )
112 			{
113 				e.printStackTrace();
114 			}
115 		}
116 
117 		if( httpRequest instanceof TestRequest )
118 		{
119 			TestCase tc = ( ( TestRequest )httpRequest ).getTestStep().getTestCase();
120 			if( tc instanceof WsdlTestCase && ( ( WsdlTestCase )tc ).isForLoadTest() )
121 			{
122 				initHeadersForLoadTest( httpMethod );
123 				return;
124 			}
125 		}
126 
127 		initHeaders( httpMethod );
128 		if( this.httpRequest.get() instanceof HttpRequest )
129 		{
130 			downloadIncludedResources = ( ( HttpRequest )this.httpRequest.get() ).getDownloadIncludedResources();
131 			if( downloadIncludedResources )
132 			{
133 				long before = ( new Date() ).getTime();
134 				addIncludedContentsAsAttachments();
135 				long after = ( new Date() ).getTime();
136 				timeTaken += ( after - before );
137 				context.setProperty( HTMLPageSourceDownloader.MISSING_RESOURCES_LIST, downloader.getMissingResourcesList() );
138 			}
139 		}
140 	}
141 
142 	private void addIncludedContentsAsAttachments()
143 	{
144 		downloader = new HTMLPageSourceDownloader();
145 		try
146 		{
147 			List<Attachment> attachmentList = downloader.downloadCssAndImages( url.toString(), ( HttpRequest )httpRequest
148 					.get() );
149 			attachments = attachmentList.toArray( new Attachment[attachmentList.size()] );
150 		}
151 		catch( ClassCastException cce )
152 		{
153 			attachments = new Attachment[1];
154 			try
155 			{
156 				attachments[0] = downloader.createAttachment( rawResponseData, url, ( HttpRequest )httpRequest.get() );
157 			}
158 			catch( IOException e )
159 			{
160 				SoapUI.log.error( e );
161 			}
162 		}
163 		catch( Exception e )
164 		{
165 			SoapUI.log.error( e );
166 		}
167 	}
168 
169 	protected void initHeaders( ExtendedHttpMethod httpMethod )
170 	{
171 		try
172 		{
173 			ByteArrayOutputStream rawResponse = new ByteArrayOutputStream();
174 			ByteArrayOutputStream rawRequest = new ByteArrayOutputStream();
175 
176 			if( !httpMethod.isFailed() )
177 			{
178 				try
179 				{
180 					rawResponse.write( String.valueOf( httpMethod.getStatusLine() ).getBytes() );
181 					rawResponse.write( "\r\n".getBytes() );
182 				}
183 				catch( Throwable e )
184 				{
185 				}
186 			}
187 
188 			rawRequest.write( ( method + " " + String.valueOf( url ) + " " + version + "\r\n" ).getBytes() );
189 
190 			requestHeaders = new StringToStringsMap();
191 			Header[] headers = httpMethod.getRequestHeaders();
192 			for( Header header : headers )
193 			{
194 				requestHeaders.put( header.getName(), header.getValue() );
195 				rawRequest.write( header.toExternalForm().getBytes() );
196 			}
197 
198 			responseHeaders = new StringToStringsMap();
199 
200 			if( !httpMethod.isFailed() )
201 			{
202 				headers = httpMethod.getResponseHeaders();
203 				for( Header header : headers )
204 				{
205 					responseHeaders.put( header.getName(), header.getValue() );
206 					rawResponse.write( header.toExternalForm().getBytes() );
207 				}
208 
209 				responseHeaders.put( "#status#", String.valueOf( httpMethod.getStatusLine() ) );
210 			}
211 
212 			if( httpMethod.getRequestEntity() != null )
213 			{
214 				rawRequest.write( "\r\n".getBytes() );
215 				if( httpMethod.getRequestEntity().isRepeatable() )
216 				{
217 					requestContentPos = rawRequest.size();
218 					MaxSizeByteArrayOutputStream tempOut = new MaxSizeByteArrayOutputStream( SoapUI.getSettings().getLong(
219 							UISettings.RAW_REQUEST_MESSAGE_SIZE, 0 ) );
220 					httpMethod.getRequestEntity().writeRequest( tempOut );
221 					tempOut.writeTo( rawRequest );
222 				}
223 				else
224 					rawRequest.write( "<request data not available>".getBytes() );
225 			}
226 
227 			if( !httpMethod.isFailed() )
228 			{
229 				rawResponse.write( "\r\n".getBytes() );
230 				rawResponse.write( httpMethod.getResponseBody() );
231 			}
232 
233 			rawResponseData = rawResponse.toByteArray();
234 			rawRequestData = rawRequest.toByteArray();
235 		}
236 		catch( Throwable e )
237 		{
238 			e.printStackTrace();
239 		}
240 	}
241 
242 	public static class MaxSizeByteArrayOutputStream extends ByteArrayOutputStream
243 	{
244 		private final long maxSize;
245 
246 		public MaxSizeByteArrayOutputStream( long maxSize )
247 		{
248 			this.maxSize = maxSize;
249 		}
250 
251 		@Override
252 		public synchronized void write( int b )
253 		{
254 			if( maxSize > 0 && size() < maxSize )
255 				super.write( b );
256 		}
257 
258 		@Override
259 		public synchronized void write( byte[] b, int off, int len )
260 		{
261 			if( maxSize > 0 && size() < maxSize )
262 			{
263 				if( size() + len < maxSize )
264 					super.write( b, off, len );
265 				else
266 					super.write( b, off, ( int )( maxSize - size() ) );
267 			}
268 		}
269 
270 		@Override
271 		public void write( byte[] b ) throws IOException
272 		{
273 			if( maxSize > 0 && size() < maxSize )
274 			{
275 				if( size() + b.length < maxSize )
276 					super.write( b );
277 				else
278 					super.write( b, 0, ( int )( maxSize - size() ) );
279 			}
280 		}
281 
282 	}
283 
284 	protected void initHeadersForLoadTest( ExtendedHttpMethod httpMethod )
285 	{
286 		try
287 		{
288 			requestHeaders = new StringToStringsMap();
289 			Header[] headers = httpMethod.getRequestHeaders();
290 			for( Header header : headers )
291 			{
292 				requestHeaders.put( header.getName(), header.getValue() );
293 			}
294 
295 			if( !httpMethod.isFailed() )
296 			{
297 				responseHeaders = new StringToStringsMap();
298 				headers = httpMethod.getResponseHeaders();
299 				for( Header header : headers )
300 				{
301 					responseHeaders.put( header.getName(), header.getValue() );
302 				}
303 
304 				responseHeaders.put( "#status#", String.valueOf( httpMethod.getStatusLine() ) );
305 			}
306 		}
307 		catch( Throwable e )
308 		{
309 			e.printStackTrace();
310 		}
311 	}
312 
313 	public StringToStringsMap getRequestHeaders()
314 	{
315 		return requestHeaders;
316 	}
317 
318 	public StringToStringsMap getResponseHeaders()
319 	{
320 		return responseHeaders;
321 	}
322 
323 	public long getTimeTaken()
324 	{
325 		return timeTaken;
326 	}
327 
328 	public SSLInfo getSSLInfo()
329 	{
330 		return sslInfo;
331 	}
332 
333 	public long getTimestamp()
334 	{
335 		return timestamp;
336 	}
337 
338 	public String getContentType()
339 	{
340 		return contentType;
341 	}
342 
343 	public URL getURL()
344 	{
345 		return url;
346 	}
347 
348 	public AbstractHttpRequestInterface<?> getRequest()
349 	{
350 		return httpRequest.get();
351 	}
352 
353 	public int getStatusCode()
354 	{
355 		return statusCode;
356 	}
357 
358 	public Attachment[] getAttachments()
359 	{
360 		return attachments;
361 	}
362 
363 	public Attachment[] getAttachmentsForPart( String partName )
364 	{
365 		return new Attachment[0];
366 	}
367 
368 	public byte[] getRawRequestData()
369 	{
370 		return rawRequestData;
371 	}
372 
373 	public byte[] getRawResponseData()
374 	{
375 		return rawResponseData;
376 	}
377 
378 	public RestRequestInterface.RequestMethod getMethod()
379 	{
380 		return method;
381 	}
382 
383 	public String getHttpVersion()
384 	{
385 		return version;
386 	}
387 
388 	public void setProperty( String name, String value )
389 	{
390 		if( properties == null )
391 			properties = new StringToStringMap();
392 
393 		properties.put( name, value );
394 	}
395 
396 	public String getProperty( String name )
397 	{
398 		return properties == null ? null : properties.get( name );
399 	}
400 
401 	public String[] getPropertyNames()
402 	{
403 		return properties == null ? new String[0] : properties.getKeys();
404 	}
405 
406 	public String getRequestContent()
407 	{
408 		return requestContentPos == -1 || rawRequestData == null ? null : new String( rawRequestData, requestContentPos,
409 				rawRequestData.length - requestContentPos );
410 	}
411 
412 	public String getContentAsXml()
413 	{
414 		if( xmlContent == null )
415 		{
416 			MediaTypeHandler typeHandler = MediaTypeHandlerRegistry.getTypeHandler( getContentType() );
417 			xmlContent = ( typeHandler == null ) ? "<xml/>" : typeHandler.createXmlRepresentation( this );
418 		}
419 		return xmlContent;
420 	}
421 }