/*
 *  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 org.apache.harmony.luni.internal.net.www.protocol.http;

import java.io.IOException;
import java.net.Proxy;
import java.net.URI;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.harmony.luni.util.PriviAction;

/**
 * <code>HttpConnectionManager</code> manages a pool of <code>HttpConnection</code>s
 * that are not currently in use and is used to get hold of persistent <code>HttpConnection</code>s.  
 * Clients should return an <code>HttpConnection</code> to the pool after use by calling 
 * <code>returnConnectionToPool</code>
 * 
 * Two system properties affect the behaviour of this class - <code>http.maxConnections</code>
 * and <code>http.keepAlive</code>.  <code>http.keepAlive</code> determines whether 
 * or not connections should be persisted and <code>http.maxConnections</code> 
 * determines the maximum number of connections to each individual host that 
 * should be kept in the pool.
 */
public class HttpConnectionManager {

    // The maximum number of connections to any location
    private static int maxConnections = 5;

    // Keeps connections alive if true
    private static boolean keepAlive = true;

    private static HttpConnectionManager defaultConnectionManager;
    private ConnectionPool pool = new ConnectionPool();

    /**
     * Returns the default connection manager
     */
    public static HttpConnectionManager getDefault() {
        if(defaultConnectionManager == null) {
            defaultConnectionManager = new HttpConnectionManager();
        }
        return defaultConnectionManager;
    }

    public HttpConnection getConnection(URI uri, int connectTimeout) throws IOException {
        checkSystemProperties();
        HttpConfiguration config = new HttpConfiguration(uri);
        return pool.getHttpConnection(config, connectTimeout);
    }

    public HttpConnection getConnection(URI uri, Proxy proxy, int connectTimeout) throws IOException {
        checkSystemProperties();
        HttpConfiguration config = new HttpConfiguration(uri, proxy);
        return pool.getHttpConnection(config, connectTimeout);
    }

    public void returnConnectionToPool(HttpConnection connection) {
        checkSystemProperties();
        pool.returnConnection(connection);
    }

    public int numFreeConnections() {
        return pool.numFreeConnections();
    }

    private void checkSystemProperties() {
        String httpMaxConnections =  AccessController.doPrivileged(new PriviAction<String>("http.maxConnections"));
        String httpKeepAlive = AccessController.doPrivileged(new PriviAction<String>("http.keepAlive"));
        if(httpMaxConnections != null) {
            maxConnections = Integer.parseInt(httpMaxConnections);
        }
        if(httpKeepAlive != null) {
            keepAlive = Boolean.parseBoolean(httpKeepAlive);
            if(!keepAlive) {
                pool.clear();
            }
        }
    }

    private static class ConnectionPool {

        private Map<HttpConfiguration, List<HttpConnection>> freeConnectionMap = new HashMap<HttpConfiguration, List<HttpConnection>>(); // Map of free Sockets

        public synchronized void clear() {
            for (Iterator<List<HttpConnection>> iter = freeConnectionMap.values().iterator(); iter.hasNext();) {
                List<HttpConnection> connections = iter.next();
                for (Iterator<HttpConnection> iterator = connections.iterator(); iterator.hasNext();) {
                    HttpConnection connection = iterator.next();
                    connection.closeSocketAndStreams();
                }
            }
            freeConnectionMap.clear();
        }

        public synchronized void returnConnection(HttpConnection connection) {
            // BEGIN android-note
            // Simplified the following test.
            // END android-note
            if(keepAlive && connection.isEligibleForRecycling()) {
                HttpConfiguration config = connection.getHttpConfiguration();
                List<HttpConnection> connections = freeConnectionMap.get(config);
                if(connections == null) {
                    connections = new ArrayList<HttpConnection>();
                    freeConnectionMap.put(config, connections);
                }
                if(connections.size() < HttpConnectionManager.maxConnections) {
                    if(!connections.contains(connection)) {
                        connections.add(connection);
                    }
                } else {
                    connection.closeSocketAndStreams();
                }
            } else {
                // Make sure all streams are closed etc.
                connection.closeSocketAndStreams();
            }
        }

        public synchronized HttpConnection getHttpConnection(HttpConfiguration config, int connectTimeout) throws IOException {
            List<HttpConnection> connections = freeConnectionMap.get(config);
            if(keepAlive && connections == null) {
                connections = new ArrayList<HttpConnection>();
                freeConnectionMap.put(config, connections);
            }
            if(!keepAlive || connections.isEmpty()) {
                HttpConnection connection = new HttpConnection(config, connectTimeout);
                return connection;
            } else {
                HttpConnection connection = connections.get(0);
                connections.remove(0);
                if(!connection.isStale()) {
                    SecurityManager security = System.getSecurityManager();
                    if (security != null) {
                        security.checkConnect(connection.getSocket().getInetAddress().getHostName(), connection.getSocket().getPort());
                    }
                    return connection;                 
                } else {
                    return getHttpConnection(config, connectTimeout);
                }
            }
        }

        public int numFreeConnections() {
            int numFree = 0;
            for (Iterator<List<HttpConnection>> iter = freeConnectionMap.values().iterator(); iter.hasNext();) {
                List<HttpConnection> connections = iter.next();
                numFree += connections.size();
            }
            return numFree;
        }
    }

    public void reset() {
        pool.clear();
    }

}