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.ByteArrayInputStream;
16  import java.io.ByteArrayOutputStream;
17  import java.io.FileInputStream;
18  import java.io.FileOutputStream;
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.net.Socket;
22  
23  import javax.net.ssl.SSLSocket;
24  
25  import org.apache.commons.httpclient.Header;
26  import org.apache.commons.httpclient.HeaderElement;
27  import org.apache.commons.httpclient.HttpConnection;
28  import org.apache.commons.httpclient.HttpMethodBase;
29  import org.apache.commons.httpclient.HttpState;
30  import org.apache.commons.httpclient.NameValuePair;
31  
32  import com.eviware.soapui.SoapUI;
33  import com.eviware.soapui.impl.wsdl.support.CompressionSupport;
34  import com.eviware.soapui.impl.wsdl.support.http.ConnectionWithSocket;
35  import com.eviware.soapui.impl.wsdl.support.http.HttpClientSupport;
36  import com.eviware.soapui.settings.HttpSettings;
37  import com.eviware.soapui.support.StringUtils;
38  import com.eviware.soapui.support.Tools;
39  
40  /***
41   * Extended PostMethod that supports limiting of response size and detailed
42   * timestamps
43   * 
44   * @author Ole.Matzura
45   */
46  
47  public final class HttpMethodSupport
48  {
49  	private long timeTaken;
50  	private long startTime;
51  	private long maxSize;
52  	private long responseReadTime;
53  
54  	private byte[] responseBody;
55  
56  	private SSLInfo sslInfo;
57  	private String dumpFile;
58  	private final HttpMethodBase httpMethod;
59  	private Throwable failureCause;
60  	private boolean decompress;
61  
62  	public HttpMethodSupport( HttpMethodBase httpMethod )
63  	{
64  		this.httpMethod = httpMethod;
65  
66  		decompress = !SoapUI.getSettings().getBoolean( HttpSettings.DISABLE_RESPONSE_DECOMPRESSION );
67  	}
68  
69  	public boolean isDecompress()
70  	{
71  		return decompress;
72  	}
73  
74  	public void setDecompress( boolean decompress )
75  	{
76  		this.decompress = decompress;
77  	}
78  
79  	public String getDumpFile()
80  	{
81  		return dumpFile;
82  	}
83  
84  	public void setDumpFile( String dumpFile )
85  	{
86  		this.dumpFile = dumpFile;
87  	}
88  
89  	public void afterReadResponse( HttpState arg0, HttpConnection arg1 )
90  	{
91  		if( arg1 instanceof ConnectionWithSocket )
92  		{
93  			Socket socket = ( ( ConnectionWithSocket )arg1 ).getConnectionSocket();
94  			if( socket instanceof SSLSocket )
95  			{
96  				sslInfo = new SSLInfo( ( SSLSocket )socket );
97  			}
98  		}
99  	}
100 
101 	public long getMaxSize()
102 	{
103 		return maxSize;
104 	}
105 
106 	public void setMaxSize( long maxSize )
107 	{
108 		this.maxSize = maxSize;
109 	}
110 
111 	public void afterWriteRequest( HttpState arg0, HttpConnection arg1 )
112 	{
113 		if( startTime == 0 )
114 			startTime = System.nanoTime();
115 	}
116 
117 	public void initStartTime()
118 	{
119 		startTime = System.nanoTime();
120 	}
121 
122 	public long getTimeTaken()
123 	{
124 		if( timeTaken == 0 )
125 			timeTaken = ( System.nanoTime() - startTime ) / 1000000;
126 
127 		return timeTaken;
128 	}
129 
130 	public long getStartTime()
131 	{
132 		return startTime;
133 	}
134 
135 	public byte[] getResponseBody() throws IOException
136 	{
137 		if( responseBody != null )
138 			return responseBody;
139 
140 		long contentLength = httpMethod.getResponseContentLength();
141 		long now = System.nanoTime();
142 
143 		InputStream instream = httpMethod.getResponseBodyAsStream();
144 
145 		if( maxSize == 0 || ( contentLength >= 0 && contentLength <= maxSize ) )
146 		{
147 			ByteArrayOutputStream out = new ByteArrayOutputStream();
148 			if( instream != null )
149 				Tools.writeAll( out, instream );
150 
151 			responseReadTime = System.nanoTime() - now;
152 			responseBody = out.toByteArray();
153 
154 			try
155 			{
156 				if( StringUtils.hasContent( dumpFile ) )
157 				{
158 					Tools.writeAll( new FileOutputStream( dumpFile ), new ByteArrayInputStream( responseBody ) );
159 				}
160 			}
161 			catch( IOException e )
162 			{
163 				e.printStackTrace();
164 			}
165 
166 			if( decompress )
167 			{
168 				String compressionAlg = HttpClientSupport.getResponseCompressionType( httpMethod );
169 				if( compressionAlg != null )
170 				{
171 					try
172 					{
173 						responseBody = CompressionSupport.decompress( compressionAlg, responseBody );
174 					}
175 					catch( Exception e )
176 					{
177 						IOException ioe = new IOException( "Decompression of response failed" );
178 						ioe.initCause( e );
179 						throw ioe;
180 					}
181 				}
182 			}
183 		}
184 		else
185 		{
186 			try
187 			{
188 				if( StringUtils.hasContent( dumpFile ) && instream != null )
189 				{
190 					FileOutputStream fileOutputStream = new FileOutputStream( dumpFile );
191 					Tools.writeAll( fileOutputStream, instream );
192 					responseReadTime = System.nanoTime() - now;
193 					fileOutputStream.close();
194 					instream = new FileInputStream( dumpFile );
195 				}
196 			}
197 			catch( IOException e )
198 			{
199 				e.printStackTrace();
200 			}
201 
202 			ByteArrayOutputStream outstream = instream == null ? new ByteArrayOutputStream() : Tools.readAll( instream,
203 					maxSize );
204 
205 			if( responseReadTime == 0 )
206 				responseReadTime = System.nanoTime() - now;
207 
208 			responseBody = outstream.toByteArray();
209 		}
210 
211 		// convert to ms
212 		responseReadTime /= 1000000;
213 
214 		return responseBody;
215 	}
216 
217 	public byte[] getDecompressedResponseBody() throws IOException
218 	{
219 		String compressionAlg = HttpClientSupport.getResponseCompressionType( httpMethod );
220 		if( compressionAlg != null )
221 		{
222 			try
223 			{
224 				return CompressionSupport.decompress( compressionAlg, responseBody );
225 			}
226 			catch( Exception e )
227 			{
228 				IOException ioe = new IOException( "Decompression of response failed" );
229 				ioe.initCause( e );
230 				throw ioe;
231 			}
232 		}
233 
234 		return responseBody;
235 	}
236 
237 	public SSLInfo getSSLInfo()
238 	{
239 		return sslInfo;
240 	}
241 
242 	public String getResponseContentType()
243 	{
244 		Header[] headers = httpMethod.getResponseHeaders( "Content-Type" );
245 		if( headers != null && headers.length > 0 && headers[0].getElements().length > 0 )
246 		{
247 			return headers[0].getElements()[0].getName();
248 		}
249 
250 		return null;
251 	}
252 
253 	public long getResponseReadTime()
254 	{
255 		return responseReadTime;
256 	}
257 
258 	/***
259 	 * Handles charset specified in Content-Encoding headers
260 	 * 
261 	 * @return
262 	 */
263 
264 	public String getResponseCharset()
265 	{
266 		Header header = httpMethod.getResponseHeader( "Content-Type" );
267 		if( header != null )
268 		{
269 			for( HeaderElement headerElement : header.getElements() )
270 			{
271 				NameValuePair parameter = headerElement.getParameterByName( "charset" );
272 				if( parameter != null )
273 					return parameter.getValue();
274 			}
275 		}
276 
277 		Header contentEncodingHeader = httpMethod.getResponseHeader( "Content-Encoding" );
278 		if( contentEncodingHeader != null )
279 		{
280 			try
281 			{
282 				String value = contentEncodingHeader.getValue();
283 				if( CompressionSupport.getAvailableAlgorithm( value ) == null )
284 				{
285 					new String( "" ).getBytes( value );
286 					return value;
287 				}
288 			}
289 			catch( Exception e )
290 			{
291 			}
292 		}
293 
294 		return null;
295 	}
296 
297 	public Throwable getFailureCause()
298 	{
299 		return failureCause;
300 	}
301 
302 	public boolean isFailed()
303 	{
304 		return failureCause != null;
305 	}
306 
307 	public void setFailed( Throwable t )
308 	{
309 		this.failureCause = t;
310 	}
311 
312 	public boolean hasResponse()
313 	{
314 		return responseBody != null;
315 	}
316 }