View Javadoc

1   /*
2    *  soapUI, copyright (C) 2006 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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.support.http;
14  
15  import java.io.ByteArrayInputStream;
16  import java.io.ByteArrayOutputStream;
17  import java.io.File;
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.security.GeneralSecurityException;
21  import java.security.KeyManagementException;
22  import java.security.KeyStoreException;
23  import java.security.NoSuchAlgorithmException;
24  import java.security.cert.CertificateException;
25  import java.util.zip.GZIPInputStream;
26  
27  import org.apache.commons.httpclient.Header;
28  import org.apache.commons.httpclient.HttpClient;
29  import org.apache.commons.httpclient.HttpMethodBase;
30  import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
31  import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
32  import org.apache.commons.httpclient.protocol.Protocol;
33  import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
34  import org.apache.commons.ssl.KeyMaterial;
35  import org.apache.log4j.Logger;
36  
37  import com.eviware.soapui.SoapUI;
38  import com.eviware.soapui.model.settings.Settings;
39  import com.eviware.soapui.model.settings.SettingsListener;
40  import com.eviware.soapui.settings.HttpSettings;
41  import com.eviware.soapui.settings.SSLSettings;
42  
43  /***
44   * HttpClient related tools
45   * 
46   * @author Ole.Matzura
47   */
48  
49  public class HttpClientSupport
50  {
51  	private final static Helper helper = new Helper();
52  
53  	/***
54  	 * Internal helper to ensure synchronized access..
55  	 */
56  
57  	private static class Helper
58  	{
59  		private HttpClient httpClient;
60  		private final static Logger log = Logger.getLogger( HttpClientSupport.Helper.class );
61  		private EasySSLProtocolSocketFactory easySSL;
62  
63  		public Helper()
64  		{
65  			try
66  			{
67  				easySSL = new EasySSLProtocolSocketFactory();
68  				initSSL( easySSL );
69  
70  				Protocol easyhttps = new Protocol( "https", ( ProtocolSocketFactory ) easySSL, 443 );
71  				Protocol.registerProtocol( "https", easyhttps );
72  			}
73  			catch( Throwable e )
74  			{
75  				log.error( "Failed to initialize SSL settings; " + e );
76  			}
77  
78  			MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
79  			connectionManager.getParams().setDefaultMaxConnectionsPerHost( 500 );
80  			connectionManager.getParams().setMaxTotalConnections( 2000 );
81  			httpClient = new HttpClient( connectionManager );
82  			
83  			SoapUI.getSettings().addSettingsListener( new SettingsListener() {
84  
85  				public void settingChanged( String name, String newValue, String oldValue )
86  				{
87  					if( name.equals( SSLSettings.KEYSTORE ) || name.equals( SSLSettings.KEYSTORE_PASSWORD ))
88  					{
89  						try
90  						{
91  							log.info( "Updating keyStore.." );
92  							initKeyMaterial( easySSL );
93  						}
94  						catch( Throwable e )
95  						{
96  							log.error( "Failed to initialize SSL settings; " + e );
97  						}
98  					}
99  				}} );
100 		}
101 
102 		private void initSSL( EasySSLProtocolSocketFactory easySSL ) throws IOException,
103 		GeneralSecurityException
104 		{
105 			log.info( "Initializing SSL" );
106 			initKeyMaterial( easySSL );
107 
108 			 /*
109 	       Commented out for now - EasySSLProtocolSocketFactory already
110 	       trusts everything!  Below is some code that might work for when
111 	       SoapUI moves away from "EasySSLProtocolSocketFactory".                     
112 
113 	    String trustStore = settings.getString( SSLSettings.TRUSTSTORE, null );
114 	    trustStore = trustStore != null ? trustStore.trim() : "";
115 	    pass = settings.getString( SSLSettings.TRUSTSTORE_PASSWORD, "" );
116 	    pwd = pass.toCharArray();
117 	    if ( !"".equals( trustStore ) ) {
118 	        File f = new File( trustStore );
119 	        if ( f.exists() ) {
120 	            TrustMaterial tm = null;
121 	            try
122 	            {
123 	                tm = new TrustMaterial( trustStore, pwd );
124 	            }
125 	            catch ( GeneralSecurityException gse )
126 	            {
127 	                String trimmedPass = pass.trim();
128 	                if ( "".equals( trimmedPass ) )
129 	                {
130 	                    // If the password is all spaces, then we'll allow
131 	                    // loading of the TrustMaterial without a password.
132 	                    tm = new TrustMaterial( trustStore );
133 	                }
134 	                else
135 	                {
136 	                    log.error( "Failed to load TrustMaterial: " + gse );
137 	                }
138 	            }
139 	            if ( tm != null )
140 	            {
141 	                easySSL.setTrustMaterial( tm );
142 	                log.info( "Added TrustStore from file [" + trustStore + "]" );
143 	            }
144 	        } else {
145 	            log.error( "Missing trustStore [" + trustStore + "]" );
146 	        }
147 	    }
148 */
149 		}
150 
151 		private void initKeyMaterial( EasySSLProtocolSocketFactory easySSL ) throws IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, CertificateException
152 		{
153 			Settings settings = SoapUI.getSettings();
154 			
155 			String keyStore = settings.getString( SSLSettings.KEYSTORE, null );
156 			keyStore = keyStore != null ? keyStore.trim() : "";
157 			String pass = settings.getString( SSLSettings.KEYSTORE_PASSWORD, "" );
158 			char[] pwd = pass.toCharArray();
159 			if( !"".equals( keyStore ) )
160 			{
161 				File f = new File( keyStore );
162 				if( f.exists() )
163 				{
164 					KeyMaterial km = null;
165 					try
166 					{
167 						km = new KeyMaterial( keyStore, pwd );
168 						log.info( "Set KeyMaterial from file [" + keyStore + "]" );
169 					}
170 					catch( GeneralSecurityException gse )
171 					{
172 						log.error( "Failed to load KeyMaterial [" + keyStore + "] " + gse );
173 					}
174 					if( km != null )
175 					{
176 						easySSL.setKeyMaterial( km );
177 					}
178 				}
179 			}
180 			else
181 			{
182 				easySSL.setKeyMaterial( null );
183 			}
184 		}
185 
186 		public HttpClient getHttpClient()
187 		{
188 			return httpClient;
189 		}
190 	}
191 
192 	public static HttpClient getHttpClient()
193 	{
194 		return helper.getHttpClient();
195 	}
196 
197 	public static void applyHttpSettings( HttpMethodBase postMethod, Settings settings )
198 	{
199 		// user agent?
200 		String userAgent = settings.getString( HttpSettings.USER_AGENT, null );
201 		if( userAgent != null && userAgent.length() > 0 )
202 			postMethod.setRequestHeader( "User-Agent", userAgent );
203 
204 		// timeout?
205 		long timeout = settings.getLong( HttpSettings.SOCKET_TIMEOUT,
206 					HttpSettings.DEFAULT_SOCKET_TIMEOUT );
207 		postMethod.getParams().setSoTimeout( ( int ) timeout );
208 	}
209 
210 	public static boolean isZippedResponse( HttpMethodBase method )
211 	{
212 		Header contentType = method.getResponseHeader( "Content-Type" );
213 		Header contentEncoding = method.getResponseHeader( "Content-Encoding" );
214 
215 		if( contentType != null && contentType.getValue().toUpperCase().endsWith( "GZIP" ) )
216 			return true;
217 
218 		if( contentEncoding != null && contentEncoding.getValue().toUpperCase().endsWith( "GZIP" ) )
219 			return true;
220 
221 		return false;
222 	}
223 
224 	public static byte[] decompress( byte[] s )
225 	{
226 		GZIPInputStream zipin;
227 		try
228 		{
229 			InputStream in = new ByteArrayInputStream( s );
230 			zipin = new GZIPInputStream( in );
231 		}
232 		catch( IOException e )
233 		{
234 			e.printStackTrace();
235 			return s;
236 		}
237 
238 		int sizeBuffer = 8192;
239 		byte[] buffer = new byte[sizeBuffer];
240 		try
241 		{
242 			ByteArrayOutputStream out = new ByteArrayOutputStream();
243 			int length;
244 			while( ( length = zipin.read( buffer, 0, sizeBuffer ) ) != -1 )
245 				out.write( buffer, 0, length );
246 			s = out.toByteArray();
247 			out.close();
248 		}
249 		catch( IOException e )
250 		{
251 			e.printStackTrace();
252 			return s;
253 		}
254 		try
255 		{
256 			zipin.close();
257 		}
258 		catch( IOException e )
259 		{
260 		}
261 
262 		return s;
263 	}
264 }