Java tutorial
/******************************************************************************* * Copyright (c) 2010 Yadu. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Yadu - initial API and implementation ******************************************************************************/ package code.google.restclient.core; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.LinkedHashMap; import java.util.Map; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpOptions; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpTrace; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.params.HttpClientParams; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.params.ConnRouteParams; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.message.BasicHeader; import org.apache.http.params.HttpParams; import org.apache.http.params.HttpProtocolParams; import org.apache.http.params.SyncBasicHttpParams; import org.apache.log4j.Logger; import code.google.restclient.common.RCConstants; import code.google.restclient.common.RCUtil; /** * @author Yaduvendra.Singh */ public class Hitter { private static final Logger LOG = Logger.getLogger(Hitter.class); private static final boolean DEBUG_ENABLED = LOG.isDebugEnabled(); private static HttpClient client = null; private static ClientConnectionManager conman = null; private String proxyHost = RCConstants.SYS_PROXY_ENABLED; private int proxyPort = -1; private Map<String, String> headers; // Dummy object for synchronizing getHttpClient() private final Object lock; public Hitter() { configureSysProxy(); headers = new LinkedHashMap<String, String>(); lock = new Object(); } public Hitter(Map<String, String> headers) { this(); this.headers = headers; } public void setHeaders(Map<String, String> headers) { this.headers = headers; } public void setProxy(String host, int port) { proxyHost = host; proxyPort = port; } private void configureSysProxy() { try { // check System properties if (RCConstants.SYS_PROXY_ENABLED.equals(proxyHost)) { String proxyHostEnvStr = System.getProperty("https.proxyHost"); String proxyPortENvStr = System.getProperty("https.proxyPort"); if (proxyHostEnvStr != null) { proxyHost = proxyHostEnvStr; proxyPort = Integer.parseInt(proxyPortENvStr); } else { proxyHost = ""; proxyPort = -1; } } else if (RCConstants.SYS_PROXY_DISABLED.equals(proxyHost)) { proxyHost = ""; proxyPort = -1; } } catch (Exception e) { LOG.error("failed to get proxy from system props"); proxyHost = ""; proxyPort = -1; } } private boolean isProxyConfigured() { if (proxyHost == null || "".equals(proxyHost)) return false; if ("DISABLED".equals(proxyHost)) return false; if (proxyPort == -1) return false; return true; } /** * Method to make POST or PUT request by sending http entity (as body) */ public void hit(String url, String methodName, HttpHandler handler, Map<String, String> requestHeaders) throws Exception { if (DEBUG_ENABLED) LOG.debug("hit() - method => " + methodName + ", url => " + url); if (HttpGet.METHOD_NAME.equals(methodName)) { if (DEBUG_ENABLED) LOG.debug("hit() - ===> GET " + url); hit(url, new HttpGet(url), handler, requestHeaders); } else if (HttpHead.METHOD_NAME.equals(methodName)) { if (DEBUG_ENABLED) LOG.debug("hit() - ===> HEAD " + url); hit(url, new HttpHead(url), handler, requestHeaders); } else if (HttpDelete.METHOD_NAME.equals(methodName)) { if (DEBUG_ENABLED) LOG.debug("hit() - ===> DELETE " + url); hit(url, new HttpDelete(url), handler, requestHeaders); } else if (HttpOptions.METHOD_NAME.equals(methodName)) { if (DEBUG_ENABLED) LOG.debug("hit() - ===> OPTIONS " + url); hit(url, new HttpOptions(url), handler, requestHeaders); } else if (HttpTrace.METHOD_NAME.equals(methodName)) { if (DEBUG_ENABLED) LOG.debug("hit() - ===> TRACE " + url); hit(url, new HttpTrace(url), handler, requestHeaders); } else if (HttpPost.METHOD_NAME.equals(methodName)) { // POST if (DEBUG_ENABLED) LOG.debug("hit() - ===> POST " + url); HttpPost httpPost = new HttpPost(url); httpPost.setEntity(handler.getReqBodyEntity()); hit(url, httpPost, handler, requestHeaders); } else if (HttpPut.METHOD_NAME.equals(methodName)) { // PUT if (DEBUG_ENABLED) LOG.debug("hit() - ===> PUT " + url); HttpPut httpPut = new HttpPut(url); httpPut.setEntity(handler.getReqBodyEntity()); hit(url, httpPut, handler, requestHeaders); } else { throw new IllegalArgumentException("hit(): Unsupported method => " + methodName); } } private HttpHandler hit(String url, HttpUriRequest request, HttpHandler handler, Map<String, String> requestHeaders) throws Exception { if (DEBUG_ENABLED) LOG.debug("hit() - hitting url (params encoded) --> " + url); HttpResponse response = null; HttpClient client = getHttpClient(); // set request headers Map<String, String> hs = new LinkedHashMap<String, String>(); if (headers != null) hs.putAll(headers); if (requestHeaders != null) hs.putAll(requestHeaders); if (!hs.isEmpty()) { for (String header : hs.keySet()) request.setHeader(new BasicHeader(header, hs.get(header))); } handler.setRequest(request); response = client.execute(request); // **** execute request **** handler.setResponse(response); return handler; } /* * Since DefaultHttpClient and its connection manager are all thread-safe, all HttpClient * impl configuration should be synchronized. this entire dance is here because we want to use * a ThreadSafeClientConnManager and not the SingleClientConnManager. */ private HttpClient getHttpClient() throws KeyManagementException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException { // Early exit: already configured. Want all the gets to be fast so not synchronizing it if (client != null) return client; synchronized (lock) { HttpParams params = new SyncBasicHttpParams(); // Set proxy if (isProxyConfigured()) { if (DEBUG_ENABLED) LOG.debug("CONFIGURING PROXY TO => " + proxyHost + ":" + proxyPort); HttpHost proxy = new HttpHost(proxyHost, proxyPort); ConnRouteParams.setDefaultProxy(params, proxy); } // http params apply at client level so shared by all request. They can be overridden by params set at request level. HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, RCConstants.DEFAULT_CHARSET); HttpProtocolParams.setUserAgent(params, RCConstants.APP_DISPLAY_NAME); HttpClientParams.setRedirecting(params, true); /* HttpConnectionParams.setTcpNoDelay(params, true); HttpConnectionParams.setLinger(params, 30); HttpConnectionParams.setConnectionTimeout(params, 30000); HttpConnectionParams.setSoTimeout(params, 30000); HttpProtocolParams.setUseExpectContinue(params, false); HttpClientParams.setCookiePolicy(params, CookiePolicy.BROWSER_COMPATIBILITY); */ SchemeRegistry registry = new SchemeRegistry(); registry.register(getPlainScheme()); registry.register(getSSLScheme(isDisabledCertVerifier(), isDisabledHostVerifier())); if (conman == null) conman = new ThreadSafeClientConnManager(registry); if (client == null) { client = new DefaultHttpClient(conman); ((DefaultHttpClient) client).setParams(params); ((DefaultHttpClient) client).setKeepAliveStrategy(new CustomKeepAliveStrategy()); /* // set custom request retry handler which doesn't allow retry for POST request HttpRequestRetryHandler retryHandler = new CustomRetryHandler(); ((DefaultHttpClient) client).setHttpRequestRetryHandler(retryHandler); client.getParams().setParameter(CoreProtocolPNames.WAIT_FOR_CONTINUE, 10000); // 10 seconds */ } return client; } } private Scheme getPlainScheme() { return new Scheme("http", RCConstants.PLAIN_SOCKET_PORT, PlainSocketFactory.getSocketFactory()); } private Scheme getSSLScheme(boolean disableVerifyCert, boolean disableVerifyHost) throws NoSuchAlgorithmException, KeyManagementException, UnrecoverableKeyException, KeyStoreException { SSLSocketFactory sslFactory = null; if (isUseSelfSignedCertVerifier()) { TrustSelfSignedStrategy selfSignedStrategy = new TrustSelfSignedStrategy(); // AllowAllHostnameVerifier doesn't verify host names contained in SSL certificate. It should not be set in // production environment. It may allow man in middle attack. Other host name verifiers for specific needs // are StrictHostnameVerifier and BrowserCompatHostnameVerifier. if (disableVerifyHost) sslFactory = new SSLSocketFactory(selfSignedStrategy, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); else sslFactory = new SSLSocketFactory(selfSignedStrategy); // BROWSER_COMPATIBLE_HOSTNAME_VERIFIER is used by default } else { SSLContext sslContext = SSLContext.getInstance("TLS"); if (disableVerifyCert) sslContext.init(null, new TrustManager[] { getNoCheckTrustManager() }, null); else sslContext.init(null, null, null); if (disableVerifyHost) sslFactory = new SSLSocketFactory(sslContext, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); else sslFactory = new SSLSocketFactory(sslContext); } return new Scheme("https", RCConstants.SSL_SOCKET_PORT, sslFactory); } private TrustManager getNoCheckTrustManager() { return new X509TrustManager() { @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Do nothing } @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { // Do nothing } @Override public X509Certificate[] getAcceptedIssuers() { return null; } }; } /** * First checks property disable.ssl.cert.verifier as system property if not found it uses configured one. * * @return */ private boolean isDisabledCertVerifier() { String disable = RCUtil.getSSLOverrideProperty("disable.ssl.cert.verifier"); if (disable == null) return RCConstants.DISABLE_SSL_CERT_VERIFIER; else return new Boolean(disable); } /** * First checks property disable.host.name.verifier as system property if not found it uses configured one. * * @return */ private boolean isDisabledHostVerifier() { String disable = RCUtil.getSSLOverrideProperty("disable.host.name.verifier"); if (disable == null) return RCConstants.DISABLE_HOST_NAME_VERIFIER; else return new Boolean(disable); } /** * First checks property disable.host.name.verifier as system property if not found it uses configured one. * * @return */ private boolean isUseSelfSignedCertVerifier() { String disable = RCUtil.getSSLOverrideProperty("use.self.signed.cert.verifier"); if (disable == null) return RCConstants.USE_SELF_SIGNED_CERT_VERIFIER; else return new Boolean(disable); } /* public static void main(String[] args) { Hitter hitter = new Hitter(); String url = "https://localhost.mlbam.com:8443/"; HttpHandler httpHandler = new HttpHandler(); try { hitter.hit(url, "GET", httpHandler, null); } catch ( Exception e ) { // TODO Auto-generated catch block e.printStackTrace(); } LOG.debug("Response Headers: \n" + httpHandler.getResponseHeaders()); System.out.println("Response Headers: \n" + httpHandler.getResponseHeaders()); } */ }