com.klarna.checkout.stubs.HttpClientStub.java Source code

Java tutorial

Introduction

Here is the source code for com.klarna.checkout.stubs.HttpClientStub.java

Source

/*
 * Copyright 2013 Klarna AB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * File containing the ConnectorOptions class.
 */
package com.klarna.checkout.stubs;

import com.klarna.checkout.IHttpClient;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.http.Header;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.ProtocolException;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.CircularRedirectException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.EntityEnclosingRequestWrapper;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

/**
 * Stubbed implementation of IHttpClient.
 */
public class HttpClientStub implements IHttpClient {

    /**
     * HttpUriRequest.
     */
    private HttpUriRequest httpUriReq;
    /**
     * A list holding the expected responses.
     */
    private ArrayList<HTTPResponseStub> responseList;
    /**
     * Memory for the latest response seen.
     */
    private HTTPResponseStub lastResponse;
    /**
     * Store for ResponseInterceptors.
     */
    private final ArrayList<HttpResponseInterceptor> responseInterceptors;
    /**
     * Store for RequestInterceptors.
     */
    private final ArrayList<HttpRequestInterceptor> requestInterceptors;
    /**
     * HttpParams storage.
     */
    private final HttpParams params;
    /**
     * Visited locations.
     */
    private Set<URI> visited;
    /**
     * Expected Location URI.
     */
    private URI expecedLocation;
    /**
     * Data holder.
     */
    private HashMap<String, String> data;

    /**
     * Constructor.
     */
    public HttpClientStub() {
        responseInterceptors = new ArrayList<HttpResponseInterceptor>();
        requestInterceptors = new ArrayList<HttpRequestInterceptor>();
        responseList = new ArrayList<HTTPResponseStub>();
        params = null;
        visited = new HashSet<URI>();
        data = new HashMap<String, String>();
    }

    /**
     * Constructor taking an HttpParams argument.
     *
     * @param parameters HttpParams to send in.
     */
    public HttpClientStub(final HttpParams parameters) {
        this.params = parameters;
        responseInterceptors = new ArrayList<HttpResponseInterceptor>();
        requestInterceptors = new ArrayList<HttpRequestInterceptor>();
        responseList = new ArrayList<HTTPResponseStub>();
        visited = new HashSet<URI>();
    }

    /**
     * @return the stored HttpUriRequest
     */
    public HttpUriRequest getHttpUriRequest() {
        return httpUriReq;
    }

    /**
     * Set a HttpUriRequest.
     *
     * @param req Item to set.
     */
    public void setHur(final HttpUriRequest req) {
        this.httpUriReq = req;
    }

    /**
     * Basic execution.
     *
     * @param hur HttpUriRequest object
     *
     * @return first element in the lastResponse list.
     *
     * @throws IOException if an I/O error occurs
     * @throws ClientProtocolException if a client protocol violation happened
     */
    @Override
    public HttpResponse execute(final HttpUriRequest hur) throws IOException, ClientProtocolException {
        this.httpUriReq = hur;
        this.lastResponse = this.getResponse();
        return this.lastResponse;
    }

    /**
     * Unused stub.
     *
     * @return nothing.
     */
    @Override
    public HttpParams getParams() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Unused stub.
     *
     * @return nothing.
     */
    @Override
    public ClientConnectionManager getConnectionManager() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Unused stub.
     *
     * @param hur HttpUriRequest
     * @param hc HttpContext
     *
     * @return nothing.
     *
     * @throws IOException never
     * @throws ClientProtocolException never
     */
    @Override
    public HttpResponse execute(final HttpUriRequest hur, final HttpContext hc)
            throws IOException, ClientProtocolException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Unused stub.
     *
     * @param hh HttpHost
     * @param hr HttpRequest
     *
     * @return nothing.
     *
     * @throws IOException never
     * @throws ClientProtocolException never
     */
    @Override
    public HttpResponse execute(final HttpHost hh, final HttpRequest hr)
            throws IOException, ClientProtocolException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Unused stub.
     *
     * @param hh HttpHost
     * @param hr HttpRequest
     * @param hc HttpContext
     *
     * @return nothing.
     *
     * @throws IOException never
     * @throws ClientProtocolException never
     */
    @Override
    public HttpResponse execute(final HttpHost hh, final HttpRequest hr, final HttpContext hc)
            throws IOException, ClientProtocolException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Uppercase data to simulate it having passed on to the server.
     *
     * @throws IOException in case of an IO error.
     */
    private void fixData() throws IOException {
        if (this.httpUriReq.getMethod().equals("POST")) {
            HttpEntityEnclosingRequest h = (HttpEntityEnclosingRequest) this.httpUriReq;

            InputStream is = h.getEntity().getContent();
            java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");

            String str = "";
            while (s.hasNext()) {
                str = str.concat(s.next());
            }
            JSONParser jsonParser = new JSONParser();
            HashMap<String, String> obj = null;
            try {
                obj = (HashMap<String, String>) jsonParser.parse(str);
            } catch (ParseException ex) {
                Logger.getLogger(HttpClientStub.class.getName()).log(Level.SEVERE, null, ex);
            }
            if (obj != null && obj.containsKey("test")) {
                str = obj.get("test").toUpperCase();
                this.data.put("test", str);
            }

            ByteArrayInputStream in = new ByteArrayInputStream(JSONObject.toJSONString(this.data).getBytes());

            this.lastResponse.setEntity(new InputStreamEntity(in, in.available()));
        }
    }

    /**
     * Stubbed Execute implementation.
     *
     * @param <T> The class ResponseHandler operates on
     * @param hur HttpUriRequest object
     * @param rh ResponseHandler object
     * @param hc HttpContext holder
     *
     * @return ResponseHandler result
     *
     * @throws IOException never
     */
    @Override
    public <T> T execute(final HttpUriRequest hur, final ResponseHandler<? extends T> rh, final HttpContext hc)
            throws IOException {
        this.httpUriReq = hur;

        List<Integer> redirects = new ArrayList();
        redirects.add(301);
        redirects.add(302);
        redirects.add(303);
        this.visited.clear();
        if (this.httpUriReq instanceof HttpEntityEnclosingRequest) {
            try {
                this.httpUriReq = new EntityEnclosingRequestWrapper((HttpEntityEnclosingRequest) hur);
            } catch (ProtocolException ex) {
                throw new IOException(ex);
            }
        }
        int status;
        do {
            try {
                for (HttpRequestInterceptor hri : requestInterceptors) {
                    hri.process(this.httpUriReq, hc);
                }
            } catch (HttpException ex) {
                throw new ClientProtocolException(ex);
            }

            if (!this.visited.add(this.httpUriReq.getURI())) {
                throw new ClientProtocolException(new CircularRedirectException());
            }

            this.lastResponse = this.getResponse();

            if (this.lastResponse.getStatusLine().getStatusCode() < 400) {
                fixData();
            }

            try {
                for (HttpResponseInterceptor hri : responseInterceptors) {
                    hri.process(this.lastResponse, hc);
                }
            } catch (HttpException ex) {
                throw new ClientProtocolException(ex);
            }
            status = this.lastResponse.getStatusLine().getStatusCode();
            Header location = this.lastResponse.getLastHeader("Location");
            if (location != null) {
                this.httpUriReq = new HttpGet(location.getValue());
            }
        } while (redirects.contains(status));

        if (this.data.containsKey("test")) {
            ByteArrayInputStream bis = new ByteArrayInputStream(JSONObject.toJSONString(data).getBytes());
            this.lastResponse.setEntity(new InputStreamEntity(bis, bis.available()));
        }

        return rh.handleResponse(this.lastResponse);
    }

    /**
     * Unused stub.
     *
     * @param <T> Class
     * @param hh HttpHost
     * @param hr HttpRequest
     * @param rh ResponseHandler
     *
     * @return nothing
     *
     * @throws IOException never
     * @throws ClientProtocolException never
     */
    @Override
    public <T> T execute(final HttpHost hh, final HttpRequest hr, final ResponseHandler<? extends T> rh)
            throws IOException, ClientProtocolException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Unused stub.
     *
     * @param <T> Class
     * @param hh HttpHost
     * @param hr HttpRequest
     * @param rh ResponseHandler
     * @param hc HttpContext
     *
     * @return nothing
     *
     * @throws IOException never
     * @throws ClientProtocolException never
     */
    @Override
    public <T> T execute(final HttpHost hh, final HttpRequest hr, final ResponseHandler<? extends T> rh,
            final HttpContext hc) throws IOException, ClientProtocolException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Add a response with only a status code.
     *
     * @param i status code
     */
    public void addResponse(final int i) {
        addResponse(new HTTPResponseStub(i, new HashMap<String, String>(), ""));
    }

    /**
     * Add a response with a status code and a payload.
     *
     * @param i status code
     * @param str payload string
     */
    public void addResponse(final int i, final String str) {
        addResponse(new HTTPResponseStub(i, new HashMap<String, String>(), str));
    }

    /**
     * Add a complete response.
     *
     * @param httpResponseStub response to set
     */
    public void addResponse(final HTTPResponseStub httpResponseStub) {
        this.responseList.add(httpResponseStub);
    }

    /**
     * Add a Fitnesse response.
     *
     * @param uri uri
     * @param status status
     * @param headers headers
     * @throws URISyntaxException if uri could not be parsed.
     */
    public void addResponse(final String uri, final int status, final Map<String, String> headers)
            throws URISyntaxException {
        this.expecedLocation = new URI(uri);
        addResponse(new HTTPResponseStub(status, headers, ""));
    }

    /**
     * @return the first item in the response list.
     */
    public HTTPResponseStub getResponse() {
        return this.responseList.remove(0);
    }

    /**
     * Unused stub.
     *
     * @param <T> Class
     * @param hur HttpUriRequest
     * @param rh ResponseHandler
     *
     * @return nothing
     *
     * @throws IOException never
     * @throws ClientProtocolException never
     */
    public <T> T execute(final HttpUriRequest hur, final ResponseHandler<? extends T> rh)
            throws IOException, ClientProtocolException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    /**
     * Add a responseInterceptor.
     *
     * @param hri responseInterceptor to add
     */
    public void addResponseInterceptor(final HttpResponseInterceptor hri) {
        responseInterceptors.add(hri);
    }

    /**
     * Add a requestInterceptor.
     *
     * @param hri requestInterceptor to add
     */
    public void addRequestInterceptor(final HttpRequestInterceptor hri) {
        requestInterceptors.add(hri);
    }

    /**
     * Stubbed BasicHttpResponse.
     */
    public static class HTTPResponseStub extends BasicHttpResponse {

        /**
         * Constructor.
         *
         * @param code status code
         * @param headers http header map
         * @param payloadJson payload string
         */
        public HTTPResponseStub(final int code, final Map<String, String> headers, final String payloadJson) {

            super(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), code, "ok"));
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                this.setHeader(entry.getKey(), entry.getValue());
            }

            try {
                InputStream is = new ByteArrayInputStream(payloadJson.getBytes("UTF-8"));
                this.setEntity(new InputStreamEntity(is, is.available()));
            } catch (UnsupportedEncodingException ex) {
                Logger.getLogger(HttpClientStub.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(HttpClientStub.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}