/*
 * Copyright (c) 1996, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package sun.rmi.transport.proxy;

import java.io.*;
import java.net.*;
import java.security.*;
import java.util.*;
import java.rmi.server.LogStream;
import java.rmi.server.RMISocketFactory;
import sun.rmi.runtime.Log;
import sun.rmi.runtime.NewThreadAction;
import sun.security.action.GetBooleanAction;
import sun.security.action.GetLongAction;

/**
 * RMIMasterSocketFactory attempts to create a socket connection to the
 * specified host using successively less efficient mechanisms
 * until one succeeds.  If the host is successfully connected to,
 * the factory for the successful mechanism is stored in an internal
 * hash table keyed by the host name, so that future attempts to
 * connect to the same host will automatically use the same
 * mechanism.
 */
public class RMIMasterSocketFactory extends RMISocketFactory {

    /** "proxy" package log level */
    static int logLevel = LogStream.parseLevel(getLogLevel());

    private static String getLogLevel() {
        return java.security.AccessController.doPrivileged(
            new sun.security.action.GetPropertyAction("sun.rmi.transport.proxy.logLevel"));
    }

    /* proxy package log */
    static final Log proxyLog =
        Log.getLog("sun.rmi.transport.tcp.proxy",
                   "transport", RMIMasterSocketFactory.logLevel);

    /** timeout for attemping direct socket connections */
    private static long connectTimeout = getConnectTimeout();

    private static long getConnectTimeout() {
        return java.security.AccessController.doPrivileged(
                new GetLongAction("sun.rmi.transport.proxy.connectTimeout",
                              15000)).longValue(); // default: 15 seconds
    }

    /** whether to fallback to HTTP on general connect failures */
    private static final boolean eagerHttpFallback =
        java.security.AccessController.doPrivileged(new GetBooleanAction(
            "sun.rmi.transport.proxy.eagerHttpFallback")).booleanValue();

    /** table of hosts successfully connected to and the factory used */
    private Hashtable successTable = new Hashtable();

    /** maximum number of hosts to remember successful connection to */
    private static final int MaxRememberedHosts = 64;

    /** list of the hosts in successTable in initial connection order */
    private Vector hostList = new Vector(MaxRememberedHosts);

    /** default factory to initally use for direct socket connection */
    protected RMISocketFactory initialFactory = new RMIDirectSocketFactory();

    /** ordered list of factories to try as alternate connection
      * mechanisms if a direct socket connections fails */
    protected Vector altFactoryList;

    /**
     * Create a RMIMasterSocketFactory object.  Establish order of
     * connection mechanisms to attempt on createSocket, if a direct
     * socket connection fails.
     */
    public RMIMasterSocketFactory() {
        altFactoryList = new Vector(2);
        boolean setFactories = false;

        try {
            String proxyHost;
            proxyHost = java.security.AccessController.doPrivileged(
                new sun.security.action.GetPropertyAction("http.proxyHost"));

            if (proxyHost == null)
                proxyHost = java.security.AccessController.doPrivileged(
                    new sun.security.action.GetPropertyAction("proxyHost"));

            Boolean tmp = java.security.AccessController.doPrivileged(
                new sun.security.action.GetBooleanAction("java.rmi.server.disableHttp"));

            if (!tmp.booleanValue() &&
                (proxyHost != null && proxyHost.length() > 0)) {
                setFactories = true;
            }
        } catch (Exception e) {
            // unable to obtain the properties, so assume default behavior.
            setFactories = true;
        }

        if (setFactories) {
            altFactoryList.addElement(new RMIHttpToPortSocketFactory());
            altFactoryList.addElement(new RMIHttpToCGISocketFactory());
        }
    }

    /**
     * Create a new client socket.  If we remember connecting to this host
     * successfully before, then use the same factory again.  Otherwise,
     * try using a direct socket connection and then the alternate factories
     * in the order specified in altFactoryList.
     */
    public Socket createSocket(String host, int port)
        throws IOException
    {
        if (proxyLog.isLoggable(Log.BRIEF)) {
            proxyLog.log(Log.BRIEF, "host: " + host + ", port: " + port);
        }

        /*
         * If we don't have any alternate factories to consult, short circuit
         * the fallback procedure and delegate to the initial factory.
         */
        if (altFactoryList.size() == 0) {
            return initialFactory.createSocket(host, port);
        }

        RMISocketFactory factory;

        /*
         * If we remember successfully connecting to this host before,
         * use the same factory.
         */
        factory = (RMISocketFactory) successTable.get(host);
        if (factory != null) {
            if (proxyLog.isLoggable(Log.BRIEF)) {
                proxyLog.log(Log.BRIEF,
                    "previously successful factory found: " + factory);
            }
            return factory.createSocket(host, port);
        }

        /*
         * Next, try a direct socket connection.  Open socket in another
         * thread and only wait for specified timeout, in case the socket
         * would otherwise spend minutes trying an unreachable host.
         */
        Socket initialSocket = null;
        Socket fallbackSocket = null;
        final AsyncConnector connector =
            new AsyncConnector(initialFactory, host, port,
                AccessController.getContext());
                // connection must be attempted with
                // this thread's access control context
        IOException initialFailure = null;

        try {
            synchronized (connector) {

                Thread t = java.security.AccessController.doPrivileged(
                    new NewThreadAction(connector, "AsyncConnector", true));
                t.start();

                try {
                    long now = System.currentTimeMillis();
                    long deadline = now + connectTimeout;
                    do {
                        connector.wait(deadline - now);
                        initialSocket = checkConnector(connector);
                        if (initialSocket != null)
                            break;
                        now = System.currentTimeMillis();
                    } while (now < deadline);
                } catch (InterruptedException e) {
                    throw new InterruptedIOException(
                        "interrupted while waiting for connector");
                }
            }

            // assume no route to host (for now) if no connection yet
            if (initialSocket == null)
                throw new NoRouteToHostException(
                    "connect timed out: " + host);

            proxyLog.log(Log.BRIEF, "direct socket connection successful");

            return initialSocket;

        } catch (UnknownHostException e) {
            initialFailure = e;
        } catch (NoRouteToHostException e) {
            initialFailure = e;
        } catch (SocketException e) {
            if (eagerHttpFallback) {
                initialFailure = e;
            } else {
                throw e;
            }
        } finally {
            if (initialFailure != null) {

                if (proxyLog.isLoggable(Log.BRIEF)) {
                    proxyLog.log(Log.BRIEF,
                        "direct socket connection failed: ", initialFailure);
                }

                // Finally, try any alternate connection mechanisms.
                for (int i = 0; i < altFactoryList.size(); ++ i) {
                    factory = (RMISocketFactory) altFactoryList.elementAt(i);
                    try {
                        if (proxyLog.isLoggable(Log.BRIEF)) {
                            proxyLog.log(Log.BRIEF,
                                "trying with factory: " + factory);
                        }

                        // For HTTP connections, the output (POST request) must
                        // be sent before we verify a successful connection.
                        // So, sacrifice a socket for the sake of testing...
                        // The following sequence should verify a successful
                        // HTTP connection if no IOException is thrown.
                        Socket testSocket = factory.createSocket(host, port);
                        InputStream in = testSocket.getInputStream();
                        int b = in.read(); // probably -1 for EOF...
                        testSocket.close();
                    } catch (IOException ex) {
                        if (proxyLog.isLoggable(Log.BRIEF)) {
                            proxyLog.log(Log.BRIEF, "factory failed: ", ex);
                        }

                        continue;
                    }
                    proxyLog.log(Log.BRIEF, "factory succeeded");

                    // factory succeeded, open new socket for caller's use
                    try {
                        fallbackSocket = factory.createSocket(host, port);
                    } catch (IOException ex) {  // if it fails 2nd time,
                    }                           // just give up
                    break;
                }
            }
        }

        synchronized (successTable) {
            try {
                // check once again to see if direct connection succeeded
                synchronized (connector) {
                    initialSocket = checkConnector(connector);
                }
                if (initialSocket != null) {
                    // if we had made another one as well, clean it up...
                    if (fallbackSocket != null)
                        fallbackSocket.close();
                    return initialSocket;
                }
                // if connector ever does get socket, it won't be used
                connector.notUsed();
            } catch (UnknownHostException e) {
                initialFailure = e;
            } catch (NoRouteToHostException e) {
                initialFailure = e;
            } catch (SocketException e) {
                if (eagerHttpFallback) {
                    initialFailure = e;
                } else {
                    throw e;
                }
            }
            // if we had found an alternate mechanism, go and use it
            if (fallbackSocket != null) {
                // remember this successful host/factory pair
                rememberFactory(host, factory);
                return fallbackSocket;
            }
            throw initialFailure;
        }
    }

    /**
     * Remember a successful factory for connecting to host.
     * Currently, excess hosts are removed from the remembered list
     * using a Least Recently Created strategy.
     */
    void rememberFactory(String host, RMISocketFactory factory) {
        synchronized (successTable) {
            while (hostList.size() >= MaxRememberedHosts) {
                successTable.remove(hostList.elementAt(0));
                hostList.removeElementAt(0);
            }
            hostList.addElement(host);
            successTable.put(host, factory);
        }
    }

    /**
     * Check if an AsyncConnector succeeded.  If not, return socket
     * given to fall back to.
     */
    Socket checkConnector(AsyncConnector connector)
        throws IOException
    {
        Exception e = connector.getException();
        if (e != null) {
            e.fillInStackTrace();
            /*
             * The AsyncConnector implementation guaranteed that the exception
             * will be either an IOException or a RuntimeException, and we can
             * only throw one of those, so convince that compiler that it must
             * be one of those.
             */
            if (e instanceof IOException) {
                throw (IOException) e;
            } else if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            } else {
                throw new Error("internal error: " +
                    "unexpected checked exception: " + e.toString());
            }
        }
        return connector.getSocket();
    }

    /**
     * Create a new server socket.
     */
    public ServerSocket createServerSocket(int port) throws IOException {
        //return new HttpAwareServerSocket(port);
        return initialFactory.createServerSocket(port);
    }


    /**
     * AsyncConnector is used by RMIMasterSocketFactory to attempt socket
     * connections on a separate thread.  This allows RMIMasterSocketFactory
     * to control how long it will wait for the connection to succeed.
     */
    private class AsyncConnector implements Runnable {

        /** what factory to use to attempt connection */
        private RMISocketFactory factory;

        /** the host to connect to */
        private String host;

        /** the port to connect to */
        private int port;

        /** access control context to attempt connection within */
        private AccessControlContext acc;

        /** exception that occurred during connection, if any */
        private Exception exception = null;

        /** the connected socket, if successful */
        private Socket socket = null;

        /** socket should be closed after created, if ever */
        private boolean cleanUp = false;

        /**
         * Create a new asynchronous connector object.
         */
        AsyncConnector(RMISocketFactory factory, String host, int port,
                       AccessControlContext acc)
        {
            this.factory = factory;
            this.host    = host;
            this.port    = port;
            this.acc     = acc;
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkConnect(host, port);
            }
        }

        /**
         * Attempt socket connection in separate thread.  If successful,
         * notify master waiting,
         */
        public void run() {
            try {
                /*
                 * Using the privileges of the thread that wants to make the
                 * connection is tempting, but it will fail with applets with
                 * the current applet security manager because the applet
                 * network connection policy is not captured in the permission
                 * framework of the access control context we have.
                 *
                 * java.security.AccessController.beginPrivileged(acc);
                 */
                try {
                    Socket temp = factory.createSocket(host, port);
                    synchronized (this) {
                        socket = temp;
                        notify();
                    }
                    rememberFactory(host, factory);
                    synchronized (this) {
                        if (cleanUp)
                          try {
                              socket.close();
                          } catch (IOException e) {
                          }
                    }
                } catch (Exception e) {
                    /*
                     * Note that the only exceptions which could actually have
                     * occurred here are IOException or RuntimeException.
                     */
                    synchronized (this) {
                        exception = e;
                        notify();
                    }
                }
            } finally {
                /*
                 * See above comments for matching beginPrivileged() call that
                 * is also commented out.
                 *
                 * java.security.AccessController.endPrivileged();
                 */
            }
        }

        /**
         * Get exception that occurred during connection attempt, if any.
         * In the current implementation, this is guaranteed to be either
         * an IOException or a RuntimeException.
         */
        private synchronized Exception getException() {
            return exception;
        }

        /**
         * Get successful socket, if any.
         */
        private synchronized Socket getSocket() {
            return socket;
        }

        /**
         * Note that this connector's socket, if ever successfully created,
         * will not be used, so it should be cleaned up quickly
         */
        synchronized void notUsed() {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                }
            }
            cleanUp = true;
        }
    }
}
