com.gistlabs.mechanize.PageRequest.java Source code

Java tutorial

Introduction

Here is the source code for com.gistlabs.mechanize.PageRequest.java

Source

/**
 * Copyright (C) 2012-2014 Gist Labs, LLC. (http://gistlabs.com)
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
package com.gistlabs.mechanize;

import static org.junit.Assert.assertEquals;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Arrays;

import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicHttpResponse;
import org.junit.Assert;
import org.junit.internal.ArrayComparisonFailure;

import com.gistlabs.mechanize.exceptions.MechanizeExceptionFactory;
import com.gistlabs.mechanize.headers.Header;
import com.gistlabs.mechanize.headers.Headers;
import com.gistlabs.mechanize.parameters.Parameters;
import com.gistlabs.mechanize.util.apache.ContentType;
import com.gistlabs.mechanize.util.apache.URLEncodedUtils;

public class PageRequest {
    public final String httpMethod;
    public final String uri;
    public Parameters parameters;

    public Headers headers = new Headers();
    public final InputStream body;
    public boolean wasExecuted = false;
    public HttpClient client = null;
    public HttpRequest request = null;
    public String contentType = ContentType.TEXT_HTML.getMimeType();
    public String charset = "utf-8";
    private String contentLocation = null;

    public PageRequest(final String uri, final String body) {
        this("GET", uri, body);
    }

    public PageRequest(final String method, final String uri, final String body) {
        this(method, uri, new Parameters(), body);
    }

    public PageRequest(final String method, final String uri, final InputStream body) {
        this(method, uri, new Parameters(), body);
    }

    public PageRequest(final String method, final String uri, final Parameters parameters, final String body) {
        this(method, uri, parameters, new ByteArrayInputStream(body.getBytes()));
    }

    public PageRequest(final String method, final String uri, final Parameters parameters, final InputStream body) {
        this.httpMethod = method;
        this.uri = uri;
        this.parameters = parameters;
        this.body = body;
    }

    public PageRequest setParameters(Parameters parameters) {
        this.parameters = parameters;
        return this;
    }

    public Parameters getParameters() {
        return parameters;
    }

    public PageRequest addHeader(final String header, final String... values) {
        this.headers.add(header, values);

        return this;
    }

    public PageRequest setContentType(String contentType) {
        this.contentType = contentType;
        return this;
    }

    public boolean wasExecuted() {
        return wasExecuted;
    }

    public void setEncoding(final String charset) {
        this.charset = charset;
    }

    public PageRequest setContentLocation(final String contentLocation) {
        this.contentLocation = contentLocation;
        return this;
    }

    public HttpResponse consume(final HttpClient client, final HttpRequestBase request) throws Exception {
        if (!wasExecuted) {
            this.client = client;
            this.request = request;

            if (!request.getMethod().equalsIgnoreCase(httpMethod))
                throw new IllegalArgumentException(
                        String.format("Expected %s, but was %s", httpMethod, request.getMethod()));

            if (request.getURI().toString().equals(uri)) {
                HttpResponse response = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 1), 200, "OK");
                BasicHttpEntity entity = new BasicHttpEntity();
                if (contentLocation != null)
                    response.addHeader(new BasicHeader("Content-Location", contentLocation));
                entity.setContentEncoding(charset);
                entity.setContentType(this.contentType);
                entity.setContent(this.body);
                response.setEntity(new BufferedHttpEntity(entity));

                assertParameters(request);
                assertHeaders(request);

                this.wasExecuted = true;
                return response;
            } else {
                assertEquals("URI of the next PageRequest does not match", uri, request.getURI().toString());
                return null;
            }
        } else
            throw new UnsupportedOperationException("Request already executed");
    }

    private void assertHeaders(final HttpRequestBase request) throws ArrayComparisonFailure {
        for (Header header : headers) {
            org.apache.http.Header[] requestHeaders = request.getHeaders(header.getName());
            boolean foundMatch = false;
            for (org.apache.http.Header requestHeader : requestHeaders)
                if (header.getValues().contains(requestHeader.getValue()))
                    foundMatch = true;
            if (!foundMatch)
                Assert.fail(String.format("Could not find request header matching: %s", header));
        }
        if (request instanceof HttpPost) {
            HttpPost post = (HttpPost) request;
            HttpEntity entity = post.getEntity();
            Parameters actualParameters = extractParameters(entity);

            String[] expectedNames = parameters.getNames();
            String[] actualNames = actualParameters.getNames();
            Arrays.sort(expectedNames);
            Arrays.sort(actualNames);
            Assert.assertArrayEquals("Expected and actual parameters should equal by available parameter names",
                    expectedNames, actualNames);

            for (String name : expectedNames) {
                String[] expectedValue = parameters.get(name);
                String[] actualValue = actualParameters.get(name);
                Assert.assertArrayEquals("Expected parameter of next PageRequest '" + uri + "' must match",
                        expectedValue, actualValue);
            }
        }
    }

    private void assertParameters(final HttpRequestBase request) throws ArrayComparisonFailure {
        if (request instanceof HttpPost) {
            HttpPost post = (HttpPost) request;
            HttpEntity entity = post.getEntity();
            Parameters actualParameters = extractParameters(entity);

            String[] expectedNames = parameters.getNames();
            String[] actualNames = actualParameters.getNames();
            Arrays.sort(expectedNames);
            Arrays.sort(actualNames);
            Assert.assertArrayEquals("Expected and actual parameters should equal by available parameter names",
                    expectedNames, actualNames);

            for (String name : expectedNames) {
                String[] expectedValue = parameters.get(name);
                String[] actualValue = actualParameters.get(name);
                Assert.assertArrayEquals("Expected parameter of next PageRequest '" + uri + "' must match",
                        expectedValue, actualValue);
            }
        }
    }

    private Parameters extractParameters(final HttpEntity entity) {
        if (entity instanceof UrlEncodedFormEntity)
            return extractParameters((UrlEncodedFormEntity) entity);
        if (entity instanceof MultipartEntity)
            return extractParameters((MultipartEntity) entity);
        throw new ClassCastException(String
                .format("Can't convert %s to either UrlEncodedFormEntity or MultipartEntity", entity.getClass()));
    }

    private Parameters extractParameters(final MultipartEntity entity) {
        Parameters parameters = new Parameters();

        // appears to be impossible to get parts...?

        return parameters;
    }

    private Parameters extractParameters(final UrlEncodedFormEntity entity) {
        try {
            InputStream stream = entity.getContent();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
            StringBuilder content = new StringBuilder();
            while (true) {
                String line = reader.readLine();
                if (line != null) {
                    if (content.length() > 0)
                        content.append("\n");
                    content.append(line);
                } else
                    break;
            }

            Parameters parameters = new Parameters();
            for (NameValuePair param : URLEncodedUtils.parse(content.toString(), Charset.forName("UTF-8")))
                parameters.add(param.getName(), param.getValue());
            return parameters;
        } catch (IOException e) {
            throw MechanizeExceptionFactory.newException(e);
        }
    }

    @Override
    public String toString() {
        return "<" + httpMethod + ":" + uri + "{" + parameters + "}" + ">";
    }

}