Package org.agorava.rest

Source Code of org.agorava.rest.RequestImpl

/*
* Copyright 2013 Agorava
*
* 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.
*/

package org.agorava.rest;

import org.agorava.api.exception.AgoravaException;
import org.agorava.api.exception.ConnectionException;
import org.agorava.api.rest.Request;
import org.agorava.api.rest.RequestTuner;
import org.agorava.api.rest.Verb;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
* Represents an HTTP Request object
*
* @author Pablo Fernandez
*/
public class RequestImpl implements Request {
    private static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded";

    private static final String CONTENT_LENGTH = "Content-Length";

    private static final String CONTENT_TYPE = "Content-Type";

    private static RequestTuner NOOP = new RequestTuner() {
        @Override
        public void tune(Request _) {
        }
    };

    private String url;

    private Verb verb;

    private HttpParametersImpl querystringParams;

    private HttpParametersImpl bodyParams;

    private Map<String, String> headers;

    private String payload = null;

    protected HttpURLConnection getConnection() {
        return connection;
    }

    private HttpURLConnection connection;

    private String charset;

    private byte[] bytePayload = null;

    private boolean connectionKeepAlive = false;

    private Long connectTimeout = null;

    private Long readTimeout = null;

    /**
     * Creates a new Http Request
     *
     * @param verb Http Verb (GET, POST, etc)
     * @param url  url with optional querystring parameters.
     */
    public RequestImpl(Verb verb, String url) {
        this.verb = verb;
        this.url = url;
        this.querystringParams = new HttpParametersImpl();
        this.bodyParams = new HttpParametersImpl();
        this.headers = new HashMap<String, String>();
    }

    @Override
    public ResponseImpl send(RequestTuner tuner) {
        try {
            createConnection();
            return doSend(tuner);
        } catch (Exception e) {
            throw new ConnectionException(e);
        }
    }

    @Override
    public ResponseImpl send() {
        return send(NOOP);
    }

    private void createConnection() throws IOException {
        String completeUrl = getCompleteUrl();
        if (connection == null) {
            System.setProperty("http.keepAlive", connectionKeepAlive ? "true" : "false");
            connection = (HttpURLConnection) new URL(completeUrl).openConnection();
        }
    }

    @Override
    public String getCompleteUrl() {
        return querystringParams.asUrl(url);
    }

    ResponseImpl doSend(RequestTuner tuner) throws IOException {
        connection.setRequestMethod(this.verb.name());
        if (connectTimeout != null) {
            connection.setConnectTimeout(connectTimeout.intValue());
        }
        if (readTimeout != null) {
            connection.setReadTimeout(readTimeout.intValue());
        }
        addHeaders(connection);
        if (verb.equals(Verb.PUT) || verb.equals(Verb.POST)) {
            addBody(connection, getByteBodyContents());
        }
        tuner.tune(this);
        return new ResponseImpl(this);
    }

    void addHeaders(HttpURLConnection conn) {
        for (String key : headers.keySet())
            conn.setRequestProperty(key, headers.get(key));
    }

    void addBody(HttpURLConnection conn, byte[] content) throws IOException {
        conn.setRequestProperty(CONTENT_LENGTH, String.valueOf(content.length));

        // Set default content type if none is set.
        if (conn.getRequestProperty(CONTENT_TYPE) == null) {
            conn.setRequestProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
        }
        conn.setDoOutput(true);
        conn.getOutputStream().write(content);
    }

    @Override
    public void addHeader(String key, String value) {
        this.headers.put(key, value);
    }

    @Override
    public void addBodyParameter(String key, String value) {
        this.bodyParams.add(key, value);
    }

    @Override
    public void addQuerystringParameter(String key, String value) {
        this.querystringParams.add(key, value);
    }

    @Override
    public void addPayload(String payload) {
        this.payload = payload;
    }

    @Override
    public void addPayload(byte[] payload) {
        this.bytePayload = payload;
    }

    @Override
    public HttpParametersImpl getQueryStringParams() {
        try {
            HttpParametersImpl result = new HttpParametersImpl();
            String queryString = new URL(url).getQuery();
            result.addQuerystring(queryString);
            result.addAll(querystringParams);
            return result;
        } catch (MalformedURLException mue) {
            throw new AgoravaException("Malformed URL : " + url, mue);
        }
    }

    @Override
    public HttpParametersImpl getBodyParams() {
        return bodyParams;
    }

    @Override
    public String getUrl() {
        return url;
    }

    @Override
    public String getSanitizedUrl() {
        return url.replaceAll("\\?.*", "").replace("\\:\\d{4}", "");
    }

    @Override
    public String getBodyContents() {
        try {
            return new String(getByteBodyContents(), getCharset());
        } catch (UnsupportedEncodingException uee) {
            throw new AgoravaException("Unsupported Charset: " + charset, uee);
        }
    }

    byte[] getByteBodyContents() {
        if (bytePayload != null) return bytePayload;
        String body = (payload != null) ? payload : bodyParams.asFormUrlEncodedString();
        try {
            return body.getBytes(getCharset());
        } catch (UnsupportedEncodingException uee) {
            throw new AgoravaException("Unsupported Charset: " + getCharset(), uee);
        }
    }

    @Override
    public Verb getVerb() {
        return verb;
    }

    @Override
    public Map<String, String> getHeaders() {
        return headers;
    }

    @Override
    public String getCharset() {
        return charset == null ? Charset.defaultCharset().name() : charset;
    }

    @Override
    public void setConnectTimeout(int duration, TimeUnit unit) {
        this.connectTimeout = unit.toMillis(duration);
    }

    @Override
    public void setReadTimeout(int duration, TimeUnit unit) {
        this.readTimeout = unit.toMillis(duration);
    }

    @Override
    public void setCharset(String charsetName) {
        this.charset = charsetName;
    }

    @Override
    public void setConnectionKeepAlive(boolean connectionKeepAlive) {
        this.connectionKeepAlive = connectionKeepAlive;
    }

    /*
     * We need this in order to stub the connection object for test cases
     */
    void setConnection(HttpURLConnection connection) {
        this.connection = connection;
    }

    @Override
    public String toString() {
        return String.format("@Request(%s %s)", getVerb(), getUrl());
    }

    @Override
    public void addBodyParameters(Map<String, ?> toAdd) {
        for (String key : toAdd.keySet()) {
            addBodyParameter(key, toAdd.get(key).toString());

        }
    }
}
TOP

Related Classes of org.agorava.rest.RequestImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.