All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.openshift.internal.client.httpclient.UrlConnectionHttpClient Maven / Gradle / Ivy

The newest version!
/******************************************************************************* 
 * Copyright (c) 2013 Red Hat, Inc. 
 * Distributed under license by Red Hat, Inc. All rights reserved. 
 * This program is 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: 
 * Red Hat, Inc. - initial API and implementation 
 ******************************************************************************/
package com.openshift.internal.client.httpclient;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.openshift.client.HttpMethod;
import com.openshift.client.IHttpClient;
import com.openshift.client.utils.Base64Coder;
import com.openshift.internal.client.utils.StreamUtils;
import com.openshift.internal.client.utils.StringUtils;

/**
 * @author Andre Dietisheim
 * @author Nicolas Spano
 */
public class UrlConnectionHttpClient implements IHttpClient {

	private static final Logger LOGGER = LoggerFactory.getLogger(UrlConnectionHttpClient.class);

	private static final String SYSPROP_OPENSHIFT_CONNECT_TIMEOUT = "com.openshift.httpclient.timeout";
	private static final String SYSPROP_DEFAULT_CONNECT_TIMEOUT = "sun.net.client.defaultConnectTimeout";
	private static final String SYSPROP_DEFAULT_READ_TIMEOUT = "sun.net.client.defaultReadTimeout";

	private static final String USERAGENT_FOR_KEYAUTH = "OpenShift";

	private String userAgent;
	private boolean sslChecks;
	private String username;
	private String password;
	private String authKey;
	private String authIV;
	private IMediaType requestMediaType;
	private String acceptedMediaType;
	private String acceptVersion;

	public UrlConnectionHttpClient(String username, String password, String userAgent, boolean sslChecks,
			IMediaType requestMediaType, String acceptedMediaType, String version) {
		this(username, password, userAgent, sslChecks, requestMediaType, acceptedMediaType, version, null, null);
	}

	public UrlConnectionHttpClient(String username, String password, String userAgent, boolean sslChecks,
			IMediaType requestMediaType, String acceptedMediaType, String version, String authKey, String authIV) {
		this.username = username;
		this.password = password;
		this.userAgent = setupUserAgent(authKey, authIV, userAgent);
		this.sslChecks = sslChecks;
		this.requestMediaType = requestMediaType;
		this.acceptedMediaType = acceptedMediaType;
		this.authKey = authKey;
		this.authIV = authIV;
		this.acceptVersion = version;
	}

	/** TODO: unify with #setUserAgent **/
	private String setupUserAgent(String authKey, String authIV, String userAgent) {
		if (!StringUtils.isEmpty(authKey)) {
			if (userAgent == null) {
				userAgent = "OpenShift";
			} else if (!userAgent.startsWith("OpenShift")) {
				userAgent = "OpenShift-" + userAgent;
			}
		}
		return userAgent;
	}

	public void setAcceptedMediaType(String acceptedMediaType) {
		this.acceptedMediaType = acceptedMediaType;
	}

	public String getAcceptedMediaType() {
		return acceptedMediaType;
	}

	public String get(URL url) throws HttpClientException, SocketTimeoutException {
		return get(url, NO_TIMEOUT);
	}

	@Override
	public String get(URL url, int timeout) throws HttpClientException, SocketTimeoutException {

		HttpURLConnection connection = null;
		try {
			return write(null, HttpMethod.GET.toString(), url, timeout, requestMediaType);
		} catch (SocketTimeoutException e) {
			throw e;
		/* TODO: cleanup exception handling */
		} catch (IOException e) {
			throw createException(e, connection);
		} finally {
			disconnect(connection);
		}
	}

	public void setUserAgent(String userAgent) {
		this.userAgent = userAgent;
	}

	public String getUserAgent() {
		return userAgent;
	}

	public void setAcceptVersion(String version) {
		this.acceptVersion = version;
	}

	public String getAcceptVersion() {
		return acceptVersion;
	}

    public IMediaType getRequestMediaType() {
        return requestMediaType;
    }

    public void setRequestMediaType(IMediaType requestMediaType) {
        this.requestMediaType = requestMediaType;
    }

    public String put(Map parameters, URL url)
			throws SocketTimeoutException, EncodingException, HttpClientException {
		return put(requestMediaType.encodeParameters(parameters), url);
	}

	@Override
	public String put(Map parameters, URL url, int timeout) 
			throws HttpClientException, SocketTimeoutException, EncodingException {
		return put(parameters, url, timeout, requestMediaType);
	}

    @Override
    public String put(Map parameters, URL url, int timeout, IMediaType mediaType) throws HttpClientException, SocketTimeoutException, EncodingException {
        return write(mediaType.encodeParameters(parameters), HttpMethod.PUT.toString(), url, timeout, mediaType);
    }

    protected String put(String data, URL url) throws HttpClientException, SocketTimeoutException {
		return write(data, HttpMethod.PUT.toString(), url, NO_TIMEOUT, requestMediaType);
	}

	public String post(Map parameters, URL url)
			throws SocketTimeoutException, EncodingException, HttpClientException {
		return post(requestMediaType.encodeParameters(parameters), url);
	}

	protected String post(String data, URL url) throws HttpClientException, SocketTimeoutException {
		return write(data, HttpMethod.POST.toString(), url, NO_TIMEOUT, requestMediaType);
	}

	public String post(Map data, URL url, int timeout) 
			throws HttpClientException, SocketTimeoutException, EncodingException {
        return post(data, url, timeout, requestMediaType);
	}

    @Override
    public String post(Map parameters, URL url, int timeout, IMediaType mediaType) throws HttpClientException, SocketTimeoutException, EncodingException {
        return write(mediaType.encodeParameters(parameters), HttpMethod.POST.toString(), url, timeout, mediaType);
    }

    public String delete(Map parameters, URL url)
			throws HttpClientException, SocketTimeoutException, EncodingException {
		return delete(requestMediaType.encodeParameters(parameters), url);
	}

	@Override
	public String delete(Map parameters, URL url, int timeout) throws HttpClientException,
			SocketTimeoutException,
            EncodingException {
		return delete(parameters, url, timeout, requestMediaType);
	}

    @Override
    public String delete(Map parameters, URL url, int timeout, IMediaType mediaType) throws HttpClientException, SocketTimeoutException, EncodingException {
        return write(mediaType.encodeParameters(parameters), HttpMethod.DELETE.toString(), url, timeout, mediaType);
    }

    public String delete(URL url)
			throws HttpClientException, SocketTimeoutException, UnsupportedEncodingException {
		return delete((String) null, url);
	}

	protected String delete(String data, URL url) throws HttpClientException, SocketTimeoutException {
		return write(data, HttpMethod.DELETE.toString(), url, NO_TIMEOUT, requestMediaType);
	}

	protected String write(String data, String requestMethod, URL url, int timeout, IMediaType mediaType)
			throws SocketTimeoutException, HttpClientException {
		HttpURLConnection connection = null;
		try {
			connection = createConnection(username, password, authKey, authIV, userAgent, url, timeout, mediaType);
			connection.setRequestMethod(requestMethod);
			connection.setDoOutput(true);
			if (data != null) {
				LOGGER.trace("Sending \"{}\" to {}", data, url);
				StreamUtils.writeTo(data.getBytes(), connection.getOutputStream());
			}
			return StreamUtils.readToString(connection.getInputStream());
		} catch (SocketTimeoutException e) {
			throw e;
		} catch (IOException e) {
			throw createException(e, connection);
		} finally {
			disconnect(connection);
		}

	}

	private void disconnect(HttpURLConnection connection) {
		if (connection != null) {
			connection.disconnect();
		}
	}

	private HttpClientException createException(IOException ioe, HttpURLConnection connection)
			throws SocketTimeoutException {
		try {
			int responseCode = connection.getResponseCode();
			String errorMessage = createErrorMessage(ioe, connection);
			switch (responseCode) {
			case STATUS_INTERNAL_SERVER_ERROR:
				return new InternalServerErrorException(errorMessage, ioe);
			case STATUS_BAD_REQUEST:
				return new BadRequestException(errorMessage, ioe);
			case STATUS_UNAUTHORIZED:
				return new UnauthorizedException(errorMessage, ioe);
			case STATUS_NOT_FOUND:
				return new NotFoundException(errorMessage, ioe);
			default:
				return new HttpClientException(errorMessage, ioe);
			}
		} catch (SocketTimeoutException e) {
			throw e;
		} catch (IOException e) {
			return new HttpClientException(e);
		}
	}

	protected String createErrorMessage(IOException ioe, HttpURLConnection connection) throws IOException {
		String errorMessage = StreamUtils.readToString(connection.getErrorStream());
		if (!StringUtils.isEmpty(errorMessage)) {
			return errorMessage;
		}
		StringBuilder builder = new StringBuilder("Connection to ")
				.append(connection.getURL());
		String reason = connection.getResponseMessage();
		if (!StringUtils.isEmpty(reason)) {
			builder.append(": ").append(reason);
		}
		return builder.toString();
	}

	private boolean isHttps(URL url) {
		return "https".equals(url.getProtocol());
	}

	/**
	 * Sets a trust manager that will always trust.
	 * 

* TODO: dont swallog exceptions and setup things so that they dont disturb * other components. */ private void setPermissiveSSLSocketFactory(HttpsURLConnection connection) { try { SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init( new KeyManager[0], new TrustManager[] { new PermissiveTrustManager() }, new SecureRandom()); SSLSocketFactory socketFactory = sslContext.getSocketFactory(); ((HttpsURLConnection) connection).setSSLSocketFactory(socketFactory); } catch (KeyManagementException e) { // ignore } catch (NoSuchAlgorithmException e) { // ignore } } protected HttpURLConnection createConnection(String username, String password, String userAgent, URL url) throws IOException { return createConnection(username, password, null, null, userAgent, url, NO_TIMEOUT, requestMediaType); } protected HttpURLConnection createConnection(String username, String password, String authKey, String authIV, String userAgent, URL url, int timeout, IMediaType mediaType) throws IOException { LOGGER.trace( "creating connection to {} using username \"{}\" and password \"{}\"", new Object[] { url, username, password }); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); setSSLChecks(url, connection); setAuthorisation(username, password, authKey, authIV, connection); connection.setUseCaches(false); connection.setDoInput(true); connection.setAllowUserInteraction(false); setConnectTimeout(connection); setReadTimeout(timeout, connection); // wont work when switching http->https // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4620571 connection.setInstanceFollowRedirects(true); setAcceptHeader(connection); setUserAgent(connection); connection.setRequestProperty(PROPERTY_CONTENT_TYPE, mediaType.getType()); return connection; } private void setUserAgent(HttpURLConnection connection) { String userAgent = this.userAgent; if (!StringUtils.isEmpty(authKey)) { userAgent = USERAGENT_FOR_KEYAUTH; } if (userAgent != null) { connection.setRequestProperty(PROPERTY_USER_AGENT, userAgent); } } private void setAcceptHeader(HttpURLConnection connection) { StringBuilder builder = new StringBuilder(acceptedMediaType); if (acceptVersion != null) { builder.append(SEMICOLON).append(SPACE) .append(VERSION).append(EQUALS).append(acceptVersion); } connection.setRequestProperty(PROPERTY_ACCEPT, builder.toString()); } private void setAuthorisation(String username, String password, String authKey, String authIV, HttpURLConnection connection) { if (username == null || username.trim().length() == 0 || password == null || password.trim().length() == 0) { if (authKey != null && authIV != null) { connection.setRequestProperty(PROPERTY_AUTHKEY, authKey); connection.setRequestProperty(PROPERTY_AUTHIV, authIV); } } else { String credentials = Base64Coder.encode( new StringBuilder().append(username).append(COLON).append(password).toString().getBytes()); connection.setRequestProperty(PROPERTY_AUTHORIZATION, new StringBuilder().append(AUTHORIZATION_BASIC).append(SPACE).append(credentials).toString()); } } private void setSSLChecks(URL url, HttpURLConnection connection) { if (isHttps(url) && !sslChecks) { HttpsURLConnection httpsConnection = (HttpsURLConnection) connection; httpsConnection.setHostnameVerifier(new NoopHostnameVerifier()); setPermissiveSSLSocketFactory(httpsConnection); } } private void setConnectTimeout(URLConnection connection) { int timeout = getTimeout( getSystemPropertyInteger(SYSPROP_OPENSHIFT_CONNECT_TIMEOUT), getSystemPropertyInteger(SYSPROP_DEFAULT_CONNECT_TIMEOUT), DEFAULT_CONNECT_TIMEOUT); connection.setConnectTimeout(timeout); } private void setReadTimeout(int timeout, URLConnection connection) { timeout = getTimeout(timeout, getSystemPropertyInteger(SYSPROP_DEFAULT_READ_TIMEOUT), DEFAULT_READ_TIMEOUT); connection.setReadTimeout(timeout); } private int getTimeout(int timeout, int systemPropertyTimeout, int defaultTimeout) { if (timeout == NO_TIMEOUT) { timeout = systemPropertyTimeout; if (timeout == NO_TIMEOUT) { timeout = defaultTimeout; } } return timeout; } private int getSystemPropertyInteger(String key) { try { return Integer.parseInt(System.getProperty(key)); } catch (NumberFormatException e) { return -1; } } private class PermissiveTrustManager implements X509TrustManager { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } } private class NoopHostnameVerifier implements HostnameVerifier { public boolean verify(String hostname, SSLSession sslSession) { return true; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy