/*
 * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.net.www.http;

import java.io.InputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.util.*;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A class that implements a cache of idle Http connections for keep-alive
 *
 * @author Stephen R. Pietrowicz (NCSA)
 * @author Dave Brown
 */
public class KeepAliveCache extends ConcurrentHashMap implements Runnable {
    private static final long serialVersionUID = -2937172892064557949L;

    /* maximum # keep-alive connections to maintain at once
     * This should be 2 by the HTTP spec, but because we don't support pipe-lining
     * a larger value is more appropriate. So we now set a default of 5, and the value
     * refers to the number of idle connections per destination (in the cache) only.
     * It can be reset by setting system property "http.maxConnections".
     */
    static final int MAX_CONNECTIONS = 5;
    static int result = -1;
    static int getMaxConnections() {
        if (result == -1) {
            result = java.security.AccessController.doPrivileged(
                new sun.security.action.GetIntegerAction("http.maxConnections",
                                                         MAX_CONNECTIONS))
                .intValue();
            if (result <= 0)
                result = MAX_CONNECTIONS;
        }
            return result;
    }

    static final int LIFETIME = 5000;

    private Thread keepAliveTimer = null;

    /**
     * Constructor
     */
    public KeepAliveCache() {}

    /**
     * Register this URL and HttpClient (that supports keep-alive) with the cache
     * @param url  The URL contains info about the host and port
     * @param http The HttpClient to be cached
     */
    public synchronized void put(final URL url, Object obj, HttpClient http) {
        boolean startThread = (keepAliveTimer == null);
        if (!startThread) {
            if (!keepAliveTimer.isAlive()) {
                startThread = true;
            }
        }
        if (startThread) {
            clear();
            /* Unfortunately, we can't always believe the keep-alive timeout we got
             * back from the server.  If I'm connected through a Netscape proxy
             * to a server that sent me a keep-alive
             * time of 15 sec, the proxy unilaterally terminates my connection
             * The robustness to to get around this is in HttpClient.parseHTTP()
             */
            final KeepAliveCache cache = this;
            java.security.AccessController.doPrivileged(
                new java.security.PrivilegedAction() {
                public Object run() {
                   // We want to create the Keep-Alive-Timer in the
                    // system threadgroup
                    ThreadGroup grp = Thread.currentThread().getThreadGroup();
                    ThreadGroup parent = null;
                    while ((parent = grp.getParent()) != null) {
                        grp = parent;
                    }

                    keepAliveTimer = new Thread(grp, cache, "Keep-Alive-Timer");
                    keepAliveTimer.setDaemon(true);
                    keepAliveTimer.setPriority(Thread.MAX_PRIORITY - 2);
                    keepAliveTimer.start();
                    return null;
                }
            });
        }

        KeepAliveKey key = new KeepAliveKey(url, obj);
        ClientVector v = (ClientVector)super.get(key);

        if (v == null) {
            int keepAliveTimeout = http.getKeepAliveTimeout();
            v = new ClientVector(keepAliveTimeout > 0?
                                 keepAliveTimeout*1000 : LIFETIME);
            v.put(http);
            super.put(key, v);
        } else {
            v.put(http);
        }
    }

    /* remove an obsolete HttpClient from it's VectorCache */
    public synchronized void remove (HttpClient h, Object obj) {
        KeepAliveKey key = new KeepAliveKey(h.url, obj);
        ClientVector v = (ClientVector)super.get(key);
        if (v != null) {
            v.remove(h);
            if (v.empty()) {
                removeVector(key);
            }
        }
    }

    /* called by a clientVector thread when all it's connections have timed out
     * and that vector of connections should be removed.
     */
    synchronized void removeVector(KeepAliveKey k) {
        super.remove(k);
    }

    /**
     * Check to see if this URL has a cached HttpClient
     */
    public synchronized Object get(URL url, Object obj) {

        KeepAliveKey key = new KeepAliveKey(url, obj);
        ClientVector v = (ClientVector)super.get(key);
        if (v == null) { // nothing in cache yet
            return null;
        }
        return v.get();
    }

    /* Sleeps for an alloted timeout, then checks for timed out connections.
     * Errs on the side of caution (leave connections idle for a relatively
     * short time).
     */
    public void run() {
        int total_cache;
        do {
            try {
                Thread.sleep(LIFETIME);
            } catch (InterruptedException e) {}
            synchronized (this) {
                /* Remove all unused HttpClients.  Starting from the
                 * bottom of the stack (the least-recently used first).
                 * REMIND: It'd be nice to not remove *all* connections
                 * that aren't presently in use.  One could have been added
                 * a second ago that's still perfectly valid, and we're
                 * needlessly axing it.  But it's not clear how to do this
                 * cleanly, and doing it right may be more trouble than it's
                 * worth.
                 */

                long currentTime = System.currentTimeMillis();

                Iterator itr = keySet().iterator();
                ArrayList keysToRemove = new ArrayList();

                while (itr.hasNext()) {
                    KeepAliveKey key = (KeepAliveKey)itr.next();
                    ClientVector v = (ClientVector)get(key);
                    synchronized (v) {
                        int i;

                        for (i = 0; i < v.size(); i++) {
                            KeepAliveEntry e = (KeepAliveEntry)v.elementAt(i);
                            if ((currentTime - e.idleStartTime) > v.nap) {
                                HttpClient h = e.hc;
                                h.closeServer();
                            } else {
                                break;
                            }
                        }
                        v.subList(0, i).clear();

                        if (v.size() == 0) {
                            keysToRemove.add(key);
                        }
                    }
                }
                itr = keysToRemove.iterator();
                while (itr.hasNext()) {
                    removeVector((KeepAliveKey)itr.next());
                }
            }
        } while (size() > 0);

        return;
    }

    /*
     * Do not serialize this class!
     */
    private void writeObject(java.io.ObjectOutputStream stream)
    throws IOException {
        throw new NotSerializableException();
    }

    private void readObject(java.io.ObjectInputStream stream)
    throws IOException, ClassNotFoundException {
        throw new NotSerializableException();
    }
}

/* FILO order for recycling HttpClients, should run in a thread
 * to time them out.  If > maxConns are in use, block.
 */


class ClientVector extends java.util.Stack {
    private static final long serialVersionUID = -8680532108106489459L;

    // sleep time in milliseconds, before cache clear
    int nap;



    ClientVector (int nap) {
        this.nap = nap;
    }

    synchronized HttpClient get() {
        if (empty()) {
            return null;
        } else {
            // Loop until we find a connection that has not timed out
            HttpClient hc = null;
            long currentTime = System.currentTimeMillis();
            do {
                KeepAliveEntry e = (KeepAliveEntry)pop();
                if ((currentTime - e.idleStartTime) > nap) {
                    e.hc.closeServer();
                } else {
                    hc = e.hc;
                }
            } while ((hc== null) && (!empty()));
            return hc;
        }
    }

    /* return a still valid, unused HttpClient */
    synchronized void put(HttpClient h) {
        if (size() > KeepAliveCache.getMaxConnections()) {
            h.closeServer(); // otherwise the connection remains in limbo
        } else {
            push(new KeepAliveEntry(h, System.currentTimeMillis()));
        }
    }

    /*
     * Do not serialize this class!
     */
    private void writeObject(java.io.ObjectOutputStream stream)
    throws IOException {
        throw new NotSerializableException();
    }

    private void readObject(java.io.ObjectInputStream stream)
    throws IOException, ClassNotFoundException {
        throw new NotSerializableException();
    }
}


class KeepAliveKey {
    private String      protocol = null;
    private String      host = null;
    private int         port = 0;
    private Object      obj = null; // additional key, such as socketfactory

    /**
     * Constructor
     *
     * @param url the URL containing the protocol, host and port information
     */
    public KeepAliveKey(URL url, Object obj) {
        this.protocol = url.getProtocol();
        this.host = url.getHost();
        this.port = url.getPort();
        this.obj = obj;
    }

    /**
     * Determine whether or not two objects of this type are equal
     */
    public boolean equals(Object obj) {
        if ((obj instanceof KeepAliveKey) == false)
            return false;
        KeepAliveKey kae = (KeepAliveKey)obj;
        return host.equals(kae.host)
            && (port == kae.port)
            && protocol.equals(kae.protocol)
            && this.obj == kae.obj;
    }

    /**
     * The hashCode() for this object is the string hashCode() of
     * concatenation of the protocol, host name and port.
     */
    public int hashCode() {
        String str = protocol+host+port;
        return this.obj == null? str.hashCode() :
            str.hashCode() + this.obj.hashCode();
    }
}

class KeepAliveEntry {
    HttpClient hc;
    long idleStartTime;

    KeepAliveEntry(HttpClient hc, long idleStartTime) {
        this.hc = hc;
        this.idleStartTime = idleStartTime;
    }
}
