Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ce2ef18c authored by Maksymilian Osowski's avatar Maksymilian Osowski
Browse files

Updated FsUtils to use apache HttpClient instead of java.net UrlConnection.

It fixed sockets leaking during readDataFromUrl() invocations.

Change-Id: Ifb1aeb32fe9bb4ffa353cf521b5174a83de270db
parent 3a47e952
Loading
Loading
Loading
Loading
+99 −47
Original line number Diff line number Diff line
@@ -20,19 +20,35 @@ import android.util.Log;

import com.android.dumprendertree2.forwarder.ForwarderManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ClientConnectionManager;
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.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.util.LinkedList;
import java.util.List;

@@ -45,6 +61,29 @@ public class FsUtils {
    private static final String SCRIPT_URL = ForwarderManager.getHostSchemePort(false) +
            "WebKitTools/DumpRenderTree/android/get_layout_tests_dir_contents.php";

    private static final int HTTP_TIMEOUT_MS = 5000;

    private static HttpClient sHttpClient;

    private static HttpClient getHttpClient() {
        if (sHttpClient == null) {
            HttpParams params = new BasicHttpParams();

            SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(),
                    ForwarderManager.HTTP_PORT));
            schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(),
                    ForwarderManager.HTTPS_PORT));

            ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(params,
                    schemeRegistry);
            sHttpClient = new DefaultHttpClient(connectionManager, params);
            HttpConnectionParams.setSoTimeout(sHttpClient.getParams(), HTTP_TIMEOUT_MS);
            HttpConnectionParams.setConnectionTimeout(sHttpClient.getParams(), HTTP_TIMEOUT_MS);
        }
        return sHttpClient;
    }

    public static void writeDataToStorage(File file, byte[] bytes, boolean append) {
        Log.d(LOG_TAG, "writeDataToStorage(): " + file.getAbsolutePath());
        try {
@@ -98,32 +137,34 @@ public class FsUtils {
            return null;
        }

        HttpGet httpRequest = new HttpGet(url.toString());
        ResponseHandler<byte[]> handler = new ResponseHandler<byte[]>() {
            @Override
            public byte[] handleResponse(HttpResponse response) throws IOException {
                if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    return null;
                }
                HttpEntity entity = response.getEntity();
                return (entity == null ? null : EntityUtils.toByteArray(entity));
            }
        };

        byte[] bytes = null;
        try {
            InputStream inputStream = null;
            ByteArrayOutputStream outputStream = null;
            /**
             * TODO: Not exactly sure why some requests hang indefinitely, but adding this
             * timeout (in static getter for http client) in loop helps.
             */
            boolean timedOut;
            do {
                timedOut = false;
                try {
                URLConnection urlConnection = url.openConnection();
                inputStream = urlConnection.getInputStream();
                outputStream = new ByteArrayOutputStream();

                byte[] buffer = new byte[4096];
                int length;
                while ((length = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, length);
                }

                bytes = outputStream.toByteArray();
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                    bytes = getHttpClient().execute(httpRequest, handler);
                } catch (SocketTimeoutException e) {
                    timedOut = true;
                    Log.w(LOG_TAG, "Expected SocketTimeoutException: " + url, e);
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            }
        } catch (FileNotFoundException e) {
            Log.w(LOG_TAG, "readDataFromUrl(): File not found: " + e.getMessage());
            } while (timedOut);
        } catch (IOException e) {
            Log.e(LOG_TAG, "url=" + url, e);
        }
@@ -135,8 +176,6 @@ public class FsUtils {
            boolean mode) {
        String modeString = (mode ? "folders" : "files");

        List<String> results = new LinkedList<String>();

        URL url = null;
        try {
            url = new URL(SCRIPT_URL +
@@ -146,34 +185,47 @@ public class FsUtils {
        } catch (MalformedURLException e) {
            Log.e(LOG_TAG, "path=" + dirRelativePath + " recurse=" + recurse + " mode=" +
                    modeString, e);
            return results;
            return new LinkedList<String>();
        }

        try {
            InputStream inputStream = null;
            BufferedReader bufferedReader = null;
            try {
                URLConnection urlConnection = url.openConnection();
                inputStream = urlConnection.getInputStream();
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        HttpGet httpRequest = new HttpGet(url.toString());
        ResponseHandler<LinkedList<String>> handler = new ResponseHandler<LinkedList<String>>() {
            @Override
            public LinkedList<String> handleResponse(HttpResponse response)
                    throws IOException {
                LinkedList<String> lines = new LinkedList<String>();

                String relativePath;
                while ((relativePath = bufferedReader.readLine()) != null) {
                    results.add(relativePath);
                if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                    return lines;
                }
                HttpEntity entity = response.getEntity();
                if (entity == null) {
                    return lines;
                }

                BufferedReader reader =
                        new BufferedReader(new InputStreamReader(entity.getContent()));
                String line;
                try {
                    while ((line = reader.readLine()) != null) {
                        lines.add(line);
                    }
                } finally {
                if (inputStream != null) {
                    inputStream.close();
                    if (reader != null) {
                        reader.close();
                    }
                if (bufferedReader != null) {
                    bufferedReader.close();
                }

                return lines;
            }
        };

        try {
            return getHttpClient().execute(httpRequest, handler);
        } catch (IOException e) {
            Log.e(LOG_TAG, "path=" + dirRelativePath + " recurse=" + recurse + " mode=" +
                    modeString, e);
            Log.e(LOG_TAG, "url=" + url, e);
        }

        return results;
        return new LinkedList<String>();
    }
}
 No newline at end of file