/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * 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 android.webkit.cts;

import libcore.io.Base64;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.RequestLine;
import org.apache.http.StatusLine;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.impl.cookie.DateUtils;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;

import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import android.webkit.MimeTypeMap;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509TrustManager;

/**
 * Simple http test server for testing webkit client functionality.
 */
public class CtsTestServer {
    private static final String TAG = "CtsTestServer";

    public static final String FAVICON_PATH = "/favicon.ico";
    public static final String USERAGENT_PATH = "/useragent.html";

    public static final String TEST_DOWNLOAD_PATH = "/download.html";
    private static final String DOWNLOAD_ID_PARAMETER = "downloadId";
    private static final String NUM_BYTES_PARAMETER = "numBytes";

    private static final String ASSET_PREFIX = "/assets/";
    private static final String RAW_PREFIX = "raw/";
    private static final String FAVICON_ASSET_PATH = ASSET_PREFIX + "webkit/favicon.png";
    private static final String APPCACHE_PATH = "/appcache.html";
    private static final String APPCACHE_MANIFEST_PATH = "/appcache.manifest";
    private static final String REDIRECT_PREFIX = "/redirect";
    private static final String QUERY_REDIRECT_PATH = "/alt_redirect";
    private static final String DELAY_PREFIX = "/delayed";
    private static final String BINARY_PREFIX = "/binary";
    private static final String SET_COOKIE_PREFIX = "/setcookie";
    private static final String COOKIE_PREFIX = "/cookie";
    private static final String LINKED_SCRIPT_PREFIX = "/linkedscriptprefix";
    private static final String AUTH_PREFIX = "/auth";
    private static final String SHUTDOWN_PREFIX = "/shutdown";
    public static final String NOLENGTH_POSTFIX = "nolength";
    private static final int DELAY_MILLIS = 2000;

    public static final String AUTH_REALM = "Android CTS";
    public static final String AUTH_USER = "cts";
    public static final String AUTH_PASS = "secret";
    // base64 encoded credentials "cts:secret" used for basic authentication
    public static final String AUTH_CREDENTIALS = "Basic Y3RzOnNlY3JldA==";

    public static final String MESSAGE_401 = "401 unauthorized";
    public static final String MESSAGE_403 = "403 forbidden";
    public static final String MESSAGE_404 = "404 not found";

    public enum SslMode {
        INSECURE,
        NO_CLIENT_AUTH,
        WANTS_CLIENT_AUTH,
        NEEDS_CLIENT_AUTH,
    }

    private static Hashtable<Integer, String> sReasons;

    private ServerThread mServerThread;
    private String mServerUri;
    private AssetManager mAssets;
    private Context mContext;
    private Resources mResources;
    private SslMode mSsl;
    private MimeTypeMap mMap;
    private Vector<String> mQueries;
    private ArrayList<HttpEntity> mRequestEntities;
    private final Map<String, HttpRequest> mLastRequestMap = new HashMap<String, HttpRequest>();
    private long mDocValidity;
    private long mDocAge;
    private X509TrustManager mTrustManager;

    /**
     * Create and start a local HTTP server instance.
     * @param context The application context to use for fetching assets.
     * @throws IOException
     */
    public CtsTestServer(Context context) throws Exception {
        this(context, false);
    }

    public static String getReasonString(int status) {
        if (sReasons == null) {
            sReasons = new Hashtable<Integer, String>();
            sReasons.put(HttpStatus.SC_UNAUTHORIZED, "Unauthorized");
            sReasons.put(HttpStatus.SC_NOT_FOUND, "Not Found");
            sReasons.put(HttpStatus.SC_FORBIDDEN, "Forbidden");
            sReasons.put(HttpStatus.SC_MOVED_TEMPORARILY, "Moved Temporarily");
        }
        return sReasons.get(status);
    }

    /**
     * Create and start a local HTTP server instance.
     * @param context The application context to use for fetching assets.
     * @param ssl True if the server should be using secure sockets.
     * @throws Exception
     */
    public CtsTestServer(Context context, boolean ssl) throws Exception {
        this(context, ssl ? SslMode.NO_CLIENT_AUTH : SslMode.INSECURE);
    }

    /**
     * Create and start a local HTTP server instance.
     * @param context The application context to use for fetching assets.
     * @param sslMode Whether to use SSL, and if so, what client auth (if any) to use.
     * @throws Exception
     */
    public CtsTestServer(Context context, SslMode sslMode) throws Exception {
        this(context, sslMode, new CtsTrustManager());
    }

    /**
     * Create and start a local HTTP server instance.
     * @param context The application context to use for fetching assets.
     * @param sslMode Whether to use SSL, and if so, what client auth (if any) to use.
     * @param trustManager the trustManager
     * @throws Exception
     */
    public CtsTestServer(Context context, SslMode sslMode, X509TrustManager trustManager)
            throws Exception {
        mContext = context;
        mAssets = mContext.getAssets();
        mResources = mContext.getResources();
        mSsl = sslMode;
        mRequestEntities = new ArrayList<HttpEntity>();
        mMap = MimeTypeMap.getSingleton();
        mQueries = new Vector<String>();
        mTrustManager = trustManager;
        mServerThread = new ServerThread(this, mSsl);
        if (mSsl == SslMode.INSECURE) {
            mServerUri = "http:";
        } else {
            mServerUri = "https:";
        }
        mServerUri += "//localhost:" + mServerThread.mSocket.getLocalPort();
        mServerThread.start();
    }

    /**
     * Terminate the http server.
     */
    public void shutdown() {
        try {
            // Avoid a deadlock between two threads where one is trying to call
            // close() and the other one is calling accept() by sending a GET
            // request for shutdown and having the server's one thread
            // sequentially call accept() and close().
            URL url = new URL(mServerUri + SHUTDOWN_PREFIX);
            URLConnection connection = openConnection(url);
            connection.connect();

            // Read the input from the stream to send the request.
            InputStream is = connection.getInputStream();
            is.close();

            // Block until the server thread is done shutting down.
            mServerThread.join();

        } catch (MalformedURLException e) {
            throw new IllegalStateException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e);
        } catch (KeyManagementException e) {
            throw new IllegalStateException(e);
        }
    }

    private URLConnection openConnection(URL url)
            throws IOException, NoSuchAlgorithmException, KeyManagementException {
        if (mSsl == SslMode.INSECURE) {
            return url.openConnection();
        } else {
            // Install hostname verifiers and trust managers that don't do
            // anything in order to get around the client not trusting
            // the test server due to a lack of certificates.

            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
            connection.setHostnameVerifier(new CtsHostnameVerifier());

            SSLContext context = SSLContext.getInstance("TLS");
            try {
                context.init(ServerThread.getKeyManagers(), getTrustManagers(), null);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            connection.setSSLSocketFactory(context.getSocketFactory());

            return connection;
        }
    }

    /**
     * {@link X509TrustManager} that trusts everybody. This is used so that
     * the client calling {@link CtsTestServer#shutdown()} can issue a request
     * for shutdown by blindly trusting the {@link CtsTestServer}'s
     * credentials.
     */
    private static class CtsTrustManager implements X509TrustManager {
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
            // Trust the CtSTestServer's client...
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) {
            // Trust the CtSTestServer...
        }

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }

    /**
     * @return a trust manager array of size 1.
     */
    private X509TrustManager[] getTrustManagers() {
        return new X509TrustManager[] { mTrustManager };
    }

    /**
     * {@link HostnameVerifier} that verifies everybody. This permits
     * the client to trust the web server and call
     * {@link CtsTestServer#shutdown()}.
     */
    private static class CtsHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    /**
     * Return the URI that points to the server root.
     */
    public String getBaseUri() {
        return mServerUri;
    }

    /**
     * Return the absolute URL that refers to the given asset.
     * @param path The path of the asset. See {@link AssetManager#open(String)}
     */
    public String getAssetUrl(String path) {
        StringBuilder sb = new StringBuilder(getBaseUri());
        sb.append(ASSET_PREFIX);
        sb.append(path);
        return sb.toString();
    }

    /**
     * Return an artificially delayed absolute URL that refers to the given asset. This can be
     * used to emulate a slow HTTP server or connection.
     * @param path The path of the asset. See {@link AssetManager#open(String)}
     */
    public String getDelayedAssetUrl(String path) {
        return getDelayedAssetUrl(path, DELAY_MILLIS);
    }

    /**
     * Return an artificially delayed absolute URL that refers to the given asset. This can be
     * used to emulate a slow HTTP server or connection.
     * @param path The path of the asset. See {@link AssetManager#open(String)}
     * @param delayMs The number of milliseconds to delay the request
     */
    public String getDelayedAssetUrl(String path, int delayMs) {
        StringBuilder sb = new StringBuilder(getBaseUri());
        sb.append(DELAY_PREFIX);
        sb.append("/");
        sb.append(delayMs);
        sb.append(ASSET_PREFIX);
        sb.append(path);
        return sb.toString();
    }

    /**
     * Return an absolute URL that refers to the given asset and is protected by
     * HTTP authentication.
     * @param path The path of the asset. See {@link AssetManager#open(String)}
     */
    public String getAuthAssetUrl(String path) {
        StringBuilder sb = new StringBuilder(getBaseUri());
        sb.append(AUTH_PREFIX);
        sb.append(ASSET_PREFIX);
        sb.append(path);
        return sb.toString();
    }

    /**
     * Return an absolute URL that indirectly refers to the given asset.
     * When a client fetches this URL, the server will respond with a temporary redirect (302)
     * referring to the absolute URL of the given asset.
     * @param path The path of the asset. See {@link AssetManager#open(String)}
     */
    public String getRedirectingAssetUrl(String path) {
        return getRedirectingAssetUrl(path, 1);
    }

    /**
     * Return an absolute URL that indirectly refers to the given asset.
     * When a client fetches this URL, the server will respond with a temporary redirect (302)
     * referring to the absolute URL of the given asset.
     * @param path The path of the asset. See {@link AssetManager#open(String)}
     * @param numRedirects The number of redirects required to reach the given asset.
     */
    public String getRedirectingAssetUrl(String path, int numRedirects) {
        StringBuilder sb = new StringBuilder(getBaseUri());
        for (int i = 0; i < numRedirects; i++) {
            sb.append(REDIRECT_PREFIX);
        }
        sb.append(ASSET_PREFIX);
        sb.append(path);
        return sb.toString();
    }

    /**
     * Return an absolute URL that indirectly refers to the given asset, without having
     * the destination path be part of the redirecting path.
     * When a client fetches this URL, the server will respond with a temporary redirect (302)
     * referring to the absolute URL of the given asset.
     * @param path The path of the asset. See {@link AssetManager#open(String)}
     */
    public String getQueryRedirectingAssetUrl(String path) {
        StringBuilder sb = new StringBuilder(getBaseUri());
        sb.append(QUERY_REDIRECT_PATH);
        sb.append("?dest=");
        try {
            sb.append(URLEncoder.encode(getAssetUrl(path), "UTF-8"));
        } catch (UnsupportedEncodingException e) {
        }
        return sb.toString();
    }

    /**
     * getSetCookieUrl returns a URL that attempts to set the cookie
     * "key=value" when fetched.
     * @param path a suffix to disambiguate mulitple Cookie URLs.
     * @param key the key of the cookie.
     * @return the url for a page that attempts to set the cookie.
     */
    public String getSetCookieUrl(String path, String key, String value) {
        StringBuilder sb = new StringBuilder(getBaseUri());
        sb.append(SET_COOKIE_PREFIX);
        sb.append(path);
        sb.append("?key=");
        sb.append(key);
        sb.append("&value=");
        sb.append(value);
        return sb.toString();
    }

    /**
     * getLinkedScriptUrl returns a URL for a page with a script tag where
     * src equals the URL passed in.
     * @param path a suffix to disambiguate mulitple Linked Script URLs.
     * @param url the src of the script tag.
     * @return the url for the page with the script link in.
     */
    public String getLinkedScriptUrl(String path, String url) {
        StringBuilder sb = new StringBuilder(getBaseUri());
        sb.append(LINKED_SCRIPT_PREFIX);
        sb.append(path);
        sb.append("?url=");
        try {
            sb.append(URLEncoder.encode(url, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
        }
        return sb.toString();
    }

    public String getBinaryUrl(String mimeType, int contentLength) {
        StringBuilder sb = new StringBuilder(getBaseUri());
        sb.append(BINARY_PREFIX);
        sb.append("?type=");
        sb.append(mimeType);
        sb.append("&length=");
        sb.append(contentLength);
        return sb.toString();
    }

    public String getCookieUrl(String path) {
        StringBuilder sb = new StringBuilder(getBaseUri());
        sb.append(COOKIE_PREFIX);
        sb.append("/");
        sb.append(path);
        return sb.toString();
    }

    public String getUserAgentUrl() {
        StringBuilder sb = new StringBuilder(getBaseUri());
        sb.append(USERAGENT_PATH);
        return sb.toString();
    }

    public String getAppCacheUrl() {
        StringBuilder sb = new StringBuilder(getBaseUri());
        sb.append(APPCACHE_PATH);
        return sb.toString();
    }

    /**
     * @param downloadId used to differentiate the files created for each test
     * @param numBytes of the content that the CTS server should send back
     * @return url to get the file from
     */
    public String getTestDownloadUrl(String downloadId, int numBytes) {
        return Uri.parse(getBaseUri())
                .buildUpon()
                .path(TEST_DOWNLOAD_PATH)
                .appendQueryParameter(DOWNLOAD_ID_PARAMETER, downloadId)
                .appendQueryParameter(NUM_BYTES_PARAMETER, Integer.toString(numBytes))
                .build()
                .toString();
    }

    /**
     * Returns true if the resource identified by url has been requested since
     * the server was started or the last call to resetRequestState().
     *
     * @param url The relative url to check whether it has been requested.
     */
    public synchronized boolean wasResourceRequested(String url) {
        Iterator<String> it = mQueries.iterator();
        while (it.hasNext()) {
            String request = it.next();
            if (request.endsWith(url)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns all received request entities since the last reset.
     */
    public synchronized ArrayList<HttpEntity> getRequestEntities() {
        return mRequestEntities;
    }

    public synchronized int getRequestCount() {
        return mQueries.size();
    }

    /**
     * Set the validity of any future responses in milliseconds. If this is set to a non-zero
     * value, the server will include a "Expires" header.
     * @param timeMillis The time, in milliseconds, for which any future response will be valid.
     */
    public synchronized void setDocumentValidity(long timeMillis) {
        mDocValidity = timeMillis;
    }

    /**
     * Set the age of documents served. If this is set to a non-zero value, the server will include
     * a "Last-Modified" header calculated from the value.
     * @param timeMillis The age, in milliseconds, of any document served in the future.
     */
    public synchronized void setDocumentAge(long timeMillis) {
        mDocAge = timeMillis;
    }

    /**
     * Resets the saved requests and request counts.
     */
    public synchronized void resetRequestState() {

        mQueries.clear();
        mRequestEntities = new ArrayList<HttpEntity>();
    }

    /**
     * Returns the last HttpRequest at this path. Can return null if it is never requested.
     */
    public synchronized HttpRequest getLastRequest(String requestPath) {
        String relativeUrl = getRelativeUrl(requestPath);
        if (!mLastRequestMap.containsKey(relativeUrl))
            return null;
        return mLastRequestMap.get(relativeUrl);
    }
    /**
     * Hook for adding stuffs for HTTP POST. Default implementation does nothing.
     * @return null to use the default response mechanism of sending the requested uri as it is.
     *         Otherwise, the whole response should be handled inside onPost.
     */
    protected HttpResponse onPost(HttpRequest request) throws Exception {
        return null;
    }

    /**
     * Return the relative URL that refers to the given asset.
     * @param path The path of the asset. See {@link AssetManager#open(String)}
     */
    private String getRelativeUrl(String path) {
        StringBuilder sb = new StringBuilder(ASSET_PREFIX);
        sb.append(path);
        return sb.toString();
    }

    /**
     * Generate a response to the given request.
     * @throws InterruptedException
     * @throws IOException
     */
    private HttpResponse getResponse(HttpRequest request) throws Exception {
        RequestLine requestLine = request.getRequestLine();
        HttpResponse response = null;
        String uriString = requestLine.getUri();
        Log.i(TAG, requestLine.getMethod() + ": " + uriString);

        synchronized (this) {
            mQueries.add(uriString);
            mLastRequestMap.put(uriString, request);
            if (request instanceof HttpEntityEnclosingRequest) {
                mRequestEntities.add(((HttpEntityEnclosingRequest)request).getEntity());
            }
        }

        if (requestLine.getMethod().equals("POST")) {
            HttpResponse responseOnPost = onPost(request);
            if (responseOnPost != null) {
                return responseOnPost;
            }
        }

        URI uri = URI.create(uriString);
        String path = uri.getPath();
        String query = uri.getQuery();
        if (path.equals(FAVICON_PATH)) {
            path = FAVICON_ASSET_PATH;
        }
        if (path.startsWith(DELAY_PREFIX)) {
            String delayPath = path.substring(DELAY_PREFIX.length() + 1);
            String delay = delayPath.substring(0, delayPath.indexOf('/'));
            path = delayPath.substring(delay.length());
            try {
                Thread.sleep(Integer.valueOf(delay));
            } catch (InterruptedException ignored) {
                // ignore
            }
        }
        if (path.startsWith(AUTH_PREFIX)) {
            // authentication required
            Header[] auth = request.getHeaders("Authorization");
            if ((auth.length > 0 && auth[0].getValue().equals(AUTH_CREDENTIALS))
                // This is a hack to make sure that loads to this url's will always
                // ask for authentication. This is what the test expects.
                 && !path.endsWith("embedded_image.html")) {
                // fall through and serve content
                path = path.substring(AUTH_PREFIX.length());
            } else {
                // request authorization
                response = createResponse(HttpStatus.SC_UNAUTHORIZED);
                response.addHeader("WWW-Authenticate", "Basic realm=\"" + AUTH_REALM + "\"");
            }
        }
        if (path.startsWith(BINARY_PREFIX)) {
            List <NameValuePair> args = URLEncodedUtils.parse(uri, "UTF-8");
            int length = 0;
            String mimeType = null;
            try {
                for (NameValuePair pair : args) {
                    String name = pair.getName();
                    if (name.equals("type")) {
                        mimeType = pair.getValue();
                    } else if (name.equals("length")) {
                        length = Integer.parseInt(pair.getValue());
                    }
                }
                if (length > 0 && mimeType != null) {
                    ByteArrayEntity entity = new ByteArrayEntity(new byte[length]);
                    entity.setContentType(mimeType);
                    response = createResponse(HttpStatus.SC_OK);
                    response.setEntity(entity);
                    response.addHeader("Content-Disposition", "attachment; filename=test.bin");
                    response.addHeader("Content-Type", mimeType);
                    response.addHeader("Content-Length", "" + length);
                } else {
                    // fall through, return 404 at the end
                }
            } catch (Exception e) {
                // fall through, return 404 at the end
                Log.w(TAG, e);
            }
        } else if (path.startsWith(ASSET_PREFIX)) {
            path = path.substring(ASSET_PREFIX.length());
            // request for an asset file
            try {
                InputStream in;
                if (path.startsWith(RAW_PREFIX)) {
                  String resourceName = path.substring(RAW_PREFIX.length());
                  int id = mResources.getIdentifier(resourceName, "raw", mContext.getPackageName());
                  if (id == 0) {
                    Log.w(TAG, "Can't find raw resource " + resourceName);
                    throw new IOException();
                  }
                  in = mResources.openRawResource(id);
                } else {
                  in = mAssets.open(path);
                }
                response = createResponse(HttpStatus.SC_OK);
                InputStreamEntity entity = new InputStreamEntity(in, in.available());
                String mimeType =
                    mMap.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(path));
                if (mimeType == null) {
                    mimeType = "text/html";
                }
                entity.setContentType(mimeType);
                response.setEntity(entity);
                if (query == null || !query.contains(NOLENGTH_POSTFIX)) {
                    response.setHeader("Content-Length", "" + entity.getContentLength());
                }
            } catch (IOException e) {
                response = null;
                // fall through, return 404 at the end
            }
        } else if (path.startsWith(REDIRECT_PREFIX)) {
            response = createResponse(HttpStatus.SC_MOVED_TEMPORARILY);
            String location = getBaseUri() + path.substring(REDIRECT_PREFIX.length());
            Log.i(TAG, "Redirecting to: " + location);
            response.addHeader("Location", location);
        } else if (path.equals(QUERY_REDIRECT_PATH)) {
            String location = Uri.parse(uriString).getQueryParameter("dest");
            if (location != null) {
                Log.i(TAG, "Redirecting to: " + location);
                response = createResponse(HttpStatus.SC_MOVED_TEMPORARILY);
                response.addHeader("Location", location);
            }
        } else if (path.startsWith(COOKIE_PREFIX)) {
            /*
             * Return a page with a title containing a list of all incoming cookies,
             * separated by '|' characters. If a numeric 'count' value is passed in a cookie,
             * return a cookie with the value incremented by 1. Otherwise, return a cookie
             * setting 'count' to 0.
             */
            response = createResponse(HttpStatus.SC_OK);
            Header[] cookies = request.getHeaders("Cookie");
            Pattern p = Pattern.compile("count=(\\d+)");
            StringBuilder cookieString = new StringBuilder(100);
            cookieString.append(cookies.length);
            int count = 0;
            for (Header cookie : cookies) {
                cookieString.append("|");
                String value = cookie.getValue();
                cookieString.append(value);
                Matcher m = p.matcher(value);
                if (m.find()) {
                    count = Integer.parseInt(m.group(1)) + 1;
                }
            }

            response.addHeader("Set-Cookie", "count=" + count + "; path=" + COOKIE_PREFIX);
            response.setEntity(createPage(cookieString.toString(), cookieString.toString()));
        } else if (path.startsWith(SET_COOKIE_PREFIX)) {
            response = createResponse(HttpStatus.SC_OK);
            Uri parsedUri = Uri.parse(uriString);
            String key = parsedUri.getQueryParameter("key");
            String value = parsedUri.getQueryParameter("value");
            String cookie = key + "=" + value;
            response.addHeader("Set-Cookie", cookie);
            response.setEntity(createPage(cookie, cookie));
        } else if (path.startsWith(LINKED_SCRIPT_PREFIX)) {
            response = createResponse(HttpStatus.SC_OK);
            String src = Uri.parse(uriString).getQueryParameter("url");
            String scriptTag = "<script src=\"" + src + "\"></script>";
            response.setEntity(createPage("LinkedScript", scriptTag));
        } else if (path.equals(USERAGENT_PATH)) {
            response = createResponse(HttpStatus.SC_OK);
            Header agentHeader = request.getFirstHeader("User-Agent");
            String agent = "";
            if (agentHeader != null) {
                agent = agentHeader.getValue();
            }
            response.setEntity(createPage(agent, agent));
        } else if (path.equals(TEST_DOWNLOAD_PATH)) {
            response = createTestDownloadResponse(Uri.parse(uriString));
        } else if (path.equals(SHUTDOWN_PREFIX)) {
            response = createResponse(HttpStatus.SC_OK);
            // We cannot close the socket here, because we need to respond.
            // Status must be set to OK, or else the test will fail due to
            // a RunTimeException.
        } else if (path.equals(APPCACHE_PATH)) {
            response = createResponse(HttpStatus.SC_OK);
            response.setEntity(createEntity("<!DOCTYPE HTML>" +
                    "<html manifest=\"appcache.manifest\">" +
                    "  <head>" +
                    "    <title>Waiting</title>" +
                    "    <script>" +
                    "      function updateTitle(x) { document.title = x; }" +
                    "      window.applicationCache.onnoupdate = " +
                    "          function() { updateTitle(\"onnoupdate Callback\"); };" +
                    "      window.applicationCache.oncached = " +
                    "          function() { updateTitle(\"oncached Callback\"); };" +
                    "      window.applicationCache.onupdateready = " +
                    "          function() { updateTitle(\"onupdateready Callback\"); };" +
                    "      window.applicationCache.onobsolete = " +
                    "          function() { updateTitle(\"onobsolete Callback\"); };" +
                    "      window.applicationCache.onerror = " +
                    "          function() { updateTitle(\"onerror Callback\"); };" +
                    "    </script>" +
                    "  </head>" +
                    "  <body onload=\"updateTitle('Loaded');\">AppCache test</body>" +
                    "</html>"));
        } else if (path.equals(APPCACHE_MANIFEST_PATH)) {
            response = createResponse(HttpStatus.SC_OK);
            try {
                StringEntity entity = new StringEntity("CACHE MANIFEST");
                // This entity property is not used when constructing the response, (See
                // AbstractMessageWriter.write(), which is called by
                // AbstractHttpServerConnection.sendResponseHeader()) so we have to set this header
                // manually.
                // TODO: Should we do this for all responses from this server?
                entity.setContentType("text/cache-manifest");
                response.setEntity(entity);
                response.setHeader("Content-Type", "text/cache-manifest");
            } catch (UnsupportedEncodingException e) {
                Log.w(TAG, "Unexpected UnsupportedEncodingException");
            }
        }
        if (response == null) {
            response = createResponse(HttpStatus.SC_NOT_FOUND);
        }
        StatusLine sl = response.getStatusLine();
        Log.i(TAG, sl.getStatusCode() + "(" + sl.getReasonPhrase() + ")");
        setDateHeaders(response);
        return response;
    }

    private void setDateHeaders(HttpResponse response) {
        long time = System.currentTimeMillis();
        synchronized (this) {
            if (mDocValidity != 0) {
                String expires = DateUtils.formatDate(new Date(time + mDocValidity),
                        DateUtils.PATTERN_RFC1123);
                response.addHeader("Expires", expires);
            }
            if (mDocAge != 0) {
                String modified = DateUtils.formatDate(new Date(time - mDocAge),
                        DateUtils.PATTERN_RFC1123);
                response.addHeader("Last-Modified", modified);
            }
        }
        response.addHeader("Date", DateUtils.formatDate(new Date(), DateUtils.PATTERN_RFC1123));
    }

    /**
     * Create an empty response with the given status.
     */
    private static HttpResponse createResponse(int status) {
        HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_0, status, null);

        // Fill in error reason. Avoid use of the ReasonPhraseCatalog, which is Locale-dependent.
        String reason = getReasonString(status);
        if (reason != null) {
            response.setEntity(createPage(reason, reason));
        }
        return response;
    }

    /**
     * Create a string entity for the given content.
     */
    private static StringEntity createEntity(String content) {
        try {
            StringEntity entity = new StringEntity(content);
            entity.setContentType("text/html");
            return entity;
        } catch (UnsupportedEncodingException e) {
            Log.w(TAG, e);
        }
        return null;
    }

    /**
     * Create a string entity for a bare bones html page with provided title and body.
     */
    private static StringEntity createPage(String title, String bodyContent) {
        return createEntity("<html><head><title>" + title + "</title></head>" +
                "<body>" + bodyContent + "</body></html>");
    }

    private static HttpResponse createTestDownloadResponse(Uri uri) throws IOException {
        String downloadId = uri.getQueryParameter(DOWNLOAD_ID_PARAMETER);
        int numBytes = uri.getQueryParameter(NUM_BYTES_PARAMETER) != null
                ? Integer.parseInt(uri.getQueryParameter(NUM_BYTES_PARAMETER))
                : 0;
        HttpResponse response = createResponse(HttpStatus.SC_OK);
        response.setHeader("Content-Length", Integer.toString(numBytes));
        response.setEntity(createFileEntity(downloadId, numBytes));
        return response;
    }

    private static FileEntity createFileEntity(String downloadId, int numBytes) throws IOException {
        String storageState = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equalsIgnoreCase(storageState)) {
            File storageDir = Environment.getExternalStorageDirectory();
            File file = new File(storageDir, downloadId + ".bin");
            BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(file));
            byte data[] = new byte[1024];
            for (int i = 0; i < data.length; i++) {
                data[i] = 1;
            }
            try {
                for (int i = 0; i < numBytes / data.length; i++) {
                    stream.write(data);
                }
                stream.write(data, 0, numBytes % data.length);
                stream.flush();
            } finally {
                stream.close();
            }
            return new FileEntity(file, "application/octet-stream");
        } else {
            throw new IllegalStateException("External storage must be mounted for this test!");
        }
    }

    protected DefaultHttpServerConnection createHttpServerConnection() {
        return new DefaultHttpServerConnection();
    }

    private static class ServerThread extends Thread {
        private CtsTestServer mServer;
        private ServerSocket mSocket;
        private SslMode mSsl;
        private boolean mIsCancelled;
        private SSLContext mSslContext;
        private ExecutorService mExecutorService = Executors.newFixedThreadPool(20);

        /**
         * Defines the keystore contents for the server, BKS version. Holds just a
         * single self-generated key. The subject name is "Test Server".
         */
        private static final String SERVER_KEYS_BKS =
            "AAAAAQAAABQDkebzoP1XwqyWKRCJEpn/t8dqIQAABDkEAAVteWtleQAAARpYl20nAAAAAQAFWC41" +
            "MDkAAAJNMIICSTCCAbKgAwIBAgIESEfU1jANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQGEwJVUzET" +
            "MBEGA1UECBMKQ2FsaWZvcm5pYTEMMAoGA1UEBxMDTVRWMQ8wDQYDVQQKEwZHb29nbGUxEDAOBgNV" +
            "BAsTB0FuZHJvaWQxFDASBgNVBAMTC1Rlc3QgU2VydmVyMB4XDTA4MDYwNTExNTgxNFoXDTA4MDkw" +
            "MzExNTgxNFowaTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExDDAKBgNVBAcTA01U" +
            "VjEPMA0GA1UEChMGR29vZ2xlMRAwDgYDVQQLEwdBbmRyb2lkMRQwEgYDVQQDEwtUZXN0IFNlcnZl" +
            "cjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0LIdKaIr9/vsTq8BZlA3R+NFWRaH4lGsTAQy" +
            "DPMF9ZqEDOaL6DJuu0colSBBBQ85hQTPa9m9nyJoN3pEi1hgamqOvQIWcXBk+SOpUGRZZFXwniJV" +
            "zDKU5nE9MYgn2B9AoiH3CSuMz6HRqgVaqtppIe1jhukMc/kHVJvlKRNy9XMCAwEAATANBgkqhkiG" +
            "9w0BAQUFAAOBgQC7yBmJ9O/eWDGtSH9BH0R3dh2NdST3W9hNZ8hIa8U8klhNHbUCSSktZmZkvbPU" +
            "hse5LI3dh6RyNDuqDrbYwcqzKbFJaq/jX9kCoeb3vgbQElMRX8D2ID1vRjxwlALFISrtaN4VpWzV" +
            "yeoHPW4xldeZmoVtjn8zXNzQhLuBqX2MmAAAAqwAAAAUvkUScfw9yCSmALruURNmtBai7kQAAAZx" +
            "4Jmijxs/l8EBaleaUru6EOPioWkUAEVWCxjM/TxbGHOi2VMsQWqRr/DZ3wsDmtQgw3QTrUK666sR" +
            "MBnbqdnyCyvM1J2V1xxLXPUeRBmR2CXorYGF9Dye7NkgVdfA+9g9L/0Au6Ugn+2Cj5leoIgkgApN" +
            "vuEcZegFlNOUPVEs3SlBgUF1BY6OBM0UBHTPwGGxFBBcetcuMRbUnu65vyDG0pslT59qpaR0TMVs" +
            "P+tcheEzhyjbfM32/vwhnL9dBEgM8qMt0sqF6itNOQU/F4WGkK2Cm2v4CYEyKYw325fEhzTXosck" +
            "MhbqmcyLab8EPceWF3dweoUT76+jEZx8lV2dapR+CmczQI43tV9btsd1xiBbBHAKvymm9Ep9bPzM" +
            "J0MQi+OtURL9Lxke/70/MRueqbPeUlOaGvANTmXQD2OnW7PISwJ9lpeLfTG0LcqkoqkbtLKQLYHI" +
            "rQfV5j0j+wmvmpMxzjN3uvNajLa4zQ8l0Eok9SFaRr2RL0gN8Q2JegfOL4pUiHPsh64WWya2NB7f" +
            "V+1s65eA5ospXYsShRjo046QhGTmymwXXzdzuxu8IlnTEont6P4+J+GsWk6cldGbl20hctuUKzyx" +
            "OptjEPOKejV60iDCYGmHbCWAzQ8h5MILV82IclzNViZmzAapeeCnexhpXhWTs+xDEYSKEiG/camt" +
            "bhmZc3BcyVJrW23PktSfpBQ6D8ZxoMfF0L7V2GQMaUg+3r7ucrx82kpqotjv0xHghNIm95aBr1Qw" +
            "1gaEjsC/0wGmmBDg1dTDH+F1p9TInzr3EFuYD0YiQ7YlAHq3cPuyGoLXJ5dXYuSBfhDXJSeddUkl" +
            "k1ufZyOOcskeInQge7jzaRfmKg3U94r+spMEvb0AzDQVOKvjjo1ivxMSgFRZaDb/4qw=";

        private static final String PASSWORD = "android";

        /**
         * Loads a keystore from a base64-encoded String. Returns the KeyManager[]
         * for the result.
         */
        private static KeyManager[] getKeyManagers() throws Exception {
            byte[] bytes = Base64.decode(SERVER_KEYS_BKS.getBytes());
            InputStream inputStream = new ByteArrayInputStream(bytes);

            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(inputStream, PASSWORD.toCharArray());
            inputStream.close();

            String algorithm = KeyManagerFactory.getDefaultAlgorithm();
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
            keyManagerFactory.init(keyStore, PASSWORD.toCharArray());

            return keyManagerFactory.getKeyManagers();
        }


        public ServerThread(CtsTestServer server, SslMode sslMode) throws Exception {
            super("ServerThread");
            mServer = server;
            mSsl = sslMode;
            int retry = 3;
            while (true) {
                try {
                    if (mSsl == SslMode.INSECURE) {
                        mSocket = new ServerSocket(0);
                    } else {  // Use SSL
                        mSslContext = SSLContext.getInstance("TLS");
                        mSslContext.init(getKeyManagers(), mServer.getTrustManagers(), null);
                        mSocket = mSslContext.getServerSocketFactory().createServerSocket(0);
                        if (mSsl == SslMode.WANTS_CLIENT_AUTH) {
                            ((SSLServerSocket) mSocket).setWantClientAuth(true);
                        } else if (mSsl == SslMode.NEEDS_CLIENT_AUTH) {
                            ((SSLServerSocket) mSocket).setNeedClientAuth(true);
                        }
                    }
                    return;
                } catch (IOException e) {
                    Log.w(TAG, e);
                    if (--retry == 0) {
                        throw e;
                    }
                    // sleep in case server socket is still being closed
                    Thread.sleep(1000);
                }
            }
        }

        public void run() {
            while (!mIsCancelled) {
                try {
                    Socket socket = mSocket.accept();

                    DefaultHttpServerConnection conn = mServer.createHttpServerConnection();
                    HttpParams params = new BasicHttpParams();
                    params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_0);
                    conn.bind(socket, params);

                    // Determine whether we need to shutdown early before
                    // parsing the response since conn.close() will crash
                    // for SSL requests due to UnsupportedOperationException.
                    HttpRequest request = conn.receiveRequestHeader();
                    if (isShutdownRequest(request)) {
                        mIsCancelled = true;
                    }
                    if (request instanceof HttpEntityEnclosingRequest) {
                        conn.receiveRequestEntity( (HttpEntityEnclosingRequest) request);
                    }

                    mExecutorService.submit(new HandleResponseTask(conn, request));
                } catch (IOException e) {
                    // normal during shutdown, ignore
                    Log.w(TAG, e);
                } catch (HttpException e) {
                    Log.w(TAG, e);
                } catch (UnsupportedOperationException e) {
                    // DefaultHttpServerConnection's close() throws an
                    // UnsupportedOperationException.
                    Log.w(TAG, e);
                }
            }
            try {
                mExecutorService.shutdown();
                mExecutorService.awaitTermination(1L, TimeUnit.MINUTES);
                mSocket.close();
            } catch (IOException ignored) {
                // safe to ignore
            } catch (InterruptedException e) {
                Log.e(TAG, "Shutting down threads", e);
            }
        }

        private static boolean isShutdownRequest(HttpRequest request) {
            RequestLine requestLine = request.getRequestLine();
            String uriString = requestLine.getUri();
            URI uri = URI.create(uriString);
            String path = uri.getPath();
            return path.equals(SHUTDOWN_PREFIX);
        }

        private class HandleResponseTask implements Callable<Void> {

            private DefaultHttpServerConnection mConnection;

            private HttpRequest mRequest;

            public HandleResponseTask(DefaultHttpServerConnection connection,
                    HttpRequest request) {
                this.mConnection = connection;
                this.mRequest = request;
            }

            @Override
            public Void call() throws Exception {
                HttpResponse response = mServer.getResponse(mRequest);
                mConnection.sendResponseHeader(response);
                mConnection.sendResponseEntity(response);
                mConnection.close();
                return null;
            }
        }
    }
}
