com.twotoasters.android.hoot.HootTransportHttpUrlConnection.java Source code

Java tutorial

Introduction

Here is the source code for com.twotoasters.android.hoot.HootTransportHttpUrlConnection.java

Source

/*
 * Copyright (C) 2012 Two Toasters, LLC
 *
 * 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 com.twotoasters.android.hoot;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

import org.apache.commons.io.IOUtils;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.entity.mime.MultipartEntity;

import android.util.Log;

class HootTransportHttpUrlConnection implements HootTransport {

    @Override
    public void setup(Hoot hoot) {
        mTimeout = hoot.getTimeout();
        mSSLHostNameVerifier = hoot.getSSLHostNameVerifier();
    }

    @Override
    public HootResult synchronousExecute(HootRequest request) {
        if (request.isCancelled()) {
            return request.getResult();
        }

        mStreamingMode = (request.getQueryParameters() == null && request.getData() == null
                && request.getMultipartEntity() == null) ? StreamingMode.CHUNKED : StreamingMode.FIXED;

        if (request.getStreamingMode() == HootRequest.STREAMING_MODE_FIXED) {
            mStreamingMode = StreamingMode.FIXED;
        }

        HttpURLConnection connection = null;
        try {
            String url = request.buildUri().toString();
            Log.v(TAG, "Executing [" + url + "]");
            connection = (HttpURLConnection) new URL(url).openConnection();
            if (connection instanceof HttpsURLConnection) {
                HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
                httpsConnection.setHostnameVerifier(mSSLHostNameVerifier);
            }
            connection.setConnectTimeout(mTimeout);
            connection.setReadTimeout(mTimeout);
            synchronized (mConnectionMap) {
                mConnectionMap.put(request, connection);
            }

            setRequestMethod(request, connection);
            setRequestHeaders(request, connection);

            if (request.getMultipartEntity() != null) {
                setMultipartEntity(request, connection);
            } else if (request.getData() != null) {
                setRequestData(request, connection);
            }

            HootResult hootResult = request.getResult();
            hootResult.setResponseCode(connection.getResponseCode());
            Log.d(TAG, " - received response code [" + connection.getResponseCode() + "]");
            if (request.getResult().isSuccess()) {
                hootResult.setHeaders(connection.getHeaderFields());
                hootResult.setResponseStream(new BufferedInputStream(connection.getInputStream()));
            } else {
                hootResult.setResponseStream(new BufferedInputStream(connection.getErrorStream()));
            }
            request.deserializeResult();
        } catch (Exception e) {
            request.getResult().setException(e);
            e.printStackTrace();
        } finally {
            if (connection != null) {
                synchronized (mConnectionMap) {
                    mConnectionMap.remove(request);
                }
                connection.disconnect();
                connection = null;
            }
        }
        return request.getResult();
    }

    @Override
    public void cancel(HootRequest request) {
        synchronized (mConnectionMap) {
            HttpURLConnection connection = mConnectionMap.get(request);
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    // -------------------------------------------------------------------------
    // END OF PUBLIC INTERFACE
    // -------------------------------------------------------------------------
    private int mTimeout = 15 * 1000;

    private X509HostnameVerifier mSSLHostNameVerifier;

    private enum StreamingMode {
        CHUNKED, FIXED
    };

    private void setMultipartEntity(HootRequest request, HttpURLConnection connection) throws IOException {
        OutputStream os = null;
        MultipartEntity entity = request.getMultipartEntity();
        try {
            connection.setRequestProperty(entity.getContentType().getName(), entity.getContentType().getValue());

            os = new BufferedOutputStream(connection.getOutputStream(),
                    (int) request.getMultipartEntity().getContentLength());
            entity.writeTo(os);
        } finally {
            if (os != null) {
                try {
                    os.flush();
                    os.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void setRequestData(HootRequest request, HttpURLConnection connection) throws IOException {
        OutputStream os = null;
        try {
            os = new BufferedOutputStream(connection.getOutputStream());
            IOUtils.copy(request.getData(), os);
        } finally {
            if (os != null) {
                try {
                    os.flush();
                    os.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void setRequestHeaders(HootRequest request, HttpURLConnection connection) {
        if (request.getHeaders() != null) {
            Iterator<Object> iter = request.getHeaders().keySet().iterator();
            while (iter.hasNext()) {
                String name = (String) iter.next();
                connection.addRequestProperty(name, request.getHeaders().getProperty(name));
            }
        }

        if (request.getHoot().isBasicAuth()) {
            connection.addRequestProperty("Authorization", request.getHoot().calculateBasicAuthHeader());
        }
    }

    private void setRequestMethod(HootRequest request, HttpURLConnection connection) throws ProtocolException {
        switch (request.getOperation()) {
        case DELETE:
            connection.setRequestMethod("DELETE");
            break;
        case POST:
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
            break;
        case PUT:
            connection.setRequestMethod("PUT");
            connection.setDoOutput(true);
            break;
        case HEAD:
            connection.setRequestMethod("HEAD");
            break;
        default:
            connection.setRequestMethod("GET");
            break;
        }

        if (mStreamingMode == StreamingMode.CHUNKED) {
            connection.setChunkedStreamingMode(0);
        }

        if (request.getOperation() == HootRequest.Operation.PATCH) {
            request.getHeaders().put("X-HTTP-Method-Override", "PATCH");
        }

        // TODO handle other OP types
    }

    private Map<HootRequest, HttpURLConnection> mConnectionMap = new HashMap<HootRequest, HttpURLConnection>();

    private static final String TAG = HootTransportHttpUrlConnection.class.getSimpleName();
    private StreamingMode mStreamingMode = StreamingMode.CHUNKED;

}