com.duokan.reader.domain.account.oauth.evernote.TEvernoteHttpClient.java Source code

Java tutorial

Introduction

Here is the source code for com.duokan.reader.domain.account.oauth.evernote.TEvernoteHttpClient.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.duokan.reader.domain.account.oauth.evernote;

import com.evernote.thrift.transport.TTransport;
import com.evernote.thrift.transport.TTransportException;
import org.apache.http.ConnectionReuseStrategy;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * HTTP implementation of the TTransport interface modified by Evernote to work
 * on Android. Instead of caching in memory, large Thrift messages are cached on
 * disk before being sent to the Thrift server.
 */
public class TEvernoteHttpClient extends TTransport {
    /**
     * Keep requests in RAM if they are less than 512kb.
     */
    private static final int MEMORY_BUFFER_SIZE = 512 * 1024;
    private URL url_ = null;
    private String userAgent = null;
    private final DiskBackedByteStore requestBuffer_;
    private InputStream inputStream_ = null;
    private Map<String, String> customHeaders_ = null;
    private HttpRequestBase request = null;
    private HttpParams httpParameters = new BasicHttpParams();

    /**
     * Create a new TAndroidHttpClient.
     *
     * @param url       The Thrift server URL, for example, https://www.evernote.com/edam/user.
     * @param userAgent The User-Agent string to send, which should identify the
     *                  client application.
     * @param tempPath  A temp directory where Thrift messages should be cached
     *                  before they're sent.
     * @throws TTransportException If an error occurs creating the temporary
     *                             file that will be used to cache Thrift messages to disk before sending.
     */
    public TEvernoteHttpClient(String url, String userAgent, File tempDir) throws TTransportException {

        getHTTPClient();

        this.userAgent = userAgent;
        try {
            url_ = new URL(url);
            requestBuffer_ = new DiskBackedByteStore(tempDir, "http", MEMORY_BUFFER_SIZE);
        } catch (IOException iox) {
            throw new TTransportException(iox);
        }
    }

    public void setConnectTimeout(int timeout) {
        HttpConnectionParams.setConnectionTimeout(httpParameters, timeout);
    }

    public void setReadTimeout(int timeout) {
        HttpConnectionParams.setSoTimeout(httpParameters, timeout);
    }

    public void setCustomHeaders(Map<String, String> headers) {
        customHeaders_ = headers;
    }

    public void setCustomHeader(String key, String value) {
        if (customHeaders_ == null) {
            customHeaders_ = new HashMap<String, String>();
        }
        customHeaders_.put(key, value);
    }

    public void open() {
    }

    public void close() {
        if (null != inputStream_) {
            try {
                inputStream_.close();
            } catch (IOException ioe) {
                ;
            }
            inputStream_ = null;
        }

        if (mConnectionManager != null) {
            mConnectionManager.shutdown();
            mConnectionManager = null;
        }
    }

    public boolean isOpen() {
        return true;
    }

    public int read(byte[] buf, int off, int len) throws TTransportException {
        if (inputStream_ == null) {
            throw new TTransportException("Response buffer is empty, no request.");
        }

        try {
            int ret = inputStream_.read(buf, off, len);
            if (ret == -1) {
                throw new TTransportException("No more data available.");
            }
            return ret;
        } catch (IOException iox) {
            throw new TTransportException(iox);
        }
    }

    private ClientConnectionManager mConnectionManager;
    private DefaultHttpClient mHttpClient;

    private DefaultHttpClient getHTTPClient() {

        try {
            if (mConnectionManager != null) {
                mConnectionManager.closeExpiredConnections();
                mConnectionManager.closeIdleConnections(1, TimeUnit.SECONDS);
            } else {
                BasicHttpParams params = new BasicHttpParams();

                HttpConnectionParams.setConnectionTimeout(params, 10000);
                HttpConnectionParams.setSoTimeout(params, 20000);

                ConnManagerParams.setMaxTotalConnections(params, ConnManagerParams.DEFAULT_MAX_TOTAL_CONNECTIONS);
                ConnManagerParams.setTimeout(params, 10000);

                ConnPerRouteBean connPerRoute = new ConnPerRouteBean(18); // Giving 18 connections to Evernote
                ConnManagerParams.setMaxConnectionsPerRoute(params, connPerRoute);

                SchemeRegistry schemeRegistry = new SchemeRegistry();
                schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

                schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

                mConnectionManager = new ThreadSafeClientConnManager(params, schemeRegistry);
                DefaultHttpClient httpClient = new DefaultHttpClient(mConnectionManager, params);
                httpClient.setKeepAliveStrategy(new ConnectionKeepAliveStrategy() {
                    @Override
                    public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
                        return 2 * 60 * 1000; // 2 minutes in millis
                    }
                });

                httpClient.setReuseStrategy(new ConnectionReuseStrategy() {
                    @Override
                    public boolean keepAlive(HttpResponse response, HttpContext context) {
                        return true;
                    }
                });
                mHttpClient = httpClient;
            }
        } catch (Exception ex) {
            return null;
        }

        return mHttpClient;
    }

    public void write(byte[] buf, int off, int len) {
        requestBuffer_.write(buf, off, len);
    }

    public void flush() throws TTransportException {
        long timer = System.currentTimeMillis();

        HttpEntity httpEntity = null;

        // Extract request and reset buffer
        try {
            // Prepare http post request
            HttpPost request = new HttpPost(url_.toExternalForm());
            this.request = request;
            request.addHeader("Content-Type", "application/x-thrift");
            request.addHeader("Cache-Control", "no-transform");
            if (customHeaders_ != null) {
                for (Map.Entry<String, String> header : customHeaders_.entrySet()) {
                    request.addHeader(header.getKey(), header.getValue());
                }
            }
            InputStreamEntity entity = new InputStreamEntity(requestBuffer_.getInputStream(),
                    requestBuffer_.getSize());
            request.setEntity(entity);
            request.addHeader("Accept", "application/x-thrift");
            request.addHeader("User-Agent", userAgent == null ? "Java/THttpClient" : userAgent);
            request.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);

            DefaultHttpClient dHTTP = getHTTPClient();
            HttpResponse response = dHTTP.execute(request);
            httpEntity = response.getEntity();

            int responseCode = response.getStatusLine().getStatusCode();
            if (responseCode != 200) {
                if (httpEntity != null) {
                    httpEntity.consumeContent();
                }
                throw new TTransportException("HTTP Response code: " + responseCode);
            }
            // Read the responses
            requestBuffer_.reset();
            inputStream_ = response.getEntity().getContent();
        } catch (IOException iox) {
            throw new TTransportException(iox);
        } catch (Exception ex) {
            throw new TTransportException(ex);
        } finally {
            try {
                requestBuffer_.reset();
            } catch (IOException e) {
            }
            this.request = null;
        }
    }

    public void cancel() {
        try {
            if (this.request != null) {
                this.request.abort();
            }
        } catch (Exception e) {
        }
        close();
    }

    public void reset() {

    }
}