001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.impl.wsdl.support.http;
014:
015: import java.io.ByteArrayInputStream;
016: import java.io.ByteArrayOutputStream;
017: import java.io.File;
018: import java.io.IOException;
019: import java.io.InputStream;
020: import java.security.GeneralSecurityException;
021: import java.security.KeyManagementException;
022: import java.security.KeyStoreException;
023: import java.security.NoSuchAlgorithmException;
024: import java.security.cert.CertificateException;
025: import java.util.zip.GZIPInputStream;
026:
027: import org.apache.commons.httpclient.Header;
028: import org.apache.commons.httpclient.HttpClient;
029: import org.apache.commons.httpclient.HttpMethodBase;
030: import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
031: import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
032: import org.apache.commons.httpclient.protocol.Protocol;
033: import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
034: import org.apache.commons.ssl.KeyMaterial;
035: import org.apache.log4j.Logger;
036:
037: import com.eviware.soapui.SoapUI;
038: import com.eviware.soapui.model.settings.Settings;
039: import com.eviware.soapui.model.settings.SettingsListener;
040: import com.eviware.soapui.settings.HttpSettings;
041: import com.eviware.soapui.settings.SSLSettings;
042: import com.eviware.soapui.support.Tools;
043:
044: /**
045: * HttpClient related tools
046: *
047: * @author Ole.Matzura
048: */
049:
050: public class HttpClientSupport {
051: private final static Helper helper = new Helper();
052:
053: /**
054: * Internal helper to ensure synchronized access..
055: */
056:
057: private static class Helper {
058: private HttpClient httpClient;
059: private final static Logger log = Logger
060: .getLogger(HttpClientSupport.Helper.class);
061: private EasySSLProtocolSocketFactory easySSL;
062: private MultiThreadedHttpConnectionManager connectionManager;
063:
064: public Helper() {
065: try {
066: easySSL = new EasySSLProtocolSocketFactory();
067: initSSL(easySSL);
068:
069: Protocol easyhttps = new Protocol("https",
070: (ProtocolSocketFactory) easySSL, 443);
071: Protocol.registerProtocol("https", easyhttps);
072: } catch (Throwable e) {
073: SoapUI.logError(e);
074: }
075:
076: Settings settings = SoapUI.getSettings();
077:
078: connectionManager = new MultiThreadedHttpConnectionManager();
079: connectionManager
080: .getParams()
081: .setDefaultMaxConnectionsPerHost(
082: (int) settings
083: .getLong(
084: HttpSettings.MAX_CONNECTIONS_PER_HOST,
085: 500));
086: connectionManager.getParams().setMaxTotalConnections(
087: (int) settings.getLong(
088: HttpSettings.MAX_TOTAL_CONNECTIONS, 2000));
089: httpClient = new HttpClient(connectionManager);
090:
091: settings.addSettingsListener(new SettingsListener() {
092:
093: public void settingChanged(String name,
094: String newValue, String oldValue) {
095: if (name.equals(SSLSettings.KEYSTORE)
096: || name
097: .equals(SSLSettings.KEYSTORE_PASSWORD)) {
098: try {
099: log.info("Updating keyStore..");
100: initKeyMaterial(easySSL);
101: } catch (Throwable e) {
102: SoapUI.logError(e);
103: }
104: } else if (name
105: .equals(HttpSettings.MAX_CONNECTIONS_PER_HOST)) {
106: log
107: .info("Updating max connections per host to "
108: + newValue);
109: connectionManager.getParams()
110: .setDefaultMaxConnectionsPerHost(
111: Integer.parseInt(newValue));
112: } else if (name
113: .equals(HttpSettings.MAX_TOTAL_CONNECTIONS)) {
114: log
115: .info("Updating max total connections host to "
116: + newValue);
117: connectionManager.getParams()
118: .setMaxTotalConnections(
119: Integer.parseInt(newValue));
120: }
121: }
122: });
123: }
124:
125: private void initSSL(EasySSLProtocolSocketFactory easySSL)
126: throws IOException, GeneralSecurityException {
127: log.info("Initializing SSL");
128: initKeyMaterial(easySSL);
129:
130: /*
131: Commented out for now - EasySSLProtocolSocketFactory already
132: trusts everything! Below is some code that might work for when
133: SoapUI moves away from "EasySSLProtocolSocketFactory".
134:
135: String trustStore = settings.getString( SSLSettings.TRUSTSTORE, null );
136: trustStore = trustStore != null ? trustStore.trim() : "";
137: pass = settings.getString( SSLSettings.TRUSTSTORE_PASSWORD, "" );
138: pwd = pass.toCharArray();
139: if ( !"".equals( trustStore ) ) {
140: File f = new File( trustStore );
141: if ( f.exists() ) {
142: TrustMaterial tm = null;
143: try
144: {
145: tm = new TrustMaterial( trustStore, pwd );
146: }
147: catch ( GeneralSecurityException gse )
148: {
149: String trimmedPass = pass.trim();
150: if ( "".equals( trimmedPass ) )
151: {
152: // If the password is all spaces, then we'll allow
153: // loading of the TrustMaterial without a password.
154: tm = new TrustMaterial( trustStore );
155: }
156: else
157: {
158: log.error( "Failed to load TrustMaterial: " + gse );
159: }
160: }
161: if ( tm != null )
162: {
163: easySSL.setTrustMaterial( tm );
164: log.info( "Added TrustStore from file [" + trustStore + "]" );
165: }
166: } else {
167: log.error( "Missing trustStore [" + trustStore + "]" );
168: }
169: }
170: */
171: }
172:
173: private void initKeyMaterial(
174: EasySSLProtocolSocketFactory easySSL)
175: throws IOException, NoSuchAlgorithmException,
176: KeyStoreException, KeyManagementException,
177: CertificateException {
178: Settings settings = SoapUI.getSettings();
179:
180: String keyStore = settings.getString(SSLSettings.KEYSTORE,
181: null);
182: keyStore = keyStore != null ? keyStore.trim() : "";
183: String pass = settings.getString(
184: SSLSettings.KEYSTORE_PASSWORD, "");
185: char[] pwd = pass.toCharArray();
186: if (!"".equals(keyStore)) {
187: File f = new File(keyStore);
188: if (f.exists()) {
189: KeyMaterial km = null;
190: try {
191: km = new KeyMaterial(keyStore, pwd);
192: log.info("Set KeyMaterial from file ["
193: + keyStore + "]");
194: } catch (GeneralSecurityException gse) {
195: SoapUI.logError(gse);
196: }
197: if (km != null) {
198: easySSL.setKeyMaterial(km);
199: }
200: }
201: } else {
202: easySSL.setKeyMaterial(null);
203: }
204: }
205:
206: public HttpClient getHttpClient() {
207: return httpClient;
208: }
209: }
210:
211: public static HttpClient getHttpClient() {
212: return helper.getHttpClient();
213: }
214:
215: public static void applyHttpSettings(HttpMethodBase postMethod,
216: Settings settings) {
217: // user agent?
218: String userAgent = settings.getString(HttpSettings.USER_AGENT,
219: null);
220: if (userAgent != null && userAgent.length() > 0)
221: postMethod.setRequestHeader("User-Agent", userAgent);
222:
223: // timeout?
224: long timeout = settings.getLong(HttpSettings.SOCKET_TIMEOUT,
225: HttpSettings.DEFAULT_SOCKET_TIMEOUT);
226: postMethod.getParams().setSoTimeout((int) timeout);
227: }
228:
229: public static boolean isZippedResponse(HttpMethodBase method) {
230: Header contentType = method.getResponseHeader("Content-Type");
231: Header contentEncoding = method
232: .getResponseHeader("Content-Encoding");
233:
234: if (contentType != null
235: && contentType.getValue().toUpperCase()
236: .endsWith("GZIP"))
237: return true;
238:
239: if (contentEncoding != null
240: && contentEncoding.getValue().toUpperCase().endsWith(
241: "GZIP"))
242: return true;
243:
244: return false;
245: }
246:
247: public static byte[] decompress(byte[] s) {
248: GZIPInputStream zipin;
249: try {
250: InputStream in = new ByteArrayInputStream(s);
251: zipin = new GZIPInputStream(in);
252: } catch (IOException e) {
253: SoapUI.logError(e);
254: return s;
255: }
256:
257: try {
258: ByteArrayOutputStream out = Tools.readAll(zipin, -1);
259: s = out.toByteArray();
260: out.close();
261: } catch (IOException e) {
262: SoapUI.logError(e);
263: return s;
264: }
265: try {
266: zipin.close();
267: } catch (IOException e) {
268: }
269:
270: return s;
271: }
272: }
|