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

com.paypal.base.HttpConnection Maven / Gradle / Ivy

There is a newer version: 1.14.0
Show newest version
package com.paypal.base;

import com.paypal.base.exception.ClientActionRequiredException;
import com.paypal.base.exception.HttpErrorException;
import com.paypal.base.exception.InvalidResponseDataException;
import com.paypal.base.exception.SSLConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Base HttpConnection class
 * 
 */
public abstract class HttpConnection {

	private static final Logger log = LoggerFactory
			.getLogger(HttpConnection.class);

	/**
	 * Subclasses must set the http configuration in the
	 * createAndconfigureHttpConnection() method.
	 */
	protected HttpConfiguration config;

	/**
	 * Subclasses must create and set the connection in the
	 * createAndconfigureHttpConnection() method.
	 */
	protected HttpURLConnection connection;

	public HttpConnection() {

	}

	public Map> getResponseHeaderMap() {
		return connection.getHeaderFields();
	}

	/**
	 * Executes HTTP request
	 * 
	 * @param url
	 * @param payload
	 * @param headers
	 * @return String response
	 * @throws InvalidResponseDataException
	 * @throws IOException
	 * @throws InterruptedException
	 * @throws HttpErrorException
	 * @throws ClientActionRequiredException
	 */
	public String execute(String url, String payload,
			Map headers) throws InvalidResponseDataException,
			IOException, InterruptedException, HttpErrorException {
		BufferedReader reader;
		String successResponse;
		InputStream result = executeWithStream(url, payload, headers);
		reader = new BufferedReader(new InputStreamReader(result,
				Constants.ENCODING_FORMAT));
		successResponse = read(reader);

		return successResponse;
	}

	/**
	 * Executes HTTP request
	 * 
	 * @param url URL for the connection
	 * @param payload Request payload
	 * @param headers Headers map
	 * @return String response
	 * @throws InvalidResponseDataException
	 * @throws IOException
	 * @throws InterruptedException
	 * @throws HttpErrorException
	 * @throws ClientActionRequiredException
	 */
	public InputStream executeWithStream(String url, String payload,
			Map headers) throws InvalidResponseDataException,
			IOException, InterruptedException, HttpErrorException {
		InputStream successResponse = null;
		String errorResponse = null;
		int responseCode = -1;
		BufferedReader reader = null;
		OutputStreamWriter writer = null;
		connection.setRequestProperty("Content-Length", String.valueOf(payload.trim().length()));
		try {
			setHttpHeaders(headers);
			String mode = ConfigManager.getInstance().getConfigurationMap()
					.get(Constants.MODE);
			// Print if on live
			if (!Constants.LIVE.equalsIgnoreCase(mode)) {
				logCurlRequest(payload, headers);
			}

			// This exception is used to make final log more explicit
			Exception lastException = null;
			int retry = 0;
			retryLoop: do {
				try {
					if (Arrays.asList("POST", "PUT", "PATCH").contains(connection.getRequestMethod().toUpperCase())) {
						writer = new OutputStreamWriter(
								this.connection.getOutputStream(),
								Charset.forName(Constants.ENCODING_FORMAT));
						writer.write(payload);
						writer.flush();
					}

					responseCode = connection.getResponseCode();

					// SUCCESS
					if (responseCode >= 200 && responseCode < 300) {

						try {
							successResponse = connection.getInputStream();
						} catch (IOException e) {
							successResponse = connection.getErrorStream();
						}
						break retryLoop;
					}

					// FAILURE
					reader = new BufferedReader(new InputStreamReader(
							connection.getInputStream(),
							Constants.ENCODING_FORMAT));
					errorResponse = read(reader);
					String msg = "Response code: " + responseCode + "\tError response: " + errorResponse;

					if (responseCode >= 300 && responseCode < 500) {
						// CLIENT SIDE EXCEPTION
						throw new ClientActionRequiredException(responseCode, errorResponse, msg, new IOException(msg));
					} else if (responseCode >= 500) {
						// SERVER SIDE EXCEPTION
						throw new HttpErrorException(responseCode, errorResponse, msg, new IOException(msg));
					}
				} catch (IOException e) {
					lastException = e;
					try {
						responseCode = connection.getResponseCode();
						if (connection.getErrorStream() != null) {
							reader = new BufferedReader(new InputStreamReader(
									connection.getErrorStream(),
									Constants.ENCODING_FORMAT));
							errorResponse = read(reader);
							log.error("Response code: " + responseCode
									+ "\tError response: " + errorResponse);
						}
						if ((errorResponse == null)
								|| (errorResponse.length() == 0)) {
							errorResponse = e.getMessage();
						}
						if (responseCode <= 500) {
							String msg = "Response code: " + responseCode + "\tError response: " + errorResponse;
							throw new HttpErrorException(responseCode,
									errorResponse, msg, e);
						}
					} catch (HttpErrorException ex) {
						throw ex;
					} catch (Exception ex) {
						lastException = ex;
						log.error(
								"Caught exception while handling error response",
								ex);
					}
				}
				// RETRY LOGIC
				retry++;
				if (retry > 0) {
					log.error(" Retry  No : " + retry + "...");
					Thread.sleep(this.config.getRetryDelay());
				}
			} while (retry < this.config.getMaxRetry());

			if (successResponse == null
					|| (successResponse.available() <= 0 && !(responseCode >= 200 && responseCode < 300))) {
				throw new HttpErrorException(
						"retry fails..  check log for more information",
						lastException);
			}
		} finally {
			try {
				if (reader != null) {
					reader.close();
				}
				if (writer != null) {
					writer.close();
				}
			} finally {
				reader = null;
				writer = null;
			}
		}
		return successResponse;
	}

	/**
	 * Logs the curl format based request, which could be helpful for debugging purposes.
	 *
	 * @param payload Payload Data
	 * @param headers Headers Map
     */
	private void logCurlRequest(String payload, Map headers) {
		String cmd = "curl command: \n";
		cmd += "curl -v '" + connection.getURL().toString() + "' \\\n";
		if (headers != null) {
			for (String key : headers.keySet()) {
				String value = headers.get(key);
				cmd += "-H \"" + key + ": " + value + "\" \\\n";
			}
		}
		cmd += "-d '" + payload + "'";
		log.debug(cmd);
	}

	/**
	 * Set ssl parameters for client authentication
	 * 
	 * @param certPath
	 * @param certKey
	 * @throws SSLConfigurationException
	 */
	public abstract void setupClientSSL(String certPath, String certKey)
			throws SSLConfigurationException;

	/**
	 * create and configure HttpsURLConnection object
	 * 
	 * @param clientConfiguration
	 * @throws IOException
	 */
	public abstract void createAndconfigureHttpConnection(
			HttpConfiguration clientConfiguration) throws IOException;

	protected String read(BufferedReader reader) throws IOException {
		String inputLine;
		StringBuilder response = new StringBuilder();
		while ((inputLine = reader.readLine()) != null) {
			response.append(inputLine);
		}
		return response.toString();
	}

	/**
	 * Set headers for HttpsURLConnection object
	 * 
	 * @param headers
	 */
	protected void setHttpHeaders(Map headers) {
		if (headers != null && !headers.isEmpty()) {
			Iterator> itr = headers.entrySet().iterator();
			while (itr.hasNext()) {
				Map.Entry pairs = itr.next();
				String key = pairs.getKey();
				String value = pairs.getValue();
				this.connection.setRequestProperty(key, value);
			}
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy